add SD driver and FATFS library (tentative)

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/twl_wrapsdk/trunk@96 4ee2a332-4b2b-5046-8439-1ba90f034370
This commit is contained in:
Shirait 2007-05-30 10:22:28 +00:00
parent 0cee338ff1
commit 4fe5688d29
79 changed files with 46287 additions and 0 deletions

View File

@ -230,3 +230,45 @@
0x514,,SNDCAP0LEN,16,rw,SND,volatile,LEN,0,16,,,,,,,,,,,,,,,,,,,,,,,,,,,
0x518,,SNDCAP1DAD,32,w,SND,volatile,DEST,0,27,,,,,,,,,,,,,,,,,,,,,,,,,,,
0x51c,,SNDCAP1LEN,16,rw,SND,volatile,LEN,0,16,,,,,,,,,,,,,,,,,,,,,,,,,,,
#SDƒCƒ“ƒ^ƒtƒF<C692>[ƒX twl p195,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
0x800,,SD_CMD,16,rw,SD,volatile,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
0x802,,SD_PORTSEL,16,rw,SD,volatile,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
0x804,,SD_ARG0,16,rw,SD,volatile,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
0x806,,SD_ARG1,16,rw,SD,volatile,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
0x808,,SD_STOP,16,rw,SD,volatile,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
0x80A,,SD_SECCNT,16,rw,SD,volatile,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
0x80C,,SD_RSP0,16,r,SD,volatile,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
0x80E,,SD_RSP1,16,r,SD,volatile
0x810,,SD_RSP2,16,r,SD,volatile
0x812,,SD_RSP3,16,r,SD,volatile
0x814,,SD_RSP4,16,r,SD,volatile
0x816,,SD_RSP5,16,r,SD,volatile
0x818,,SD_RSP6,16,r,SD,volatile
0x81A,,SD_RSP7,16,r,SD,volatile
0x81C,,SD_INFO1,16,rw,SD,volatile
0x81E,,SD_INFO2,16,rw,SD,volatile
0x820,,SD_INFO1_MASK,16,rw,SD,volatile
0x822,,SD_INFO2_MASK,16,rw,SD,volatile
0x824,,SD_CLK_CTRL,16,rw,SD,volatile
0x826,,SD_SIZE,16,rw,SD,volatile
0x828,,SD_OPTION,16,rw,SD,volatile
0x82C,,SD_ERR_STS1,16,r,SD,volatile
0x82E,,SD_ERR_STS2,16,r,SD,volatile
0x830,,SD_BUF0,16,rw,SD,volatile
0x834,,SDIO_MODE,16,rw,SD,volatile
0x836,,SDIO_INFO1,16,rw,SD,volatile
0x838,,SDIO_INF1_MASK,16,rw,SD,volatile
0x8D8,,CC_EXT_MODE,16,rw,SD,volatile
0x8E0,,SOFT_RST,16,rw,SD,volatile
0x8E2,,VERSITON,16,r,SD,permanent
0x8F2,,SD_PWR,16,rw,SD,volatile
0x8F4,,EXT_SDIO,16,rw,SD,volatile
0x8F6,,EXT_WP,16,r,SD,volatile
0x8F8,,EXT_CD,16,rw,SD,volatile
0x8FA,,EXT_CD_DAT3,16,rw,SD,volatile
0x8FC,,EXT_CD_MASK,16,rw,SD,volatile
0x8FE,,EXT_CD_DAT3_MASK,16,rw,SD,volatile
0x900,,SDIF_CNT,16,rw,SD,volatile
0x904,,SDIF_FDS,16,rw,SD,volatile
0x908,,SDIF_FSC,16,rw,SD,volatile
0x90C,,SDIF_FI,32,rw,SD,volatile

Can't render this file because it has a wrong number of fields in line 17.

View File

@ -0,0 +1,34 @@
#! make -f
#----------------------------------------------------------------------------
# Project: TwlSDK - libraries
# File: Makefile
#
# Copyright 2007 Nintendo. All rights reserved.
#
# These coded instructions, statements, and computer programs contain
# proprietary information of Nintendo of America Inc. and/or Nintendo
# Company Ltd., and are protected by Federal copyright law. They may
# not be disclosed to third parties or copied or duplicated in any form,
# in whole or in part, without the prior written consent of Nintendo.
#
# $Log: $
# $NoKeywords: $
#----------------------------------------------------------------------------
include $(TWLSDK_ROOT)/build/buildtools/commondefs
#----------------------------------------------------------------------------
SUBDIRS = \
sdmc \
#----------------------------------------------------------------------------
export NITRO_BLXCHECKED = yes
#----------------------------------------------------------------------------
include $(TWLSDK_ROOT)/build/buildtools/modulerules
#===== End of Makefile =====

View File

@ -0,0 +1,66 @@
#! make -f
#----------------------------------------------------------------------------
# Project: TwlSDK - libraries - mi/ARM7
# File: Makefile
#
# Copyright 2007 Nintendo. All rights reserved.
#
# These coded instructions, statements, and computer programs contain
# proprietary information of Nintendo of America Inc. and/or Nintendo
# Company Ltd., and are protected by Federal copyright law. They may
# not be disclosed to third parties or copied or duplicated in any form,
# in whole or in part, without the prior written consent of Nintendo.
#
# $Log: $
# $NoKeywords: $
#----------------------------------------------------------------------------
SUBDIRS =
#----------------------------------------------------------------------------
# build ARM & THUMB libraries
TWL_CODEGEN_ALL ?= True
# Codegen for sub processer
TWL_PROC = ARM7
SRCDIR = ../common/src src
INCDIR = ../common
INCDIR += $(TWLSDK_ROOT)/include/twl \
$(TWLSDK_ROOT)/include/twl/devices/sdmc/ARM7 \
$(TWLSDK_ROOT)/include/twl/fatfs/ARM7 \
SRCS = \
sdmc.c \
sdif.c \
drsdmc.c
TARGET_LIB = libsd_sp$(TWL_LIBSUFFIX).a
#----------------------------------------------------------------------------
# DEBUG版ビルドの場合、RELEASE版でビルドして
# DEBUG版のライブラリを装います。
ifdef NITRO_DEBUG
NITRO_BUILD_TYPE = RELEASE
endif
include $(TWLSDK_ROOT)/build/buildtools/commondefs
INSTALL_TARGETS = $(TARGETS)
INSTALL_DIR = $(TWL_INSTALL_LIBDIR)
#----------------------------------------------------------------------------
do-build: $(TARGETS)
include $(TWLSDK_ROOT)/build/buildtools/modulerules
#===== End of Makefile =====

View File

@ -0,0 +1,686 @@
/*---------------------------------------------------------------------------*
Project: CTR - rtfs interface for SD Memory Card
File: drsdmc.h
Copyright 2006,2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
*---------------------------------------------------------------------------*/
#include <rtfs.h>
#include <portconf.h>
//#if (INCLUDE_SD)
#include "sdmc_config.h"
#include "sdmc.h"
#include "sdif_ip.h"
#include "sdif_reg.h"
#if (SD_DEBUG_PRINT_ON == 1)
#if (CTR_DEF_ENVIRONMENT_DSEMU == 1)
#define PRINTDEBUG osTPrintf
#else
#include <ctr/vlink.h>
#define PRINTDEBUG vlink_dos_printf
#endif
#else
#define PRINTDEBUG( ...) ((void)0)
#endif
#define NUM_SD_PAGES
#define SD_PAGE_SIZE
/*---------------------------------------------------------------------------*
extern変数
*---------------------------------------------------------------------------*/
//extern ER_ID sdmc_dtq_id;
//extern ER_ID sdmc_result_dtq_id;
extern void (*func_SDCARD_In)(void); /* カード挿入イベント用コールバック保存用 */
extern void (*func_SDCARD_Out)(void); /* カード排出イベント用コールバック保存用 */
extern volatile s16 SDCARD_OutFlag; /* カード排出発生判定フラグ */
extern int rtfs_first_stat_flag[26];
/*SDメモリカードのスペック構造体*/
extern SdmcSpec sdmc_current_spec;
/*---------------------------------------------------------------------------*
extern関数
*---------------------------------------------------------------------------*/
extern SDMC_ERR_CODE sdmcGoIdle(void (*func1)(),void (*func2)());
/*---------------------------------------------------------------------------*
static変数
*---------------------------------------------------------------------------*/
static int sdmc_drive_no;
void (*func_usr_sdmc_out)(void) = NULL; /* カード排出イベントのユーザコールバック */
/*---------------------------------------------------------------------------*
static関数
*---------------------------------------------------------------------------*/
void i_sdmcRemovedIntr( void);
static void sdi_get_CHS_params( void);
static u32 sdi_get_ceil( u32 cval, u32 mval);
static void sdi_get_nom( void);
static void sdi_get_fatparams( void);
static void sdi_build_partition_table( void);
/*---------------------------------------------------------------------------*
Name: sdmcCheckMedia
Description: MBRのシグネチャおよび
Arguments:
Returns: TRUE/FALSE
FALSEなら pc_format_media
*---------------------------------------------------------------------------*/
BOOL sdmcCheckMedia( void)
{
u16 i;
SdmcResultInfo SdResult;
u8* bufp;
u32 buffer[512/4];
u8 systemid;
/**/
if( sdmcReadFifo( buffer, 1, 0, NULL, &SdResult)) {
return( FALSE);
}
bufp = (u8*)buffer;
/* Check the Signature Word. */
if( (bufp[510]!=0x55) || (bufp[511]!=0xAA)) {
return( FALSE);
}
/* Check the System ID of partition. */
systemid = bufp[450];
if( (systemid!=0x01) && (systemid!=0x04) && (systemid!=0x06) &&
(systemid!=0x0B) && (systemid!=0x0C)) {
return( FALSE);
}
/* Check the System ID of unuse partitions. */
for( i=1; i<4; i++) {
systemid = bufp[450+(16*i)];
if( systemid != 0x00) {
return( FALSE);
}
}
/**/
/*もっと厳密にチェックするならパーティション0開始位置の
調*/
return( TRUE);
}
/*---------------------------------------------------------------------------*
Name: sdmcRtfsIo
Description:
Arguments: driveno :
block :
buffer :
count :
reading : TRUE
Returns: TRUE/FALSE
*---------------------------------------------------------------------------*/
BOOL sdmcRtfsIo( int driveno, dword block, void* buffer, word count, BOOLEAN reading)
{
u16 result;
SdmcResultInfo SdResult;
if( reading) {
PRINTDEBUG( "DEVCTL_IO_READ ... block:%x, count:%x -> buf:%x\n", block, count, buffer);
result = sdmcReadFifo( buffer, count, block, NULL, &SdResult);
// result = sdmcRead( buffer, count, block, NULL, &SdResult);
}else{
PRINTDEBUG( "DEVCTL_IO_WRITE ... block:%x, count:%x <- buf:%x\n", block, count, buffer);
result = sdmcWriteFifo( buffer, count, block, NULL, &SdResult);
// result = sdmcWrite( buffer, count, block, NULL, &SdResult);
}
if( result) {
return FALSE;
}
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: sdmcRtfsCtrl
Description:
Arguments: driveno :
opcode :
pargs :
Returns:
Memo : DRIVE_FLAGS_REMOVABLEの場合IO関数を呼ぶ前に
CTRL関数のDEVCTL_CHECK_STATUSが呼ばれる
DEVTEST_CHANGEDDEVTEST_NOCHANGEが確認されるとRTFSはセクタ0を
FATパラメータを取得した上で目的のセクタを読みに行く
CTRL関数の前にはDEVCTL_CHECK_STATUSが呼ばれないのでDEVCTL_
GET_GEOMETRYでは自前で再挿入をチェックする必要がある
*---------------------------------------------------------------------------*/
int sdmcRtfsCtrl( int driveno, int opcode, void* pargs)
{
DDRIVE *pdr;
DEV_GEOMETRY gc;
int heads, secptrack;
pdr = pc_drno_to_drive_struct( driveno);
switch( opcode) {
case DEVCTL_GET_GEOMETRY: //formatまたはpartirionするときにRTFSが使うパラメータ
PRINTDEBUG( "DEVCTL_GET_GEOMETRY\n");
if( (pdr->drive_flags & DRIVE_FLAGS_INSERTED) == 0) { /* 抜かれていた場合 */
if( SDCARD_OutFlag == TRUE) { /* 今現在も抜かれているとき */
return( -1);
}else{ /* 今現在は再挿入されているとき */
/*-- GoIdleセット --*/
if( func_SDCARD_Out != i_sdmcRemovedIntr) {
func_usr_sdmc_out = func_SDCARD_Out; //ユーザコールバック取得
}
sdmcGoIdle( func_SDCARD_In, i_sdmcRemovedIntr); //カード初期化シーケンス
/*------------------*/
}
}
rtfs_memset( &gc, (byte)0, sizeof(gc));
sdi_get_CHS_params(); //最初に呼ぶこと
sdi_get_fatparams();
sdi_get_nom();
PRINTDEBUG( "heads : 0x%x\n", sdmc_current_spec.heads);
PRINTDEBUG( "secptrack : 0x%x\n", sdmc_current_spec.secptrack);
PRINTDEBUG( "cylinders : 0x%x\n", sdmc_current_spec.cylinders);
PRINTDEBUG( "SC : 0x%x\n", sdmc_current_spec.SC);
PRINTDEBUG( "BU : 0x%x\n", sdmc_current_spec.BU);
PRINTDEBUG( "RDE : 0x%x\n", sdmc_current_spec.RDE);
PRINTDEBUG( "SS : 0x%x\n", sdmc_current_spec.SS);
PRINTDEBUG( "RSC : 0x%x\n", sdmc_current_spec.RSC);
PRINTDEBUG( "FATBITS : 0x%x\n", sdmc_current_spec.FATBITS);
PRINTDEBUG( "SF : 0x%x\n", sdmc_current_spec.SF);
PRINTDEBUG( "SSA : 0x%x\n", sdmc_current_spec.SSA);
PRINTDEBUG( "NOM : 0x%x\n", sdmc_current_spec.NOM);
gc.dev_geometry_lbas = (sdmc_current_spec.adjusted_memory_capacity);// - sdmc_current_spec.NOM);
gc.dev_geometry_heads = sdmc_current_spec.heads;
gc.dev_geometry_cylinders = sdmc_current_spec.cylinders;
gc.dev_geometry_secptrack = sdmc_current_spec.secptrack;
/**/
gc.fmt_parms_valid = TRUE;
gc.fmt.oemname[0] = 'C';
gc.fmt.oemname[1] = 'T';
gc.fmt.oemname[2] = 'R';
gc.fmt.oemname[3] = '\0';
gc.fmt.secpalloc = sdmc_current_spec.SC; /*sectors per cluster(FIX by capacity)*/
gc.fmt.secreserved = sdmc_current_spec.RSC;//sdmc_current_spec.RSC;/*reserved sectors(FIX 1 at FAT12,16)*/
gc.fmt.numfats = 2;
gc.fmt.secpfat = sdmc_current_spec.SF;
gc.fmt.numhide = sdmc_current_spec.NOM; /**/
gc.fmt.numroot = sdmc_current_spec.RDE; /*FIX*/
gc.fmt.mediadesc = 0xF8;
gc.fmt.secptrk = sdmc_current_spec.secptrack; //CHS Recommendation
gc.fmt.numhead = sdmc_current_spec.heads;
gc.fmt.numcyl = sdmc_current_spec.cylinders;
gc.fmt.physical_drive_no = driveno;
gc.fmt.binary_volume_label = BIN_VOL_LABEL;
gc.fmt.text_volume_label[0] = '\0';
//TODO:dev_geometry_lbasもセットする必要あるか調べること
PRINTDEBUG( "heads : 0x%x, secptrack : 0x%x, cylinders : 0x%x\n", gc.dev_geometry_heads, gc.dev_geometry_secptrack, gc.dev_geometry_cylinders);
#if (TARGET_OS_CTR == 1)
miCpuCopy8( &gc, pargs, sizeof(gc));
// copybuff( pargs, &gc, sizeof(gc));
#else
MI_CpuCopy8( &gc, pargs, sizeof(gc));
#endif
return( 0);
case DEVCTL_FORMAT:
PRINTDEBUG( "DEVCTL_FORMAT\n");
sdi_build_partition_table(); //MBRセクタ(パーティションテーブル含む)書き込み
return( 0);
case DEVCTL_REPORT_REMOVE: //抜かれたとき
PRINTDEBUG( "DEVCTL_REPORT_REMOVE\n");
pdr->drive_flags &= ~DRIVE_FLAGS_INSERTED;
return( 0);
case DEVCTL_CHECKSTATUS: //REMOVABLEの場合、毎回R/W前に呼ばれる
PRINTDEBUG( "DEVCTL_CHECKSTATUS\n");
if (!(pdr->drive_flags & DRIVE_FLAGS_REMOVABLE)) { //リムーバブルでない場合
return(DEVTEST_NOCHANGE);
}
if (pdr->drive_flags & DRIVE_FLAGS_INSERTED) { /* 抜かれてない場合 */
if( rtfs_first_stat_flag[driveno]) { //初回のCHECKSTATUS時
rtfs_first_stat_flag[driveno] = 0;
PRINTDEBUG( "CHANGED!\n");
return(DEVTEST_CHANGED);
}else{
PRINTDEBUG( "DEVTEST_NOCHANGE\n");
return( DEVTEST_NOCHANGE);
}
}else{ /* 抜かれていた場合 */
if( SDCARD_OutFlag == FALSE) { /* 排出フラグ参照 */
pdr->drive_flags |= DRIVE_FLAGS_INSERTED;
/*-- GoIdleセット --*/
if( func_SDCARD_Out != i_sdmcRemovedIntr) {
func_usr_sdmc_out = func_SDCARD_Out; //ユーザコールバック取得
}
sdmcGoIdle( func_SDCARD_In, i_sdmcRemovedIntr); //カード初期化シーケンス
/*------------------*/
PRINTDEBUG( "DEVTEST_CHANGED\n");
return( DEVTEST_CHANGED); //挿さっている
}else{
PRINTDEBUG( "DEVTEST_NOMEDIA\n");
return( DEVTEST_NOMEDIA); //挿さってない
}
}
case DEVCTL_WARMSTART: //attachのときしか呼ばれない
PRINTDEBUG( "DEVCTL_WARMSTART\n");
/*-- GoIdleセット --*/
if( func_SDCARD_Out != i_sdmcRemovedIntr) {
func_usr_sdmc_out = func_SDCARD_Out; //ユーザコールバック取得
}
sdmcGoIdle( func_SDCARD_In, i_sdmcRemovedIntr); //カード初期化シーケンス
/*------------------*/
pdr->drive_flags |= (DRIVE_FLAGS_VALID | DRIVE_FLAGS_REMOVABLE | DRIVE_FLAGS_PARTITIONED);
pdr->partition_number = 0;
if( SDCARD_OutFlag == FALSE) { /* 排出フラグ参照 */
pdr->drive_flags |= DRIVE_FLAGS_INSERTED;
}else{ /* カード未挿入のとき */
pdr->drive_flags &= (~(DRIVE_FLAGS_INSERTED)); //抜かれているだけではVALIDフラグは落とさないらしい
}
return( 0);
case DEVCTL_POWER_RESTORE:
PRINTDEBUG( "DEVCTL_POWER_RESTORE\n");
break;
case DEVCTL_POWER_LOSS:
PRINTDEBUG( "DEVCTL_POWER_LOSS\n");
break;
default:
PRINTDEBUG( "DEVCTL_unknown\n");
break;
}
return( 0);
}
/*---------------------------------------------------------------------------*
RTFSが次回"DEVCTL_GET_GEOMETRY"
*---------------------------------------------------------------------------*/
void i_sdmcRemovedIntr( void)
{
DDRIVE *pdr;
pdr = pc_drno_to_drive_struct( sdmc_drive_no);
if( pdr) {
pdr->dev_table_perform_device_ioctl( pdr->driveno,
DEVCTL_REPORT_REMOVE,
(void*)0);
}
if( func_usr_sdmc_out) {
func_usr_sdmc_out(); //ユーザコールバック
}
}
/*---------------------------------------------------------------------------*
Name: sdmcRtfsAttach
Description: sdmcドライバをドライブに割り当てる
Arguments: driveno :
Returns:
*---------------------------------------------------------------------------*/
BOOL sdmcRtfsAttach( int driveno)
{
BOOLEAN result;
DDRIVE pdr;
pdr.dev_table_drive_io = sdmcRtfsIo;
pdr.dev_table_perform_device_ioctl = sdmcRtfsCtrl;
pdr.register_file_address = (dword) 0; /* Not used */
pdr.interrupt_number = 0; /* Not used */
pdr.drive_flags = 0;//DRIVE_FLAGS_FAILSAFE;
pdr.partition_number = 0; /* Not used */
pdr.pcmcia_slot_number = 0; /* Not used */
pdr.controller_number = 0;
pdr.logical_unit_number = 0;
result = rtfs_attach( driveno, &pdr, "SD"); //構造体がFSライブラリ側にコピーされる
/*drivenoをグローバル変数に記憶*/
sdmc_drive_no = driveno;
return( result);
}
/*SD File System Specification(仕様書)に基づいた値を出す*/
static void sdi_get_CHS_params( void)
{
int mbytes;
// mbytes = (sdmc_current_spec.card_capacity / (1024 * 1024)) * 512;
mbytes = (sdmc_current_spec.card_capacity >> 11);
while( 1) {
if( mbytes <= 2) {
sdmc_current_spec.heads = 2;
sdmc_current_spec.secptrack = 16;
break;
}
if( mbytes <= 16) {
sdmc_current_spec.heads = 2;
sdmc_current_spec.secptrack = 32;
break;
}
if( mbytes <= 32) {
sdmc_current_spec.heads = 4;
sdmc_current_spec.secptrack = 32;
break;
}
if( mbytes <= 128) {
sdmc_current_spec.heads = 8;
sdmc_current_spec.secptrack = 32;
break;
}
if( mbytes <= 256) {
sdmc_current_spec.heads = 16;
sdmc_current_spec.secptrack = 32;
break;
}
if( mbytes <= 504) {
sdmc_current_spec.heads = 16;
sdmc_current_spec.secptrack = 63;
break;
}
if( mbytes <= 1008) {
sdmc_current_spec.heads = 32;
sdmc_current_spec.secptrack = 63;
break;
}
if( mbytes <= 2016) {
sdmc_current_spec.heads = 64;
sdmc_current_spec.secptrack = 63;
break;
}
if( mbytes <= 2048) {
sdmc_current_spec.heads = 128;
sdmc_current_spec.secptrack = 63;
break;
}
if( mbytes <= 4032) {
sdmc_current_spec.heads = 128;
sdmc_current_spec.secptrack = 63;
break;
}
if( mbytes <= 32768) {
sdmc_current_spec.heads = 255;
sdmc_current_spec.secptrack = 63;
break;
}
}
/*シリンダ数を計算*/
sdmc_current_spec.cylinders = (sdmc_current_spec.memory_capacity /
(sdmc_current_spec.heads * sdmc_current_spec.secptrack));
/*memory_capacityを再計算してadjusted_memory_capacityに格納*/
sdmc_current_spec.adjusted_memory_capacity = sdmc_current_spec.cylinders *
(sdmc_current_spec.heads * sdmc_current_spec.secptrack);
}
/*引数を超える最も小さい整数を算出する*/
static u32 sdi_get_ceil( u32 cval, u32 mval)
{
return( (cval / mval) + (1 * (cval % mval != 0)));
}
/*マスターブートセクタのセクタ数を返す*/
static void sdi_get_nom( void)
{
u32 RSC = 1; //FAT12,16では1
u32 RDE = 512; //ルートディレクトリエントリ。FIX
u32 SS = 512; //セクタサイズ。FIX
u32 TS, SC, n;
u32 MAX, SFdash;
TS = sdmc_current_spec.adjusted_memory_capacity;
SC = sdmc_current_spec.SC;
sdmc_current_spec.SF = sdi_get_ceil( TS/SC * sdmc_current_spec.FATBITS, SS*8);
/*-----------------------SDHCのとき----------------------------*/
if( sdmc_current_spec.csd_ver2_flag) {
sdmc_current_spec.NOM = sdmc_current_spec.BU;
do {
n = sdi_get_ceil( 2*sdmc_current_spec.SF, sdmc_current_spec.BU);
sdmc_current_spec.RSC = (sdmc_current_spec.BU * n) - ( 2 * sdmc_current_spec.SF);
if( sdmc_current_spec.RSC < 9) {
sdmc_current_spec.RSC += sdmc_current_spec.BU;
}
sdmc_current_spec.SSA = sdmc_current_spec.RSC + (2 * sdmc_current_spec.SF);
do {
MAX = ((TS - sdmc_current_spec.NOM - sdmc_current_spec.SSA) / SC) + 1;
SFdash = sdi_get_ceil( (2+(MAX-1)) * sdmc_current_spec.FATBITS, SS*8);
if( SFdash > sdmc_current_spec.SF) {
sdmc_current_spec.SSA += sdmc_current_spec.BU;
sdmc_current_spec.RSC += sdmc_current_spec.BU;
}else{
break;
}
}while( 1);
if( SFdash != sdmc_current_spec.SF) {
sdmc_current_spec.SF -= 1;
}else{
break;
}
}while( 1);
}else{ /*-------------------------SDのとき-------------------------------*/
do {
sdmc_current_spec.SSA = RSC + ( 2 * sdmc_current_spec.SF) + sdi_get_ceil( 32*RDE, SS);
n = sdi_get_ceil( sdmc_current_spec.SSA, sdmc_current_spec.BU);
sdmc_current_spec.NOM = (sdmc_current_spec.BU * n) - sdmc_current_spec.SSA;
if( sdmc_current_spec.NOM != sdmc_current_spec.BU) {
sdmc_current_spec.NOM += sdmc_current_spec.BU;
}
do {
MAX = ((TS - sdmc_current_spec.NOM - sdmc_current_spec.SSA) / SC) + 1;
SFdash = sdi_get_ceil( (2+(MAX-1)) * sdmc_current_spec.FATBITS, SS*8);
if( SFdash > sdmc_current_spec.SF) {
sdmc_current_spec.NOM += sdmc_current_spec.BU;
}else{
break;
}
}while( 1);
if( SFdash != sdmc_current_spec.SF) {
sdmc_current_spec.SF = SFdash;
}else{
break; //complete
}
}while( 1);
}
return;
}
/*FATのビット数を返す*/
static void sdi_get_fatparams( void)
{
int mbytes;
// mbytes = (sdmc_current_spec.card_capacity / (1024 * 1024)) * 512;
mbytes = (sdmc_current_spec.card_capacity >> 11);
if( mbytes <= 64) {
sdmc_current_spec.FATBITS = 12;
sdmc_current_spec.RDE = 512;
sdmc_current_spec.RSC = 1;
}else{
if( mbytes <= 2048) {
sdmc_current_spec.FATBITS = 16;
sdmc_current_spec.RDE = 512;
sdmc_current_spec.RSC = 1;
}else{
sdmc_current_spec.FATBITS = 32;
sdmc_current_spec.RDE = 0; //FAT32のときは未使用。0にしておかないとRTFSが BAD FORMAT を返す。
sdmc_current_spec.RSC = 1;
}
}
if( mbytes <= 8) {
sdmc_current_spec.SC = 16;
sdmc_current_spec.BU = 16;
return;
}
if( mbytes <= 64) {
sdmc_current_spec.SC = 32;
sdmc_current_spec.BU = 32;
return;
}
if( mbytes <= 256) {
sdmc_current_spec.SC = 32;
sdmc_current_spec.BU = 64;
return;
}
if( mbytes <= 1024) {
sdmc_current_spec.SC = 32;
sdmc_current_spec.BU = 128;
return;
}
if( mbytes <= 2048) {
sdmc_current_spec.SC = 64;
sdmc_current_spec.BU = 128;
return;
}
if( mbytes <= 32768) {
sdmc_current_spec.SC = 64;
sdmc_current_spec.BU = 8192;
return;
}
}
/*MBRセクタ(パーティションセクタ含む)を生成して書き込む*/
static void sdi_build_partition_table( void)
{
u16 MbrSectDat[512/2];
u32 starting_head, starting_sect, starting_cyl;
u32 ending_head, ending_sect, ending_cyl;
u32 total_sect;
#if (SD_DEBUG_PRINT_ON == 1)
u32 starting_data, ending_data;
#endif
u32 systemid;
SdmcResultInfo SdResult;
/**/
starting_head = sdmc_current_spec.NOM % (sdmc_current_spec.heads *
sdmc_current_spec.secptrack);
starting_head /= sdmc_current_spec.secptrack;
/**/
starting_sect = (sdmc_current_spec.NOM % sdmc_current_spec.secptrack) + 1;
/**/
starting_cyl = sdmc_current_spec.NOM / (sdmc_current_spec.heads *
sdmc_current_spec.secptrack);
/**/
total_sect = (sdmc_current_spec.adjusted_memory_capacity - sdmc_current_spec.NOM);
ending_head = (sdmc_current_spec.NOM + total_sect - 1) %
(sdmc_current_spec.heads * sdmc_current_spec.secptrack);
ending_head /= sdmc_current_spec.secptrack;
/**/
ending_sect = ((sdmc_current_spec.NOM + total_sect - 1) %
sdmc_current_spec.secptrack) + 1;
/**/
ending_cyl = (sdmc_current_spec.NOM + total_sect - 1) /
(sdmc_current_spec.heads * sdmc_current_spec.secptrack);
/**/
if( sdmc_current_spec.FATBITS == 32) { //FAT32のとき
if( total_sect < 0xFB0400) { //8032.5MBが閾値(SD FileSystemSpec2.00参照)
systemid = 0x0B; /* FAT32 */
}else{
systemid = 0x0C; /* FAT32(拡張INT13対応) */
}
}else{ //FAT12,FAT16のとき
if( total_sect < 32680) {
systemid = 0x01; /* FAT12 */
}else if( total_sect < 65536) {
systemid = 0x04; /* FAT16(16MB32MB未満) */
}else{
systemid = 0x06; /* FAT16(32MB4GB) */
}
}
/*MBRセクタ(パーティションテーブル含む)作成*/
#if (TARGET_OS_CTR == 1)
miCpuFill8( MbrSectDat, 0, 512);
#else
MI_CpuFill8( MbrSectDat, 0, 512);
#endif
MbrSectDat[446/2] = (starting_head<<8);
//上位8bit:starting_cylの下位8bit, 下位8bit:starting_cylの上位2bit + starting_sect 6bit.
MbrSectDat[448/2] = (starting_cyl<<8) + ((starting_cyl>>2) & 0xC0) + starting_sect;
MbrSectDat[450/2] = (ending_head<<8) + systemid;
//上位8bit:ending_cylの下位8bit, 下位8bit:ending_cylの上位2bit + ending_sect 6bit.
MbrSectDat[452/2] = (ending_cyl<<8) + ((ending_cyl>>2) & 0xC0) + ending_sect;
MbrSectDat[454/2] = sdmc_current_spec.NOM;
MbrSectDat[456/2] = (sdmc_current_spec.NOM>>16);
MbrSectDat[458/2] = total_sect;
MbrSectDat[460/2] = (total_sect>>16);
MbrSectDat[510/2] = 0xAA55;
/*セクタ0に書き込み*/
sdmcWriteFifo( MbrSectDat, 1, 0, NULL, &SdResult);
/**/
PRINTDEBUG( "total sect : 0x%x\n", total_sect);
PRINTDEBUG( "starting head : 0x%x\n", starting_head);
PRINTDEBUG( "starting sect : 0x%x\n", starting_sect);
PRINTDEBUG( "starting cyl : 0x%x\n", starting_cyl);
PRINTDEBUG( "ending head : 0x%x\n", ending_head);
PRINTDEBUG( "ending sect : 0x%x\n", ending_sect);
PRINTDEBUG( "ending cyl : 0x%x\n", ending_cyl);
PRINTDEBUG( "\n");
#if (SD_DEBUG_PRINT_ON == 1)
starting_data = (starting_cyl<<8) + ((starting_cyl>>2) & 0xC0) + starting_sect;
PRINTDEBUG( "starting data : 0x%x\n", starting_data);
ending_data = (ending_cyl<<8) + ((ending_cyl>>2) & 0xC0) + ending_sect;
PRINTDEBUG( "endign data : 0x%x\n", ending_data);
#endif
}
//#endif /*(INCLUDE_SD)*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,349 @@
/*
** Copyright (c) 2000-2001 Matsushita Electric Industrial Co., Ltd.
** All Rights Reserved.
*/
/*
** $Module SDカードアクセスモジュール
** $Filename SD_CARD_IP.H
** $Version 1.0
** $Date 01/02/16
** $Log 01/02/16 rev1.0
** ()
*/
#ifndef __SD_CARD_IP_H__
#define __SD_CARD_IP_H__
//#define IO3 0 /* Insert Remove SW = FALSE IO3 = TRUE */
//#define MAX_SD_CLOCK_4M 0 /* MAX SD Clock 4.608MHz */
//#define MAX_SD_CLOCK_9M 1 /* MAX SD Clock 9.216MHz */
/*---------------------------------------------
---------------------------------------------*/
/* SD_CNTレジスタ */
#define SDIF_CNT_USEDTC (0x0001) /* DTC使用フラグ (R/W) */
#define SDIF_CNT_USEFIFO (0x0002) /* FIFO使用フラグ (R/W) */
#define SDIF_CNT_FULL (0x0100) /* FIFO FULLフラグ (RO) */
#define SDIF_CNT_NEMP (0x0200) /* FIFO NOT EMPTYフラグ (RO) */
#define SDIF_CNT_FCLR (0x0400) /* FIFO クリアフラグ (WO) */
#define SDIF_CNT_FFIE (0x0800) /* FIFO FULLで割り込み (R/W) */
#define SDIF_CNT_FEIE (0x1000) /* FIFO EMPTYで割り込み (R/W) */
#define SDCARD_UseFifoFlag ((*SDIF_CNT) & SDIF_CNT_USEFIFO)
/*-------------------------------------
-------------------------------------*/
/* SD_CMDレジスタ*/
#define SD_CMD_CMD 0x0000 /* SDカードへの通常アクセス(CMD) */
#define SD_CMD_ACMD 0x0040 /* SDカードへのセキュリティアクセス(ACMD) */
/* SD_STOPレジスタ */
#define SD_STOP_STP 0x0001 /* データ転送終了を知らせる */
#define SD_STOP_SEC_ENABLE 0x0100 /* SD_SECCNTレジスタ有効セクタカウントレジスタ */
/* SD_SECCNTレジスタ */
#define SD_SECCNT_END 0x0000 /* SD_SECCNTレジスタ カウントチェック */
/* SD_SIZEレジスタ */
#define SD_SIZE_DATA_LENGTH_1B 0x0001 /* SDカード転送データサイズ 1Bytes */
#define SD_SIZE_DATA_LENGTH_2B 0x0002 /* SDカード転送データサイズ 2Bytes */
#define SD_SIZE_DATA_LENGTH_4B 0x0004 /* SDカード転送データサイズ 4Bytes */
#define SD_SIZE_DATA_LENGTH_8B 0x0008 /* SDカード転送データサイズ 8Bytes (SCR) */
#define SD_SIZE_DATA_LENGTH_16B 0x0010 /* SDカード転送データサイズ 16Bytes */
#define SD_SIZE_DATA_LENGTH_32B 0x0020 /* SDカード転送データサイズ 32Bytes */
#define SD_SIZE_DATA_LENGTH_64B 0x0040 /* SDカード転送データサイズ 64Bytes (SD_Status) */
#define SD_SIZE_DATA_LENGTH_128B 0x0080 /* SDカード転送データサイズ 128Bytes */
#define SD_SIZE_DATA_LENGTH_256B 0x0100 /* SDカード転送データサイズ 256Bytes */
#define SD_SIZE_DATA_LENGTH_512B 0x0200 /* SDカード転送データサイズ 512Bytes (データ) */
/* SD_OPTIONレジスタ */
#define SD_OPTION_WIDTH_1BIT 0x8000 /* ビット幅の選択 1bit幅 */
#define SD_OPTION_MSEL_C2NOUSE 0x4000 /* C2モジュール未使用 */
#define SD_CD_DETECT_TIME 0xFFF0 /* CD 検出タイムだけをクリアするためのマスク */
/* SD_INFO2レジスタ */
#define SD_INFO2_ERR_ILA 0x8000 /* イリーガルアクセスエラー */
#define SD_INFO2_BWE 0x0200 /* SDカードから512byteのデータ書込み要求 */
#define SD_INFO2_BRE 0x0100 /* SDカードから512byteのデータ読込み要求 */
#define SD_INFO2_ERR_ALLCLR 0x807F /* SD Card エラーレジスタクリア */
#define SD_INFO2_ERR_SDDAT0 0x0080 /* SD Card Busy bit */
#define SD_INFO2_ERR_RESTIMEOUT 0x0040 /* レスポンスタイムアウトエラー */
#define SD_INFO2_ERR_UNDERFLOW 0x0020 /* FIFO アンダーフローエラー */
#define SD_INFO2_ERR_OVERFLOW 0x0010 /* FIFO オーバーフローエラー */
#define SD_INFO2_ERR_TIMEOUT 0x0008 /* レスポンス以外のタイムアウトエラー */
#define SD_INFO2_ERR_END 0x0004 /* フレーム終了認識できないときのENDエラー */
#define SD_INFO2_ERR_CRC 0x0002 /* CRC エラー */
#define SD_INFO2_ERR_CMD 0x0001 /* CMDエラー */
#define SD_INFO2_RW_SET 0x0300 /* SDカード Read/Write 要求割込み要因チェック */
#define SD_INFO2_ERROR_SET 0x807F /* SDカード エラー割込み要因チェック */
/* SD_INFO2_MASKレジスタ */
#define SD_INFO2_MASK_ILA 0x8000 /* イリーガルアクセスエラー割込みマスク */
#define SD_INFO2_MASK_BWE 0x0200 /* SDカードからのデータ書込み要求割込み禁止 */
#define SD_INFO2_MASK_BRE 0x0100 /* SDカードからのデータ読込み要求割込み禁止 */
#define SD_INFO2_MASK_ALLERRMASK 0x807F /* 全エラー割り込み禁止 */
#define SD_INFO2_MASK_EXCEPT_OVERFLOW 0x802F /* 全エラー割り込み禁止 FIFO Overflow Errorを除く */
#define SD_INFO2_MASK_RESTIMEOUT 0x0040 /* Time out 割込みEnable */
#define SD_INFO2_MASK_UNDERFLOW 0x0020 /* FIFO アンダーフロー 割込みEnable */
#define SD_INFO2_MASK_OVERFLOW 0x0010 /* FIFO オーバーフロー 割込みEnable */
#define SD_INFO2_MASK_TIMEOUT 0x0008 /* Time out 割込みEnable */
#define SD_INFO2_MASK_END 0x0004 /* END エラー 割込みEnable */
#define SD_INFO2_MASK_CRC 0x0002 /* CRC エラー 割込みEnable */
#define SD_INFO2_MASK_CMD 0x0001 /* CMD エラー 割込みEnable */
#define SD_INFO2_MASK_ERRSET 0x807F /* SDカード エラー割込み要因チェック */
/* SD_INFO1レジスタ */
#define SD_INFO1_DAT3DETECT 0x0400 /* (IO3検出) card detect(検出=1) : CTRでは使用できない*/
#define SD_INFO1_DAT3INSERT 0x0200 /* (IO3検出) card inserted(挿入=1) : CTRでは使用できない */
#define SD_INFO1_DAT3REMOVE 0x0100 /* (IO3検出) card removed(抜け=1) : CTRでは使用できない */
#define SD_INFO1_DAT3INIT 0x0300 /* (IO3検出) の初期化 */
#define SD_INFO1_WRITEPROTECT 0x0080 /* write protect(書き込み禁止=1) */
#define SD_INFO1_DETECT 0x0020 /* card detect(検出=1) */
#define SD_INFO1_INSERT 0x0010 /* card inserted(挿入=1) */
#define SD_INFO1_REMOVE 0x0008 /* card removed(抜け=1) */
#define SD_INFO1_ALL_END 0x0004 /* R/W access all end */
#define SD_INFO1_RES_END 0x0001 /* Response end */
#define SD_INFO1_INIT 0x0005 /* SD Cardの状態を初期化 */
#define SD_INFO1_SET 0x031D /* SDカード 挿抜 and RWアクセス終了 and レスポンス終了 要求割込み要因チェック */
/* SD_INFO1_MASKレジスタ (0:割り込み許可、1:割り込み禁止)*/
#define SD_INFO1_MASK_DAT3INSERT 0x0200 /* (IO3検出) card inserted(挿入) 割込み禁止 */
#define SD_INFO1_MASK_DAT3REMOVE 0x0100 /* (IO3検出) card removed(抜け) 割込み禁止 */
#define SD_INFO1_MASK_INSERT 0x0010 /* card inserted(挿入) 割込み禁止 */
#define SD_INFO1_MASK_REMOVE 0x0008 /* card removed(抜け) 割込み禁止 */
#define SD_INFO1_MASK_ALL_END 0x0004 /* R/W access all end 割込み禁止 */
#define SD_INFO1_MASK_RES_END 0x0001 /* Response end 割込み禁止 */
/* CC_EXT_MODEレジスタ */
#define CC_EXT_MODE_PIO 0x0000 /* PIOモード */
#define CC_EXT_MODE_DMA 0x0002 /* DMAモード */
/* SOFT_RSTレジスタ */
#define SOFT_RST_SDIF_RST 0x0001 /* SD I/Fモジュールをリセット */
/* SD_CLK_CTRLレジスタ */
#define SD_CLK_CTRL_SDCLKEN 0x0100 /* SDカードクロック出力イネーブル */
#define SD_CLK_CTRL_512 0x0180 /* SDクロックの周波数分周比512*/
#define SD_CLK_CTRL_256 0x0140 /* SDクロックの周波数分周比256*/
#define SD_CLK_CTRL_128 0x0120 /* SDクロックの周波数分周比128*/
#define SD_CLK_CTRL_64 0x0110 /* SDクロックの周波数分周比 64*/
#define SD_CLK_CTRL_32 0x0108 /* SDクロックの周波数分周比 32*/
#define SD_CLK_CTRL_16 0x0104 /* SDクロックの周波数分周比 16*/
#define SD_CLK_CTRL_8 0x0102 /* SDクロックの周波数分周比 8*/
#define SD_CLK_CTRL_4 0x0101 /* SDクロックの周波数分周比 4*/
#define SD_CLK_CTRL_2 0x0100 /* SDクロックの周波数分周比 2*/
/*-------------------------------------
-------------------------------------*/
#define SDCARD_PORT_NO 0x0300 /* カードポート選択数 */
#define SDCARD_PORT_NO_MAX 0x04//0x02 /* カードポート最大選択数 */
#define SDCARD_PORT_NO_MIN 0x01 /* カードポート最小選択数 */
#define SDCARD_PORT_SELECT_NO 0x0001 /* カードポート番号ビット */
#define SDCARD_PORT0 0x0000 /* カードポート番号ビット */
#define SDCARD_PORT1 0x0001 /* カードポート番号ビット */
/* EXT_WPレジスタポート1以降のライトプロテクト */
#define EXT_WP_PORT1 0x0001 /* ポート1write protect(書き込み禁止=1)*/
/* EXT_CDレジスタ */
#define EXT_CD_PORT1_REMOVE 0x0001 /* ポート1 card detect検出=1 */
#define EXT_CD_PORT1_INSERT 0x0002 /* ポート1 card inserted挿入=1 */
#define EXT_CD_PORT1_DETECT 0x0004 /* ポート1 card removed抜け=1 */
/* EXT_CD_DAT3レジスタ */
//#define EXT_CD_PORT1_DAT3INIT 0x0003 /* ポート1 card の状態 (IO3検出) の初期化 */
#define EXT_CD_PORT1_DAT3REMOVE 0x0001 /* ポート1 dat3 card detect検出=1 */
#define EXT_CD_PORT1_DAT3INSERT 0x0002 /* ポート1 dat3 card inserted挿入=1 */
#define EXT_CD_PORT1_DAT3DETECT 0x0004 /* ポート1 dat3 card removed抜け=1) */
/* EXT_CD_DAT3_MASKレジスタ */
#define EXT_CD_MASK_PORT1INSERT 0x0002 /* port1 card inserted(挿入) 割込み禁止 */
#define EXT_CD_MASK_PORT1REMOVE 0x0001 /* port1 card removed(抜け) 割込み禁止 */
#define EXT_CD_MASK_PORT1DAT3INSERT 0x0002 /* port1 (IO3検出) card inserted(挿入) 割込み禁止 */
#define EXT_CD_MASK_PORT1DAT3REMOVE 0x0001 /* port1 (IO3検出) card removed(抜け) 割込み禁止 */
/*-------------------------------------
--------------------------------------*/
#define SDCARD_DETECT_VISUAL_BIT 0x0400 /*** upper layer card detected visual bit ***/
/*-------------------------------------
-------------------------------------*/
#define SDCARD_WP_PERMANENT_BIT 0x0020 /*** permanent write protection ***/
#define SDCARD_WP_TEMPORARY_BIT 0x0010 /*** temporary write protection ***/
/*-------------------------------------
SD or MMCカードコマンド
-------------------------------------*/
#define GO_IDLE_STATE (0) /* resets all cards to idle state */
#define SEND_OP_COND (1) /* Asks all cards in idle state to send their operation conditions */
#define ALL_SEND_CID (2) /* send CID numbers */
#define SEND_RELATIVE_ADDR (3) /* ask the card to publish a new relative address(RCA) */
#define SET_BUS_WIDTH (6) /* ビット幅の選択 */
#define SELECT_CARD (7) /* Command toggles acard between thr Stand-by and Transfer states */
#define SEND_CSD (9) /* addressed card sends its card-specific data(CSD) */
#define STOP_TRANSMISSION (12) /* forces the card to stop transmission */
#define SD_SEND_STATUS (13) /* addressed card sends its status register */
#define SET_BLOCKLEN (16) /* sets the block length */
#define READ_MULTIPLE_BLOCK (18) /* マルチブロックリード */
#define WRITE_MULTIPLE_BLOCK (25) /* マルチブロックライト */
#define APP_CMD (55) /* CMD55 */
#define SD_STATUS (13) /* ACMD13 Send the SD_CARD status */
#define SEND_NUM_WR_SECTORS (22) /* ACMD22 書きこみ完了セクタ数取得 */
#define SD_APP_OP_COND (41) /* ACMD41 */
#define SEND_SCR (51) /* SD configuration register (SCR) */
/* MMCplus, eMMCの定義 */
#define EXT_CSD_ACCESS (6)
/* Extended Commandの定義 */
#define EXT_NORMAL (0)
#define EXT_SDIO (0x4000)
#define EXT_COM_R3 (0x0700)
#define EXT_CMD (0x00C0)
#define SEND_IF_COND (8) /* Physical Layer 2.0 で追加されたコマンド */
#define SEND_IF_COND_EXT (EXT_SDIO | EXT_COM_R3 | EXT_CMD | SEND_IF_COND)
/*-------------------------------------
IP
-------------------------------------*/
#define SD_OrFPGA(reg,value) ((reg) |= (value));
#define SD_AndFPGA(reg,value) ((reg) &= (value));
#define SD_SetFPGA(reg,value) ((reg) = (value));
#define SD_GetFPGA(dest,reg) ((dest) = (reg));
/***********************************************************************
***********************************************************************/
typedef union{
u32 dat;
struct {
u16 low;
u16 high;
} dt2word;
} LELONG;
/*-------------------------------------
-------------------------------------*/
#define RSP_R3_OCR31 0x8000 /* Use OCR Busy bit Check */
#define RSP_R3_OCR_VDD 0x0030 /* Use OCR VDD bit Check (3.2-3.3v,3.3-3.4v is OK)*/
/*--- SCR[0]に対する4bitバス幅対応フラグのマスク ---*/
//SCRのbit50に相当するが、SCRとSD_STATUSはMSBから送られてくることを考慮してある
#define SCR_DAT_BUS_WIDTH_4BIT 0x0400 /* SCR DAT Bus width supported 4bit */
/*--- 127bitCSD (CSD[0]CSD[7])関連 ---*/
#define CSD_VDD_R_CURR_MIN 0x0038 /* "VDD_R_CURR_MIN" (for CSD[3]) */
#define CSD_VDD_R_CURR_MAX 0x0007 /* "VDD_R_CURR_MAX" (for CSD[3]) */
#define CSD_VDD_W_CURR_MIN 0xE000 /* "VDD_W_CURR_MIN" (for CSD[2]) */
#define CSD_VDD_W_CURR_MAX 0x1C00 /* "VDD_W_CURR_MAX" (for CSD[2]) */
#define CSD_READ_BL_LEN 0x0F00 /* "READ_BL_LEN" (for CSD[4])*/
#define CSD_WRITE_BL_LEN_BIT_25_24 0x0003 /* "WRITE_BL_LEN" (for CSD[1])*/
#define CSD_WRITE_BL_LEN_BIT_23_22 0xC000 /* "WRITE_BL_LEN" (for CSD[0]*/
#define CSD_READ_BL_PARTIAL 0x0080 /* "READ_BL_PARTIAL" (for CSD[4]) */
#define CSD_TRANSFER_RATE 0x0700 /* "Transfer rate unit" of "TRAN_SPEED" (for CSD[5]) */
#define CSD_TRAN_SPEED_100K 0x0000 /* 100Kbit/s (for CSD Transfer rate) */
#define CSD_TRAN_SPEED_1M 0x0001 /* 1Mbit/s (for CSD Transfer rate) */
#define CSD_TRAN_SPEED_10M 0x0002 /* 10Mbit/s (for CSD Transfer rate) */
#define CSD_TRAN_SPEED_100M 0x0003 /* 100Mbit/s (for CSD Transfer rate) */
#define CSD_TRAN_SPEED_OTHER 0x0004 /* Reserve (for CSD Transfer rate) */
#define CSD_C_SIZE_MULT 0x0380 /* RSP2 の bit[49:47] */
#define CSD_C_SIZE_BIT_73_72 0x0003 /* RSP3 の bit[73:72](C_SIZE) */
#define CSD_C_SIZE_BIT_71_62 0xFFC0 /* RSP3 の bit[71:62](C_SIZE) */
//SDHC(CSD format version2)の場合
#define CSD_C_SIZE_BIT_69_56 0x3FFF /* SD_CSD[3] */
#define CSD_C_SIZE_BIT_55_48 0xFF00 /* SD_CSD[2] */
#define CSD_STRUCT_BIT_127_126 0x00C0 /* SD_CSD[7] */
//#define VDD_R_CURR_MIN 0x0000 /* CSD max read current@VDD min */
//#define VDD_R_CURR_MAX 0x0007 /* CSD max read current@VDD max */
//#define VDD_W_CURR_MIN 0x0000 /* CSD max write current@VDD min */
//#define VDD_W_CURR_MAX 0x0007 /* CSD max write current@VDD max */
/*--- R1レスポンスの card status(32bit)に対するマスク ---*/
#define RSP_R1_STATUS_ERR 0xF9FF0008 /* R1レスポンスのカードステータスのチェック */
#define SDCARD_STATUS_OUT_OF_RANGE 0x80000000 /* Card Status OUT_OF_RANGE のチェック */
#define RSP_R1_CURRENT_STATE 0x1E00 /* CARD current state */
/*-------------------------------------------------------*/
/* レスポンスのRSP0 & RSP_R1_CURRENT_STATEを1ビット右シフトした値に対するフラグ */
#define CURRENT_STATE_DATA 0x0500 /* CARD current state data */
#define CURRENT_STATE_RCV 0x0600 /* CARD current state rcv */
/* カードステータス */
#define SD_MEMORY_CARD 0x00FF /* SD_CARD_TYPE SD memory card */
/*-------------------------------------
-------------------------------------*/
void SD_Init(void); /* SD Cardインターフェース部をリセット&初期設定 */
void SD_EnableInfo(void); /* SD Card 挿抜 割り込みイネーブル・ディスエーブル */
u16 SD_Command(u16 ucCommand); /* SDカードコマンド送出 */
u16 SD_AppCommand(void); /* SDカード RCA = 1をセット後 CMD55 発行 */
u16 SD_AppOpCond(void); /* ACMD41 発行 busyでなくなるまで繰り返し */
u16 SD_SendOpCond(void); /* CMD1 発行 busyでなくなるまで繰り返し */
u16 SD_SendIfCond(void); /* CMD8 発行 (SDHCのみ反応してくる) */
u16 SD_SendRelativeAddr(void); /* CMD3 発行 正常終了時 RCA<-ResのRCA */
u16 SD_SelectCard(void); /* CMD7 発行 Command toggles acard between the Stand-by and Transfer states */
u16 SD_SetBlockLength(u32 ulBlockLength); /* ブロックレングス(1セクタの転送量)の設定 */
u16 SD_SendCID(void); /* card identification data の取得コマンド発行 */
u16 SD_SendCSD(void); /* card-specific data の取得コマンド発行 */
u16 SD_SendSCR(void); /* SD register の取得コマンド発行 */
u16 SD_SDStatus(void); /* SD STATUS の取得コマンド発行 */
u16 SD_SendStatus(void); /* SD status register の取得コマンド発行 */
u16 SD_MultiReadBlock(u32 ulOffset); /* マルチセクタリードコマンド発行 */
u16 SD_ClockDivSet(u16 usTranSpeed); /* カードの動作クロック設定 */
void SD_EnableClock( void); /* SDカードのクロック有効 */
void SD_DisableClock( void); /* SDカードのクロック無効省電力 */
u16 SD_SelectBitWidth(s16 b4bit); /* ビット幅の選択 */
u16 MMCP_WriteBusWidth(s16 b4bit);
u16 MMCP_BusTest( BOOL readflag);
s16 SD_FPGA_irq(void); /* カード転送要求時のFPGAの制御 */
void SD_StopTransmission(void); /* カード転送終了をFPGAに通知する。 */
void SD_TransEndFPGA(void); /* カード転送の終了処理(割り込みマスクを戻す) */
u16 SD_CheckStatus(BOOL bRead); /* Normal response command カードステータスのチェック */
u16 SD_SwapByte(u16 *data); /* 上位byte、下位byteを入れ替える関数 */
void SD_EnableSeccnt( u32 ulSDCARD_SectorCount); /* SD_SECCNTレジスタ有効化&値設定 */
void SD_DisableSeccnt( void); /* SD_SECCNTレジスタ無効化 */
void SD_SetErr(u16 Error); /* エラーステータスを設定する */
void SD_ClrErr(u16 Error); /* エラーステータスをクリアする */
BOOL SD_CheckFPGAReg(u16 reg,u16 value); /* IPレジスタにフラグが立っているか判定 */
void SD_TransReadyFPGA(void); /* 転送処理準備FPGA設定 */
u16 SD_TransCommand(u16 ucCommand); /* 命令発行処理 */
u16 SD_MultiWriteBlock(u32 ulOffset); /* マルチセクタライトコマンド発行 */
u16 SD_SendNumWRSectors(void); /* ACMD22 書きこみ完了セクタ数取得コマンド発行 */
#endif /* __SD_CARD_IP_H__ */

View File

@ -0,0 +1,109 @@
/*---------------------------------------------------------------------------*
Project: CTR - SD driver
File: sd_ip_reg.h
Copyright 2006 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
*---------------------------------------------------------------------------*/
#ifndef __SD_IP_REG_H__
#define __SD_IP_REG_H__
/*********************************************
SD IPレジスタ
(R/W) : readable and writable
(RO) : read only
*********************************************/
#if (CTR_DEF_ENVIRONMENT_DSEMU == 1)
#define SD_IP_BASE (0x08030000) // NTR用ブレッドボード設定
#else
#define SD_IP_BASE (0x400B0000) // IOP実機設定
#endif
#define SD_CMD (*(vu16 *)(SD_IP_BASE + 0x00)) /* CMD発行レジスタ(R/W) */
#define SD_PORTSEL (*(vu16 *)(SD_IP_BASE + 0x02)) /* ポート選択レジスタ(R/W) */
#define SD_ARG0 (*(vu16 *)(SD_IP_BASE + 0x04)) /* Argument[15:0] (R/W) */
#define SD_ARG1 (*(vu16 *)(SD_IP_BASE + 0x06)) /* Argument[31:16] (R/W) */
#define SD_STOP (*(vu16 *)(SD_IP_BASE + 0x08)) /* 転送終了後STOP、SD_SECCNT有効 (R/W) */
#define SD_SECCNT (*(vu16 *)(SD_IP_BASE + 0x0A)) /* 転送セクタ数制御 (R/W) */
#define SD_RSP0 (*(vu16 *)(SD_IP_BASE + 0x0C)) /* Response [23:8] (RO) */
#define SD_RSP1 (*(vu16 *)(SD_IP_BASE + 0x0E)) /* Response [39:24] (RO) */
#define SD_RSP2 (*(vu16 *)(SD_IP_BASE + 0x10)) /* Response [55:40] (RO) */
#define SD_RSP3 (*(vu16 *)(SD_IP_BASE + 0x12)) /* Response [71:56] (RO) */
#define SD_RSP4 (*(vu16 *)(SD_IP_BASE + 0x14)) /* Response [87:72] (RO) */
#define SD_RSP5 (*(vu16 *)(SD_IP_BASE + 0x16)) /* Response [103:88] (RO) */
#define SD_RSP6 (*(vu16 *)(SD_IP_BASE + 0x18)) /* Response [119:104] (RO) */
#define SD_RSP7 (*(vu16 *)(SD_IP_BASE + 0x1A)) /* Response [127:120] (RO) */
#define SD_INFO1 (*(vu16 *)(SD_IP_BASE + 0x1C)) /* SDメモリーカードの状態 (R/W) */
#define SD_INFO2 (*(vu16 *)(SD_IP_BASE + 0x1E)) /* バッファ制御とエラー情報 (R/W) */
#define SD_INFO1_MASK (*(vu16 *)(SD_IP_BASE + 0x20)) /* SD_INFO1割込みマスク (R/W) */
#define SD_INFO2_MASK (*(vu16 *)(SD_IP_BASE + 0x22)) /* SD_INFO2割込みマスク (R/W) */
#define SD_CLK_CTRL (*(vu16 *)(SD_IP_BASE + 0x24)) /* SDクロック設定 (R/W) */
#define SD_SIZE (*(vu16 *)(SD_IP_BASE + 0x26)) /* ビット幅と転送データ長の設定 (R/W) */
#define SD_OPTION (*(vu16 *)(SD_IP_BASE + 0x28)) /* タイムアウト、width、CD検出タイム (R/W) */
#define SD_ERR_STS1 (*(vu16 *)(SD_IP_BASE + 0x2C)) /* CMD, CRC, ENDエラー割込み原因 (RO) */
#define SD_ERR_STS2 (*(vu16 *)(SD_IP_BASE + 0x2E)) /* タイムアウトエラー割込み原因 (RO) */
#define SD_BUF0 (vu16 *)(SD_IP_BASE + 0x30) /* SDバッファ読込書込データポート (R/W) */
#define CC_EXT_MODE (*(vu16 *)(SD_IP_BASE + 0xD8)) /* DMAモード/PIOモード切り替え */
#define SOFT_RST (*(vu16 *)(SD_IP_BASE + 0xE0)) /* ソフトウェアリセット (R/W) */
#define VERSION (*(vu16 *)(SD_IP_BASE + 0xE2)) /* Version レジスタ (RO) */
#define EXT_WP (*(vu16 *)(SD_IP_BASE + 0xF6)) /* 拡張SD Card ライトプロテクト (RO) */
#define EXT_CD (*(vu16 *)(SD_IP_BASE + 0xF8)) /* 拡張SD Card 検出、挿入、抜け フラグ (R/W) */
#define EXT_CD_DAT3 (*(vu16 *)(SD_IP_BASE + 0xFA)) /* 拡張SD Card 検出、挿入、抜け フラグ (R/W) */
#define EXT_CD_MASK (*(vu16 *)(SD_IP_BASE + 0xFC)) /* 拡張SD Card 検出、挿入、抜け 割込みマスク (R/W) */
#define EXT_CD_DAT3_MASK (*(vu16 *)(SD_IP_BASE + 0xFE)) /* 拡張SD Card 検出、挿入、抜け 割込みマスク (R/W) */
/*********************************************
SD I/F
*********************************************/
#if (CTR_DEF_ENVIRONMENT_DSEMU == 1)
#define SD_IF_BASE (0x08030100) // NTR用ブレッドボード設定
#else
#define SD_IF_BASE (0x400B0100) // IOP実機設定
#endif
#define SDIF_CNT ((vu32 *)(SD_IF_BASE+0x00)) /* コントロール */
#define SDIF_FDS ((vu32 *)(SD_IF_BASE+0x04)) /* FIFOサイズ */
#define SDIF_FSC ((vu32 *)(SD_IF_BASE+0x08)) /* セクタカウント */
#define SDIF_FI ((vu32 *)(SD_IF_BASE+0x0c)) /* FIFOウィンドウ */
#define SDIF_CNT_L ((vu16 *)(SD_IF_BASE+0x00))
#define SDIF_CNT_H ((vu16 *)(SD_IF_BASE+0x02))
#define SDIF_FDS_L ((vu16 *)(SD_IF_BASE+0x04))
#define SDIF_FDS_H ((vu16 *)(SD_IF_BASE+0x06))
#define SDIF_FSC_L ((vu16 *)(SD_IF_BASE+0x08))
#define SDIF_FSC_H ((vu16 *)(SD_IF_BASE+0x0a))
#define SDIF_FI_L ((vu16 *)(SD_IF_BASE+0x0c))
#define SDIF_FI_H ((vu16 *)(SD_IF_BASE+0x0e))
/*********************************************
INTCレジスタ
*********************************************/
#if (CTR_DEF_ENVIRONMENT_DSEMU == 1)
#define CTR_INT_BASE (0x08000000)
#else
#define CTR_INT_BASE (0x40010000)
#endif
#define CTR_INT_SE (CTR_INT_BASE + 0x00) //割り込み要求選択レジスタ
#define CTR_INT_IE (CTR_INT_BASE + 0x04) //IE
#define CTR_INT_IF (CTR_INT_BASE + 0x08) //IF
#define CTR_IE_SD_MASK (1<<13) //SD割り込みフラグ
#endif /* __SD_IP_REG_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,85 @@
/*
** Copyright (c) 2000-2001 Matsushita Electric Industrial Co., Ltd.
** All Rights Reserved.
*/
/*
** $System IP1.1 without C2
** $Subsystem
** $Filename CARDDRV.H
** $Version 1.0
** $Date 01/02/16
** $Log 01/02/16 rev1.0
** ()
*/
#ifndef __SDMC_CONFIG_H__
#define __SDMC_CONFIG_H__
#include <twl.h>
#ifdef USE_OS
#include <sd_ip_reg.h> /* IP 対応レジスタ定義 */
#endif
/*********************************************
OS
*********************************************/
#define TARGET_OS_CTR (0)
#define TARGET_OS_NITRO (TARGET_OS_CTR ^ 1)
/*********************************************
SDドライバ
*********************************************/
#define SD_DEBUG_PRINT_ON 0 /* デバッグ表示 */
#define WP_ena 1 /* ライトプロテクトのチェック有効 */
#define TIMEOUT 1 /* FPGA Timeout none = FALSE */
#define SCR 1 /* Send SCR Command = TRUE */
#define RESID 1 /* Write Error Resid enable = TRUE */
#define ATC_ON 0 /* ATC転送 使用/未使用 */
#define SecEnable 1 /* SD_SECCNTレジスタ Enable */
#define SecDisenable 0 /* SD_SECCNTレジスタ Disable */
//#define STANDBYMODE 0x04 /*** 5772 standby control bit ***/
/*********************************************
(ms単位)
*********************************************/
#define SDCARD_RW_TIMEOUT (4000)
#define SDCARD_STDBY_TIMEOUT (50)
#define SDCARD_CLOCK_WAIT (500)
#define SDCARD_SDCLK_WAIT (10)
#define SDCARD_INITIAL_TIMEOUT (800)
#define SDCARD_RESET_TIMEOUT (1500)
#define SDCARD_ERASE_TIMEOUT (1)
#define SDCARD_ERRPROC_TIMEOUT (2000)
/*********************************************
(Multiple Block R/W )
*********************************************/
#define SDCARD_RETRY_COUNT (3)
/*********************************************
*********************************************/
#define SECTOR_SIZE (512) /* 1セクタのバイト数 */
#define SECTOR_MAX (255) /* SYSFPGA アクセス最大セクタ数 */
/*--- 上位レイヤに返すステータス値(SDCARD_Getstatus参照)用 ---*/
#define SDCARD_FLAG_CLR (0x3FFF) /* カード判定部分クリア用 */
#define SDCARD_FLAG_SD (0x8000) /* カード判定部分SDカード */
#define SDCARD_FLAG_MMC (0x4000) /* カード判定部分MMCカード */
#define SDCARD_PORT1_CLR (0x0007) /* カードポート1判定部分クリア用 */
#endif /*__SDMC_CONFIG_H__*/

View File

@ -0,0 +1,34 @@
#! make -f
#----------------------------------------------------------------------------
# Project: TwlSDK - libraries - spi
# File: Makefile
#
# Copyright 2007 Nintendo. All rights reserved.
#
# These coded instructions, statements, and computer programs contain
# proprietary information of Nintendo of America Inc. and/or Nintendo
# Company Ltd., and are protected by Federal copyright law. They may
# not be disclosed to third parties or copied or duplicated in any form,
# in whole or in part, without the prior written consent of Nintendo.
#
# $Log: $
# $NoKeywords: $
#----------------------------------------------------------------------------
include $(TWLSDK_ROOT)/build/buildtools/commondefs
#----------------------------------------------------------------------------
# SUBDIRS = ARM9
ifdef TWL_WITH_ARM7
SUBDIRS += ARM7
endif
#----------------------------------------------------------------------------
include $(TWLSDK_ROOT)/build/buildtools/modulerules
#===== End of Makefile =====

View File

@ -0,0 +1,74 @@
#! make -f
#----------------------------------------------------------------------------
# Project: TwlSDK - libraries - mi/ARM7
# File: Makefile
#
# Copyright 2007 Nintendo. All rights reserved.
#
# These coded instructions, statements, and computer programs contain
# proprietary information of Nintendo of America Inc. and/or Nintendo
# Company Ltd., and are protected by Federal copyright law. They may
# not be disclosed to third parties or copied or duplicated in any form,
# in whole or in part, without the prior written consent of Nintendo.
#
# $Log: $
# $NoKeywords: $
#----------------------------------------------------------------------------
SUBDIRS =
#----------------------------------------------------------------------------
# build ARM & THUMB libraries
TWL_CODEGEN_ALL ?= True
# Codegen for sub processer
TWL_PROC = ARM7
SRCDIR = ../common/src src
INCDIR = ../common
INCDIR += . \
$(TWLSDK_ROOT)/include/twl/ARM7 \
$(TWLSDK_ROOT)/include/twl/fatfs/ARM7 \
SRCS = apistat.c prfsapi.c rtlowl.c apickdsk.c apiwrite.c \
prfscore.c rtnvfat.c apicnfig.c \
prfsnvio.c rttermin.c apideltr.c appdemo.c prfstest.c \
rtutbyte.c apienum.c csascii.c rtutil.c \
apifilio.c csjis.c rtdevio.c rtvfat.c apifilmv.c csjistab.c \
rtdrobj.c apifrmat.c csstrtab.c rtfat16.c apigetwd.c \
rtfat32.c apigfrst.c csunicod.c rtfatxx.c apiinfo.c \
portio.c apiinit.c portkern.c \
apimkdir.c apirealt.c \
prapipro.c apiregrs.c prblock.c apisetwd.c \
rtkernfn.c \
drdefault.c drfile.c attach.c \
TARGET_LIB = libfatfs_sp$(TWL_LIBSUFFIX).a
#----------------------------------------------------------------------------
# DEBUG版ビルドの場合、RELEASE版でビルドして
# DEBUG版のライブラリを装います。
ifdef NITRO_DEBUG
NITRO_BUILD_TYPE = RELEASE
endif
include $(TWLSDK_ROOT)/build/buildtools/commondefs
INSTALL_TARGETS = $(TARGETS)
INSTALL_DIR = $(TWL_INSTALL_LIBDIR)
#----------------------------------------------------------------------------
do-build: $(TARGETS)
include $(TWLSDK_ROOT)/build/buildtools/modulerules
#===== End of Makefile =====

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,450 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS inc, 1996
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/******************************************************************************
PC_ERTFS_CONFIG() - Set up the ERTFS configuration block and allocate
or assign memory blocks for ERTFS usage.
The user must modify this code if he wishes to reconfigure ERTFS.
He must also initialize the RTFS configuration structure with the
addresses of memory blocks to be used by ERTFS.
Tutorial:
pc_ertfs_config(void) initializes the ertfs configuration block and
provides ERTFS with the addresses of memory that it needs. It is
called from the ertfs initialization routine pc_ertfs_init().
This routine is designed to be modified by the user if he wishes to
change the default configuration. To simplify the user's task we
define some configuration constants in this file that may be modified
to change the configuration. These constants are only used locally to
this file. If another method of configuring ERTFS is more appropriate
for your environment then devize an alternate method to initialize the
configuration block.
The default configuration is:
ALLOC_FROM_HEAP 1 Use malloc() to allocate, set to 0 to use declared
memory arrays.
NDRIVES 10 L: Max number of drives from 0 to 25 A: - Z:
Note: A FAT buffer pool must be allocated for each drives. If NDRIVES
is changed you must add code to allocate or assign more FAT buffer pools.
The default configuration allocates or assigns 10 fat buffer pools,
If you increase NDRIVES then add code that duplicates the cuurent code
that initialises prtfs_cfg->fat_buffers[9], to dircves 10, 11. 12 ...
If you decrease NDRIVES then removes the cuurent code that
initialises prtfs_cfg->fat_buffers[9], 8, 7, 6 etc
If you are not using ALLOC_FROM_HEAP you shaoul also add or remove the
memory array declarations.
NUM_USERS 1 Maximum number of USER contexts set to 1 for POLLED
mode, otherwise set to the number of tasks that
will simultaneously use ERTFS
NBLKBUFFS 10 Number of blocks in the buffer pool. Uses 532
bytes per block. Impacts performance during
directory traversals. Must be at least 4
BLKHASHSIZE 16 Size of the block buffer hash table.
This value must be a power of two.
NUSERFILES 10 The maximum number of open Files at a time
LARGE_FAT_SIZE 32 The number of 520 byte blocks committed for
buffering fat blocks on drive C:
LARGE_FAT_HASHSIZE 32 The number of 12 byte hash table entries
committed for use on drive C:
This value must be a power of two.
SMALL_FAT_SIZE 2 The number of 520 byte blocks committed for
buffering fat blocks on drives other than C:
SMALL_FAT_HASHSIZE 2 The number of 12 byte hash table entries
committed for use on drives other than C:
This value must be a power of two.
Note: Each drive may have a different fat buffer and cache sizes. For
convenience here we only use two possible different sizes. You may tune
each drive individually by setting the configuration value:
prtfs_cfg->cfg_FAT_BUFFER_SIZE[DRIVENUMBER]; and
prtfs_cfg->cfg_FAT_CACHE_SIZE[DRIVENUMBER];
prtfs_cfg->fat_buffers[DRIVENUMBER];
prtfs_cfg->fat_hash_table[DRIVENUMBER];
*/
#include <rtfs.h>
#define ALLOC_FROM_HEAP 0 /* Set this to 1 to use malloc() to allocate
ERTFS memory at startup, set to 0 to use
declare memory arrays and provide ertfs
with the addresses of those arrays */
#define NDRIVES 8 /* Number of drives */
#define NUM_USERS 1 /* Must be one for POLLOS */
#define NBLKBUFFS 20 /* Number of blocks in the buffer pool. Uses 532
bytes per block. Impacts performance during
directory traversals must be at least 4 */
#define BLKHASHSIZE 16 /* This value must be a power of two.
Size of the block buffer hash table. */
#define LARGE_FAT_SIZE 16 /* Number of 520 byte blocks committed for
buffering fat blocks on drive C: */ //ctr modified 32->16
#define LARGE_FAT_HASHSIZE 16 /* This value must be a power of two.
Number of 12 byte hash table entries //ctr modified 32->16
committed for use on drive C: */
#define SMALL_FAT_SIZE 2 /* Number of 520 byte blocks committed for
buffering fat blocks all other drives */
#define SMALL_FAT_HASHSIZE 2 /* This value must be a power of two.
Number of 12 byte hash table entries
committed for use on all other drivees */
#define NUSERFILES 10 /* Maximum Number of open Files at a time */
/* Directory Object Needs. Conservative guess is One CWD per user per drive +
One per file + one per User for directory traversal */
/* This is calculated... do not change */
#define NFINODES (32 + NUM_USERS*NDRIVES + NUM_USERS + NUSERFILES)
#define NDROBJS (32 + NUM_USERS*NDRIVES + NUM_USERS + NUSERFILES)
RTFS_CFG *prtfs_cfg; /* The user must initialize this value to point
to a valid configuration block */
static RTFS_CFG rtfs_cfg_core; /* The user must initialize this value to point */
#if (ALLOC_FROM_HEAP)
/* Using malloc to allocate memory at startup. If malloc is not avaiable
but some other heap manager is, then change the calls to malloc() to
call your heap manager instead */
#include <malloc.h>
#else
/* Not using malloc to allocate memory so declare arrays that we can send
assign to the configuration block at startup. */
DDRIVE __mem_drives_structures[NDRIVES];
BLKBUFF __mem_block_pool[NBLKBUFFS];
BLKBUFF * __mem_block_hash_table[BLKHASHSIZE];
PC_FILE __mem_file_pool[NUSERFILES];
DROBJ __mem_drobj_pool[NDROBJS];
FINODE __mem_finode_pool[NFINODES];
RTFS_SYSTEM_USER __rtfs_user_table[NUM_USERS];
FATBUFF KS_FAR __fat_buffer_0[SMALL_FAT_SIZE];
FATBUFF KS_FAR __fat_buffer_1[SMALL_FAT_SIZE];
FATBUFF KS_FAR __fat_buffer_2[LARGE_FAT_SIZE];
FATBUFF KS_FAR __fat_buffer_3[SMALL_FAT_SIZE];
FATBUFF KS_FAR __fat_buffer_4[SMALL_FAT_SIZE];
FATBUFF KS_FAR __fat_buffer_5[SMALL_FAT_SIZE];
FATBUFF KS_FAR __fat_buffer_6[SMALL_FAT_SIZE];
FATBUFF KS_FAR __fat_buffer_7[SMALL_FAT_SIZE];
FATBUFF KS_FAR __fat_buffer_8[SMALL_FAT_SIZE];
FATBUFF KS_FAR __fat_buffer_9[SMALL_FAT_SIZE];
FATBUFF * KS_FAR __fat_hash_table_0[SMALL_FAT_HASHSIZE];
FATBUFF * KS_FAR __fat_hash_table_1[SMALL_FAT_HASHSIZE];
FATBUFF * KS_FAR __fat_hash_table_2[LARGE_FAT_HASHSIZE];
FATBUFF * KS_FAR __fat_hash_table_3[SMALL_FAT_HASHSIZE];
FATBUFF * KS_FAR __fat_hash_table_4[SMALL_FAT_HASHSIZE];
FATBUFF * KS_FAR __fat_hash_table_5[SMALL_FAT_HASHSIZE];
FATBUFF * KS_FAR __fat_hash_table_6[SMALL_FAT_HASHSIZE];
FATBUFF * KS_FAR __fat_hash_table_7[SMALL_FAT_HASHSIZE];
FATBUFF * KS_FAR __fat_hash_table_8[SMALL_FAT_HASHSIZE];
FATBUFF * KS_FAR __fat_hash_table_9[SMALL_FAT_HASHSIZE];
byte * KS_FAR __fat_primary_cache_0[SMALL_FAT_HASHSIZE];
byte * KS_FAR __fat_primary_cache_1[SMALL_FAT_HASHSIZE];
byte * KS_FAR __fat_primary_cache_2[LARGE_FAT_HASHSIZE];
byte * KS_FAR __fat_primary_cache_3[SMALL_FAT_HASHSIZE];
byte * KS_FAR __fat_primary_cache_4[SMALL_FAT_HASHSIZE];
byte * KS_FAR __fat_primary_cache_5[SMALL_FAT_HASHSIZE];
byte * KS_FAR __fat_primary_cache_6[SMALL_FAT_HASHSIZE];
byte * KS_FAR __fat_primary_cache_7[SMALL_FAT_HASHSIZE];
byte * KS_FAR __fat_primary_cache_8[SMALL_FAT_HASHSIZE];
byte * KS_FAR __fat_primary_cache_9[SMALL_FAT_HASHSIZE];
dword KS_FAR __fat_primary_index_0[SMALL_FAT_HASHSIZE];
dword KS_FAR __fat_primary_index_1[SMALL_FAT_HASHSIZE];
dword KS_FAR __fat_primary_index_2[LARGE_FAT_HASHSIZE];
dword KS_FAR __fat_primary_index_3[SMALL_FAT_HASHSIZE];
dword KS_FAR __fat_primary_index_4[SMALL_FAT_HASHSIZE];
dword KS_FAR __fat_primary_index_5[SMALL_FAT_HASHSIZE];
dword KS_FAR __fat_primary_index_6[SMALL_FAT_HASHSIZE];
dword KS_FAR __fat_primary_index_7[SMALL_FAT_HASHSIZE];
dword KS_FAR __fat_primary_index_8[SMALL_FAT_HASHSIZE];
dword KS_FAR __fat_primary_index_9[SMALL_FAT_HASHSIZE];
#endif /* (ALLOC_FROM_HEAP) */
BOOLEAN pc_ertfs_config(void) /* __apifn__*/
{
/* Important: prtfs_cfg must point to a configuration block */
prtfs_cfg = &rtfs_cfg_core;
/* Important: the configuration block must be zeroed */
rtfs_memset(prtfs_cfg, 0, sizeof(rtfs_cfg_core));
/* Set Configuration values */
prtfs_cfg->cfg_NDRIVES = NDRIVES;
prtfs_cfg->cfg_NBLKBUFFS = NBLKBUFFS;
prtfs_cfg->cfg_BLK_HASHTBLE_SIZE = BLKHASHSIZE;
prtfs_cfg->cfg_NUSERFILES = NUSERFILES;
prtfs_cfg->cfg_NDROBJS = NDROBJS;
prtfs_cfg->cfg_NFINODES = NFINODES;
prtfs_cfg->cfg_NUM_USERS = NUM_USERS;
/* Set FAT size configuration values for each drive */
prtfs_cfg->cfg_FAT_BUFFER_SIZE[0] = SMALL_FAT_SIZE;
prtfs_cfg->cfg_FAT_BUFFER_SIZE[1] = SMALL_FAT_SIZE;
prtfs_cfg->cfg_FAT_BUFFER_SIZE[2] = LARGE_FAT_SIZE;
prtfs_cfg->cfg_FAT_BUFFER_SIZE[3] = SMALL_FAT_SIZE;
prtfs_cfg->cfg_FAT_BUFFER_SIZE[4] = SMALL_FAT_SIZE;
prtfs_cfg->cfg_FAT_BUFFER_SIZE[5] = SMALL_FAT_SIZE;
prtfs_cfg->cfg_FAT_BUFFER_SIZE[6] = SMALL_FAT_SIZE;
prtfs_cfg->cfg_FAT_BUFFER_SIZE[7] = SMALL_FAT_SIZE;
prtfs_cfg->cfg_FAT_BUFFER_SIZE[8] = SMALL_FAT_SIZE;
prtfs_cfg->cfg_FAT_BUFFER_SIZE[9] = SMALL_FAT_SIZE;
prtfs_cfg->cfg_FAT_HASHTBL_SIZE[0] = SMALL_FAT_HASHSIZE;
prtfs_cfg->cfg_FAT_HASHTBL_SIZE[1] = SMALL_FAT_HASHSIZE;
prtfs_cfg->cfg_FAT_HASHTBL_SIZE[2] = LARGE_FAT_HASHSIZE;
prtfs_cfg->cfg_FAT_HASHTBL_SIZE[3] = SMALL_FAT_HASHSIZE;
prtfs_cfg->cfg_FAT_HASHTBL_SIZE[4] = SMALL_FAT_HASHSIZE;
prtfs_cfg->cfg_FAT_HASHTBL_SIZE[5] = SMALL_FAT_HASHSIZE;
prtfs_cfg->cfg_FAT_HASHTBL_SIZE[6] = SMALL_FAT_HASHSIZE;
prtfs_cfg->cfg_FAT_HASHTBL_SIZE[7] = SMALL_FAT_HASHSIZE;
prtfs_cfg->cfg_FAT_HASHTBL_SIZE[8] = SMALL_FAT_HASHSIZE;
prtfs_cfg->cfg_FAT_HASHTBL_SIZE[9] = SMALL_FAT_HASHSIZE;
/* Core that must be provided by the user */
#if (!ALLOC_FROM_HEAP)
/* Not using malloc() so assign memory arrays to the configuration block */
prtfs_cfg->mem_drives_structures = (DDRIVE *) &__mem_drives_structures[0];
prtfs_cfg->mem_block_pool = (BLKBUFF *) &__mem_block_pool[0];
prtfs_cfg->mem_block_hash_table = (BLKBUFF **) &__mem_block_hash_table[0];
prtfs_cfg->mem_file_pool = (PC_FILE *) &__mem_file_pool[0];
prtfs_cfg->mem_drobj_pool = (DROBJ *) &__mem_drobj_pool[0];
prtfs_cfg->mem_finode_pool = (FINODE *) &__mem_finode_pool[0];
prtfs_cfg->rtfs_user_table = (RTFS_SYSTEM_USER *) &__rtfs_user_table[0];
prtfs_cfg->fat_buffers[0] = (FATBUFF *) &__fat_buffer_0[0];
prtfs_cfg->fat_buffers[1] = (FATBUFF *) &__fat_buffer_1[0];
prtfs_cfg->fat_buffers[2] = (FATBUFF *) &__fat_buffer_2[0];
prtfs_cfg->fat_buffers[3] = (FATBUFF *) &__fat_buffer_3[0];
prtfs_cfg->fat_buffers[4] = (FATBUFF *) &__fat_buffer_4[0];
prtfs_cfg->fat_buffers[5] = (FATBUFF *) &__fat_buffer_5[0];
prtfs_cfg->fat_buffers[6] = (FATBUFF *) &__fat_buffer_6[0];
prtfs_cfg->fat_buffers[7] = (FATBUFF *) &__fat_buffer_7[0];
prtfs_cfg->fat_buffers[8] = (FATBUFF *) &__fat_buffer_8[0];
prtfs_cfg->fat_buffers[9] = (FATBUFF *) &__fat_buffer_9[0];
prtfs_cfg->fat_hash_table[0] = (FATBUFF **) &__fat_hash_table_0[0];
prtfs_cfg->fat_hash_table[1] = (FATBUFF **) &__fat_hash_table_1[0];
prtfs_cfg->fat_hash_table[2] = (FATBUFF **) &__fat_hash_table_2[0];
prtfs_cfg->fat_hash_table[3] = (FATBUFF **) &__fat_hash_table_3[0];
prtfs_cfg->fat_hash_table[4] = (FATBUFF **) &__fat_hash_table_4[0];
prtfs_cfg->fat_hash_table[5] = (FATBUFF **) &__fat_hash_table_5[0];
prtfs_cfg->fat_hash_table[6] = (FATBUFF **) &__fat_hash_table_6[0];
prtfs_cfg->fat_hash_table[7] = (FATBUFF **) &__fat_hash_table_7[0];
prtfs_cfg->fat_hash_table[8] = (FATBUFF **) &__fat_hash_table_8[0];
prtfs_cfg->fat_hash_table[9] = (FATBUFF **) &__fat_hash_table_9[0];
prtfs_cfg->fat_primary_cache[0] = (byte **) &__fat_primary_cache_0[0];
prtfs_cfg->fat_primary_cache[1] = (byte **) &__fat_primary_cache_1[0];
prtfs_cfg->fat_primary_cache[2] = (byte **) &__fat_primary_cache_2[0];
prtfs_cfg->fat_primary_cache[3] = (byte **) &__fat_primary_cache_3[0];
prtfs_cfg->fat_primary_cache[4] = (byte **) &__fat_primary_cache_4[0];
prtfs_cfg->fat_primary_cache[5] = (byte **) &__fat_primary_cache_5[0];
prtfs_cfg->fat_primary_cache[6] = (byte **) &__fat_primary_cache_6[0];
prtfs_cfg->fat_primary_cache[7] = (byte **) &__fat_primary_cache_7[0];
prtfs_cfg->fat_primary_cache[8] = (byte **) &__fat_primary_cache_8[0];
prtfs_cfg->fat_primary_cache[9] = (byte **) &__fat_primary_cache_9[0];
prtfs_cfg->fat_primary_index[0] = (dword *) &__fat_primary_index_0[0];
prtfs_cfg->fat_primary_index[1] = (dword *) &__fat_primary_index_1[0];
prtfs_cfg->fat_primary_index[2] = (dword *) &__fat_primary_index_2[0];
prtfs_cfg->fat_primary_index[3] = (dword *) &__fat_primary_index_3[0];
prtfs_cfg->fat_primary_index[4] = (dword *) &__fat_primary_index_4[0];
prtfs_cfg->fat_primary_index[5] = (dword *) &__fat_primary_index_5[0];
prtfs_cfg->fat_primary_index[6] = (dword *) &__fat_primary_index_6[0];
prtfs_cfg->fat_primary_index[7] = (dword *) &__fat_primary_index_7[0];
prtfs_cfg->fat_primary_index[8] = (dword *) &__fat_primary_index_8[0];
prtfs_cfg->fat_primary_index[9] = (dword *) &__fat_primary_index_9[0];
return(TRUE);
#else
/* Use Malloc do allocated ERTFS data */
prtfs_cfg->mem_drives_structures = (DDRIVE *) malloc(prtfs_cfg->cfg_NDRIVES*sizeof(DDRIVE));
prtfs_cfg->mem_block_pool = (BLKBUFF*) malloc(prtfs_cfg->cfg_NBLKBUFFS*sizeof(BLKBUFF));
prtfs_cfg->mem_block_hash_table = (BLKBUFF **) malloc(prtfs_cfg->cfg_BLK_HASHTBLE_SIZE*sizeof(BLKBUFF *));
prtfs_cfg->mem_file_pool = (PC_FILE *) malloc(prtfs_cfg->cfg_NUSERFILES* sizeof(PC_FILE));
prtfs_cfg->mem_drobj_pool = (DROBJ *) malloc(prtfs_cfg->cfg_NDROBJS* sizeof(DROBJ));
prtfs_cfg->mem_finode_pool = (FINODE *) malloc(prtfs_cfg->cfg_NFINODES* sizeof(FINODE));
prtfs_cfg->rtfs_user_table = (RTFS_SYSTEM_USER *) malloc(prtfs_cfg->cfg_NUM_USERS * sizeof(RTFS_SYSTEM_USER));
prtfs_cfg->fat_buffers[0] = (FATBUFF *) malloc(prtfs_cfg->cfg_FAT_BUFFER_SIZE[0]*sizeof(FATBUFF));
prtfs_cfg->fat_buffers[1] = (FATBUFF *) malloc(prtfs_cfg->cfg_FAT_BUFFER_SIZE[1]*sizeof(FATBUFF));
prtfs_cfg->fat_buffers[2] = (FATBUFF *) malloc(prtfs_cfg->cfg_FAT_BUFFER_SIZE[2]*sizeof(FATBUFF));
prtfs_cfg->fat_buffers[3] = (FATBUFF *) malloc(prtfs_cfg->cfg_FAT_BUFFER_SIZE[3]*sizeof(FATBUFF));
prtfs_cfg->fat_buffers[4] = (FATBUFF *) malloc(prtfs_cfg->cfg_FAT_BUFFER_SIZE[4]*sizeof(FATBUFF));
prtfs_cfg->fat_buffers[5] = (FATBUFF *) malloc(prtfs_cfg->cfg_FAT_BUFFER_SIZE[5]*sizeof(FATBUFF));
prtfs_cfg->fat_buffers[6] = (FATBUFF *) malloc(prtfs_cfg->cfg_FAT_BUFFER_SIZE[6]*sizeof(FATBUFF));
prtfs_cfg->fat_buffers[7] = (FATBUFF *) malloc(prtfs_cfg->cfg_FAT_BUFFER_SIZE[7]*sizeof(FATBUFF));
prtfs_cfg->fat_buffers[8] = (FATBUFF *) malloc(prtfs_cfg->cfg_FAT_BUFFER_SIZE[8]*sizeof(FATBUFF));
prtfs_cfg->fat_buffers[9] = (FATBUFF *) malloc(prtfs_cfg->cfg_FAT_BUFFER_SIZE[9]*sizeof(FATBUFF));
prtfs_cfg->fat_hash_table[0] = (FATBUFF **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[0]*sizeof(FATBUFF *));
prtfs_cfg->fat_hash_table[1] = (FATBUFF **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[1]*sizeof(FATBUFF *));
prtfs_cfg->fat_hash_table[2] = (FATBUFF **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[2]*sizeof(FATBUFF *));
prtfs_cfg->fat_hash_table[3] = (FATBUFF **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[3]*sizeof(FATBUFF *));
prtfs_cfg->fat_hash_table[4] = (FATBUFF **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[4]*sizeof(FATBUFF *));
prtfs_cfg->fat_hash_table[5] = (FATBUFF **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[5]*sizeof(FATBUFF *));
prtfs_cfg->fat_hash_table[6] = (FATBUFF **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[6]*sizeof(FATBUFF *));
prtfs_cfg->fat_hash_table[7] = (FATBUFF **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[7]*sizeof(FATBUFF *));
prtfs_cfg->fat_hash_table[8] = (FATBUFF **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[8]*sizeof(FATBUFF *));
prtfs_cfg->fat_hash_table[9] = (FATBUFF **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[9]*sizeof(FATBUFF *));
prtfs_cfg->fat_primary_cache[0] = (byte **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[0]*sizeof(byte *));
prtfs_cfg->fat_primary_cache[1] = (byte **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[1]*sizeof(byte *));
prtfs_cfg->fat_primary_cache[2] = (byte **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[2]*sizeof(byte *));
prtfs_cfg->fat_primary_cache[3] = (byte **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[3]*sizeof(byte *));
prtfs_cfg->fat_primary_cache[4] = (byte **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[4]*sizeof(byte *));
prtfs_cfg->fat_primary_cache[5] = (byte **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[5]*sizeof(byte *));
prtfs_cfg->fat_primary_cache[6] = (byte **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[6]*sizeof(byte *));
prtfs_cfg->fat_primary_cache[7] = (byte **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[7]*sizeof(byte *));
prtfs_cfg->fat_primary_cache[8] = (byte **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[8]*sizeof(byte *));
prtfs_cfg->fat_primary_cache[9] = (byte **) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[9]*sizeof(byte *));
prtfs_cfg->fat_primary_index[0] = (dword *) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[0]*sizeof(dword));
prtfs_cfg->fat_primary_index[1] = (dword *) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[1]*sizeof(dword));
prtfs_cfg->fat_primary_index[2] = (dword *) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[2]*sizeof(dword));
prtfs_cfg->fat_primary_index[3] = (dword *) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[3]*sizeof(dword));
prtfs_cfg->fat_primary_index[4] = (dword *) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[4]*sizeof(dword));
prtfs_cfg->fat_primary_index[5] = (dword *) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[5]*sizeof(dword));
prtfs_cfg->fat_primary_index[6] = (dword *) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[6]*sizeof(dword));
prtfs_cfg->fat_primary_index[7] = (dword *) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[7]*sizeof(dword));
prtfs_cfg->fat_primary_index[8] = (dword *) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[8]*sizeof(dword));
prtfs_cfg->fat_primary_index[9] = (dword *) malloc(prtfs_cfg->cfg_FAT_HASHTBL_SIZE[9]*sizeof(dword));
/* Do some sanity checks */
if (!prtfs_cfg->mem_drives_structures ||
!prtfs_cfg->mem_block_pool ||
!prtfs_cfg->mem_block_hash_table ||
!prtfs_cfg->mem_file_pool ||
!prtfs_cfg->mem_drobj_pool ||
!prtfs_cfg->mem_finode_pool ||
!prtfs_cfg->rtfs_user_table)
goto malloc_failed;
if (!prtfs_cfg->fat_buffers[0] ||
!prtfs_cfg->fat_buffers[1] ||
!prtfs_cfg->fat_buffers[2] ||
!prtfs_cfg->fat_buffers[3] ||
!prtfs_cfg->fat_buffers[4] ||
!prtfs_cfg->fat_buffers[5] ||
!prtfs_cfg->fat_buffers[6] ||
!prtfs_cfg->fat_buffers[7] ||
!prtfs_cfg->fat_buffers[8] ||
!prtfs_cfg->fat_buffers[9])
goto malloc_failed;
if (!prtfs_cfg->fat_hash_table[0] ||
!prtfs_cfg->fat_hash_table[1] ||
!prtfs_cfg->fat_hash_table[2] ||
!prtfs_cfg->fat_hash_table[3] ||
!prtfs_cfg->fat_hash_table[4] ||
!prtfs_cfg->fat_hash_table[5] ||
!prtfs_cfg->fat_hash_table[6] ||
!prtfs_cfg->fat_hash_table[7] ||
!prtfs_cfg->fat_hash_table[8] ||
!prtfs_cfg->fat_hash_table[9])
goto malloc_failed;
if (!prtfs_cfg->fat_primary_cache[0] ||
!prtfs_cfg->fat_primary_cache[1] ||
!prtfs_cfg->fat_primary_cache[2] ||
!prtfs_cfg->fat_primary_cache[3] ||
!prtfs_cfg->fat_primary_cache[4] ||
!prtfs_cfg->fat_primary_cache[5] ||
!prtfs_cfg->fat_primary_cache[6] ||
!prtfs_cfg->fat_primary_cache[7] ||
!prtfs_cfg->fat_primary_cache[8] ||
!prtfs_cfg->fat_primary_cache[9])
goto malloc_failed;
if (!prtfs_cfg->fat_primary_index[0] ||
!prtfs_cfg->fat_primary_index[1] ||
!prtfs_cfg->fat_primary_index[2] ||
!prtfs_cfg->fat_primary_index[3] ||
!prtfs_cfg->fat_primary_index[4] ||
!prtfs_cfg->fat_primary_index[5] ||
!prtfs_cfg->fat_primary_index[6] ||
!prtfs_cfg->fat_primary_index[7] ||
!prtfs_cfg->fat_primary_index[8] ||
!prtfs_cfg->fat_primary_index[9])
goto malloc_failed;
return(TRUE);
malloc_failed:
if (prtfs_cfg->mem_drives_structures) free(prtfs_cfg->mem_drives_structures );
if (prtfs_cfg->mem_block_pool) free(prtfs_cfg->mem_block_pool);
if (prtfs_cfg->mem_block_hash_table) free(prtfs_cfg->mem_block_hash_table);
if (prtfs_cfg->mem_file_pool) free(prtfs_cfg->mem_file_pool);
if (prtfs_cfg->mem_drobj_pool) free(prtfs_cfg->mem_drobj_pool);
if (prtfs_cfg->mem_finode_pool) free(prtfs_cfg->mem_finode_pool);
if (prtfs_cfg->rtfs_user_table) free(prtfs_cfg->rtfs_user_table);
if (prtfs_cfg->fat_buffers[0]) free(prtfs_cfg->fat_buffers[0]);
if (prtfs_cfg->fat_buffers[1]) free(prtfs_cfg->fat_buffers[1]);
if (prtfs_cfg->fat_buffers[2]) free(prtfs_cfg->fat_buffers[2]);
if (prtfs_cfg->fat_buffers[3]) free(prtfs_cfg->fat_buffers[3]);
if (prtfs_cfg->fat_buffers[4]) free(prtfs_cfg->fat_buffers[4]);
if (prtfs_cfg->fat_buffers[5]) free(prtfs_cfg->fat_buffers[5]);
if (prtfs_cfg->fat_buffers[6]) free(prtfs_cfg->fat_buffers[6]);
if (prtfs_cfg->fat_buffers[7]) free(prtfs_cfg->fat_buffers[7]);
if (prtfs_cfg->fat_buffers[8]) free(prtfs_cfg->fat_buffers[8]);
if (prtfs_cfg->fat_buffers[9]) free(prtfs_cfg->fat_buffers[9]);
if (prtfs_cfg->fat_hash_table[0]) free(prtfs_cfg->fat_hash_table[0]);
if (prtfs_cfg->fat_hash_table[1]) free(prtfs_cfg->fat_hash_table[1]);
if (prtfs_cfg->fat_hash_table[2]) free(prtfs_cfg->fat_hash_table[2]);
if (prtfs_cfg->fat_hash_table[3]) free(prtfs_cfg->fat_hash_table[3]);
if (prtfs_cfg->fat_hash_table[4]) free(prtfs_cfg->fat_hash_table[4]);
if (prtfs_cfg->fat_hash_table[5]) free(prtfs_cfg->fat_hash_table[5]);
if (prtfs_cfg->fat_hash_table[6]) free(prtfs_cfg->fat_hash_table[6]);
if (prtfs_cfg->fat_hash_table[7]) free(prtfs_cfg->fat_hash_table[7]);
if (prtfs_cfg->fat_hash_table[8]) free(prtfs_cfg->fat_hash_table[8]);
if (prtfs_cfg->fat_hash_table[9]) free(prtfs_cfg->fat_hash_table[9]);
if (prtfs_cfg->fat_primary_cache[0]) free(prtfs_cfg->fat_primary_cache[0]);
if (prtfs_cfg->fat_primary_cache[1]) free(prtfs_cfg->fat_primary_cache[1]);
if (prtfs_cfg->fat_primary_cache[2]) free(prtfs_cfg->fat_primary_cache[2]);
if (prtfs_cfg->fat_primary_cache[3]) free(prtfs_cfg->fat_primary_cache[3]);
if (prtfs_cfg->fat_primary_cache[4]) free(prtfs_cfg->fat_primary_cache[4]);
if (prtfs_cfg->fat_primary_cache[5]) free(prtfs_cfg->fat_primary_cache[5]);
if (prtfs_cfg->fat_primary_cache[6]) free(prtfs_cfg->fat_primary_cache[6]);
if (prtfs_cfg->fat_primary_cache[7]) free(prtfs_cfg->fat_primary_cache[7]);
if (prtfs_cfg->fat_primary_cache[8]) free(prtfs_cfg->fat_primary_cache[8]);
if (prtfs_cfg->fat_primary_cache[9]) free(prtfs_cfg->fat_primary_cache[9]);
if (prtfs_cfg->fat_primary_index[0]) free(prtfs_cfg->fat_primary_index[0]);
if (prtfs_cfg->fat_primary_index[1]) free(prtfs_cfg->fat_primary_index[1]);
if (prtfs_cfg->fat_primary_index[2]) free(prtfs_cfg->fat_primary_index[2]);
if (prtfs_cfg->fat_primary_index[3]) free(prtfs_cfg->fat_primary_index[3]);
if (prtfs_cfg->fat_primary_index[4]) free(prtfs_cfg->fat_primary_index[4]);
if (prtfs_cfg->fat_primary_index[5]) free(prtfs_cfg->fat_primary_index[5]);
if (prtfs_cfg->fat_primary_index[6]) free(prtfs_cfg->fat_primary_index[6]);
if (prtfs_cfg->fat_primary_index[7]) free(prtfs_cfg->fat_primary_index[7]);
if (prtfs_cfg->fat_primary_index[8]) free(prtfs_cfg->fat_primary_index[8]);
if (prtfs_cfg->fat_primary_index[9]) free(prtfs_cfg->fat_primary_index[9]);
return(FALSE);
#endif
}

View File

@ -0,0 +1,249 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* APIDELTR.C - Contains user api level source code.
The following routines are included:
pc_deltree - Delete an entire directory tree.
*/
#include <rtfs.h>
/****************************************************************************
PC_DELTREE - Delete a directory tree.
Description
Delete the directory specified in name, all subdirectories of that
directory, and all files contained therein. Fail if name is not a
directory, or is read only.
Returns
Returns TRUE if the directory was successfully removed.
errno will be set to one of these values
0 - No error
PEINVALIDDRIVEID- Drive component of path is invalid
PEINVALIDPATH - Path specified by name is badly formed.
PENOENT - Can't find path specified by name.
PEACCES - Directory or one of its subdirectories is read only or
in use.
An ERTFS system error
*****************************************************************************/
/* Remove a directory */
BOOLEAN pc_deltree(byte *name) /*__apifn__*/
{
DROBJ *parent_obj;
DROBJ *pobj;
DROBJ *pdotdot;
DROBJ *pchild;
BOOLEAN ret_val;
DDRIVE *pdrive;
byte *path;
byte *filename;
byte fileext[4];
int driveno;
int p_errno;
int dir_depth;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
parent_obj = 0;
pchild = 0;
pobj = 0;
pdotdot = 0;
ret_val = FALSE;
dir_depth = 1;
p_errno = 0;
rtfs_set_errno(0); /* pc_deltree: clear error status */
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(name);
if (driveno < 0)
{ /* pc_deltree: errno was by check_drive */
return(FALSE);
}
pdrive = pc_drno2dr(driveno);
/* Use the buffers in the DRIVE structure. Access is locked via semaphore */
path = (byte *)&(pdrive->pathname_buffer[0]);
filename = (byte *)&(pdrive->filename_buffer[0]);
/* Get out the filename and d:parent */
if (!pc_parsepath(path,filename,fileext,name))
{
p_errno = PEINVALIDPATH;
goto errex;
}
/* Find the parent and make sure it is a directory \ */
parent_obj = pc_fndnode(path);
if (!parent_obj)
goto errex; /* pc_fndnode set errno */
if (!pc_isadir(parent_obj) || pc_isavol(parent_obj))
{
p_errno = PENOENT;
goto errex;
}
/* Find the file and init the structure */
pobj = pc_get_inode(0, parent_obj, filename, (byte*)fileext, GET_INODE_MATCH);
if (!pobj)
goto errex; /* pc_get_inode set errno */
if ( !pc_isadir(pobj) || (pobj->finode->opencount > 1) ||
(pobj->finode->fattribute & ARDONLY ))
{
p_errno = PEACCES;
goto errex;
}
/* Search through the directory. look at all files */
/* Call pc_get_inode with 0 to give us an obj */
while (dir_depth > 0)
{
if (pchild)
pc_freeobj(pchild);
pchild = pc_get_inode(0, pobj, 0 , 0, GET_INODE_STAR);
if (pdotdot) {
pc_freeobj(pdotdot);
pdotdot = 0;
}
if (pchild) do
{
/* delete all nodes which are not subdirs;
step into all subdirs and destroy their contents. */
if (!(pc_isdot(pchild->finode->fname, pchild->finode->fext) ) )
{
if (!(pc_isdotdot(pchild->finode->fname, pchild->finode->fext) ) )
{
if (pc_isadir(pchild))
{
if ( (pchild->finode->opencount > 1) ||
(pchild->finode->fattribute&ARDONLY) )
{
p_errno = PEACCES;
ret_val = FALSE;
goto errex;
}
dir_depth++;
pc_freeobj(pobj);
pobj = pchild; /* enter first subdir */
pchild = 0;
goto start_over;
}
else
{
/* Be sure it is not the root. Since the root is an abstraction
we can not delete it plus Check access permissions */
if ( pc_isroot(pchild) || (pchild->finode->opencount > 1) ||
(pchild->finode->fattribute&(ARDONLY|AVOLUME|ADIRENT)))
{
p_errno = PEACCES;
ret_val = FALSE;
goto errex;
}
else
{
/* Remove the file */
/* calculate max number of clusters to release.
Add bytespcluster-1 in case we are not on a cluster boundary */
ret_val = pc_rmnode(pchild);
if (!ret_val)
goto errex; /* pc_rmnode sets errno */
goto start_over;
}
}
}
else
{
if (pdotdot)
pc_freeobj(pdotdot);
pdotdot = pc_get_mom(pchild);
}
}
}
while (pc_get_inode(pchild, pobj, 0 , 0, GET_INODE_STAR));
if (get_errno() != PENOENT)
goto errex; /* pc_get_inode set errno */
/* dir empty; step out and delete */
if (pobj) {
pc_freeobj(pobj);
pobj = 0;
}
if (pchild) {
pc_freeobj(pchild);
pchild = 0;
}
dir_depth--;
if (dir_depth > 0)
{
if (!pdotdot)
{
p_errno = PEINVALIDCLUSTER;
goto errex;
}
pchild = pc_get_inode(0, pdotdot, 0 , 0, GET_INODE_STAR);
if (pchild)
{
do
{
if (!(pc_isdot(pchild->finode->fname, pchild->finode->fext) ) )
{
if (!(pc_isdotdot(pchild->finode->fname, pchild->finode->fext) ) )
{
ret_val = pc_rmnode(pchild); /* remove the directory */
if (!ret_val)
goto errex; /* pc_mnode set errno */
break;
}
}
} while (pc_get_inode(pchild, pdotdot, 0, 0, GET_INODE_STAR));
}
else
{
if (get_errno() != PENOENT)
goto errex; /* pc_get_inode set errno */
}
pobj = pdotdot;
pdotdot = 0;
}
else
{
pobj = pc_get_inode(0, parent_obj, filename, (byte*)fileext, GET_INODE_MATCH);
if (!pobj)
goto errex; /* pc_mnode set errno */
ret_val = pc_rmnode(pobj); /* Remove the directory */
if (!ret_val)
goto errex; /* pc_mnode set errno */
}
start_over:
;
}
errex:
if (pdotdot)
pc_freeobj(pdotdot);
if (pchild)
pc_freeobj(pchild);
if (pobj)
pc_freeobj(pobj);
if (parent_obj)
pc_freeobj(parent_obj);
if (p_errno)
rtfs_set_errno(p_errno);
if (!release_drive_mount_write(driveno))/* Release lock, unmount if aborted */
ret_val = FALSE;
return(ret_val);
}

View File

@ -0,0 +1,500 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* File APIENUM.C */
/* pc_enumerate - List select all directory entries that match rules and
* allow a callback routine to process each on.
*
* Description - This routine traverses a subdirectory tree. It tests each
* directory entry to see if it matches user supplied selection criteria.
* if it does match the criteria a user supplied callback function is
* called with the full path name of the directory entry and a pointer
* to a DSTAT structure that contains detailed information about the
* directory entry. (see the manual page for a detailed description of the
* DSTAT structure.
*
* Selection criteria - Two arguments are used to determine the selection
* criteria. On is a flags word that specifies attributes the other is
* a pattern that specifies a wild card pattern.
* The flags argument contains a bitwise or of one or more of the following:
* MATCH_DIR - Select directory entries
* MATCH_VOL - Select volume labels
* MATCH_FILES - Select files
* MATCH_DOT - Select the '.' entry MATH_DIR must be true also
* MATCH_DOTDOT - Select the '..' entry MATCH_DIR must be true also
*
* The selection pattern is a standard wildcard pattern such as '*.*' or
* *.txt.
* Note: Patterns don't work the same for VFAT and DOS 8.3. If VFAT is
* enable the pattern *.* will return any file name that has a '.' in it
* in 8.3 systems it returns all files.
*
* Note: pc_enumerate() requires a fair amount of buffer space to function.
* Instead of allocating the space internally we require that the application
* pass two buffers of size EMAXPATH_BYTES in to the function. See below.
*
* Se
* Summary:
*
* int pc_enumerate(
* byte * from_pattern_buffer - pointer to a scratch buffer of size EMAXPATH_BYTES
* byte * spath_buffer - pointer to a scratch buffer of size EMAXPATH_BYTES
* byte * dpath_buffer - pointer to a scratch buffer of size EMAXPATH_BYTES
* byte * root_search - Root of the search IE C:\ or C:\USR etc.
* word match_flags - Selection flags (see above)
* byte match_pattern - Match pattern (see above)
* int maxdepth - Maximum depth of the traversal.
* Note: to scan only one level set this to
* 1. For all levels set it to 99
* PENUMCALLBACK pcallback - User callback function. (see below)
*
* Return value
* pc_enumerate() returns 0 unless the callback function returns a non-
* zero value at any point. If the callback returns a non-zero value the
* scan terminates imediately and returns the returned value to the
* application.
*
* errno is set to one of the following
* pc_enumerate() does not set errno
*
*
* About the callback.
*
* The callback function is a function that returns an integer and is passed
* the fully qualified path to the current directory entry and a DSTAT
* structure. The callback fuction must return 0 if it wishes the scan to
* continue or any other integer value to stop the scan and return the
* callback's return value to the application layer.
*
* Examples
*
* The next two function implement a multilevel directory scan.
* int rdir_callback(byte *path, DSTAT *d) {printf("%s\n", path);return(0);}
*
* rdir(byte *path, byte *pattern)
* {
* pc_enumerate(from_path,from_pattern,spath,dpath,path,
* (MATCH_DIR|MATCH_VOL|MATCH_FILES), pattern, 99, rdir_callback);
* }
*
* Poor mans deltree package
* int delfile_callback(byte *path, DSTAT *d) {
* pc_unlink(path); return(0);
* }
* int deldir_callback(byte *path, DSTAT *d) {
* pc_rmdir(path); return(0);
* }
*
*
* deltree(byte *path)
* {
* int i;
* ==> First delete all of the files
* pc_enumerate(from_path,from_pattern,spath,dpath,path,
* (MATCH_FILES), "*",99, delfile_callback);
* i = 0;
* ==> Now delete all of the dirs.. deleting path won't work until the
* ==> tree is empty
* while(!pc_rmdir(path) && i++ < 50)
* pc_enumerate(from_path,from_pattern,spath,dpath,path,
* (MATCH_DIR), "*", 99, deldir_callback);
* }
*
*/
#include <rtfs.h>
#if (!INCLUDE_CS_UNICODE) /* BUGBUG - Not doing ENUM yet */
#define MATCH_DIR 0x01
#define MATCH_VOL 0x02
#define MATCH_FILES 0x04
#define MATCH_DOT 0x08
#define MATCH_DOTDOT 0x10
typedef int (*PENUMCALLBACK)(byte *path, DSTAT *pstat);
int pc_enumerate(
byte * from_path_buffer,
byte * from_pattern_buffer,
byte * spath_buffer,
byte * dpath_buffer,
byte * root_search,
word match_flags,
byte * match_pattern,
int maxdepth,
PENUMCALLBACK pcallback);
#if (VFAT)
/* UNICODE Fixed */
/* #define ALL_FILES "*" */
#define ALL_FILES "*"
#else
/* UNICODE Fixed */
#define ALL_FILES "*.*"
/* #define ALL_FILES string_star_dot_star */
#endif
int get_parent_path(byte *parent, byte *path);
int dirscan_isdot(DSTAT *statobj);
int dirscan_isdotdot(DSTAT *statobj);
int pc_enumerate( /* __apifn__ */
byte * from_path_buffer,
byte * from_pattern_buffer,
byte * spath_buffer,
byte * dpath_buffer,
byte * root_search,
word match_flags,
byte * match_pattern,
int maxdepth,
PENUMCALLBACK pcallback)
{
int dir_index[30];
dword dir_block[30];
int depth;
DSTAT statobj;
int process_it;
int dodone;
int call_back;
int ret_val;
#if (!VFAT)
int i;
/* IN 8.3 systems we parse the match pattern into file and ext parts */
byte filepat[9];
byte extpat[9];
pc_ascii_fileparse(filepat, extpat, (byte *)match_pattern);
for(i = 0; i < 8; i++) if (filepat[i]==' ') filepat[i]=0;
for(i = 0; i < 3; i++) if (extpat[i]==' ') extpat[i]=0;
#endif
ret_val = 0;
pc_str2upper((byte *)from_path_buffer, (byte *) root_search);
depth = 0;
pc_mpath(from_pattern_buffer, from_path_buffer, (byte *)ALL_FILES);
dir_index[0] = 0;
dir_block[0] = 0;
do
{
step_into_dir:
dodone = 0;
if (pc_gfirst(&statobj, (byte *)from_pattern_buffer))
{
dodone = 1;
process_it = 0;
do
{
if (!dir_block[depth] || ((dir_block[depth] ==
((DROBJ *) (statobj.pobj))->blkinfo.my_block ) &&
(dir_index[depth] ==
((DROBJ *) (statobj.pobj))->blkinfo.my_index )))
{
process_it = 1;
}
if (process_it)
{
call_back = 1;
/* Don't report directories if not requested */
if ((statobj.fattribute & ADIRENT) &&
!(match_flags & MATCH_DIR) )
call_back = 0;
/* Don't report volumes if not requested */
if (call_back && (statobj.fattribute & AVOLUME) &&
!(match_flags & MATCH_VOL) )
call_back = 0;
/* Don't report plain files if not requested */
if (call_back && !(statobj.fattribute & (AVOLUME|ADIRENT)) &&
!(match_flags & MATCH_FILES) )
call_back = 0;
/* Don't report DOT if not requested */
if (call_back && dirscan_isdot(&statobj) && !(match_flags & MATCH_DOT))
call_back = 0;
/* Don't report DOTDOT if not requested */
if (call_back && dirscan_isdotdot(&statobj) && !(match_flags & MATCH_DOTDOT))
call_back = 0;
if (call_back)
{
/* Take it if the pattern match work */
#if (VFAT)
/* Under VFAT do a pattern match on the long file name */
if (statobj.lfname[0])
call_back = pc_patcmp_vfat(match_pattern, statobj.lfname, TRUE);
else
call_back = pc_patcmp_vfat(match_pattern, (byte *)(statobj.filename), TRUE);
#else
/* Non VFAT uses 8.3 matching conventions */
pc_ascii_fileparse(filepat, extpat, (byte *)match_pattern);
call_back =
pc_patcmp_8((byte *)&statobj.fname[0], (byte *)&filepat[0] , TRUE);
call_back = call_back &&
pc_patcmp_3((byte *)&statobj.fext[0], (byte *)&extpat[0] , TRUE);
#endif
}
/* Construct the full path */
pc_mpath(dpath_buffer, from_path_buffer, (byte *)statobj.filename);
if (call_back && pcallback)
{
/* If the callback returns non zero he says quit */
ret_val = pcallback(dpath_buffer, &statobj);
if (ret_val)
{
pc_gdone(&statobj);
goto ex_it;
}
}
}
/* If it is a subdirectory and we are still in our depth range
then process the subdirectory */
if (process_it && (depth < maxdepth) &&
!dirscan_isdot(&statobj) &&
!dirscan_isdotdot(&statobj))
{
/* Construct the full path */
pc_mpath(spath_buffer, from_path_buffer, (byte *)statobj.filename);
if (statobj.fattribute & (AVOLUME | ADIRENT))
{
if (pc_gnext(&statobj))
{
/* If path is a dir, mark our place and step in */
dir_block[depth] = ((DROBJ *) (statobj.pobj))->blkinfo.my_block;
dir_index[depth] = ((DROBJ *) (statobj.pobj))->blkinfo.my_index;
dodone = 0;
pc_gdone(&statobj);
}
else
{
dodone = 0;
pc_gdone(&statobj);
dir_index[depth] = -1;
}
depth += 1;
dir_block[depth] = 0;
dir_index[depth] = 0;
rtfs_cs_strcpy((byte *)from_path_buffer, (byte *)spath_buffer);
pc_mpath(from_pattern_buffer, from_path_buffer, (byte *)ALL_FILES);
goto step_into_dir;
}
}
} while (pc_gnext(&statobj)); /* Get the next file in dir */
if (dodone)
pc_gdone(&statobj);
}
if (!get_parent_path(from_path_buffer, from_path_buffer))
break;
pc_mpath(from_pattern_buffer, from_path_buffer, (byte *)ALL_FILES);
depth--;
while (depth >= 0 && dir_index[depth] == -1)
{
if (!get_parent_path(from_path_buffer, from_path_buffer))
break;
pc_mpath(from_pattern_buffer, from_path_buffer, (byte *)ALL_FILES);
depth--;
}
} while (depth >= 0);
ex_it:
return (ret_val);
}
int get_parent_path(byte *parent, byte *path) /*__fn__*/
{
byte *last_backslash;
int size;
last_backslash = 0;
size = 0;
while (*path != '\0')
{
size++;
if (*path == '\\')
{
last_backslash = parent;
}
*(parent++) = *(path++);
}
/* This is to prevent catastrophie if caller ignores failure */
*parent = '\0';
if (size < 3)
return (0);
if (last_backslash)
*last_backslash = '\0';
return (1);
}
/************************************************************************
* *
* File system abstraction layer *
* *
************************************************************************/
int dirscan_isdot(DSTAT *statobj)
{
return(rtfs_strcmp((byte *)".", statobj->filename)==0);
}
int dirscan_isdotdot(DSTAT *statobj)
{
return(rtfs_strcmp((byte *)"..", statobj->filename)==0);
}
#ifdef NOTDEF
/* The section from here to the bottom of the file contains code that
shows via example how to use the enumerate function.
*/
#include <conio.h>
#include <ctype.h>
#include <direct.h>
#include <dos.h>
#include <fcntl.h>
#include <io.h>
#include <sys\types.h>
#include <stdlib.h>
#include <stdio.h>
void usage(byte *progname)
{
RTFS_PRINTF("Usage: %s [options] <source_path> <dest_path_1> [<dest_path_2> ...]\n",progname);
}
rdir(byte *path, byte *pattern);
deltree(byte *path, byte *pattern);
#define FILTER ALL_FILES /* Default filter */
int main(int argc,byte **argv)
{
byte src_path[EMAXPATH_BYTES];
byte filter[20];
byte op;
rtfs_kernel_init();
argc--;
argv++;
if (argc < 2)
{
goto usage;
}
op = *argv[0];
rtfs_cs_strcpy((byte *)filter,FILTER);
argc--; argv++;
/* Process user options */
rtfs_cs_strcpy(src_path,*argv);
argc--; argv++;
if (argc)
{
rtfs_cs_strcpy(filter,*argv);
}
else
{
rtfs_cs_strcpy((byte *)filter,FILTER);
}
if (op=='R')
{
rdir(src_path, filter);
}
else if (op == 'D')
{
deltree(src_path, filter);
}
else
{
usage:
RTFS_PRINTF("(R)dir or (D)eltree PATH [pattern]\n");
}
/* treeprintnew (src_path, filter, be_verbose); */
}
/* Examples */
byte from_path[EMAXPATH_BYTES];
byte from_pattern[EMAXPATH_BYTES];
byte spath[EMAXPATH_BYTES];
byte dpath[EMAXPATH_BYTES];
/* Recursive DIR function */
int rdir_callback(byte *path, DSTAT *d)
{
RTFS_PRINTF("%s\n", path);
return(0);
}
rdir(byte *path, byte *pattern)
{
pc_enumerate(from_path,from_pattern,spath,dpath,path,
(MATCH_DIR|MATCH_VOL|MATCH_FILES), pattern, 99, rdir_callback);
}
/* Poor mans deltree package */
int delfile_callback(byte *path, DSTAT *d)
{
RTFS_PRINTF("Deleting file %s\n", path);
pc_unlink(path);
return(0);
}
int deldir_callback(byte *path, DSTAT *d)
{
RTFS_PRINTF("Deleting directory %s\n", path);
pc_rmdir(path);
return(0);
}
deltree(byte *path)
{
int i;
/* First delete all of the files */
pc_enumerate(from_path,from_pattern,spath,dpath,path,
(MATCH_FILES), "*",99, delfile_callback);
i = 0;
/* Now delete all of the dirs.. deleting the root of the path won't
work until the tree is empty */
while(!pc_rmdir(path) && i++ < 50)
{
pc_enumerate(from_path,from_pattern,spath,dpath,path,
(MATCH_DIR), "*", 99, deldir_callback);
}
}
#endif
#endif /* (!INCLUDE_CS_UNICODE) BUGBUG - Not doing ENUM yet */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,292 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* APIFILEMV.C - Contains user api level source code.
The following routines are included:
pc_mv - Rename a file.
pc_unlink - Delete a file.
*/
#include <rtfs.h>
/***************************************************************************
PC_MV - Rename a file.
Description
Renames the file in path (name) to newname. Fails if name is invalid,
newname already exists or path not found.
01-07-99 - Rewrote to support moving files between subdirectories
no longer supports renaming subdirectories or volumes
Returns
Returns TRUE if the file was renamed. Or no if the name not found.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid or they are not the same
PEINVALIDPATH - Path specified by old_name or new_name is badly formed.
PEACCESS - File or directory in use, or old_name is read only
PEEXIST - new_name already exists
An ERTFS system error
***************************************************************************/
/* Rename a file */
BOOLEAN pc_mv(byte *old_name, byte *new_name) /*__apifn__*/
{
int old_driveno;
DROBJ *old_obj;
DROBJ *old_parent_obj;
byte *path;
byte *filename;
byte fileext[4];
int new_driveno;
DROBJ *new_obj;
DROBJ *new_parent_obj;
BOOLEAN ret_val;
CLUSTERTYPE cluster;
DDRIVE *pdrive;
int p_errno;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
p_errno = 0;
/* Drives must be the same */
if ( !pc_parsedrive( &old_driveno, old_name ) ||
!pc_parsedrive( &new_driveno, new_name ) ||
old_driveno != new_driveno)
{
rtfs_set_errno(PEINVALIDDRIVEID);
return(FALSE);
}
/* Get the drive and make sure it is mounted */
old_driveno = check_drive_name_mount(old_name);
if (old_driveno < 0)
{
/* errno was set by check_drive */
return(FALSE);
}
rtfs_set_errno(0); /* pc_mv: clear error status */
old_obj = 0;
old_parent_obj = 0;
new_obj = 0;
new_parent_obj = 0;
ret_val = FALSE;
pdrive = pc_drno2dr(old_driveno);
/* Use the buffers in the DRIVE structure. Access is locked via semaphore */
path = (byte *)&(pdrive->pathname_buffer[0]);
filename = (byte *)&(pdrive->filename_buffer[0]);
/* Get out the filename and d:parent */
if (!pc_parsepath(path, filename,fileext,old_name))
{
p_errno = PEINVALIDPATH;
goto errex;
}
/* Find the parent and make sure it is a directory */
old_parent_obj = pc_fndnode(path);
if (!old_parent_obj)
goto errex; /* pc_fndinode - set errno */
if (!pc_isadir(old_parent_obj))
{
p_errno = PENOENT;
goto errex;
}
/* Find the file */
old_obj = pc_get_inode(0, old_parent_obj,
filename, (byte*)fileext, GET_INODE_MATCH);
if (!old_obj)
goto errex; /* pc_get_inode - set errno */
/* Be sure it exists and is a normal directory or file and is not open */
if (pc_isroot(old_obj) || (old_obj->finode->opencount > 1) ||
(old_obj->finode->fattribute&(ARDONLY|AVOLUME)))
{
p_errno = PEACCES;
goto errex;
}
/* At this point old_obj contains the file we are renaming */
/* See if the new directory entry already exists */
new_obj = pc_fndnode(new_name);
if (new_obj)
{
p_errno = PEEXIST;
goto errex;
}
rtfs_set_errno(0); /* pc_mv - clear errno condition after failed pc_fndnode */
/* Get out the filename and d:parent */
if (!pc_parsepath(path,filename,fileext,new_name))
{
p_errno = PEINVALIDPATH;
goto errex;
}
/* Find the parent and make sure it is a directory */
new_parent_obj = pc_fndnode(path);
if (!new_parent_obj || !pc_isadir(new_parent_obj) || pc_isavol(new_parent_obj))
goto errex;
/* The cluster value old */
cluster = pc_finode_cluster(old_obj->pdrive,old_obj->finode);
/* Create the new entry and assign cluster to it. If it is a directory
.. will be linked correctly */
new_obj = pc_mknode( new_parent_obj, filename, fileext, old_obj->finode->fattribute, cluster);
if (!new_obj)
goto errex;
/* Copy the old directory entry stuf over */
new_obj->finode->fattribute = old_obj->finode->fattribute;
new_obj->finode->ftime = old_obj->finode->ftime;
new_obj->finode->fdate = old_obj->finode->fdate;
new_obj->finode->fsize = old_obj->finode->fsize;
/* Update the new inode. Do not set archive bit or change date */
if (!pc_update_inode(new_obj, FALSE, FALSE))
goto errex;
/* Set the old cluster value to zero */
pc_pfinode_cluster(old_obj->pdrive,old_obj->finode,0);
/* Delete the old but won't delete any clusters */
if (!pc_rmnode(old_obj))
goto errex;
p_errno = 0;
ret_val = TRUE;
/* Good conditions fall through here, error exits jump to here */
errex:
if (old_parent_obj)
pc_freeobj(old_parent_obj);
if (old_obj)
pc_freeobj(old_obj);
if (new_parent_obj)
pc_freeobj(new_parent_obj);
if (new_obj)
pc_freeobj(new_obj);
/* Set errno if we have one and not set by lower level already */
if ((p_errno) && !get_errno())
rtfs_set_errno(p_errno);
if (!release_drive_mount_write(old_driveno))/* Release lock, unmount if aborted */
ret_val = FALSE;
return(ret_val);
}
/****************************************************************************
PC_UNLINK - Delete a file.
Description
Delete the file in name. Fail if not a simple file,if it is open,
does not exist or is read only.
Returns
Returns TRUE if it successfully deleted the file.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid
PEINVALIDPATH - Path specified badly formed.
PENOENT - Can't find file to delete
PEACCESS - File in use, is read only or is not a simple file.
An ERTFS system error
***************************************************************************/
/* Delete a file */
BOOLEAN pc_unlink(byte *name) /*__apifn__*/
{
DROBJ *pobj;
DROBJ *parent_obj;
BOOLEAN ret_val;
DDRIVE *pdrive;
byte *path;
byte *filename;
byte fileext[4];
int driveno;
int p_errno;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
ret_val = FALSE;
parent_obj = 0;
pobj = 0;
p_errno = 0;
rtfs_set_errno(0); /* pc_unlink: clear error status */
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(name);
if (driveno < 0)
{
/* errno was set by check_drive */
return(FALSE);
}
pdrive = pc_drno2dr(driveno);
/* Use the buffers in the DRIVE structure. Access is locked via semaphore */
path = (byte *)&(pdrive->pathname_buffer[0]);
filename = (byte *)&(pdrive->filename_buffer[0]);
/* Get out the filename and d:parent */
if (!pc_parsepath(path, filename,fileext,name))
{
p_errno = PEINVALIDPATH;
goto errex;
}
/* Find the parent and make sure it is a directory */
parent_obj = pc_fndnode(path);
if (!parent_obj)
goto errex; /* pc_fndnode set errno */
if (!pc_isadir(parent_obj) || pc_isavol(parent_obj))
{
p_errno = PEACCES;
goto errex;
}
/* Find the file */
pobj = pc_get_inode(0, parent_obj, filename, (byte*)fileext, GET_INODE_MATCH);
/* if pc_get_inode() fails it sets errno to PENOENT or to an internal or IO error status */
if (pobj)
{
/* Be sure it is not the root. Since the root is an abstraction
we can not delete it plus Check access permissions */
if ( pc_isroot(pobj) || (pobj->finode->opencount > 1) ||
(pobj->finode->fattribute&(ARDONLY|AVOLUME|ADIRENT)))
{
p_errno = PEACCES;
ret_val = FALSE;
goto errex;
}
else
{ /* pc_rmnode sets errno */
ret_val = pc_rmnode(pobj);
}
}
errex:
if (pobj)
pc_freeobj(pobj);
if (parent_obj)
{
pc_freeobj(parent_obj);
}
/* Set errno if we have one and not set by lower level already */
if ((p_errno) && !get_errno())
rtfs_set_errno(p_errno);
if (!release_drive_mount_write(driveno))/* Release lock, unmount if aborted */
ret_val = FALSE;
return(ret_val);
}

View File

@ -0,0 +1,783 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 2000
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
#include <rtfs.h>
/* */
/* New format logic */
/* */
/* */
/* */
void get_format_parameters(dword nblocks, int *psector_p_alloc, int *pnum_root_entries);
word pc_fat_size(word nreserved, word cluster_size, word n_fat_copies,
word root_sectors, dword volume_size,
int *nibs_per_entry);
void pc_calculate_chs(dword total, dword *cylinders, int *heads, int *secptrack)
{
dword c, h, s;
if (total >= 255 * 255 * 63)
{
/* this block is just an optimization of the loop below */
s = 63;
h = 255;
c = total / (255 * 63);
if (c > 1023)
c = 1023;
}
else
{
c = h = s = 1;
if (total >= 63 * 63 * 63)
s = 63;
while (c < 1023 && (c + 1) * h * s <= total)
{
if (h > c || h == 255)
c++;
else if (s > h || s == 63)
h++;
else
s++;
}
}
if (cylinders)
*cylinders = c;
if (heads)
*heads = (int) h;
if (secptrack)
*secptrack = (int) s;
}
/* */
/*1. Floppy driver must return partition info. Must format */
/*2. other drivers must return info. must format. See ATAPI */
/* 10-24-2000 added LBA formatting. Submit to main tree */
/***************************************************************************
PC_GET_MEDIA_PARMS - Get media parameters.
Description
Queries the drive s associated device driver for a description of the
installed media. This information is used by the pc_format_media,
pc_partition_media and pc_format_volume routines. The application may
use the results of this call to calculate how it wishes the media to
be partitioned.
Note that the floppy device driver uses a back door to communicate
with the format routine through the geometry structure. This allows us
to not have floppy specific code in the format routine but still use the
exact format parameters that DOS uses when it formats a floppy.
See the following definition of the pgeometry structure:
typedef struct dev_geometry {
int dev_geometry_heads; -- - Must be < 256
int dev_geometry_cylinders; -- - Must be < 1024
int dev_geometry_secptrack; -- - Must be < 64
BOOLEAN fmt_parms_valid; -- If the device io control call sets this
-- TRUE then it it telling the applications
-- layer that these format parameters should
-- be used. This is a way to format floppy
-- disks exactly as they are fromatted by dos.
FMTPARMS fmt;
} DEV_GEOMETRY;
typedef struct dev_geometry *PDEV_GEOMETRY;
Returns
Returns TRUE if it was able to get the parameters otherwise
it returns FALSE.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid
PEDEVICEFAILURE - Device driver get device geometry request failed
PEINVALIDPARMS - Device driver returned bad values
****************************************************************************/
BOOLEAN pc_get_media_parms(byte *path, PDEV_GEOMETRY pgeometry) /* __apifn__*/
{
int driveno;
dword total;
DDRIVE *pdr;
CHECK_MEM(BOOLEAN, 0)
rtfs_set_errno(0); /* pc_get_media_parms: clear error status */
/* Make sure its a valid drive number */
driveno = pc_parse_raw_drive(path);
if (driveno < 0)
{
inval:
rtfs_set_errno(PEINVALIDDRIVEID); /* pc_get_media_parms: invlid drive ID */
return(FALSE);
}
pdr = pc_drno_to_drive_struct(driveno);
if (!pdr || !(pdr->drive_flags&DRIVE_FLAGS_VALID) )
goto inval;
/* Ask - for device geometry */
if (pdr->dev_table_perform_device_ioctl(driveno, DEVCTL_GET_GEOMETRY, (void *) pgeometry))
{
rtfs_set_errno(PEDEVICEFAILURE); /* pc_get_media_parms: device get geometry failed */
return (FALSE);
}
/* The geometry consists of cylinders, heads, and sectors
per track.
The ATA spec says that the maximum values for these are
65536 cylinders, 16 heads, and 255 sectors per track.
However, the MBR spec says the maximum values are
1023 cylinders, 255 heads, and 63 sectors per track.
So, we create new values for cylinders, heads, and sectors
per track that work for the MBR but come as close as we
can get to the real disk size.
*/
total = pgeometry->dev_geometry_lbas ? pgeometry->dev_geometry_lbas : (pgeometry->dev_geometry_cylinders * pgeometry->dev_geometry_heads * pgeometry->dev_geometry_secptrack);
pc_calculate_chs(total, &pgeometry->dev_geometry_cylinders, &pgeometry->dev_geometry_heads, &pgeometry->dev_geometry_secptrack);
return(TRUE);
}
/***************************************************************************
PC_FORMAT_MEDIA - Device level format
Description
This routine performs a device level format on the specified
drive.
Returns
Returns TRUE if it was able to perform the operation otherwise
it returns FALSE.
Note: The the logical drive must be claimed before this routine is
called and later released by the caller.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid
PEDEVICEFAILURE - Device driver format request failed
****************************************************************************/
BOOLEAN pc_format_media(byte *path, PDEV_GEOMETRY pgeometry) /* __apifn__*/
{
int driveno;
DDRIVE *pdr;
CHECK_MEM(BOOLEAN, 0)
rtfs_set_errno(0); /* pc_format_media: clear error status */
/* Make sure its a valid drive number */
driveno = pc_parse_raw_drive(path);
if (driveno < 0)
{
inval:
rtfs_set_errno(PEINVALIDDRIVEID); /* pc_format_media: invalid drive id */
return(FALSE);
}
pdr = pc_drno_to_drive_struct(driveno);
if (!pdr || !(pdr->drive_flags&DRIVE_FLAGS_VALID) )
{
goto inval;
}
/* Make sure that is it closed up */
pc_dskfree(driveno);
/* Format the device geometry */
if (pdr->dev_table_perform_device_ioctl(driveno, DEVCTL_FORMAT, (void *) pgeometry))
{
rtfs_set_errno(PEDEVICEFAILURE); /* pc_format_media: driver format failed */
return(FALSE);
}
return(TRUE);
}
/***************************************************************************
PC_PARTITION_MEDIA - Write partition table
Description
A partition list is provided (a list of partition sizes
in units of LBA s) by the user.
Returns
Returns TRUE if it was able to perform the operation otherwise
it returns FALSE.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid
PEINVALIDPARMS - Inconsistent or missing parameters
PEIOERRORWRITE - Error writing partition table
An ERTFS system error
****************************************************************************/
BOOLEAN pc_partition_media(byte *path, PDEV_GEOMETRY pgeometry, dword * partition_list) /* __apifn__*/
{
int driveno;
BOOLEAN ret_val;
BLKBUFF *buf;
byte * pbuf;
dword partition_size;
int partition_number;
int nibs_per_entry;
PTABLE part;
DDRIVE *pdr;
int root_entries;
int secpalloc;
/*word secpfat;*/
int root_sectors;
word utemp;
word utemp2;
dword dwTemp;
dword starting_lba;
word cyl;
byte head,sec;
dword disk_size;
word starting_cylinder;
CHECK_MEM(BOOLEAN, 0)
ret_val = FALSE;
rtfs_set_errno(0); /* pc_partition_media: clear error status */
/* Make sure it s a valid drive number */
driveno = pc_parse_raw_drive(path);
if (driveno < 0)
{
inval:
rtfs_set_errno(PEINVALIDDRIVEID);
return(ret_val);
}
pdr = pc_drno_to_drive_struct(driveno);
if (!pdr)
goto inval;
if (!pgeometry || !partition_list || !partition_list)
{
rtfs_set_errno(PEINVALIDPARMS); /* pc_partition_media: bad arguments */
return(ret_val);
}
/* Zero the partition table to start */
rtfs_memset(&part, 0, sizeof(part));
starting_cylinder = 0;
/* 10-24-2000 - New code to support lba formatting */
/* The first partition starts at cylinder=0, head=1, sector=1 */
if (pgeometry->dev_geometry_lbas)
starting_lba = (dword) pgeometry->dev_geometry_secptrack;
else
{
starting_lba = 0; /* Not used */
/* 10-24-2000 - This was the original code */
disk_size = (dword) pgeometry->dev_geometry_cylinders;
disk_size = disk_size * (dword) pgeometry->dev_geometry_heads;
disk_size = disk_size * (dword) pgeometry->dev_geometry_secptrack;
/* The first partition starts at 1 */
starting_cylinder = 1;
}
for (partition_number = 0; partition_number < 4; partition_number++)
{
partition_size = (dword) *(partition_list+partition_number);
if (!partition_size)
break; /* End of list */
if (pgeometry->dev_geometry_lbas)
{
/* 10-24-2000 - New code to support lba formatting */
/* Apparently, we must still align to cylinders even in LBA mode */
dwTemp = (dword) pgeometry->dev_geometry_heads;
dwTemp *= (dword) pgeometry->dev_geometry_secptrack;
partition_size = ((partition_size / dwTemp) * dwTemp) - (starting_lba % dwTemp);
}
else
{
/* 10-24-2000 - This was the original code */
/* Multiply time # heads and secptrack */
partition_size = partition_size * (dword) pgeometry->dev_geometry_heads;
partition_size = partition_size * (dword) pgeometry->dev_geometry_secptrack;
}
/* Look up root_entries and cluster size */
get_format_parameters(partition_size, &secpalloc, &root_entries);
if( secpalloc == -1 )
{
/* Media capacity is too large */
rtfs_set_errno(PEDEVICEUNKNOWNMEDIA);
return( FALSE );
}
root_sectors = (int) (root_entries/16);
/* Calculate sectors per fat */
/*secpfat = */pc_fat_size( (word)1 /* reserved */, (word)secpalloc,
(word)2 /*numfats*/, (word)root_sectors /* root sectors */,
partition_size, &nibs_per_entry);
/* Now fill in the partition entry 0 */
part.ents[partition_number].boot = 0x80; /* Set this to 0x80 for bootable */
if (pgeometry->dev_geometry_lbas)
{
/* 10-24-2000 - New code to support lba formatting */
/* Do CHS */
/* SECTOR */
dwTemp = (starting_lba % pgeometry->dev_geometry_secptrack) + 1;
sec = (byte) dwTemp;
/* HEAD */
dwTemp = starting_lba / pgeometry->dev_geometry_secptrack;
dwTemp = dwTemp % pgeometry->dev_geometry_heads;
head = (byte) dwTemp;
/* CYLINDER */
dwTemp = starting_lba / pgeometry->dev_geometry_secptrack;
dwTemp = dwTemp / pgeometry->dev_geometry_heads;
if (dwTemp > 1023)
dwTemp = 1023;
cyl = (word) dwTemp;
/* Load the starting CHS */
part.ents[partition_number].s_head = head;
utemp = (word)((cyl & 0xff) << 8); /* Low 8 bit to hi bite */
utemp2 = (word)((cyl >> 2) & 0xc0); /* Hi 2 bits to bits 6 + 7 */
utemp |= utemp2;
utemp |= sec;
fr_WORD((byte *)&(part.ents[partition_number].s_cyl), utemp);
/* Load the starting LBA */
fr_DWORD((byte *)&(part.ents[partition_number].r_sec), starting_lba);
}
else
{
/* 10-24-2000 - This was the original code */
part.ents[partition_number].s_head = 1; /* Start at head 1 */
fr_WORD((byte *) &(part.ents[partition_number].s_cyl), (word)starting_cylinder);
}
if (partition_size > (dword) 0xffff)
{
if (nibs_per_entry == 8)
{
/* 10-24-2000 - New code to support lba formatting */
if (pgeometry->dev_geometry_lbas)
part.ents[partition_number].p_typ = 0x0c; /* DOS 32 bit LBA mode (was: 0x0b) */
else
/* 10-24-2000 - This was the original code */
part.ents[partition_number].p_typ = 0x0b; /* DOS 32 bit */
}
else
part.ents[partition_number].p_typ = 6; /* Huge */
}
else
{
if (nibs_per_entry == 4)
part.ents[partition_number].p_typ = 4; /* DOS 16 bit */
else
part.ents[partition_number].p_typ = 1; /* DOS 12 bit */
}
if (pgeometry->dev_geometry_lbas)
{
/* 10-24-2000 - New code to support lba formatting */
/* Load the LBA size of the partition */
fr_DWORD((byte *)&(part.ents[partition_number].p_size), partition_size);
/* Advance the starting_lba */
starting_lba += partition_size;
/* Do CHS */
/* SECTOR */
dwTemp = ((starting_lba-1) % pgeometry->dev_geometry_secptrack) + 1;
sec = (byte) dwTemp;
/* HEAD */
dwTemp = (starting_lba-1) / pgeometry->dev_geometry_secptrack;
dwTemp = dwTemp % pgeometry->dev_geometry_heads;
head = (byte) dwTemp;
/* CYLINDER */
dwTemp = (starting_lba-1) / pgeometry->dev_geometry_secptrack;
dwTemp = dwTemp / pgeometry->dev_geometry_heads;
if (dwTemp > 1023)
dwTemp = 1023;
cyl = (word) dwTemp;
/* Load the ending CHS */
part.ents[partition_number].e_head = head;
utemp = (word)((cyl & 0xff) << 8); /* Low 8 bit to hi bite */
utemp2 = (word)((cyl >> 2) & 0xc0); /* Hi 2 bits to bits 6 + 7 */
utemp |= utemp2;
utemp |= sec;
fr_WORD((byte *)&(part.ents[partition_number].e_cyl), utemp);
}
else
{
/* 10-24-2000 - This was the original code */
/* Ending head is NHEADS-1 since heads go from 0 to n */
part.ents[partition_number].e_head = (byte) (pgeometry->dev_geometry_heads-1);
/* Ending cylinder is in the top ten bits, secptrack in lower 6 ?? */
/* Relative sector starting */
fr_DWORD((byte *)&(part.ents[partition_number].r_sec), (dword) pgeometry->dev_geometry_secptrack*starting_cylinder);
/* Set up for the next partition and use new value to calculate ending cyl */
starting_cylinder = (word)((word)starting_cylinder + (word) *(partition_list+partition_number));
utemp = (word)(((starting_cylinder-1) & 0xff) << 8); /* Low 8 bit to hi bite */
utemp2 = (word)(((starting_cylinder-1) >> 2) & 0xc0); /* Hi 2 bits to bits 6 + 7 */
utemp |= utemp2;
utemp |= (word) pgeometry->dev_geometry_secptrack;
fr_WORD((byte *)&(part.ents[partition_number].e_cyl), utemp);
/* And partition size */
fr_DWORD((byte *)&(part.ents[partition_number].p_size), partition_size);
}
} /* for (partition_number = 0; partition_number < 4;.. */
/* Now for the signature */
fr_WORD((byte *)&(part.signature), 0xAA55);
/* Grab some working space */
buf = pc_scratch_blk();
if (!buf)
{
/* pc_scratch_blk set errno */
return(ret_val);
}
pbuf = buf->data;
rtfs_memset(pbuf, 0, 512);
/* Now copy the partition into a block */
/* The info starts at buf[1be] */
/* Don't use sizeof here since the structure does not pack to exact size */
copybuff((pbuf + 0x1be), &part, 0x42);
/* try the write */
if (!devio_write(driveno, 0, pbuf, 1, TRUE))
{
if (!get_errno())
rtfs_set_errno(PEIOERRORWRITE); /* pc_partition_media: write failed */
}
else
ret_val = TRUE;
pc_free_scratch_blk(buf);
return(ret_val);
}
/***************************************************************************
PC_FORMAT_VOLUME - Format a volume
Description
This routine formats the volume referred to by drive letter.
drive structure is queried to determine if the device is parttioned
or not. If the device is partitioned then the partition table is read
and the volume within the partition is formatted. If it is a non
partitioned device the device is formatted according to the supplied
pgeometry parameters. The pgeometry parameter contains the the media
size in HCN format. It also contains a
Note: The the logical drive must be claimed before this routine is
called and later released by the caller.
Returns
Returns TRUE if it was able to perform the operation otherwise
it returns FALSE.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid
PEIOERRORREADMBR- Partitioned device. IO error reading
PEINVALIDMBR - Partitioned device has no master boot record
PEINVALIDMBROFFSET - Requested partition has no entry in master boot record
PEINVALIDPARMS - Inconsistent or missing parameters
PEIOERRORWRITE - Error writing during format
An ERTFS system error
****************************************************************************/
BOOLEAN pc_format_volume(byte *path, PDEV_GEOMETRY pgeometry) /* __apifn__*/
{
DDRIVE *pdr;
BOOLEAN raw_mode_io = TRUE;
FMTPARMS fmt;
int driveno;
dword partition_size = 0;
dword ltemp;
word n_cyls = 0;
int root_entries;
int secpalloc;
word secpfat;
int root_sectors;
int nibs_per_entry,partition_status;
CHECK_MEM(BOOLEAN, 0)
rtfs_set_errno(0); /* pc_format_volume: clear error status */
/* Make sure it s a valid drive number */
driveno = pc_parse_raw_drive(path);
if (driveno < 0 || !pgeometry)
{
rtfs_set_errno(PEINVALIDDRIVEID); /* pc_format_volume: bad arguments */
return(FALSE);
}
pdr = pc_drno_to_drive_struct(driveno);
/* Check the drive structure for format strategy */
if (!pdr || !(pdr->drive_flags&DRIVE_FLAGS_VALID))
{
rtfs_set_errno(PEINVALIDDRIVEID); /* pc_format_volume: bad arguments */
return(FALSE);
}
/* Make sure all is flushed */
pc_dskfree(driveno);
/* If the format parms were provided by the driver format now */
if (pgeometry->fmt_parms_valid)
{
if( ((pgeometry->fmt.numcyl * pgeometry->fmt.numhead * pgeometry->fmt.secptrk) / pgeometry->fmt.secpalloc) > 0xFFFF) {
return(pc_mkfs32(driveno, &pgeometry->fmt, TRUE)); /* TRUE == RAW IO */ //ctr modified
}else{
return(pc_mkfs16(driveno, &pgeometry->fmt, TRUE)); /* TRUE == RAW IO */
}
}
/* If the device is partitioned read the partition table into the
drive structure.
*/
partition_status = 0;
if (pdr->drive_flags & DRIVE_FLAGS_PARTITIONED)
{
partition_status = pc_read_partition_table(driveno, pdr);
if (partition_status == READ_PARTION_OK)
{
partition_size = pdr->partition_size;
ltemp = partition_size /
(dword)(pgeometry->dev_geometry_heads * pgeometry->dev_geometry_secptrack);
n_cyls = (word) ltemp;
raw_mode_io = FALSE;
}
else if (partition_status != READ_PARTION_NO_TABLE || pdr->partition_number != 0)
{
/* pc_format_volume: errno set to PEDEVICE by pc_read_partition_table */
return(FALSE);
}
}
if (!(pdr->drive_flags & DRIVE_FLAGS_PARTITIONED) || partition_status == READ_PARTION_NO_TABLE)
{
partition_size = (dword) pgeometry->dev_geometry_cylinders;
partition_size = partition_size * (dword) pgeometry->dev_geometry_heads;
partition_size = partition_size * (dword) pgeometry->dev_geometry_secptrack;
n_cyls = (word) pgeometry->dev_geometry_cylinders;
raw_mode_io = TRUE;
}
/* Look up root_entries and cluster size */
get_format_parameters(partition_size, &secpalloc, &root_entries);
if( secpalloc == -1 )
{
/* Media capacity is too large */
rtfs_set_errno(PEDEVICEUNKNOWNMEDIA);
return( FALSE );
}
root_sectors = (int) (root_entries/16);
/* Calculate sectors per fat */
secpfat = pc_fat_size( (word)1 /* reserved */, (word)secpalloc,
(word)2 /*numfats*/, (word)root_sectors /* root sectors */,
partition_size, &nibs_per_entry);
rtfs_strcpy(&fmt.oemname[0],
rtfs_strtab_user_string(USTRING_SYS_OEMNAME) );
fmt.physical_drive_no = (byte) driveno;
fmt.binary_volume_label = BIN_VOL_LABEL;
rtfs_strcpy(fmt.text_volume_label,
rtfs_strtab_user_string(USTRING_SYS_VOLUME_LABEL) );
fmt.secpalloc = (byte) secpalloc;
fmt.numfats = (byte) 2;
fmt.secptrk = (word) pgeometry->dev_geometry_secptrack;
fmt.numhead = (word) pgeometry->dev_geometry_heads;
fmt.numcyl = (word) n_cyls;
if (nibs_per_entry == 8) /* FAT32 Format */
{
fmt.secreserved = (word) 32;
if (pdr->drive_flags & DRIVE_FLAGS_PARTITIONED)
{
if (pgeometry->dev_geometry_lbas)
/* 10-24-2000 - New code to support lba formatting */
fmt.numhide = (unsigned long) 0; /*PS Does not work as fmt.secptrk here */
else
/* 10-24-2000 - This was the original code */
fmt.numhide = (unsigned long) fmt.secptrk;
}
else
fmt.numhide = (unsigned long) pgeometry->fmt.numhide; //ctr modified
fmt.secpfat = (word) 0;
fmt.numroot = (word) 0;
fmt.mediadesc = (byte) 0xF8;
return(pc_mkfs32(driveno, &fmt, raw_mode_io));
}
else
{
fmt.secreserved = (word) 1;
fmt.numhide = pgeometry->fmt.numhide; //ctr modified
fmt.secpfat = (word) secpfat;
fmt.numroot = (word) root_entries;
fmt.mediadesc = (byte) 0xF8;
return(pc_mkfs16(driveno, &fmt, raw_mode_io));
}
}
/*****************************************************************************
PC_MKFS - Make a file system on a disk MS-DOS 4.0 version
Description
Given a drive number and a format parameter block. Put an MS-DOS
file system on the drive:
The disk MUST already have a low level format. All blocks on the drive
should be intitialize with E5s or zeros.
see pcmkfs in the samples directory.
Some common parameters. Note: For other drive types use debug to get the
parameters from block zero after FORMAT has been run.
360 720 20M 80M (DRIVE SIZE)
oemname ===== UP TO YOU. ONLY 8 Chars matter. Right filled with spaces
secpalloc 2 2 4 8
secreserved 1 1 1 1
numfats 2 2 2 2
numroot 0x70 0x70 0x200 0x200
mediadesc 0xFD 0xF9 0xF8 0xF8
secpfat 2 3 44 88
secptrk 9 9 0x11 0x11
numhead 2 2 4 8
numcyl 40 80 612 1224
Note: If pc_mkfs is called secpfat equal zero, secpfat will be calculated
internally.
Returns
Returns TRUE if the filesystem disk was successfully initialized.
See Also:
pcmkfs.c format utility program
****************************************************************************/
word pc_fat_size(word nreserved, word cluster_size, word n_fat_copies,
word root_sectors, dword volume_size,
int *nibs_per_entry) /*__fn__*/
{
dword fat_size;
dword total_clusters;
word entries_per_block;
#if (FAT32)
if ((root_sectors == 0) || ((volume_size>>11) >= 512))/* FAT32 Format */
{
fat_size = (volume_size + 128*cluster_size) / (128*cluster_size + 1);
*nibs_per_entry = 8;
return ((word)fat_size);
}
#endif
/* Calulate total cluster size. Assuming zero size fat:
We round up to the nearest cluster boundary */
total_clusters = volume_size - nreserved - root_sectors;
total_clusters /= cluster_size;
/* Calculate the number of fat entries per block in the FAT. If
< 4087 clusters total the fat entries are 12 bits hence 341
will fit. else 256 will fit
we add in n_fat_copies * 12 here since it take 12 blocks to represent
4087 clusters in 3 nibble form. So we add in the worst case FAT size
here to enhance the accuracy of our guess of the total clusters.
*/
if (total_clusters <= (dword) (4087 + (n_fat_copies * 12)) )
{
entries_per_block = 341;
*nibs_per_entry = 3;
}
else
{
entries_per_block = 256;
*nibs_per_entry = 4;
}
fat_size = (total_clusters + entries_per_block - 1)/entries_per_block;
return((word) fat_size);
}
/* Choose format parameters based on the number of blocks in the volume */
void get_format_parameters(dword nblocks, int *psectors_per_alloc, int *pnum_root_entries)
{
int sectors_per_alloc;
int num_root_entries;
#if (FAT32)
/* FAT12 */
if (nblocks <= 1000) /* <= .5 MEG */
{sectors_per_alloc = 1; num_root_entries = 32;}
else if (nblocks <= 10240) /* <= 5 MEG */
{sectors_per_alloc = 8; num_root_entries = 512;}
else if (nblocks <= 32768) /* <= 16 MEG */
{sectors_per_alloc = 4; num_root_entries = 512;}
/* FAT16 */
else if (nblocks <= 262144) /* <= 128 MEG */
{sectors_per_alloc = 4; num_root_entries = 512;}
else if (nblocks <= 524288) /* <= 256 MEG */
{sectors_per_alloc = 8; num_root_entries = 512;}
else if (nblocks <= 1048576) /* <= 512 MEG */
{sectors_per_alloc = 16; num_root_entries = 512;}
/* FAT32 */
else if (nblocks <= 16777216) /* <= 8 GIG */
{sectors_per_alloc = 8; num_root_entries = 512;}
else if (nblocks <= 33554432) /* <= 16 GIG */
{sectors_per_alloc = 16; num_root_entries = 512;}
else if (nblocks <= 67108864) /* <= 32 GIG */
{sectors_per_alloc = 32; num_root_entries = 512;}
else /* > 32 GIG */
{sectors_per_alloc = 64; num_root_entries = 512;}
#else
/* FAT12 */
if (nblocks <= 1000) /* <= .5 MEG */
{sectors_per_alloc = 1; num_root_entries = 32;}
else if (nblocks <= 10240) /* <= 5 MEG */
{sectors_per_alloc = 8; num_root_entries = 512;}
else if (nblocks <= 32768) /* <= 16 MEG */
{sectors_per_alloc = 4; num_root_entries = 512;}
/* FAT16 */
else if (nblocks <= 262144) /* <= 128 MEG */
{sectors_per_alloc = 4; num_root_entries = 512;}
else if (nblocks <= 524288) /* <= 256 MEG */
{sectors_per_alloc = 8; num_root_entries = 512;}
else if (nblocks <= 1048576) /* <= 512 MEG */
{sectors_per_alloc = 16; num_root_entries = 512;}
else if (nblocks <= 2097152) /* <= 1 GIG */
{sectors_per_alloc = 32; num_root_entries = 512;}
else if (nblocks <= 4194304) /* <= 2 GIG */
{sectors_per_alloc = 64; num_root_entries = 512;}
else /* error */
{sectors_per_alloc = -1; num_root_entries = -1;}
#endif /* (FAT32) */
*psectors_per_alloc = sectors_per_alloc;
*pnum_root_entries = num_root_entries;
}

View File

@ -0,0 +1,188 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* APIGETWD.C - Contains user api level source code.
The following routines are included:
pc_pwd - Get string representation of current working dir.
*/
#include <rtfs.h>
/*****************************************************************************
PC_PWD - Return a string containing the current working directory for
a drive.
Description
Fill in a string with the full path name of the current working directory.
Return FALSE if something went wrong.
If *drive is null or an invalid drive specifier the default drive is used.
Returns
Returns the path name in path. The function returns TRUE on success
no on failure.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid
An ERTFS system error
****************************************************************************/
static BOOLEAN pc_l_pwd(byte *, DROBJ *);
static BOOLEAN pc_gm_name(byte *path, DROBJ *pmom, DROBJ *pdotdot);
BOOLEAN pc_pwd(byte *drive, byte *path) /*__apifn__*/
{
int driveno;
DDRIVE *pdrive;
DROBJ *pobj;
BOOLEAN ret_val;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
ret_val = FALSE;
rtfs_set_errno(0); /* pc_pwd: clear error status */
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(drive);
if (driveno < 0)
{
/* errno was set by check_drive */
goto return_error;
}
/* Find the drive */
pdrive = pc_drno2dr(driveno);
if (pdrive)
{
pobj = pc_get_cwd(pdrive);
/* pc_get_cwd sets errno */
if (pobj)
{
ret_val = pc_l_pwd(path, pobj);
}
}
release_drive_mount(driveno);/* Release lock, unmount if aborted */
return_error: /* Does not have to be an error to get here */
return(ret_val);
}
static BOOLEAN pc_l_pwd(byte *path, DROBJ *pobj) /*__fn__*/
{
#define OBJDEPTH 32
DROBJ *parentlist[OBJDEPTH]; /* List of drobjs to the top */
DROBJ *dotdotlist[OBJDEPTH]; /* List of drobjs to the top */
int objcnt;
BOOLEAN ret_val;
int i;
DROBJ *tpobj;
ret_val = FALSE;
/* If it is the root we are done */
if (pc_isroot(pobj))
{
CS_OP_ASSIGN_ASCII(path,'\\');
CS_OP_INC_PTR(path);
CS_OP_TERM_STRING(path);
pc_freeobj(pobj);
return(TRUE);
}
/* Build a list of drobjs for directories and a drobj for the .. in
the directories */
tpobj = pobj;
/* Zero the object lists in case we terminate incorrectly */
for (objcnt = 0; objcnt < OBJDEPTH; objcnt++)
dotdotlist[objcnt] = parentlist[objcnt] = 0;
for (objcnt = 0; objcnt < OBJDEPTH; objcnt++)
{
/* get dotdot */
tpobj = pc_get_inode(0, tpobj, 0, 0, GET_INODE_DOTDOT);
dotdotlist[objcnt] = tpobj;
if (!tpobj)
goto clean_and_go;
/* Get the parent directory */
tpobj = pc_get_mom(tpobj);
parentlist[objcnt] = tpobj;
if (!tpobj)
goto clean_and_go;
if (pc_isroot(tpobj))
break;
}
if (objcnt >= OBJDEPTH)
{
objcnt = OBJDEPTH-1;
goto clean_and_go;
}
/* Start at the root and work backwards in the list of parents getting
the names. (note: the get name algorithm needs the parent of the
current directory and the .. of the directory */
for (i = objcnt; i >= 0; i--)
{
CS_OP_ASSIGN_ASCII(path,'\\');
CS_OP_INC_PTR(path);
CS_OP_TERM_STRING(path);
if (!pc_gm_name(path , parentlist[i],dotdotlist[i]))
goto clean_and_go;
path = CS_OP_GOTO_EOS(path);
}
ret_val = TRUE;
clean_and_go:
for (i = objcnt; i >= 0; i--)
{
if (parentlist[i])
pc_freeobj(parentlist[i]);
if (dotdotlist[i])
pc_freeobj(dotdotlist[i]);
}
pc_freeobj(pobj);
return(ret_val);
}
static BOOLEAN pc_gm_name(byte *path, DROBJ *parent_obj, DROBJ *pdotdot) /*__fn__*/
{
DROBJ *pchild;
CLUSTERTYPE clusterno;
CLUSTERTYPE fcluster;
BOOLEAN ret_val;
ret_val = FALSE;
clusterno = pc_sec2cluster(pdotdot->pdrive, pdotdot->blkinfo.my_frstblock);
pchild = pc_get_inode(0, parent_obj, 0, 0, GET_INODE_STAR);
if (pchild)
{
do
{
fcluster = pc_finode_cluster(pdotdot->pdrive,pchild->finode);
if (fcluster == clusterno)
{
/* Get a long file name if none revert to the 8.3 name */
if (!pc_get_lfn_filename(pchild,path))
pc_cs_mfile (path, pchild->finode->fname, pchild->finode->fext);
ret_val = TRUE;
break;
}
}
while (pc_get_inode(pchild, parent_obj, 0, 0, GET_INODE_STAR));
}
if (pchild)
{
pc_freeobj(pchild);
}
return(ret_val);
}

View File

@ -0,0 +1,307 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* APIGFRST.C - Contains user api level source code.
The following routines are included:
pc_gfirst - Get stats on the first file to match a pattern.
pc_gnext - Get stats on the next file to match a pattern.
pc_gdone - Free resources used by pc_gfirst/pc_gnext.
pc_upstat - Copy directory entry info to a user s stat buffer
*/
#include <rtfs.h>
/***************************************************************************
PC_GFIRST - Get first entry in a directory to match a pattern.
Description
Given a pattern which contains both a path specifier and a search pattern
fill in the structure at statobj with information about the file and set
up internal parts of statobj to supply appropriate information for calls
to pc_gnext.
Examples of patterns are:
D:\USR\RELEASE\NETWORK\*.C
D:\USR\BIN\UU*.*
D:MEMO_?.*
D:*.*
Returns
Returns TRUE if a match was found otherwise FALSE. (see also the pcls.c
utility.)
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid
PEINVALIDPATH - Path specified badly formed.
PENOENT - Not found, no match
An ERTFS system error
****************************************************************************/
void pc_upstat(DSTAT *statobj);
BOOLEAN pc_gfirst(DSTAT *statobj, byte *name) /*__apifn__*/
{
byte *mompath;
byte *filename;
byte fileext[4];
int driveno;
DDRIVE *pdrive;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
rtfs_set_errno(0); /* po_gfirst: clear error status */
rtfs_memset((byte *) statobj,0,sizeof(*statobj));
/* statobj->pobj = 0; */
/* statobj->pmom = 0; */
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(name);
if (driveno < 0)
{
/* errno was set by check_drive */
return(FALSE);
}
pdrive = pc_drno2dr(driveno);
/* Use the buffers in the DRIVE structure. Access is locked via semaphore */
mompath = (byte *)&(pdrive->pathname_buffer[0]);
filename = (byte *)&(pdrive->filename_buffer[0]);
/* Get out the filename and d:parent */
if (!pc_parsepath(mompath,filename,fileext,name))
{
release_drive_mount(driveno);/* Release lock, unmount if aborted */
rtfs_set_errno(PEINVALIDPATH); /* pc_gfirst: Bad path name */
return(FALSE);
}
/* Save the pattern. we will need it in pc_gnext */
copybuff(statobj->pname, filename, FILENAMESIZE_BYTES);
copybuff(statobj->pext, fileext, 4);
/* Copy over the path. we will need it later */
copybuff(statobj->path, mompath, EMAXPATH_BYTES);
/* Find the file and init the structure */
statobj->pmom = (void *) pc_fndnode(mompath);
/* pc_fndnode will set errno */
if (statobj->pmom)
/* Found it. Check access permissions */
{
if(pc_isadir((DROBJ *)(statobj->pmom)))
{
/* Now find pattern in the directory */
statobj->pobj = (void *) pc_get_inode(0, (DROBJ *)(statobj->pmom), filename, (byte*) fileext, GET_INODE_WILD);
if (statobj->pobj)
{
/* And update the stat structure */
pc_upstat(statobj);
/* remember the drive number. used by gnext et al. */
statobj->driveno = driveno;
/* 9-20-94 release the FINODE and allocate a dummy. This will keep everyone
who expects the drobj to own a finode happy but will not leave the
finode open which locks out unlink et al */
pc_freei(((DROBJ *)(statobj->pobj))->finode); /* Release the current */
((DROBJ *)(statobj->pobj))->finode = pc_alloci();
/* END 9-20-94 */
/* Remember the unique number associated with the drive
mount. If the drive is closed before we call gnext or
gdone we'll know about it because this number won't match */
statobj->drive_opencounter = pdrive->drive_opencounter;
release_drive_mount(driveno);/* Release lock, unmount if aborted */
return(TRUE);
}
else
{
/* pc_gfirst: if statobj->pobj is 0 pc_get_inode() has set errno to PENOENT or
to an internal or IO error status
if PENOENT set we will clear errno */
if (get_errno() == PENOENT)
rtfs_set_errno(0); /* pc_gfirst: file not found in directory
set errno to zero and return FALSE */
}
}
else
rtfs_set_errno(PEINVALIDDIR); /* pc_gfirst: Path not a directory, report not found */
}
/* If it gets here we had a problem */
if (statobj->pmom)
pc_freeobj((DROBJ *)statobj->pmom);
rtfs_memset((byte *) statobj,0,sizeof(*statobj));
release_drive_mount(driveno);/* Release lock, unmount if aborted */
return(FALSE);
}
/****************************************************************************
PC_GNEXT - Get next entry in a directory that matches a pattern.
Description
Given a pointer to a DSTAT structure that has been set up by a call to
pc_gfirst(), search for the next match of the original pattern in the
original path. Return TRUE if found and update statobj for subsequent
calls to pc_gnext.
Returns
Returns TRUE if a match was found otherwise FALSE.
errno is set to one of the following
0 - No error
PEINVALIDPARMS - statobj argument is not valid
PENOENT - Not found, no match (normal termination of scan)
An ERTFS system error
****************************************************************************/
BOOLEAN pc_gnext(DSTAT *statobj) /*__apifn__*/
{
DROBJ *nextobj;
DDRIVE *pdrive;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
/* see if the drive is still mounted. Do not use pmom et al. since they
may be purged */
if (!statobj || !statobj->pmom)
{
rtfs_set_errno(PEINVALIDPARMS); /* pc_gnext: statobj is not valid */
return(FALSE);
}
if (!check_drive_number_mount(statobj->driveno))
return(FALSE);
pdrive = pc_drno2dr(statobj->driveno);
if (statobj->drive_opencounter != pdrive->drive_opencounter)
{
rtfs_set_errno(PEINVALIDPARMS); /* pc_gnext: statobj is not valid */
release_drive_mount(statobj->driveno);/* Release lock, unmount if aborted */
return(FALSE);
}
rtfs_set_errno(0); /* po_gnext: clear error status */
/* Now find the next instance of pattern in the directory */
nextobj = pc_get_inode((DROBJ *)(statobj->pobj), (DROBJ *)(statobj->pmom),
statobj->pname, statobj->pext, GET_INODE_WILD);
if (nextobj)
{
statobj->pobj = (void *)nextobj;
/* And update the stat structure */
pc_upstat(statobj);
/* 9-20-94 release the FINODE and allocate a dummy. This will keep everyone
who expects the drobj to own a finode happy but will not leave the
finode open which locks out unlink et al */
pc_freei(((DROBJ *)(statobj->pobj))->finode); /* Release the current */
((DROBJ *)(statobj->pobj))->finode = pc_alloci();
/* END 9-20-94 */
release_drive_mount(statobj->driveno);/* Release lock, unmount if aborted */
return(TRUE);
}
else
{
if (get_errno() == PENOENT)
rtfs_set_errno(0); /* get_inode: file not found in directory
set errno to zero and return FALSE */
/* pc_gnext: nextobj is 0 pc_get_inode() has set errno to PENOENT or to an internal or IO error status */
release_drive_mount(statobj->driveno);/* Release lock, unmount if aborted */
return(FALSE);
}
}
/***************************************************************************
PC_GDONE - Free internal resources used by pc_gnext and pc_gfirst.
Description
Given a pointer to a DSTAT structure that has been set up by a call to
pc_gfirst() free internal elements used by the statobj.
NOTE: You MUST call this function when done searching through a
directory.
Returns
Nothing
errno is set to one of the following
0 - No error
PEINVALIDPARMS - statobj argument is not valid
****************************************************************************/
void pc_gdone(DSTAT *statobj) /*__apifn__*/
{
DDRIVE *pdrive;
VOID_CHECK_MEM() /* Make sure memory is initted */
/* see if the drive is still mounted. Do not use pmom et al. since they
may be purged */
/* see if the drive is still mounted. Do not use pmom et al. since they
may be purged */
if (!statobj || !statobj->pmom)
{
return;
}
if (!check_drive_number_mount(statobj->driveno))
return;
pdrive = pc_drno2dr(statobj->driveno);
if (statobj->drive_opencounter != pdrive->drive_opencounter)
{
release_drive_mount(statobj->driveno);/* Release lock, unmount if aborted */
return;
}
if (statobj->pobj)
pc_freeobj((DROBJ *)statobj->pobj);
if (statobj->pmom)
pc_freeobj((DROBJ *)statobj->pmom);
release_drive_mount(statobj->driveno);/* Release lock, unmount if aborted */
rtfs_memset((byte *) statobj,0,sizeof(*statobj));
}
/****************************************************************************
PC_UPSTAT - Copy private information to public fields for a DSTAT struc.
Description
Given a pointer to a DSTAT structure that contains a pointer to an
initialized DROBJ structure, load the public elements of DSTAT with
name filesize, date of modification et al. (Called by pc_gfirst &
pc_gnext)
Returns
Nothing
****************************************************************************/
/* Copy internal stuf so the outside world can see it */
void pc_upstat(DSTAT *statobj) /*__fn__*/
{
DROBJ *pobj;
FINODE *pi;
pobj = (DROBJ *)(statobj->pobj);
pi = pobj->finode;
copybuff( statobj->fname, pi->fname, 8);
statobj->fname[8] = CS_OP_ASCII('\0');
copybuff( statobj->fext, pi->fext, 3);
statobj->fext[3] = CS_OP_ASCII('\0');
/* put null termed file.ext into statobj */
pc_ascii_mfile((byte *)statobj->filename, (byte *)statobj->fname,
(byte *)statobj->fext);
statobj->fattribute = pi->fattribute;
statobj->ftime = pi->ftime;
statobj->fdate = pi->fdate;
statobj->fsize = pi->fsize;
/* Get the lfn value for this object. If none available make
sure it is a NULL string in ASCII or UNICODE */
if (!pc_get_lfn_filename(pobj, (byte *)statobj->lfname))
{
statobj->lfname[0] = statobj->lfname[1] = 0;
pc_cs_mfile((byte *)statobj->lfname, (byte *)statobj->fname,
(byte *)statobj->fext);
}
}

View File

@ -0,0 +1,286 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* APIINFO.C - Contains user api level source code.
The following routines are included:
pc_set_default_drive - Set the default drive number.
pc_free - Calculate and return the free space on a disk.
pc_isdir - Determine if a path is a directory.
pc_isvol - Determine if a path is a volume
pc_get_attributes - Get File Attributes
pc_getdfltdrvno - Get the default drive number.
*/
#include <rtfs.h>
/***************************************************************************
PC_SET_DEFAULT_DRIVE - Set the current default drive.
Description
Use this function to set the current default drive that will be used
when a path specifier does not contain a drive specifier.
Note: The default default is zero (drive A:)
Returns
Return FALSE if the drive is out of range.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID - Driveno is incorrect
****************************************************************************/
/* Set the currently stored default drive */
BOOLEAN pc_set_default_drive(byte *drive) /*__apifn__*/
{
int drive_no;
rtfs_set_errno(0); /* pc_set_default_drive: clear error status */
/* get drive no */
drive_no = pc_parse_raw_drive(drive);
if ( ( drive_no < 0) || !pc_validate_driveno(drive_no))
{
rtfs_set_errno(PEINVALIDDRIVEID);/* pc_set_default_drive: invalid argument */
return(FALSE);
}
else
{
rtfs_get_system_user()->dfltdrv_set = 1;
rtfs_get_system_user()->dfltdrv = drive_no;
return(TRUE);
}
}
/****************************************************************************
PC_FREE - Count the number of free bytes remaining on a disk
Description
Given a path containing a valid drive specifier count the number
of free bytes on the drive. The function also takes two additional
argument that point to location that will be loaded with the
total number of blocks on the drive and the total number of
free clusters
Returns
The number of free bytes or zero if the drive is full, -1 if not open,
or out of range.
dword *blocks_total - Contains the total block count
dword *blocks_free - Contain the total count of free blocks.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID - Driveno is incorrect
An ERTFS system error
*****************************************************************************/
/* Return # free bytes on a drive */
long pc_free(byte *path, dword *blocks_total, dword *blocks_free) /*__apifn__*/
{
int driveno;
DDRIVE *pdr;
long bytes_free;
CHECK_MEM(long, 0) /* Make sure memory is initted */
rtfs_set_errno(0); /* po_free: clear error status */
/* assume failure to start */
bytes_free = -1;
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(path);
/* if error check_drive errno was set by check_drive */
if (driveno >= 0)
{
pdr = pc_drno2dr(driveno);
if (!pdr)
{
rtfs_set_errno(PEINVALIDDRIVEID); /* pc_free: no valid drive present */
bytes_free = -1;
}
else
{
*blocks_free = pdr->known_free_clusters;
*blocks_free *= pdr->secpalloc; /* Size of each fat */
*blocks_total = pdr->maxfindex - 1; /* Number of entries in the fat */
*blocks_total *= pdr->secpalloc ; /* Size of each fat */
bytes_free = *blocks_free * 512;
}
release_drive_mount(driveno);/* Release lock, unmount if aborted */
}
return(bytes_free);
}
/*****************************************************************************
PC_ISDIR - Test if a path name is a directory
Description
Test to see if a path specification ends at a subdirectory or a
file.
Note: \ is a directory.
Returns
Returns TRUE if it is a directory.
****************************************************************************/
#define ISDIR 1
#define ISVOL 2
BOOLEAN pc_is(int op, byte *path) /*__fn__*/
{
DROBJ *pobj;
BOOLEAN ret_val = FALSE;
int driveno;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
rtfs_set_errno(0); /* pc_isdir/pc_isvol: clear errno */
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(path);
/* if check_drive failed errno was set by check_drive */
if (driveno >= 0)
{
pobj = pc_fndnode(path);
/* pc_isdir/pc_isvol: if pc_fndnode fails it will set errno */
if (pobj)
{
if (op == ISDIR)
ret_val = pc_isadir(pobj);
else if (op == ISVOL)
ret_val = pc_isavol(pobj);
pc_freeobj(pobj);
}
release_drive_mount(driveno);/* Release lock, unmount if aborted */
}
return (ret_val);
}
/*****************************************************************************
PC_ISDIR - Test if a path name is a directory
Description
Test to see if a path specification ends at a subdirectory.
Returns
Returns TRUE if it is a directory.
errno is set to one of the following
0 - No error
PENOENT - Path not found
An ERTFS system error
****************************************************************************/
BOOLEAN pc_isdir(byte *path) /*__apifn__*/
{
return(pc_is(ISDIR, path));
}
/*****************************************************************************
PC_ISVOL - Test if a path name is a volume entry
Description
Test to see if a path specification ends at a volume label
Returns
Returns TRUE if it is a volume
errno is set to one of the following
0 - No error
PENOENT - Path not found
An ERTFS system error
****************************************************************************/
BOOLEAN pc_isvol(byte *path) /*__apifn__*/
{
return(pc_is(ISVOL, path));
}
/*****************************************************************************
pc_get_attributes - Get File Attributes
Description
Given a file or directory name return the directory entry attributes
associated with the entry.
The following values are returned:
BIT Nemonic
0 ARDONLY
1 AHIDDEN
2 ASYSTEM
3 AVOLUME
4 ADIRENT
5 ARCHIVE
6-7 Reserved
Returns
Returns TRUE if successful otherwise it returns FALSE
errno is set to one of the following
0 - No error
PENOENT - Path not found
An ERTFS system error
****************************************************************************/
BOOLEAN pc_get_attributes(byte *path, byte *p_return) /*__apifn__*/
{
DROBJ *pobj;
BOOLEAN ret_val = FALSE;
int driveno;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
rtfs_set_errno(0); /* pc_get_attributes: clear errno */
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(path);
if (driveno < 0)
{
/* pc_get_attributes: if check_drive failed errno was set by check_drive */
return (FALSE);
}
pobj = pc_fndnode(path);
/* if pc_fndnode fails it will set errno */
if (pobj)
{
*p_return = pobj->finode->fattribute;
pc_freeobj(pobj);
ret_val = TRUE;
}
release_drive_mount(driveno);/* Release lock, unmount if aborted */
return (ret_val);
}
/***************************************************************************
PC_GETDFLTDRVNO - Return the current default drive.
Description
Use this function to get the current default drive when a path specifier
does not contain a drive specifier.
see also pc_setdfltdrvno()
Returns
Return the current default drive.
pc_getdfltdrvno() does not set errno
*****************************************************************************/
/* Return the currently stored default drive */
int pc_getdfltdrvno(void) /*__apifn__*/
{
CHECK_MEM(int, 0) /* Make sure memory is initted */
if (!rtfs_get_system_user()->dfltdrv_set)
return(prtfs_cfg->default_drive_id);
else
return(rtfs_get_system_user()->dfltdrv);
}

View File

@ -0,0 +1,510 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS inc, 1996
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/******************************************************************************
PC_ERTFS_INIT() - Configure ERTFS drive letter/device mapping and initialize
device drivers.
Returns
TRUE If ertfs memory and system resource init functions succeed
FALSE If ertfs memory or system resource init functions fail
The user must modify this code to assign parameters and bind device
driver entry points to ERTFS drive structures. The source code contains
examples for configuring each of the stock device drivers.
This routine initializes ERTFS resources and binds device drivers to drive
letters so it must must be called before any other calls to the ERTFS
API are made.
Device driver configuration block.
The ERTFS drive structure (struct ddrive) contains a section that must be
initialized by the user.
The following fields must be initialized -
register_file_address - IO address pointer that may be used by the
device driver to access the controller. For the stock set of drivers
only the IDE/ATAPI driver use this parameter.
interrupt_number - Interrupt vector number that the controller
will interrupt on.
drive_flags - The user sets bits in this field to tell ERTFS
and the device driver about the drive s properties. The device driver
uses this field to keep track of the device status.
These two bits may be set by the user in the main body of the
the pc_ertfs_init routine.
DRIVE_FLAGS_PARTITIONED - Set this bit if the device is a partitioned
device.
DRIVE_FLAGS_PCMCIA - Set this bit if the device is a pcmcia device.
ERTFS does not look at this bit. It is used ony by the device drivers.
DRIVE_FLAGS_FAILSAFE - Set this bit if you want pc_ertfs_init()
to call pro_failsafe_auto_init for this drive to automatically
enable failsafe operating mode.
Note: pro_failsafe_auto_init() is implemented inside the file
prapifs.c. By default the function automatically fails unless
the prapifs.c is modified and the compile time constant
named INCLUDE_FAILSAFE_AUTO_INIT is set to one. pro_failsafe_auto_init()
as implemented supports only one drive at a time. It places the
device in autorestore, autorecover and autocommit
mode. To change the default behavior or to support more than one device
you must modify the source code.
These bits are set by device driver.
DRIVE_FLAGS_VALID - Set by the driver in the WARMSTART IO Control
call if initialization succeeded. If this flags is not set then ERTFS
will not call the driver again.
DRIVE_FLAGS_FORMAT - Set by the driver in the WARMSTART IO Control
call if the device requires formatting before it may be used. If this flags is set
then ERTFS will format the device during the rtfs_init phase.
DRIVE_FLAGS_REMOVABLE - Set by the device driver init routine if the
device is removable. If this bit is set then the driver must implement
the DEVCTL_CHECKSTATUS ioctrl function.
DRIVE_FLAGS_INSERTED - This bit is used by the device driver to maintain
state information. This bit is used by the PCMCIA drivers in the
following way. The default value is ZERO. If this value is zero when the
check status IOCTRL call is made then the driver attempts to map the
device through the pcmcia controller. The pcmcia management interrupt
routine clears this bit when a card removal occurs.
partition_number - If DRIVE_FLAGS_PARTITIONED is set in the
drive_flags field then this must be initialized with the partition
number. 0,1,2 etc.
pcmcia_slot_number - If DRIVE_FLAGS_PCMCIA is set then this tells which
pcmcia slot. Must be (0 or 1) for the supplied PCMCIA subsystem.
pcmcia_cfg_opt_value - This is the value to be place in the card s
configuration option register by the pcmcia driver after power up.
controller_number - This is set by the user in init and used by
driver to access controller specific information. For example the ide
device driver supports two controllers. This value is used by the driver
to store controller specific data and calculate controller specific
addresses and values.
logical_unit_number - This is a logical unit number that is used only
by the device driver. For example the IDE driver uses logical unit
number 1 to access the slave drive. The floppy disk uses logical
unit 1 to access the secondary floppy.
driveno - This is the drive number that the user wishes ERTFS to access
this device as. 0 = A:, 1 = B: etc.
dev_table_drive_io - This is the io function for the device. The
function must perform the requested read or write operation and
return the correct status (TRUE for success, FALSE for failure).
By example here is the ide drive io function.
BOOLEAN ide_io(driveno, sector, buffer, count, BOOLEAN reading)
int driveno - 0 to prtfs_cfg->cfg_NDRIVES == A:,B:,.. the driver calls
pc_drno_to_drive_struct(driveno) to access the drive structure.
dword sector- Starting sector number to read or write
void *buffer- Buffer to read to write from.
word count - Number of sectors to transfer
reading - True for a read request, False for a write request.
dev_table_perform_device_ioctl - This is the control interface to the
device driver.
By example here is the ide drive io control function.
int ide_perform_device_ioctl(driveno, opcode, pargs)
int driveno - 0 to prtfs_cfg->cfg_NDRIVES == A:,B:,.. the driver calls
pc_drno_to_drive_struct(driveno) to access the drive structure.
int opcode - One of the following:
DEVCTL_CHECKSTATUS
DEVCTL_WARMSTART
DEVCTL_POWER_RESTORE
DEVCTL_POWER_LOSS
DEVCTL_GET_GEOMETRY
DEVCTL_FORMAT
DEVCTL_REPORT_REMOVE
void * pargs - void pointer to arguments. See details below.
Here are detailed descriptions of each OPCODE and its relation
to pargs.
DEVCTL_CHECKSTATUS - Return the status of device. ERTFS calls
the driver with this opcode before it performs IO.
Note: For the CHECKSTATUS call. ERTFS will pass a BOOLEAN value
to the driver to indicate if the volume in question has unwritten
cached data that will be lost if the driver returns anything but
DEVTEST_NOCHANGE. If this value is true then the driver may
make more aggresive efforts to correct media changes. For example
by asking the user to re-insert the correct diskette or card.
The driver must return one of the following values:
DEVTEST_NOCHANGE - The device is available and no media change
has been detected since the previous CHECKSTATUS call.
DEVTEST_NOMEDIA - The device contains no media.
DEVTEST_UNKMEDIA - The device contains media but the driver
can not read or write to it.
DEVTEST_CHANGED - The device is available to but a media change
has been detected since the previous CHECKSTATUS call. ERTFS will
close out the current logical volume and re-mount the device.
DEVCTL_WARMSTART - The device driver is called with this opcode
once at startup. For non removable media the device should verify
that the device is accessable and if so set the DRIVE_FLAGS_VALID
bit. For removable media the device should verify that the device
controller is accessable and if so set the DRIVE_FLAGS_VALID and
DRIVE_FLAGS_REMOVABLE bits. pargs is not used.
DEVCTL_POWER_RESTORE - Tell the device driver that system power
has been restored. The driver should attempt to restore the
device to the "UP" state. ERTFS never calls the driver with this
opcode. System integrators may call it to inform the driver of
power restore. pargs is not used.
DEVCTL_POWER_LOSS - Tell the device driver that system power
has been lost or will soon be lost. The driver should attempt to
go into low power mode. ERTFS never calls the driver with this
opcode. System integrators may call it to inform the driver of
power loss. pargs is not used.
DEVCTL_GET_GEOMETRY - ERTFS calls this routine to get the values
it will use to partition and format volumes.
pargs points to a structure of type DEV_GEOMETRY. The driver
should fill in the values as defined below.
typedef struct dev_geometry {
- Geometry in HCN format
int dev_geometry_heads; - Must be < 256
int dev_geometry_cylinders; - Must be < 1024
int dev_geometry_secptrack; - Must be < 64
BOOLEAN fmt_parms_valid; If the device io control call sets
this TRUE then it it telling the
the format parameters are valid
and should be used. This is a way to
format floppy disks exactly as they
are formatted by dos.
FMTPARMS fmt;
} DEV_GEOMETRY;
DEVCTL_FORMAT - ERTFS calls this routine to physically
format the device. pargs points to the DEV_GEOMETRY structure
that was returned from the GET_GEOMETRY call. The device driver
should physically format the device if needed.
DEVCTL_REPORT_REMOVE - This can be called by an external
interrupt to tell the driver that the device has been removed.
The pcmcia management interrupt calls this and the pcmcia aware
drivers, PCMSRAM.C and IDE_DRV.C, clear the DRIVE_FLAGS_INSERTED
bit in the drive structure. They later query this from the
CHECKSTATUS code. pargs is not used.
*/
#include <twl.h>
#include <rtfs_target_os.h> /* twl modified */
//#include <ctr/rtc/rtc.h> /* ctr modified */
#include <rtfs.h>
#include <portconf.h> /* For included devices */
/*ctr modified(delete prototype definition of the all driver here.)*/
int auto_format_disk(DDRIVE *pdr, byte *drivename);
void drno_to_string(byte *pname, int drno);
void print_device_names(void);
#if (STORE_DEVICE_NAMES_IN_DRIVE_STRUCT)
/*ctr modified*/
#define STORE_DEVICE_NAME(NAME) rtfs_strcpy(current_pdr->device_name, (byte *)NAME);
#else
#define STORE_DEVICE_NAME(NAME)
#endif
/*------------------ctr modified start------------------*/
//BOOLEAN i_rtfs_begin_attach( void);
BOOLEAN i_rtfs_attach( int driveno, DDRIVE* pdr, char* dev_name);
BOOLEAN i_rtfs_end_attach( void);
extern BOOLEAN rtfs_first_attach; //attach.cのattach APIがまだ未使用ならTRUE
int enabled_drivers;
DDRIVE* current_pdr;
BOOLEAN rtfs_init( void)
{
int j;
DDRIVE* pdr;
/* Call the user supplied configuration function */
prtfs_cfg = 0;
/* pc_ertfs_init: Can't used rtfs_set_errno(p_errno); */
if (!pc_ertfs_config()) /*apicnfig.c*/
{
return(FALSE);
}
if (!pc_memory_init()) /*rtkernfn.c*/
{
return(FALSE);
}
/* Allocate semaphores for all drives here and assign them to the
drive structures. If an allocation fails, fail to initialize */
pdr = prtfs_cfg->mem_drives_structures;
for (j = 0; j < prtfs_cfg->cfg_NDRIVES; j++, pdr++)
{
/* make sure this drive has a semaphore associated with it */
pdr->access_semaphore = rtfs_port_alloc_mutex();
if (!pdr->access_semaphore)
return(FALSE);
}
/*---------- ctr modified ----------*/
for( j=0; j<26; j++) {
prtfs_cfg->drno_to_dr_map[j] = 0;
}
/*----------------------------------*/
enabled_drivers = 0;
current_pdr = prtfs_cfg->mem_drives_structures;
rtfs_first_attach = FALSE; //ctr modified
// RTCの初期化
// OSAPI_RTCINIT(); //ctr modified
return( TRUE);
}
/*--- ctr modified ---*/
/*SDK_WEAK_SYMBOL BOOL rtcInit( void)
{
return( FALSE);
}*/
/*--------------------*/
/*---------------------------------------------------------------------------*
Name: rtfs_attach
Description:
Arguments: driveno :
Returns:
*---------------------------------------------------------------------------*/
SDK_WEAK_SYMBOL BOOLEAN i_rtfs_attach( int driveno, DDRIVE* pdr, char* dev_name)
{
return( FALSE);
/* if (++enabled_drivers > prtfs_cfg->cfg_NDRIVES) {
osTPrintf( "%d / %d\n", enabled_drivers, prtfs_cfg->cfg_NDRIVES);
return( FALSE);
}
current_pdr->driveno = driveno;
current_pdr->dev_table_drive_io = pdr->dev_table_drive_io;
current_pdr->dev_table_perform_device_ioctl = pdr->dev_table_perform_device_ioctl;
STORE_DEVICE_NAME(dev_name)
current_pdr->register_file_address = pdr->register_file_address;
current_pdr->interrupt_number = pdr->interrupt_number;
current_pdr->drive_flags = pdr->drive_flags;
current_pdr->partition_number = pdr->partition_number;
current_pdr->pcmcia_slot_number = pdr->pcmcia_slot_number;
current_pdr->controller_number = pdr->controller_number;
current_pdr->logical_unit_number = pdr->logical_unit_number;
current_pdr++;
return( TRUE);*/
}
/*---------------------------------------------------------------------------*
Name: rtfs_detach
Description:
Arguments: driveno :
Returns:
*---------------------------------------------------------------------------*/
/*BOOLEAN rtfs_detach( int driveno)
{
DDRIVE *target_pdr;
target_pdr = prtfs_cfg->drno_to_dr_map[pdr->driveno];
if( target_pdr->dev_table_drive_io == default_pdr->dev_table_drive_io) {
return( FALSE); //既にdetach済み
}
target_pdr->driveno = driveno;
target_pdr->dev_table_drive_io = default_pdr->dev_table_drive_io;
target_pdr->dev_table_perform_device_ioctl = default_pdr->dev_table_perform_device_ioctl;
rtfs_strcpy(target_pdr->device_name, (byte *)"DEFAULT\0"); //STORE_DEVICE_NAME(dev_name)
target_pdr->register_file_address = default_pdr->register_file_address;
target_pdr->interrupt_number = default_pdr->interrupt_number;
target_pdr->drive_flags = default_pdr->drive_flags;
target_pdr->partition_number = default_pdr->partition_number;
target_pdr->pcmcia_slot_number = default_pdr->pcmcia_slot_number;
target_pdr->controller_number = default_pdr->controller_number;
target_pdr->logical_unit_number = default_pdr->logical_unit_number;
return( TRUE);
}*/
BOOLEAN i_rtfs_end_attach( void)
{
// current_pdr = prtfs_cfg->mem_drives_structures;
return( FALSE);
}
/*----------------ctr modified end---------------*/
BOOLEAN pc_ertfs_init(void) /* __apifn__ */
{
int j;
DDRIVE *pdr;
//int drives_used;
byte drname[8]; /* Temp buffer for displaying drive letters as strings */
int default_drive;
if( rtfs_first_attach == FALSE) { return( TRUE); } //ctr modified
pdr = prtfs_cfg->mem_drives_structures;
// drives_used = 0;
//ctr modified : erase attach codes of some drivers here.
/* End User initialization section */
print_device_names();
pdr= prtfs_cfg->mem_drives_structures;
default_drive = 27; /* greater than maximum legal value */
for (j = 0; j < prtfs_cfg->cfg_NDRIVES; j++, pdr++)
{
if (pdr->dev_table_drive_io)
{
prtfs_cfg->drno_to_dr_map[pdr->driveno] = pdr; /* MAPS DRIVE structure to DRIVE: */
if (pdr->dev_table_perform_device_ioctl(pdr->driveno, DEVCTL_WARMSTART, (void *) 0) != 0)
{
prtfs_cfg->drno_to_dr_map[pdr->driveno] = 0; /* It is not there. */
/* so forget it */
continue;
}
#if (INCLUDE_FAILSAFE_CODE)
/* Call the the ertfs pro failsafe autoinit function */
if (pdr->drive_flags&DRIVE_FLAGS_FAILSAFE)
{
if (!pro_failsafe_auto_init(pdr)) //マニュアル参照
{
prtfs_cfg->drno_to_dr_map[pdr->driveno] = 0; /* Forget it, not there. */
continue;
}
}
#endif
/* Set the default drive to the lowest assigned drive letter */
if (pdr->driveno < default_drive)
{
default_drive = pdr->driveno;
}
}
}
/* If there are no valid devices return failure
otherwise use the lowest valid drive id as the system's default drive*/
if (default_drive == 27)
return(FALSE);
prtfs_cfg->default_drive_id = default_drive;
RTFS_PRINT_STRING_1(USTRING_RTFSINIT_05,PRFLG_NL); /* "Autoformatting RAM Devices\n" */
RTFS_PRINT_STRING_1(USTRING_RTFSINIT_06,PRFLG_NL); /* "==========================\n" */
pdr= prtfs_cfg->mem_drives_structures;
for (j = 0; j < prtfs_cfg->cfg_NDRIVES; j++, pdr++)
{
if ( pdr->drive_flags&DRIVE_FLAGS_VALID && pdr->drive_flags&DRIVE_FLAGS_FORMAT)
{
OS_CLAIM_LOGDRIVE(pdr->driveno) /* Autoformat Register drive in use */
drno_to_string(drname, pdr->driveno);
RTFS_PRINT_STRING_2(USTRING_RTFSINIT_07, drname,0); /* "Autoformatting Drive Id - " */
#if (STORE_DEVICE_NAMES_IN_DRIVE_STRUCT)
RTFS_PRINT_STRING_2(USTRING_RTFSINIT_08, pdr->device_name,PRFLG_NL); /* " as Device: " */
#endif
if (auto_format_disk(pdr, drname) != 0)
{
RTFS_PRINT_STRING_2(USTRING_RTFSINIT_09, drname,PRFLG_NL); /* "Autoformatting Drive Id - \n" */
}
OS_RELEASE_LOGDRIVE(pdr->driveno) /* Autoformat release */
}
}
RTFS_PRINT_STRING_1(USTRING_RTFSINIT_10, PRFLG_NL); /* " = " */
return(TRUE);
need_more_drives:
RTFS_PRINT_STRING_1(USTRING_RTFSINIT_11, PRFLG_NL); /* "NDRIVES is too small to mount all devices" */
return(FALSE);
}
int auto_format_disk(DDRIVE *pdr, byte *drivename)
{
DEV_GEOMETRY geometry;
/* check media and clear change conditions */
if (!check_drive_number_present(pdr->driveno))
return(-1);
/* This must be called before calling the later routines */
if (!pc_get_media_parms(drivename, &geometry))
return(-1);
/* Call the low level media format. Do not do this if formatting a
volume that is the second partition on the drive */
if (!pc_format_media(drivename, &geometry))
return(-1);
if (!pc_format_volume(drivename, &geometry))
return(-1);
return (0);
}
void drno_to_string(byte *pname, int drno)
{
byte c,*p;
p = pname;
c = (byte) ('A' + drno);
CS_OP_ASSIGN_ASCII(p,c);
CS_OP_INC_PTR(p);
CS_OP_ASSIGN_ASCII(p,':');
CS_OP_INC_PTR(p);
CS_OP_TERM_STRING(p);
}
void print_device_names(void)
{
int j;
DDRIVE *pdr;
byte drname[8];
RTFS_PRINT_STRING_1(USTRING_RTFSINIT_01,PRFLG_NL); /* "ERTFS Device List" */
RTFS_PRINT_STRING_1(USTRING_RTFSINIT_02,PRFLG_NL); /* "=================" */
#if (!STORE_DEVICE_NAMES_IN_DRIVE_STRUCT)
RTFS_PRINT_STRING_1(USTRING_RTFSINIT_03,PRFLG_NL); /* "Name Logging Disabled" */
#else
pdr = prtfs_cfg->mem_drives_structures;
for (j = 0; j < prtfs_cfg->cfg_NDRIVES; j++, pdr++)
{
if (pdr->dev_table_drive_io)
{
drno_to_string(drname, pdr->driveno);
RTFS_PRINT_STRING_2(USTRING_RTFSINIT_12, pdr->device_name,0); /* "Device name : " */
RTFS_PRINT_STRING_2(USTRING_RTFSINIT_13, drname,PRFLG_NL); /* " Is mounted on " */
}
}
RTFS_PRINT_STRING_1(USTRING_RTFSINIT_04,PRFLG_NL); /* " = " */
#endif
}

View File

@ -0,0 +1,307 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* APIMKDIR.C - Contains user api level source code.
The following routines are included:
pc_mkdir - Create a directory.
pc_rmdir - Delete a directory.
*/
#include <rtfs.h>
/***************************************************************************
PC_MKDIR - Create a directory.
Description
Create a sudirectory in the path specified by name. Fails if a
file or directory of the same name already exists or if the path
is not found.
Returns
Returns TRUE if it was able to create the directory, otherwise
it returns FALSE.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid
PEINVALIDPATH - Path specified badly formed.
PENOENT - Path to new directory not found
PEEXIST - File or directory of this name already exists
An ERTFS system error
****************************************************************************/
BOOLEAN pc_mkdir(byte *name) /*__apifn__*/
{
DROBJ *pobj;
DROBJ *parent_obj;
byte *path;
byte *filename;
byte fileext[4];
BOOLEAN ret_val;
int driveno;
DDRIVE *pdrive;
int p_errno;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
parent_obj = 0;
pobj = 0;
p_errno = 0;
ret_val = FALSE;
rtfs_set_errno(0); /* pc_mkdir: clear error status */
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(name);
if (driveno < 0)
{
/* errno was set by check_drive */
return(FALSE);
}
pdrive = pc_drno2dr(driveno);
/* Use the buffers in the DRIVE structure. Access is locked via semaphore */
path = (byte *)&(pdrive->pathname_buffer[0]);
filename = (byte *)&(pdrive->filename_buffer[0]);
/* Get out the filename and d:parent */
if (!pc_parsepath(path,filename,fileext,name))
{
p_errno = PEINVALIDPATH;
goto errex;
}
/* Find the parent and make sure it is a directory \ */
/* pc_fndnode set errno */
parent_obj = pc_fndnode(path);
if (!parent_obj)
goto errex;
/* Lock the parent */
if (!pc_isadir(parent_obj) || pc_isavol(parent_obj))
{
p_errno = PENOENT; /* Path is not a directory */
goto errex;
}
/* Fail if the directory exists */
pobj = pc_get_inode(0, parent_obj, filename,(byte*) fileext, GET_INODE_MATCH);
if (pobj)
{
p_errno = PEEXIST; /* Exclusive fail */
goto errex;
}
else
{
if (get_errno() != PENOENT) /* If pobj is NULL we abort on abnormal errors */
goto errex;
rtfs_set_errno(0); /* pc_mkdir: clear PENOENT error status */
pobj = pc_mknode( parent_obj,filename, fileext, ADIRENT, 0);
if (pobj)
{
p_errno = 0;
ret_val = TRUE;
}
else
{
/* pc_mknode has set errno */
goto errex;
}
}
errex:
if (pobj)
pc_freeobj(pobj);
if (parent_obj)
{
pc_freeobj(parent_obj);
}
if (p_errno)
rtfs_set_errno(p_errno);
/*---------- ctr modified ----------*/
if( pdrive) {
if( pdrive->dev_table_perform_device_ioctl) {
pdrive->dev_table_perform_device_ioctl( driveno,
DEVCTL_FLUSH,
NULL);
}
}
/*----------------------------------*/
if (!release_drive_mount_write(driveno))/* Release lock, unmount if aborted */
ret_val = FALSE;
return(ret_val);
}
/****************************************************************************
PC_RMDIR - Delete a directory.
Description
Delete the directory specified in name. Fail if name is not a directory,
is read only or contains more than the entries . and ..
Returns
Returns TRUE if the directory was successfully removed.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid
PEINVALIDPATH - Path specified badly formed.
PENOENT - Directory not found
PEACCESS - Directory is in use or is read only
An ERTFS system error
*****************************************************************************/
/* Remove a directory */
BOOLEAN pc_rmdir(byte *name) /*__apifn__*/
{
DROBJ *parent_obj;
DROBJ *pobj;
DROBJ *pchild;
BOOLEAN ret_val;
byte *path;
byte *filename;
byte fileext[4];
int driveno;
DDRIVE *pdrive;
int p_errno;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
parent_obj = 0;
pchild = 0;
pobj = 0;
rtfs_set_errno(0); /* pc_rmdir: clear error status */
ret_val = FALSE;
p_errno = 0;
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(name);
if (driveno < 0)
{
/* errno was set by check_drive */
return(FALSE);
}
pdrive = pc_drno2dr(driveno);
/* Use the buffers in the DRIVE structure. Access is locked via semaphore */
path = (byte *)&(pdrive->pathname_buffer[0]);
filename = (byte *)&(pdrive->filename_buffer[0]);
/* Get out the filename and d:parent */
if (!pc_parsepath(path,filename,fileext,name))
{
p_errno = PEINVALIDPATH;
goto errex;
}
/* Don't allow removal of . or .. PEACCES (by definition we are busy */
if (pc_isdot(filename,fileext) || pc_isdotdot(filename,fileext))
{
p_errno = PEACCES;
goto errex;
}
/* Find the parent and make sure it is a directory \ */
parent_obj = pc_fndnode(path);
if (!parent_obj)
goto errex; /* pc_fndnode set errno */
if (!pc_isadir(parent_obj))
{
p_errno = PEACCES;
goto errex;
}
/* Find the file and init the structure */
pobj = pc_get_inode(0, parent_obj, filename, (byte*)fileext,GET_INODE_MATCH);
if (!pobj)
{
/* pc_get_inode() has set errno to PENOENT or to an internal or IO error status */
goto errex;
}
if ( !pc_isadir(pobj) || (pobj->finode->opencount > 1) ||
(pobj->finode->fattribute & ARDONLY ))
{
p_errno = PEACCES;
goto errex;
}
/* Search through the directory. look at all files */
/* Any file that is not . or .. is a problem */
/* Call pc_get_inode with 0 to give us an obj */
pchild = pc_get_inode(0, pobj, 0, 0, GET_INODE_STAR);
if (pchild)
{
do
{
if (!(pc_isdot(pchild->finode->fname, pchild->finode->fext) ) )
if (!(pc_isdotdot(pchild->finode->fname, pchild->finode->fext) ) )
{
p_errno = PEACCES;
ret_val = FALSE;
goto errex;
}
}
while (pc_get_inode(pchild, pobj, 0, 0, GET_INODE_STAR));
}
/* If either of the above calls to pc_get_inode() failed due to
an error other than PENOENT then we have an error condition
Continue if the error was PEINVALIDCLUSTER that means that
the chain is corrupted. In this case proceed to delete the
directory too
*/
p_errno = get_errno();
if (!p_errno || (p_errno == PENOENT)) /* normal scan termination */
{
p_errno = 0;
rtfs_set_errno(0); /* Clear errno so others can use it */
ret_val = pc_rmnode(pobj);
}
else if (p_errno == PEINVALIDCLUSTER) /* termination because of bad
cluster */
{
/* Clear p_errno, errno is already PEINVALIDCLUSTER, if rmnode
overwrites errno that will be the value, otherwise rmnode and
children will set errno to another value */
p_errno = 0;
pc_rmnode(pobj);
ret_val = FALSE;
}
else /* Scan terminated due to IO error or internal error */
ret_val = FALSE;
errex:
if (pchild)
pc_freeobj(pchild);
if (pobj)
pc_freeobj(pobj);
if (parent_obj)
pc_freeobj(parent_obj);
if (p_errno)
rtfs_set_errno(p_errno);
/*---------- ctr modified ----------*/
if( pdrive) {
if( pdrive->dev_table_perform_device_ioctl) {
pdrive->dev_table_perform_device_ioctl( driveno,
DEVCTL_FLUSH,
NULL);
}
}
/*----------------------------------*/
if (!release_drive_mount_write(driveno))/* Release lock, unmount if aborted */
ret_val = FALSE;
return(ret_val);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,146 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* APISETCWD.C - Contains user api level source code.
The following routines are included:
pc_set_cwd - Set the current working directory.
*/
#include <rtfs.h>
/***************************************************************************
PC_SET_CWD - Set the current working directory for a drive.
Description
Find path. If it is a subdirectory make it the current working
directory for the drive.
Returns
Returns TRUE if the current working directory was changed.
errno is set to one of the following
0 - No error
PEINVALIDPATH - Path specified badly formed.
PENOENT - Path not found
PEINVALIDDIR - Not a directory
An ERTFS system error
****************************************************************************/
BOOLEAN pc_set_cwd(byte *name) /* __apifn__ */
{
DROBJ *pobj;
int driveno;
DDRIVE *pdrive;
DROBJ *parent_obj;
byte fileext[4];
byte *path, *pfilename,*pfilename_plus_1, *pfileext;
BOOLEAN ret_val;
int p_errno;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
rtfs_set_errno(0); /* pc_set_cwd: clear error status */
ret_val = FALSE;
p_errno = 0;
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(name);
if (driveno < 0)
{ /* errno was set by check_drive */
return(FALSE);
}
pdrive = pc_drno2dr(driveno);
/* Use the buffers in the DRIVE structure. Access is locked via semaphore */
pfilename_plus_1 = pfilename = (byte *)&(pdrive->filename_buffer[0]);
pfileext = &fileext[0];
CS_OP_INC_PTR(pfilename_plus_1);
path = (byte *)&(pdrive->pathname_buffer[0]);
/* Get out the filename and d:parent */
if (!pc_parsepath(path, pfilename,pfileext,name))
{
p_errno = PEINVALIDPATH;
goto errex;
}
/* Find the parent and make sure it is a directory */
parent_obj = pc_fndnode(path);
if (!parent_obj)
goto errex; /* pc_fndnode set errno */
if (!pc_isadir(parent_obj))
{
p_errno = PEACCES; /* Path is not a directory */
goto errex;
}
/* Get the directory */
if (CS_OP_CMP_ASCII(pfilename,'\0') || CS_OP_CMP_ASCII(pfilename,' '))
{
pobj = parent_obj;
}
else if (CS_OP_CMP_ASCII(pfilename,'.') && CS_OP_CMP_ASCII(pfilename_plus_1,'.'))
{
if (pc_isroot(parent_obj))
pobj = parent_obj;
else
{
pobj = pc_get_inode(0, parent_obj, 0, 0, GET_INODE_DOTDOT);
/* If the request is cd .. then we just found the .. directory entry
we have to call get_mom to access the parent. */
pc_freeobj(parent_obj);
if (!pobj) /* pc_get_inode() has set errno to PENOENT or to an internal or IO error status */
goto errex;
parent_obj = pobj;
/* Find parent_objs parent. By looking back from .. */
pobj = pc_get_mom(parent_obj);
pc_freeobj(parent_obj);
if (!pobj)
{ /* if pc_get_mom() set errno, use it otherwise set PENOENT */
if (!get_errno())
p_errno = PENOENT; /* Not found */
goto errex;
}
}
}
else if (CS_OP_CMP_ASCII(pfilename,'.'))
{
pobj = parent_obj;
}
else
{
pobj = pc_get_inode(0, parent_obj, pfilename, pfileext, GET_INODE_MATCH);
pc_freeobj(parent_obj);
}
if (!pobj)
{
/* pc_get_inode set errno */
goto errex;
}
else if (!pc_isadir(pobj))
{
pc_freeobj(pobj);
p_errno = PEINVALIDDIR; /* Path is not a directory */
goto errex;
}
driveno = pobj->pdrive->driveno;
if (rtfs_get_system_user()->lcwd[driveno] != 0)
pc_freeobj((DROBJ *)(rtfs_get_system_user()->lcwd[driveno]));
rtfs_get_system_user()->lcwd[driveno] = (void *) pobj;
ret_val = TRUE;
errex:
release_drive_mount(driveno);/* Release lock, unmount if aborted */
if (p_errno)
rtfs_set_errno(p_errno);
return(ret_val);
}

View File

@ -0,0 +1,194 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* APISTAT.C - Contains user api level source code.
The following routines are included:
pc_fstat - Obtain statistics on an open file
pc_stat - Obtain statistics on a path.
*/
#include <rtfs.h>
void pc_finode_stat(FINODE *pi, ERTFS_STAT *pstat); /*__fn__*/
/****************************************************************************
PS_FSTAT - Obtain statistics on an open file
Description
Fills in the stat buffer for information about an open file.
See pc_stat for a description of the stat buffer.
Returns
Returns 0 if all went well otherwise it returns -1
errno is set to one of the following
0 - No error
PEBADF - Invalid file descriptor
****************************************************************************/
int pc_fstat(PCFD fd, ERTFS_STAT *pstat) /*__apifn__*/
{
PC_FILE *pfile;
CHECK_MEM(int, -1) /* Make sure memory is initted */
rtfs_set_errno(0); /* pc_fstat: clear error status */
/* Get the file structure and semaphore lock the drive */
pfile = pc_fd2file(fd, 0);
if (!pfile)
{ /* fd2file set errno */
return(-1);
}
else
{
/* cal pc_finode_stat() to update the stat structure */
pc_finode_stat(pfile->pobj->finode, pstat);
release_drive_mount(pfile->pobj->pdrive->driveno);/* Release lock, unmount if aborted */
return(0);
}
}
/****************************************************************************
PC_STAT - Obtain statistics on a path.
Description
This routine searches for the file or directory provided in the first
argument. If found it fills in the stat structure as described here.
st_dev - The entry s drive number
st_mode;
S_IFMT type of file mask
S_IFCHR character special (unused)
S_IFDIR directory
S_IFBLK block special (unused)
S_IFREG regular (a file)
S_IWRITE Write permitted
S_IREAD Read permitted.
st_rdev - The entry s drive number
st_size - file size
st_atime - creation date in DATESTR format
st_mtime - creation date in DATESTR format
st_ctime - creation date in DATESTR format
t_blksize - optimal blocksize for I/O (cluster size)
t_blocks - blocks allocated for file
fattributes - The DOS attributes. This is non-standard but supplied
if you want to look at them
Returns
Returns 0 if all went well otherwise it returns -1.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid
PENOENT - File or directory not found
An ERTFS system error
****************************************************************************/
int pc_stat(byte *name, ERTFS_STAT *pstat) /*__apifn__*/
{
DROBJ *pobj;
int driveno;
int ret_val;
CHECK_MEM(int, -1) /* Make sure memory is initted */
rtfs_set_errno(0); /* pc_stat: clear error status */
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(name);
if (driveno < 0)
{ /* errno was set by check_drive */
return(-1);
}
/* pc_fndnode will set errno */
pobj = pc_fndnode(name);
if (pobj)
{
if (pobj->isroot)
{
pstat->st_rdev =
pstat->st_dev = pobj->finode->my_drive->driveno;
pstat->st_ino = 0;
pstat->fattribute = ADIRENT;
pstat->st_mode = S_IFDIR;
pstat->st_nlink = 1; /* (always 1) */
pstat->st_size = 0; /* file size, in bytes */
pstat->st_atime.date = pstat->st_atime.time = 0;
pstat->st_mtime = pstat->st_atime; /* last modification */
pstat->st_ctime = pstat->st_atime; /* last status change */
pstat->st_blksize = (dword) pobj->finode->my_drive->bytespcluster;
pstat->st_blocks = (dword) ((pobj->finode->fsize + 511)>>9);
}
else
{
/* cal pc_finode_stat() to update the stat structure */
pc_finode_stat(pobj->finode, pstat);
}
ret_val = 0;
}
else
ret_val = -1;
if (pobj)
pc_freeobj(pobj);
release_drive_mount(driveno);/* Release lock, unmount if aborted */
return(ret_val);
}
/****************************************************************************
PC_FINODE_STAT - Convert finode information to stat info for stat and fstat
Description
Given a pointer to a FINODE and a ERTFS_STAT structure
load ERTFS_STAT with filesize, date of modification et al. Interpret
the fattributes field of the finode to fill in the st_mode field of the
the stat structure.
Returns
Nothing
****************************************************************************/
void pc_finode_stat(FINODE *pi, ERTFS_STAT *pstat) /*__fn__*/
{
pstat->st_dev = pi->my_drive->driveno; /* (drive number, rtfs) */
pstat->st_ino = 0; /* inode number (0) */
pstat->st_mode = 0; /* (see S_xxxx below) */
/* Store away the DOS file attributes in case someone needs them */
pstat->fattribute = pi->fattribute;
pstat->st_mode |= S_IREAD;
if(!(pstat->fattribute & ARDONLY))
pstat->st_mode |= S_IWRITE;
if (pstat->fattribute & ADIRENT)
pstat->st_mode |= S_IFDIR;
if (!(pstat->fattribute & (AVOLUME|ADIRENT)))
pstat->st_mode |= S_IFREG;
pstat->st_nlink = 1; /* (always 1) */
pstat->st_rdev = pstat->st_dev; /* (drive number, rtfs) */
pstat->st_size = pi->fsize; /* file size, in bytes */
pstat->st_atime.date = pi->fdate; /* last access */
pstat->st_atime.time = pi->ftime;
pstat->st_mtime = pstat->st_atime; /* last modification */
pstat->st_ctime = pstat->st_atime; /* last status change */
/* optimal buffering size. is a cluster */
pstat->st_blksize = (dword) pi->my_drive->bytespcluster;
/* blocks is file size / 512. with round up */
pstat->st_blocks = (dword) ((pi->fsize + 511)>>9);
}

View File

@ -0,0 +1,828 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* APIWRITE.C - Contains user api level file IO source code.
The following routines are included:
po_write - Write Bytes to a file.
po_flush - Flush an open file
po_trunc - Truncate an open file
pc_set_attributes - Set File Attributes
pc_diskflush - Flush the FAT and all files on a disk
*/
#include <rtfs.h>
/***************************************************************************
PO_WRITE - Write to a file.
Description
Attempt to write count bytes from buf to the current file pointer of file
at fd. The file pointer is updated.
Returns
Returns the number of bytes written or -1 on error.
errno is set to one of the following
0 - No error
PEBADF - Invalid file descriptor
PEACCES - File is read only
PEIOERRORWRITE - Error performing write
PEIOERRORREAD - Error reading block for merge and write
PENOSPC - Disk full
An ERTFS system error
****************************************************************************/
int po_write(PCFD fd, byte *in_buff, int count) /*__apifn__*/
{
PC_FILE *pfile;
DDRIVE *pdrive;
dword block_in_cluster;
dword byte_offset_in_block;
dword n_blocks_left;
dword n_to_write, n_w_to_write;
CLUSTERTYPE next_cluster;
CLUSTERTYPE n_clusters;
dword ltemp;
int n_bytes;
int n_written;
int n_left;
dword alloced_size;
dword block_to_write;
int end_of_chain;
BOOLEAN extending_file;
int ret_val;
int p_errno;
CHECK_MEM(int, -1) /* Make sure memory is initted */
/* Return 0 (none written) on bad args */
if (!count)
return(0);
p_errno = 0;
rtfs_set_errno(0); /* po_write: clear error status */
/* Get the FILE. must be open for write */
/* Get the file structure and semaphore lock the drive */
pfile = pc_fd2file(fd, PO_WRONLY|PO_RDWR);
if (!pfile)
{ /* fd2file set errno */
ret_val = -1;
goto return_unlocked;
}
pdrive = pfile->pobj->pdrive;
/* Only one process may write at a time */
/* if the file is zero sized make sure the current cluster pointer
is invalid */
if (!pfile->pobj->finode->fsize)
pfile->fptr_cluster = 0;
/* Round the file size up to its cluster size by adding in clustersize-1
and masking off the low bits */
alloced_size = (pfile->pobj->finode->fsize + pdrive->byte_into_cl_mask) &
~(pdrive->byte_into_cl_mask);
if (alloced_size < pfile->pobj->finode->fsize)
alloced_size = 0xffffffff;
/* Set the cluster and block file pointers if not already set */
if (!_synch_file_ptrs(pfile))
{ /* _synch_file_ptrs set errno */
ret_val = -1;
goto return_locked;
}
/* Seek to the end if append mode */
if (pfile->flag & PO_APPEND)
{
if (pfile->pobj->finode->fsize)
{
if (!_po_ulseek(pfile, 0L, &ltemp, PSEEK_END))
{ /* po_ulseek will set error status */
ret_val = -1;
goto return_locked;
}
if (!_synch_file_ptrs(pfile))
{ /* _synch_file_ptrs set errno */
ret_val = -1;
goto return_locked;
}
}
}
/* Check if this write will wrap past 4 Gigabytes
if so truncate the count to 4 Gig minus 1*/
ltemp = pfile->fptr + count;
if (ltemp < pfile->fptr)
{
#if (RTFS_TRUNCATE_WRITE_TO_MAX)
ltemp = 0xffffffff;
count = ltemp - pfile->fptr;
#else
p_errno = PETOOLARGE;
ret_val = -1;
goto return_locked;
#endif
}
if (ltemp > RTFS_MAX_FILE_SIZE)
{
#if (RTFS_TRUNCATE_WRITE_TO_MAX)
ltemp = RTFS_MAX_FILE_SIZE;
count = ltemp - pfile->fptr;
#else
p_errno = PETOOLARGE;
ret_val = -1;
goto return_locked;
#endif
}
/* calculate initial values */
n_left = count;
n_written = 0;
while (n_left)
{
end_of_chain = 0;
block_in_cluster = (dword) (pfile->fptr & pdrive->byte_into_cl_mask);
block_in_cluster >>= 9;
if (pfile->fptr >= alloced_size)
{
/* Extending the file */
extending_file = TRUE;
ltemp = (dword) n_left;
n_blocks_left = (dword) ((ltemp + 511) >> 9);
/* how many clusters are left-
* assume 1 for the current cluster.
* subtract out the blocks in the current
* round up by adding secpalloc-1 and then
* divide by sectors per cluster
| n_clusters = 1 +
| (n_blocks_left-
| (pdrive->secpalloc-block_in_cluster)
| + pdrive->secpalloc-1) >> pdrive->log2_secpalloc;
==>
*/
n_clusters = ( CLUSTERTYPE ) (1 +
((n_blocks_left + block_in_cluster -1) >> pdrive->log2_secpalloc));
/* Call pc_alloc_chain to build a chain up to n_cluster clusters
long. Return the first cluster in pfile->fptr_cluster and
return the # of clusters in the chain. If pfile->fptr_cluster
is non zero link the current cluster to the new one */
n_clusters = FATOP(pdrive)->fatop_alloc_chain(pdrive, &(pfile->fptr_cluster), n_clusters, TRUE);
if (!n_clusters)
{ /* Allocchain will set errno to PENOSPC or an IO or internal error */
break;
}
/* Calculate the last cluster in this chain. */
next_cluster = (CLUSTERTYPE) (pfile->fptr_cluster + n_clusters -1);
/* link the chain to the directory object if just starting */
if (!pc_finode_cluster(pfile->pobj->pdrive,pfile->pobj->finode))
pc_pfinode_cluster(pfile->pobj->pdrive,pfile->pobj->finode,pfile->fptr_cluster);
/* calculate the new block pointer */
pfile->fptr_block = pc_cl2sector(pdrive, pfile->fptr_cluster);
/* calculate amount of space used by the file */
ltemp = n_clusters << pdrive->log2_secpalloc; ltemp <<= 9;
alloced_size += ltemp;
if (alloced_size < ltemp)
alloced_size = 0xffffffff;
}
else /* Not extending the file. (writing inside the file) */
{
extending_file = FALSE;
ltemp = (dword) n_left;
n_blocks_left = (dword) ((ltemp + 511) >> 9);
/* how many clusters are left-
* assume 1 for the current cluster.
* subtract out the blocks in the current
* round up by adding secpalloc-1 and then
* divide by sectors per cluster
| n_clusters = 1 +
| (n_blocks_left-
| (pdrive->secpalloc-block_in_cluster)
| + pdrive->secpalloc-1) >> pdrive->log2_secpalloc;
==>
*/
n_clusters = (CLUSTERTYPE) (1 +
((n_blocks_left + block_in_cluster -1) >> pdrive->log2_secpalloc));
/* how many contiguous clusters can we get ? <= n_clusters */
end_of_chain = 0;
n_clusters = FATOP(pdrive)->fatop_get_chain(pdrive, pfile->fptr_cluster,
&next_cluster, n_clusters, &end_of_chain);
if (!n_clusters)
{
/* get_chain already set errno */
ret_val = (int) -1;
goto return_locked;
}
}
/* Are we inside a block */
if ( (pfile->fptr & 0x1ffL) || (n_left < 512) )
{
block_in_cluster = (dword) (pfile->fptr & pdrive->byte_into_cl_mask);
block_in_cluster >>= 9;
block_to_write = pfile->fptr_block + block_in_cluster;
byte_offset_in_block = (dword) (pfile->fptr & 0x1ffL);
/* Copy source data to the local buffer */
n_bytes = (int) (512 - byte_offset_in_block);
if (n_bytes > n_left)
n_bytes = n_left;
/* READ - Use the block buffer pool to read for us */
if (!pc_load_file_buffer(pfile, block_to_write))
break; /* load_file_block set errno */
/* Merge the data and mark it dirty */
if (in_buff)
copybuff(&(pfile->pobj->finode->pfile_buffer->data[byte_offset_in_block]), in_buff, n_bytes);
pfile->pobj->finode->file_buffer_dirty = 1;
if (!(pfile->pobj->finode->openflags & OF_BUFFERED))
{
/* Write the buffer. and discard it */
if (!pc_load_file_buffer(pfile, 0))
break; /* load_file_block set errno */
}
if (in_buff)
in_buff += n_bytes;
n_left = (int) (n_left - n_bytes);
pfile->fptr += n_bytes;
n_written += n_bytes;
/* Are we on a cluster boundary ? */
if (!(pfile->fptr & pdrive->byte_into_cl_mask))
{
if (--n_clusters) /* If contiguous */
{
pfile->fptr_block += pdrive->secpalloc;
pfile->fptr_cluster += (CLUSTERTYPE)1;
}
else
{
/* Check for corrupted file
We are about to advance fptr_cluster by
making next_cluster the current cluster.
If the file pointer is less than the current file
size, but we are at the end of chain we know
that there is no next_cluster and the chain is
corrupted. It shorter than the file size indicates.
Reset the byte pointer to match the current
block and cluster pointers, set errno to
PEINVALIDCLUSTER, return -1
We check against alloced_size here because next
time through the write routine will check and if
fptr >= alloced_size then it will link a new cluster
to the file.
*/
if (!extending_file &&
pfile->fptr < alloced_size &&
end_of_chain)
{
pfile->fptr -= n_bytes;
p_errno = PEINVALIDCLUSTER;
ret_val = -1;
goto return_locked;
}
else
{
/* NOTE: Put the next cluster into the pointer. If we had
alloced a chain this value is the last cluster in
the chain and does not concur with the byte file pointer.
This is not a problem since the cluster pointer is known
to be off at this point any (fptr>=alloced_size) */
pfile->fptr_cluster = next_cluster;
pfile->fptr_block = pc_cl2sector(pdrive, next_cluster);
}
} /* if (--nclusters) {} else {}; */
} /* if (!(pfile->fptr & byte_into_cl_mask)) */
} /* if ( (pfile->fptr & 0x1ff) || (n_left < 512) ) */
if (n_clusters && (n_left>511))
{
/* If we get here we need to write contiguous blocks */
block_in_cluster = (dword) (pfile->fptr & pdrive->byte_into_cl_mask);
block_in_cluster >>= 9;
block_to_write = pfile->fptr_block + block_in_cluster;
/* how many do we write ? */
ltemp = (dword) n_left;
n_blocks_left = (dword) (ltemp >> 9);
n_to_write = (dword) ((n_clusters << pdrive->log2_secpalloc) - block_in_cluster);
if (n_to_write > n_blocks_left)
{
n_to_write = n_blocks_left;
/* If we are not writing to the end of the chain we may not
advance the cluster pointer to the beginning of the next
chain. We add in block_in_cluster so we account for the
partial cluster we have already seen */
next_cluster = (CLUSTERTYPE) (pfile->fptr_cluster +
((n_to_write+block_in_cluster) >> pdrive->log2_secpalloc));
}
/* Devio takes words for blocks so split it up */
ltemp = n_to_write;
while (ltemp)
{
if (ltemp > 0xffff)
n_w_to_write = 0xffff;
else
n_w_to_write = ltemp & 0xffff;
/* Set pdrive->drive_flags to tell the device driver we are perfroming
file data transfer */
pdrive->drive_flags |= DRIVE_FLAGS_FILEIO;
if (in_buff && !devio_write(pdrive->driveno, block_to_write, in_buff, (word) n_w_to_write, FALSE))
{
pdrive->drive_flags &= ~DRIVE_FLAGS_FILEIO;
/* set errno to IO error unless devio set PEDEVICE */
if (!get_errno())
p_errno = PEIOERRORWRITE;
ret_val = n_written;
goto return_locked;
}
pdrive->drive_flags &= ~DRIVE_FLAGS_FILEIO;
/* Purge the file block buffer if it was in our range, since we will overwrite */
pc_sync_file_buffer(pfile, block_to_write, n_w_to_write, FALSE);
n_bytes = (int) n_w_to_write * 512;
if (in_buff)
in_buff = in_buff + n_bytes;
block_to_write += n_w_to_write;
ltemp = ltemp - n_w_to_write;
}
/* See note above */
n_bytes = (int) n_to_write * 512;
n_left = n_left - n_bytes;
pfile->fptr += n_bytes;
n_written += n_bytes;
pfile->fptr_cluster = next_cluster;
pfile->fptr_block = pc_cl2sector(pdrive, next_cluster);
}
} /* while n_left */
ret_val = n_written;
/* If we wrote anything change the last modified time and date */
if (pfile->pobj && ret_val > 0)
{
DATESTR crdate;
pc_getsysdate(&crdate);
pfile->pobj->finode->fattribute |= ARCHIVE;
pfile->pobj->finode->ftime = crdate.time;
pfile->pobj->finode->fdate = crdate.date;
pfile->needs_flush = TRUE;
}
return_locked:
if (pfile->pobj && (pfile->fptr > pfile->pobj->finode->fsize))
{
pfile->needs_flush = TRUE;
pfile->pobj->finode->fsize = pfile->fptr;
pfile->pobj->finode->fattribute |= ARCHIVE;
}
/* If the file pointer is beyond the space allocated to the file note it.
since we may need to adjust this files cluster and block pointers
later if someone else extends the file behind our back */
if (pfile->fptr >= alloced_size)
pfile->at_eof = TRUE;
else
pfile->at_eof = FALSE;
/* If the file is open in auto flush mode flush directory entry changes to disk */
if (pfile->flag & PO_AFLUSH)
if (!_po_flush(pfile))
ret_val = -1;
if (!release_drive_mount_write(pdrive->driveno))/* Release lock, unmount if aborted */
return(-1);
return_unlocked:
if (p_errno)
rtfs_set_errno(p_errno);
return(ret_val);
}
/**************************************************************************
PO_TRUNCATE - Truncate an open file.
Description
Move the file pointer offset bytes from the beginning of the file
and truncate the file beyond that point by adjusting the file size
and freeing the cluster chain past the file pointer.
Returns
Returns TRUE if successful otherwise FALSE
errno is set to one of the following
0 - No error
PEBADF - Invalid file descriptor
PEACCES - File is read only or opened more than once
PEINVALIDPARMS - Invalid or inconsistent arguments
An ERTFS system error
*****************************************************************************/
BOOLEAN po_truncate(PCFD fd, dword offset) /*__apifn__*/
{
PC_FILE *pfile;
DDRIVE *pdrive;
BOOLEAN ret_val;
CLUSTERTYPE first_cluster_to_release;
CLUSTERTYPE last_cluster_in_chain;
CLUSTERTYPE clno;
int p_errno;
dword clusters_to_release;
dword old_chain_len;
dword new_chain_len;
dword range_check;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
p_errno = 0;
rtfs_set_errno(0); /* po_truncate: clear error status */
/* Assume failure */
ret_val = FALSE;
/* Get the FILE. must be open for write */
/* Get the file structure and semaphore lock the drive */
pfile = pc_fd2file(fd, PO_WRONLY|PO_RDWR);
/* Make sure we have write privilages */
if (!pfile)
goto return_error;
pdrive = pfile->pobj->pdrive;
/* Can only truncate a file that you hold exclusively */
if (pfile->pobj->finode->opencount > 1)
{
p_errno = PEACCES;
goto errex;
}
/* Set the cluster and block file pointers if not already set */
if (!_synch_file_ptrs(pfile))
{ /* _synch_file_ptrs set errno */
goto errex;
}
/* Make sure the file buffer is clear */
pc_load_file_buffer(pfile, 0);
if (offset > pfile->pobj->finode->fsize)
{
p_errno = PEINVALIDPARMS;
goto errex;
}
/* Call the internal seek routine that we share with po_lseek. Seek to
offset from the origin of zero. */
if (!_po_ulseek(pfile, offset, &offset, PSEEK_SET))
goto errex; /* _po_lseek() set errno */
else if (offset == pfile->pobj->finode->fsize)
{
ret_val = TRUE;
}
else
{
pfile->needs_flush = TRUE;
/* calculate maximum number of clusters we will need to release */
/* Round the file size up to its cluster size by adding in clustersize-1
and masking off the low bits */
old_chain_len = pc_chain_length(pdrive, pfile->pobj->finode->fsize);
new_chain_len = pc_chain_length(pdrive, offset);
clusters_to_release = old_chain_len - new_chain_len;
/* Are we on a cluster boundary ? */
if (!(offset & pdrive->byte_into_cl_mask))
{
/* Free the current cluster and beyond since we are on a cluster boundary. */
first_cluster_to_release = pfile->fptr_cluster;
/* Find the previous cluster so we can terminate the chain */
clno = pc_finode_cluster(pdrive,pfile->pobj->finode);
last_cluster_in_chain = clno;
range_check = 0;
while (clno != first_cluster_to_release)
{
if ((clno < 2) || (clno > pdrive->maxfindex) || (++range_check > old_chain_len) )
{
rtfs_set_errno(PEINVALIDCLUSTER);
goto errex;
}
last_cluster_in_chain = clno;
clno = FATOP(pdrive)->fatop_clnext(pdrive , clno); /* File */
if (!clno)
{ /* FATOP will set errno */
goto errex;
}
}
/* Set ptr_cluster to last in chain so read&write will work right */
pfile->fptr_cluster = last_cluster_in_chain;
if (last_cluster_in_chain)
{
if ((clno < 2) || (clno > pdrive->maxfindex))
{
rtfs_set_errno(PEINVALIDCLUSTER);
goto errex;
}
pfile->fptr_block = pc_cl2sector(pdrive, last_cluster_in_chain);
}
else
pfile->fptr_block = 0;
pfile->at_eof = TRUE;
}
else /* Simple case. we are not on a cluster boundary. Just free*/
{ /* The chain beyond us and terminate the list */
last_cluster_in_chain = pfile->fptr_cluster;
first_cluster_to_release = FATOP(pdrive)->fatop_clnext(pdrive, pfile->fptr_cluster); /* File */
if (!first_cluster_to_release) /* if 0 and not end of chain it's an error */
{ /* clnext set errno */
goto errex;
}
/* Clear cluster number if clnext returned eof */
if (first_cluster_to_release == 0xffffffff)
first_cluster_to_release = 0;
pfile->at_eof = TRUE;
}
/* Now update the directory entry. */
pfile->pobj->finode->fsize = offset;
if (!offset) /* If the file goes to zero size unlink the chain */
{
pc_pfinode_cluster(pdrive,pfile->pobj->finode,0);
pfile->fptr_cluster = 0;
pfile->fptr_block = 0;
pfile->fptr = 0;
pfile->at_eof = FALSE;
/* We are freeing the whole chain so we do not mark last_cluster in chain */
last_cluster_in_chain = 0;
}
ret_val = TRUE; /* If it doesn't get changed to false, it worked */
/* Convert to native. Overwrite the existing inode.Set archive/date */
if (!pc_update_inode(pfile->pobj, TRUE, TRUE))
ret_val = FALSE;
/* Terminate the chain and free the lost chain part */
/* Free the rest of the chain */
if (ret_val && clusters_to_release && first_cluster_to_release)
{
/* Release the chain FATOP will set erno if needed - set min and max
the same so it must delete exactly this many clusters */
if (!FATOP(pdrive)->fatop_freechain(pdrive, first_cluster_to_release, clusters_to_release, clusters_to_release))
ret_val = FALSE;
}
/* Null terminate the chain */
if (ret_val && last_cluster_in_chain)
{
if (!FATOP(pdrive)->fatop_pfaxxterm(pdrive, last_cluster_in_chain)) /* File */
ret_val = FALSE;
}
if (ret_val && !FATOP(pdrive)->fatop_flushfat(pdrive->driveno))
ret_val = FALSE;
}
errex:
if (!release_drive_mount_write(pdrive->driveno))/* Release lock, unmount if aborted */
return(FALSE);
return_error: /* No only errors return through here. Everything does. */
if (p_errno)
rtfs_set_errno(p_errno);
return(ret_val);
}
/*
* Note: when this routine is caled the files finode is LOCKED so the code
* need not be reentrant relative to the finode.
*/
/* Internal version of po_flush() called by po_flush and po_close */
BOOLEAN _po_flush(PC_FILE *pfile) /*__fn__*/
{
/*---------- ctr modified ----------*/
int driveno;
DDRIVE *pdr;
/*----------------------------------*/
BOOLEAN ret_val;
/* Flush the file buffer if it is in use */
if (!pc_flush_file_buffer(pfile))
return(FALSE);
ret_val = TRUE;
/* Convert to native. Overwrite the existing inode.Set archive
set date. */
if (pfile->needs_flush)
{
if (pc_update_inode(pfile->pobj, TRUE, TRUE))
{ /* pc_update_inode and FATOP both set errno */
pfile->needs_flush = FALSE;
/* Flush the file allocation table */
if (!FATOP(pfile->pobj->pdrive)->fatop_flushfat(pfile->pobj->pdrive->driveno))
ret_val = FALSE;
}
else
ret_val = FALSE;
}
/*---------- ctr modified ----------*/
driveno = pfile->pobj->pdrive->driveno;
pdr = pc_drno_to_drive_struct( driveno);
if( pdr) {
if( pdr->dev_table_perform_device_ioctl) {
if( pdr->dev_table_perform_device_ioctl( driveno,
DEVCTL_FLUSH,
NULL) != 0) {
ret_val = FALSE;
}
}
}
/*----------------------------------*/
return(ret_val);
}
/****************************************************************************
PO_FLUSH - Flush a file.
Description
Flush the file updating the disk.
Returns
Returns TRUE if all went well otherwise it returns FALSE.
errno is set to one of the following
0 - No error
PEBADF - Invalid file descriptor
PEACCES - File is read only
An ERTFS system error
****************************************************************************/
BOOLEAN po_flush(PCFD fd) /*__apifn__*/
{
PC_FILE *pfile;
BOOLEAN ret_val;
int driveno;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
rtfs_set_errno(0); /* po_flush: clear error status */
/* Get the FILE. must be open for write */
/* Get the file structure and semaphore lock the drive */
pfile = pc_fd2file(fd, PO_WRONLY|PO_RDWR);
if (pfile)
{
driveno = pfile->pobj->pdrive->driveno;
ret_val = _po_flush(pfile); /* _po_flush() will set errno */
if (!release_drive_mount_write(driveno))/* Release lock, unmount if aborted */
ret_val = -1;
return(ret_val);
}
else
{ /* fd2file set errno */
return(FALSE);
}
}
/*****************************************************************************
pc_set_attributes - Set File Attributes
Description
Given a file or directory name return set directory entry attributes
associated with the entry.
The following values may be set:
BIT Nemonic
0 ARDONLY
1 AHIDDEN
2 ASYSTEM
5 ARCHIVE
Note: bits 3 & 4 (AVOLUME,ADIRENT) may not be changed.
Returns
Returns TRUE if successful otherwise it returns FALSE.
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid
PEINVALIDPATH - Path specified badly formed.
PENOENT - Path not found
PEACCESS - Object is read only
PEINVALIDPARMS - attribute argument is invalid
An ERTFS system error
****************************************************************************/
BOOLEAN pc_set_attributes(byte *path, byte attributes) /*__apifn__*/
{
DROBJ *pobj;
BOOLEAN ret_val;
int driveno;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
rtfs_set_errno(0); /* pc_set_attributes: clear error status */
if ((attributes&(0x40|0x80)) !=0 ) /* Illegal */
{
rtfs_set_errno(PEINVALIDPARMS);
return(FALSE);
}
driveno = check_drive_name_mount(path);
if (driveno < 0)
{ /* errno was set by check_drive */
return (FALSE);
}
ret_val = FALSE;
/* pc_fndnode will set errno */
pobj = pc_fndnode(path);
if (pobj)
{
/* Change the attributes if legal */
if (
(attributes & (AVOLUME|ADIRENT)) == /* Still same type */
(pobj->finode->fattribute & (AVOLUME|ADIRENT)))
{
pobj->finode->fattribute = attributes;
/* Overwrite the existing inode. Do not set archive/date */
/* pc_update_inode() will set errno */
ret_val = pc_update_inode(pobj, FALSE, FALSE);
}
else
rtfs_set_errno(PEACCES);
pc_freeobj(pobj);
}
if (!release_drive_mount_write(driveno))/* Release lock, unmount if aborted */
ret_val = FALSE;
return (ret_val);
}
/****************************************************************************
PC_DISKFLUSH - Flush the FAT and all files on a disk
Description
If an application may call this functions to force all files
to be flushed and the fat to be flushed. After this call returns
the disk image is synchronized with RTFSs internal view of the
voulme.
Returns
TRUE if the disk flushed else no
errno is set to one of the following
0 - No error
PEINVALIDDRIVEID- Drive component is invalid
An ERTFS system error
****************************************************************************/
BOOLEAN pc_diskflush(byte *path) /*__apifn__*/
{
int driveno;
DDRIVE *pdrive;
BOOLEAN ret_val;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
rtfs_set_errno(0); /* pc_diskflush: clear error status */
ret_val = FALSE;
driveno = check_drive_name_mount(path);
/* if error, errno was set by check_drive */
if (driveno >= 0)
{
/* Find the drive */
pdrive = pc_drno2dr(driveno);
if (pdrive)
{
/*---------- ctr modified ----------*/
if (pc_flush_all_fil(pdrive)) {
if (FATOP(pdrive)->fatop_flushfat(driveno)) {
ret_val = TRUE;
}
}
if( pdrive->dev_table_perform_device_ioctl) {
if( pdrive->dev_table_perform_device_ioctl( driveno,
DEVCTL_FLUSH,
NULL) == 0) {
ret_val = TRUE;
}
}/*----------------------------------*/
}
if (!release_drive_mount_write(driveno))/* Release lock, unmount if aborted */
ret_val = FALSE;
}
return(ret_val);
}
/*ctr modified
pc_diskflushはRTFSのバッファを吐き出す処理を行うが
nandはドライバ側でもバッファを持っているためデバイスに反映されない
_po_flushにDEVCTL_FLUSHを引っ掛けていることにより対策
mkdir, rmdirなどは_po_flushを素通りしてしまうので
pc_diskflushにもDEVCTL_FLUSHを引っ掛けることにより対策
pc_diskflushを呼ばないといけないのでmkdir,rmdirなどに
pc_diskflushでDEVCTL_FLUSHは削除してよいかも
*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright Peter Van Oudenaren , 1993
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
* appdemo.c - Top level demo code. Initializes ertfs and calls the test shell.
*/
#include <rtfs.h>
void tst_shell(void);
void rtfs_app_entry(void) /* __fn__ */
{
/* Initialize ertfs */
if (!pc_ertfs_init())
{
RTFS_PRINT_STRING_1(USTRING_RTFSDEM_01, PRFLG_NL); /* "pc_ertfs_init failed" */
return;
}
tst_shell();
}

View File

@ -0,0 +1,274 @@
/*---------------------------------------------------------------------------*
Project: CTR - for RTFS
File: attach.c
2006 Nintendo.
*---------------------------------------------------------------------------*/
#include <twl.h>
#include <rtfs.h>
#include <portconf.h> /* For included devices */
#include "drdefault.h" /* default driver */
/*---------------------------------------------------------------------------*
global変数
*---------------------------------------------------------------------------*/
BOOLEAN rtfs_first_attach = TRUE; //attach APIがまだ未使用ならTRUE
//attachされてからDEVCTL_CHECKSTATUSが呼ばれてなければ1
int rtfs_first_stat_flag[26] ={
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};
/*---------------------------------------------------------------------------*
extern変数
*---------------------------------------------------------------------------*/
extern int enabled_drivers;
extern DDRIVE* current_pdr;
extern int auto_format_disk(DDRIVE *pdr, byte *drivename);
extern void drno_to_string(byte *pname, int drno);
extern DDRIVE* pc_drno_to_drive_struct(int driveno);
extern void print_device_names(void);
/*---------------------------------------------------------------------------*
extern関数
*---------------------------------------------------------------------------*/
/*-------------- ctr modified(new function) -------------*/
//extern BOOLEAN i_rtfs_begin_attach( void);
extern BOOLEAN i_rtfs_attach( int driveno, DDRIVE* pdr, char* dev_name);
extern BOOLEAN i_rtfs_end_attach( void);
/*-------------------------------------------------------*/
/*---------------------------------------------------------------------------*
static関数
*---------------------------------------------------------------------------*/
static void i_rtfsInit( DDRIVE* pdr);
static int i_rtfs_close_disk( int driveno);
/*---------------------------------------------------------------------------*
Name: rtfs_attach
Description:
Arguments: driveno :
Returns:
*---------------------------------------------------------------------------*/
BOOLEAN rtfs_attach( int driveno, DDRIVE* pdr, char* dev_name)
{
DDRIVE *target_pdr;
// osTPrintf( "original attach\n");
if( rtfs_first_attach) { //最初のattachだった場合
rtfs_init();//i_rtfs_begin_attach();
rtfs_first_attach = FALSE;
}
/*アタッチする構造体を選択*/
target_pdr = pc_drno_to_drive_struct( driveno);
if( target_pdr == 0) { /*未登録なら新しい構造体へ*/
// osTPrintf( "target_pdr = current_pdr\n");
target_pdr = current_pdr;
}else{
/* if( target_pdr->dev_table_drive_io == pdr->dev_table_drive_io) {
return( TRUE); //自分自身ならスルー
}*/
if(( target_pdr->dev_table_drive_io != defaultRtfsIo)&&
( target_pdr->dev_table_drive_io != NULL)){
return( FALSE); /*default以外のドライバがattach済みならエラー*/
}
}
if (++enabled_drivers > prtfs_cfg->cfg_NDRIVES) {
// osTPrintf( "%s : too many drives attached - ");
// osTPrintf( "%d / %d\n", enabled_drivers, prtfs_cfg->cfg_NDRIVES);
return( FALSE);
}
target_pdr->driveno = driveno;
target_pdr->dev_table_drive_io = pdr->dev_table_drive_io;
target_pdr->dev_table_perform_device_ioctl = pdr->dev_table_perform_device_ioctl;
rtfs_strcpy(target_pdr->device_name, (byte *)dev_name);
target_pdr->register_file_address = pdr->register_file_address;
target_pdr->interrupt_number = pdr->interrupt_number;
target_pdr->drive_flags = pdr->drive_flags | DRIVE_FLAGS_REMOVABLE | DRIVE_FLAGS_INSERTED;
target_pdr->partition_number = pdr->partition_number;
target_pdr->pcmcia_slot_number = pdr->pcmcia_slot_number;
target_pdr->controller_number = pdr->controller_number;
target_pdr->logical_unit_number = pdr->logical_unit_number;
rtfs_first_stat_flag[driveno] = 1; /* 初回DEVCTL_CHECKSTATUSフラグON */
i_rtfsInit( target_pdr);
/**/
if( target_pdr == current_pdr) {
current_pdr++;
}
return( TRUE);
}
/**/
static void i_rtfsInit( DDRIVE* pdr)
{
byte drname[8]; /* Temp buffer for displaying drive letters as strings */
/* WARMSTART */
if( pdr->dev_table_drive_io) {
prtfs_cfg->drno_to_dr_map[pdr->driveno] = pdr; /* MAPS DRIVE structure to DRIVE: */
if (pdr->dev_table_perform_device_ioctl(pdr->driveno, DEVCTL_WARMSTART, (void *) 0) != 0)
{
prtfs_cfg->drno_to_dr_map[pdr->driveno] = 0; /* It is not there. */
/* so forget it */
}
#if (INCLUDE_FAILSAFE_CODE)
/* Call the the ertfs pro failsafe autoinit function */
if (pdr->drive_flags&DRIVE_FLAGS_FAILSAFE)
{
if (!pro_failsafe_auto_init(pdr)) //マニュアル参照
{
prtfs_cfg->drno_to_dr_map[pdr->driveno] = 0; /* Forget it, not there. */
}
}
#endif
/* Set the default drive to the lowest assigned drive letter */
prtfs_cfg->default_drive_id = pdr->driveno;
}
/* autoformatting ram devices */
if ( pdr->drive_flags&DRIVE_FLAGS_VALID && pdr->drive_flags&DRIVE_FLAGS_FORMAT)
{
OS_CLAIM_LOGDRIVE(pdr->driveno) /* Autoformat Register drive in use */
drno_to_string(drname, pdr->driveno);
// RTFS_PRINT_STRING_2(USTRING_RTFSINIT_07, drname,0); /* "Autoformatting Drive Id - " */
#if (STORE_DEVICE_NAMES_IN_DRIVE_STRUCT)
// RTFS_PRINT_STRING_2(USTRING_RTFSINIT_08, pdr->device_name,PRFLG_NL); /* " as Device: " */
#endif
if (auto_format_disk(pdr, drname) != 0) {
// RTFS_PRINT_STRING_2(USTRING_RTFSINIT_09, drname,PRFLG_NL); /* "Autoformatting Drive Id - \n" */
}
OS_RELEASE_LOGDRIVE(pdr->driveno) /* Autoformat release */
}
}
/*---------------------------------------------------------------------------*
Name: rtfs_detach
Description:
Arguments: driveno :
Returns:
*---------------------------------------------------------------------------*/
BOOLEAN rtfs_detach( int driveno)
{
DDRIVE *target_pdr;
// osTPrintf( "original detach\n");
target_pdr = pc_drno_to_drive_struct( driveno);
if( target_pdr == 0) {
return( FALSE); //未割り当てなのでdetachの必要なし
}else{
if( (target_pdr->dev_table_drive_io == defaultRtfsIo) ||
(target_pdr->dev_table_drive_io == NULL)) {
return( FALSE); //既にdetach済み
}
}
/*open中のファイルを全てcloseする*/
i_rtfs_close_disk( driveno);
--enabled_drivers;
target_pdr->driveno = driveno;
target_pdr->dev_table_drive_io = defaultRtfsIo;
target_pdr->dev_table_perform_device_ioctl = defaultRtfsCtrl;
rtfs_strcpy(target_pdr->device_name, (byte *)"DEFAULT\0"); //STORE_DEVICE_NAME(dev_name)
target_pdr->register_file_address = 0;
target_pdr->interrupt_number = 0;
target_pdr->drive_flags = 0;
target_pdr->partition_number = 0;
target_pdr->pcmcia_slot_number = 0;
target_pdr->controller_number = 0;
target_pdr->logical_unit_number = 0;
/*REMOVE扱い*/
target_pdr->drive_flags |= DRIVE_FLAGS_REMOVABLE;
target_pdr->drive_flags &= ~DRIVE_FLAGS_INSERTED;
return( TRUE);
}
/*---------------------------------------------------------------------------*
Name: i_rtfs_close_disk
Description: open中のファイルを全てcloseする
Arguments: driveno :
Returns:
*---------------------------------------------------------------------------*/
static int i_rtfs_close_disk( int driveno)
{
PC_FILE *pfile;
PCFD i;
DROBJ *pobj;
int ret_val = 0;
rtfs_set_errno(0); /* clear errno */
pfile = prtfs_cfg->mem_file_pool;
for (i=0;i<pc_nuserfiles();i++, pfile++)
{
if( (pfile->is_free) == FALSE) //open中か
{
if( !pfile->pobj) {//PECLOSEDエラーに相当(pc_fd2file参照)
OS_CLAIM_FSCRITICAL()
pfile->is_free = TRUE;
OS_RELEASE_FSCRITICAL()
}else{ //正常にopen中
if( (pfile->pobj->pdrive->driveno) == driveno) {
#if (RTFS_WRITE)
if (pfile->flag & ( PO_RDWR | PO_WRONLY ) )
{
if (!_po_flush(pfile))
{ /* _po_flush has set errno */
ret_val = -1;
}
}
#endif
/* Release the FD and its core */
//pc_freefile( pfile); apifilio.c内のstatic関数なので以下に展開
OS_CLAIM_FSCRITICAL()
pobj = pfile->pobj;
pfile->is_free = TRUE;
OS_RELEASE_FSCRITICAL()
pc_freeobj(pobj);
}
}
}
}
if (!release_drive_mount_write(driveno)) {/* Release lock, unmount if aborted */
return (-1);
}
return( ret_val);
}

View File

@ -0,0 +1,525 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 2002
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
* UTILASCI.C - Contains ASCII string manipulation and character
* conversion routines
*/
#include <rtfs.h>
#if (INCLUDE_CS_ASCII)
byte *ascii_goto_eos(byte *p)
{
while (*p) p++;
return(p);
}
void pc_byte2upper(byte *to, byte *from)
{
byte c;
c = *from;
if ((c >= 'a') && (c <= 'z'))
c = (byte) ('A' + c - 'a');
*to = c;
}
void pc_ascii_strn2upper(byte *to, byte *from, int n)
{
int i;
for (i = 0; i < n; i++,to++, from++)
pc_byte2upper(to, from);
}
void pc_ascii_str2upper(byte *to, byte *from)
{
while(*from)
pc_byte2upper(to++, from++);
*to = '\0';
}
void pc_str2upper(byte *to, byte *from)
{
pc_ascii_str2upper(to, from);
}
/***************************************************************************
PC_MFILE - Build a file spec (xxx.yyy) from a file name and extension
Description
Fill in to with a concatenation of file and ext. File and ext are
not assumed to be null terminated but must be blank filled to [8,3]
chars respectively. 'to' will be a null terminated string file.ext.
ASCII character function only. Unicode not required
Returns
A pointer to 'to'.
****************************************************************************/
byte *pc_ascii_mfile(byte *to, byte *filename, byte *ext)
{
byte *p;
int i;
byte *retval = to;
p = filename;
i = 0;
while(*p)
{
if (*p == ' ')
break;
else
{
*to++ = *p++;
i++;
}
if (i == 8)
break;
}
if (p != filename)
{
p = ext;
if (*p && *p != ' ')
*to++ = '.';
i = 0;
while(p && *p)
{
if (*p == ' ')
break;
else
{
*to++ = *p++;
i++;
}
if (i == 3)
break;
}
}
*to = '\0';
return (retval);
}
/* Version of MFILE that converts path from byte orientation to
native char set before returning. pc_mfile and pc_cs_mfile are
the same for ascii */
byte *pc_cs_mfile(byte *to, byte *filename, byte *ext)
{
return(pc_ascii_mfile(to, filename, ext));
}
byte * rtfs_cs_strcat(byte * targ, byte * src) /*__fn__*/
{
return(rtfs_strcat(targ, src));
}
int rtfs_cs_strcmp(byte * s1, byte * s2)
{
return (rtfs_strcmp(s1, s2));
}
int rtfs_cs_strcpy(byte * targ, byte * src)
{
return (rtfs_strcpy(targ, src));
}
/* return number of ascii chars in a string */
int rtfs_cs_strlen(byte * string) /*__fn__*/
{
return (rtfs_strlen(string));
}
/* return number of bytes in an ascii character string */
int rtfs_cs_strlen_bytes(byte * string) /*__fn__*/
{
return (rtfs_strlen(string));
}
int ascii_ascii_index(byte *p, byte base)
{
byte c;
pc_byte2upper(&c, p);
return((int) (c - base));
}
int ascii_compare_nc(byte *p1, byte *p2)
{
byte c,d;
if (*p1 == *p2)
return(1);
else
{
pc_byte2upper(&c, p1);
pc_byte2upper(&d, p2);
return(c == d);
}
}
/***************************************************************************
PC_FILEPARSE - Parse a file xxx.yyy into filename/pathname
Description
Take a file named XXX.YY and return SPACE padded NULL terminated
filename [XXX ] and fileext [YY ] components. If the name or ext are
less than [8,3] characters the name/ext is space filled and null termed.
If the name/ext is greater than [8,3] the name/ext is truncated. '.'
is used to seperate file from ext, the special cases of . and .. are
also handled.
Returns
Returns TRUE
****************************************************************************/
/* UNICODE - Called by pc_malias not by others if vfat - Okay as ascii */
/* UNICODE - pc_enum usage is probably incorrect */
/* Take a string xxx[.yy] and put it into filename and fileext */
/* Note: add a check legal later */
BOOLEAN pc_ascii_fileparse(byte *filename, byte *fileext, byte *p) /* __fn__*/
{
int i;
/* Defaults */
rtfs_memset(filename, ' ', 8);
filename[8] = '\0';
rtfs_memset(fileext, ' ', 3);
fileext[3] = '\0';
/* Special cases of . and .. */
if (*p == '.')
{
*filename = '.';
if (*(p+1) == '.')
{
*(++filename) = '.';
return (TRUE);
}
else if (*(p + 1) == '\0')
return (TRUE);
else
return (FALSE);
}
i = 0;
while (*p)
{
if (*p == '.')
{
p++;
break;
}
else
if (i++ < 8)
*filename++ = *p;
p++;
}
i = 0;
while (*p)
{
if (i++ < 3)
*fileext++ = *p;
p++;
}
return (TRUE);
}
/***************************************************************************
PC_VALID_SFN - See if filename is a valid short file name
Description
Determines validity of a short file name based on the following criteria:
- the file name must be between 0 and 8 characters
- the file extension must be between 0 and 3 characters
- the file name must not begin with a period
- it must not be a reserved DOS file name
- it must not contain any characters that are illegal within sfn's
Returns
TRUE if filename is a valid sfn, FALSE otherwise
****************************************************************************/
BOOLEAN pc_valid_sfn(byte *filename)
{
int len,period_count,ext_start;
byte name_part[9];
BOOLEAN badchar;
if(name_is_reserved(filename)) return(FALSE);
name_part[0] = 0;
for(len=0,badchar=FALSE,period_count=0,ext_start=0; filename[len]!=0; len++)
{
if(_illegal_alias_char(filename[len])) badchar = TRUE;
if(filename[len] == '.')
{
ext_start = len+1;
period_count++;
}
else
{
if (!ext_start && len < 8)
{
name_part[len] = filename[len];
name_part[len+1] = 0;
}
}
}
/* check if the file name part contains a reserved name */
if(name_is_reserved(name_part)) return(FALSE);
if( (filename[0] == ' ') || /* 1st char is a space */
(len == 0) || /* no name */
badchar || /* contains illegal chars */
(period_count > 1) || /* contains more than one extension */
((len-ext_start)>3 && period_count>0) || /* extension is longer than 3 chars */
(period_count==0 && len > 8) || /* name is longer than 8 chars */
(ext_start > 9) || /* name is longer than 8 chars */
(ext_start==1) ) return(FALSE); /* no name; 1st char is a period */
return(TRUE);
}
#if (VFAT) /* Small piece of compile time VFAT vs's NONVFAT code */
/***************************************************************************
PC_VALID_LFN - See if filename is a valid long file name
Description
Determines validity of a long file name based on the following criteria:
- the file must be between 0 and 256 characters in length
- it must not be a reserved DOS file name
- it must not contain any characters that are illegal within lfn's
Returns
TRUE if filename is a valid lfn, FALSE otherwise
*****************************************************************************/
BOOLEAN validate_filename(byte * filename, byte * ext)
{
int len,n;
byte name_part[9];
RTFS_ARGSUSED_PVOID((void *) ext);
name_part[0] = 0;
for(n=0,len=0; filename[n]!=0; len++,n++)
{
if(_illegal_lfn_char(filename[n]))
return(FALSE);
else
{
if (len < 5) /* handles lpt1, aux, con etc */
{
if(filename[len] == '.')
{
name_part[len] = 0;
if(name_is_reserved(name_part)) return(FALSE);
}
else
{
name_part[len] = filename[len];
if (filename[len+1] == 0)
{
name_part[len+1] = 0;
if(name_is_reserved(name_part)) return(FALSE);
}
}
}
}
}
if( (len == 0) || (len > 255) ) return(FALSE);
return(TRUE);
}
BOOLEAN pc_cs_malias(byte *alias, byte *input_file, int try)
{
int n,i,s;
byte filename[9],fileext[4];
/* Check if invalid short file name.Case is ignored. If ignored we fix it later ! */
if ((try == -1) && !pc_valid_sfn((byte *)input_file))
return(FALSE);
/* Process the ASCII alias name */
while(*input_file=='.' || *input_file==' ') input_file++;
/* find extension start */
for(n=0,i=0; input_file[n]!=0; n++) /* i holds the position right */
{ /* after the last period */
if(input_file[n]=='.') i=n+1;
}
if(i>0 && input_file[i]!=0){
/* copy extension to fileext[] */
for(n=i,s=0; input_file[n]!=0 && s<3; n++)
{
if(input_file[n]!=' ')
{
if(_illegal_alias_char(input_file[n]))
{
fileext[s++] = '_';
}
else
fileext[s++] = input_file[n];
}
}
fileext[s]=0;} else { i=512; fileext[0]=0; } /* null terminate */
/* copy file name to filename[], filtering out spaces, periods and
replacing characters illegal in alias names with '_' */
for(n=0,s=0; n<i && input_file[n]!=0 && s<8; n++)
{
if(input_file[n]!=' ' && input_file[n]!='.')
{
if(_illegal_alias_char(input_file[n]) || input_file[n]>127)
{
filename[s++] = '_';
}
else
filename[s++] = input_file[n];
}
}
for(;s<8;s++) /* pad with spaces */
{
filename[s] = ' ';
}
filename[8]=0; /* null terminate filename[] */
pc_ascii_str2upper(filename,filename);
pc_ascii_str2upper(fileext,fileext);
if (try != -1)
{
/* append (TEXT[])i to filename[] */
for(n=7,s=try; s>0 && n>0; s/=10,n--)
{
filename[n] = (byte)(((byte)s%10)+'0');
}
if(n==0 && s>0)
return(FALSE);
else
filename[n]='~';
}
/* copy filename[] to alias[], filtering out spaces */
for(n=0,s=0; s<8; s++)
{
if(filename[s]!=' ')
alias[n++]=filename[s];
}
if(fileext[0] != 0)
{
alias[n++]='.'; /* insert separating period */
/* copy fileext[] to alias[] */
for(s=0; fileext[s]!=0; s++,n++)
{
alias[n]=fileext[s];
}
}
alias[n]=0; /* null terminate alias[] */
return(TRUE);
}
#endif
#if (!VFAT) /* Small piece of compile time VFAT vs's NONVFAT code */
BOOLEAN validate_8_3_name(byte * name,int len) /*__fn__*/
{
int i;
int last;
last = len-1;
for (i = 0; i < len; i++)
{
/* If we hit a space make sure the rest of the string is spaces */
if (name[i] == ' ')
{
for (; i < len; i++)
{
if (name[i] != ' ')
return(FALSE);
}
break;
}
}
return(TRUE);
}
BOOLEAN validate_filename(byte * name, byte * ext)
{
byte sfn_buffer[14]; /* Only uses 13 but keep declarations even */
if (!( validate_8_3_name(name,8) && validate_8_3_name(ext,3)) )
return(FALSE);
pc_ascii_mfile(sfn_buffer, name, ext);
return (pc_valid_sfn(sfn_buffer));
}
BOOLEAN pc_patcmp_8(byte *p, byte *pattern, BOOLEAN dowildcard) /* __fn__*/
{
int size = 8;
/* Kludge. never match a deleted file */
if (*p == PCDELETE)
return (FALSE);
else if (*pattern == PCDELETE) /* But E5 in the Pattern matches 0x5 */
{
if (*p == 0x5)
{
size -= 1;
p++;
pattern++;
}
else
return (FALSE);
}
while (size--)
{
if(dowildcard)
{
if (*pattern == '*') /* '*' matches the rest of the name */
return (TRUE);
if (*pattern != '?' && !ascii_compare_nc(pattern,p))
return (FALSE);
}
else
{
if (!ascii_compare_nc(pattern,p))
return (FALSE);
}
p++;
pattern++;
}
return (TRUE);
}
BOOLEAN pc_patcmp_3(byte *p, byte *pattern, BOOLEAN dowildcard) /* __fn__*/
{
int size = 3;
while (size--)
{
if(dowildcard)
{
if (*pattern == '*') /* '*' matches the rest of the name */
return (TRUE);
if (*pattern != '?' && !ascii_compare_nc(pattern,p))
return (FALSE);
}
else
{
if (!ascii_compare_nc(pattern,p))
return (FALSE);
}
p++;
pattern++;
}
return (TRUE);
}
#endif /* VFAT */
#endif

View File

@ -0,0 +1,910 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 2002
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* JIS.C - Contains Japanese string manipulation and character conversion routines */
/* See also jistab.c */
#include <rtfs.h>
#if (INCLUDE_CS_JIS)
byte *jis_goto_eos(byte *p)
{
while (*p)
p = jis_increment(p);
return(p);
}
/* Return the length of a JIS character, 1 or 2 */
int jis_char_length(byte *p)
{
if ((*p >= 0x81 && *p <= 0x9f) || (*p >= 0xe0 && *p <= 0xfc))
return(2);
else
return(1);
}
/* Copy JIS character, 1 or 2 bytes */
int jis_char_copy(byte *to, byte *from)
{
int len;
len = jis_char_length(from);
*to++ = *from++;
if (len == 2)
*to++ = *from++;
return(len);
}
/* Advance a pointer to the next JIS character in a string */
byte *jis_increment(byte *p)
{
return(p + jis_char_length(p));
}
/* return number of jis chars in a string */
/* Return 1 if p1 and p2 are the same */
int jis_compare(byte *p1, byte *p2)
{
/* If 1st char same and (len is 1 or 2nd char the same */
return ( (*p1 == *p2) && (jis_char_length(p1)==1 || (*(p1+1) == *(p2+1))) );
}
int jis_ascii_index(byte *p, byte base)
{
byte c;
pc_byte2upper(&c, p);
return((int) (c - base));
}
int jis_compare_nc(byte *p1, byte *p2)
{
byte c,d;
if (jis_compare(p1, p2))
return(1);
else if (jis_char_length(p1)==1 && jis_char_length(p2)==1)
{
pc_byte2upper(&c, p1);
pc_byte2upper(&d, p2);
return(c == d);
}
else
return(0);
}
void pc_ascii_strn2upper(byte *to, byte *from, int n) /* __fn__*/
{
int i;
byte c;
for (i = 0; i < n; i++)
{
if (jis_char_length(from) == 2)
{
*to++ = *from++;
*to++ = *from++;
}
else
{
c = *from++;
if ((c >= 'a') && (c <= 'z'))
c = (byte) ('A' + c - 'a');
*to++ = c;
}
}
}
void pc_byte2upper(byte *to, byte *from) /* __fn__*/
{
byte c;
c = *from;
if ((c >= 'a') && (c <= 'z'))
c = (byte) ('A' + c - 'a');
*to = c;
}
void pc_ascii_str2upper(byte *to, byte *from) /* __fn__*/
{
byte c;
while(*from)
{
if (jis_char_length(from) == 2)
{
*to++ = *from++;
*to++ = *from++;
}
else
{
c = *from++;
if ((c >= 'a') && (c <= 'z'))
c = (byte) ('A' + c - 'a');
*to++ = c;
}
}
*to = '\0';
}
void pc_str2upper(byte *to, byte *from) /* __fn__*/
{
pc_ascii_str2upper(to, from);
}
/* compares 2 strings; returns 0 if they match */
int rtfs_cs_strcmp(byte * s1, byte * s2) /*__fn__*/
{
while (*s1 && *s2)
{
if (!jis_compare(s1, s2))
return(1);
s1 = jis_increment(s1);
s2 = jis_increment(s2);
}
if (!*s1 && !*s2)
return(0);
else
return(1);
}
/* This works because JIS has no ZERO in hi byte of 16 bit jis chars */
byte * rtfs_cs_strcat(byte * targ, byte * src) /*__fn__*/
{
/* Call the byte oriented function */
return(rtfs_strcat(targ, src));
}
/* This works because JIS has no ZERO in hi byte of 16 bit jis chars */
int rtfs_cs_strcpy(byte * targ, byte * src)
{
/* Call the byte oriented function */
return (rtfs_strcpy(targ, src));
}
/* return number of jis chars in a string */
int rtfs_cs_strlen(byte * string) /*__fn__*/
{
int len=0;
while (*string)
{
string = jis_increment(string);
len++;
}
return len;
}
/* return number of bytes in a jis character string */
int rtfs_cs_strlen_bytes(byte * string) /*__fn__*/
{
byte *s;
int len;
s = string;
while (*string)
{
string = jis_increment(string);
}
len = (int) (s-string);
return len;
}
/***************************************************************************
PC_MFILE - Build a file spec (xxx.yyy) from a file name and extension
Description
Fill in to with a concatenation of file and ext. File and ext are
not assumed to be null terminated but must be blank filled to [8,3]
chars respectively. 'to' will be a null terminated string file.ext.
ASCII character function only. Unicode not required
Returns
A pointer to 'to'.
****************************************************************************/
byte *pc_ascii_mfile(byte *to, byte *filename, byte *ext) /* __fn__*/
{
byte *p;
int i,l;
byte *retval = to;
p = filename;
i = 0;
while(*p)
{
l = jis_char_length(p);
if (*p == ' ')
break;
else
{
if (l == 2)
{
if (i>6)
break;
*to++ = *p++;
}
*to++ = *p++;
i += l;
}
if (i == 8)
break;
}
if (p != filename)
{
p = ext;
if (*p && *p != ' ')
*to++ = '.';
i = 0;
while(p && *p)
{
l = jis_char_length(p);
if (*p == ' ')
break;
else
{
if (l == 2)
{
if (i>1)
break;
*to++ = *p++;
}
*to++ = *p++;
i += l;
}
if (i == 3)
break;
}
}
*to = '\0';
return (retval);
}
/* Version of MFILE that converts path from byte orientation to
native char set before returning. pc_mfile and pc_cs_mfile are
the same for jis */
byte *pc_cs_mfile(byte *to, byte *filename, byte *ext)
{
return(pc_ascii_mfile(to, filename, ext));
}
/***************************************************************************
PC_FILEPARSE - Parse a file xxx.yyy into filename/pathname
Description
Take a file named XXX.YY and return SPACE padded NULL terminated
filename [XXX ] and fileext [YY ] components. If the name or ext are
less than [8,3] characters the name/ext is space filled and null termed.
If the name/ext is greater than [8,3] the name/ext is truncated. '.'
is used to seperate file from ext, the special cases of . and .. are
also handled.
Returns
Returns TRUE
****************************************************************************/
/* Take a string xxx[.yy] and put it into filename and fileext */
/* Note: add a check legal later */
BOOLEAN pc_ascii_fileparse(byte *filename, byte *fileext, byte *p) /* __fn__*/
{
int i;
int l;
/* Defaults */
rtfs_memset(filename, ' ', 8);
filename[8] = '\0';
rtfs_memset(fileext, ' ', 3);
fileext[3] = '\0';
/* Special cases of . and .. */
if (*p == '.')
{
*filename = '.';
if (*(p+1) == '.')
{
*(++filename) = '.';
return (TRUE);
}
else if (*(p + 1) == '\0')
return (TRUE);
else
return (FALSE);
}
i = 0;
while (*p)
{
l = jis_char_length(p);
if (*p == '.')
{
p++;
break;
}
else
{
if (i + l <= 8)
{
jis_char_copy(filename, p);
filename += l;
i += l;
}
p += l;
}
}
i = 0;
while (*p)
{
l = jis_char_length(p);
if (i + l <= 3)
{
jis_char_copy(fileext, p);
fileext += l;
i += l;
}
p += l;
}
return (TRUE);
}
/* Return TRUE if illegal for an 8 dot 3 file */
static BOOLEAN _illegal_jis_file_char(byte *p, int islfn)
{
byte c;
if (jis_char_length(p) == 1)
{
c = *p;
/* Test for valid chars. Note: we accept lower case because that
is patched in pc_ino2dos() at a lower level */
if ( (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') )
return(FALSE); /* Valid */
if (c >= 0xa1 && c <= 0xdf) /* Katakana */
return(FALSE); /* Valid */
if (islfn)
return (_illegal_lfn_char(c)); /* same as ascii */
return (_illegal_alias_char(c)); /* same as ascii */
}
else /* length is 2 */
{
p++;
c = *p;
if (c >= 0x40 && c <= 0x7e)
return(FALSE); /* Valid */
if (c >= 0x80 && c <= 0xfc)
return(FALSE); /* Valid */
return(TRUE); /* Invalid */
}
}
/* Return TRUE if illegal for an 8 dot 3 file */
BOOLEAN _illegal_jis_alias_char(byte *p)
{
return(_illegal_jis_file_char(p, 0));
}
/*****************************************************************************
PC_VALID_SFN - See if filename is a valid short file name
Description
Determines validity of a short file name based on the following criteria:
- the file name must be between 0 and 8 characters
- the file extension must be between 0 and 3 characters
- the file name must not begin with a period
- it must not be a reserved DOS file name
- it must not contain any characters that are illegal within sfn's
Returns
TRUE if filename is a valid sfn, FALSE otherwise
*****************************************************************************/
BOOLEAN pc_valid_sfn(byte *filename) /* __fn__ */
{
int len,period_count,ext_start;
BOOLEAN badchar;
byte name_part[9];
int char_len;
byte *pname;
if(name_is_reserved(filename)) return(FALSE);
pname = filename;
len = 0;
badchar=FALSE;
period_count=0;
ext_start=0;
name_part[0] = 0;
while(*pname)
{
if(_illegal_jis_alias_char(pname)) badchar = TRUE;
if(*pname == '.')
{
ext_start = len+1;
period_count++;
}
char_len = jis_char_length(pname);
if (!ext_start && len < 8)
{
if (char_len == 2) /* end the test name for reserved */
name_part[len] = 0;
else
name_part[len] = *pname;
name_part[len+1] = 0;
}
pname += char_len;
len += char_len;
}
if(name_is_reserved(name_part)) return(FALSE);
if( (filename[0] == ' ') || /* 1st char is a space */
(len == 0) || /* no name */
badchar || /* contains illegal chars */
(period_count > 1) || /* contains more than one extension */
((len-ext_start)>3 && period_count>0) || /* extension is longer than 3 chars */
(period_count==0 && len > 8) || /* name is longer than 8 chars */
(ext_start > 9) || /* name is longer than 8 chars */
(ext_start==1) ) return(FALSE); /* no name; 1st char is a period */
return(TRUE);
}
#if (VFAT) /* Small piece of compile time VFAT vs's NONVFAT code */
BOOLEAN _illegal_jis_lfn_char(byte *p)
{
return(_illegal_jis_file_char(p, 1));
}
/***************************************************************************
validate_filename - See if filename is a valid long file name
Description
Determines validity of a long file name based on the following criteria:
- the file must be between 0 and 256 characters in length
- it must not be a reserved DOS file name
- it must not contain any characters that are illegal within lfn's
Returns
TRUE if filename is a valid lfn, FALSE otherwise
*****************************************************************************/
BOOLEAN validate_filename(byte * filename, byte * ext)
{
int len;
byte name_part[9];
RTFS_ARGSUSED_PVOID((void *) ext);
for(len=0; *filename; len++)
{
if (_illegal_jis_lfn_char(filename))
return(FALSE);
if (len < 5) /* handles lpt1, aux, con etc */
{
if(*filename == '.')
{
name_part[len] = 0;
if(name_is_reserved(name_part)) return(FALSE);
}
else
{
name_part[len] = *filename;
if (*(filename+1) == 0)
{
name_part[len+1] = 0;
if(name_is_reserved(name_part)) return(FALSE);
}
}
}
filename = jis_increment(filename);
}
if( (len == 0) || (len > 255) ) return(FALSE);
return(TRUE);
}
/* JIS Version */
BOOLEAN pc_cs_malias(byte *alias, byte *input_file, int try) /*__fn__*/
{
int n,s;
byte filename[9],fileext[4];
byte *p_in, *p_in_ext, *p_temp, *p_temp_2;
int char_len, jis_ext_len;
/* Fill filename[8] with spaces before we start. */
rtfs_memset(filename, ' ', 8);
/* Check if invalid short file name.Case is ignored. If ignored we fix it later ! */
if ((try == -1) && !pc_valid_sfn((byte *)input_file))
return(FALSE);
/* Process the JIS alias name */
p_in = input_file;
while(*p_in =='.' || *p_in ==' ') p_in = jis_increment(p_in);
/* find extension start */
/* p_in_ext holds the position right */
/* after the last period (or it is 0 */
p_in_ext = 0;
p_temp = p_in;
while(*p_temp)
{
if (*p_temp =='.')
{
p_temp = jis_increment(p_temp);
p_in_ext = p_temp;
}
else
p_temp = jis_increment(p_temp);
}
p_temp_2 = &fileext[0];
jis_ext_len = 0; /* We'll use this later to append ext to alias */
if(p_in_ext && *p_in_ext!=0){
/* copy extension to fileext[] */
p_temp = p_in_ext;
for(s=0; *p_temp!=0 && s<3;p_temp+=char_len)
{
char_len = jis_char_length(p_temp);
if(*p_temp!=' ')
{
/* finish if 2 bite jis overflows 3 */
if(s==2&&char_len==2)
{
break;
}
/* use '_' if illegal*/
else if(_illegal_jis_alias_char(p_temp))
{
*p_temp_2++ = '_';
s += 1;
}
else
{
*p_temp_2++ = *p_temp;
if (char_len==2)
*p_temp_2++ = *(p_temp+1);
s += char_len;
}
}
}
jis_ext_len = s; /* Save for later. bytes in */
}
*p_temp_2 = 0; /* NULL terminate extention */
/* copy file name to filename[], filtering out spaces, periods and
replacing characters illegal in alias names with '_' */
p_temp = input_file;
p_temp_2 = filename;
for(s=0; *p_temp!=0 && s<8; p_temp += char_len)
{
if (p_in_ext && p_temp>=p_in_ext) /* hit extension ? */
break;
char_len = jis_char_length(p_temp);
/* break and use ' ' if 2 bite jis overflows 6 */
if(s==5&&char_len==2)
{
break;
}
else if(*p_temp!=' ' && *p_temp !='.')
{
if(_illegal_jis_alias_char(p_temp))
{
*p_temp_2++ = '_';
s += 1;
}
else
{
*p_temp_2++ = *p_temp;
if (char_len==2)
*p_temp_2++ = *(p_temp+1);
s += char_len;
}
}
}
filename[8]=0; /* null terminate filename[] */
pc_ascii_str2upper(filename,filename);
pc_ascii_str2upper(fileext,fileext);
/* append (TEXT[])i to filename[] */
if (try != -1)
{
for(n=7,s=try; s>0 && n>0; s/=10,n--)
{
filename[n] = (byte)(((byte)s%10)+'0');
}
if(n==0 && s>0)
return(FALSE);
else
filename[n]='~';
}
p_temp_2 = alias;
p_temp = filename;
/* copy filename[] to alias[], filtering out spaces */
s = 0;
while(*p_temp)
{
char_len = jis_char_length(p_temp);
if (s == 7 && char_len == 2)
break;
if(*p_temp!=' ')
{
*p_temp_2++=*p_temp++;
if (char_len == 2)
*p_temp_2++=*p_temp++;
s += char_len;
if (s == 8)
break;
}
else
p_temp++;
}
if(jis_ext_len != 0)
{
*p_temp_2++='.'; /* insert separating period */
/* copy fileext[] to alias[] */
for(s=0; s < jis_ext_len; s++)
{
*p_temp_2++ = fileext[s];
}
}
*p_temp_2=0; /* null terminate alias[] */
return(TRUE);
}
#endif
#if (!VFAT) /* Small piece of compile time VFAT vs's NONVFAT code */
BOOLEAN validate_8_3_name(byte * name,int len) /*__fn__*/
{
int i;
int last;
last = len-1;
for (i = 0; i < len; i++)
{
/* If we hit a space make sure the rest of the string is spaces */
if (name[i] == ' ')
{
for (; i < len; i++)
{
if (name[i] != ' ')
return(FALSE);
}
break;
}
else
{
if (_illegal_jis_alias_char(&name[i]))
return(FALSE);
/* If it is a 2 byte char advance i */
if (jis_char_length(&name[i])==2)
{
if (i == last)
return(FALSE); /* two byte at the end. no good */
i++;
}
}
}
return(TRUE);
}
BOOLEAN validate_filename(byte * name, byte * ext) /*__fn__*/
{
byte sfn_buffer[14]; /* Only uses 13 but keep declarations even */
if (!( validate_8_3_name(name,8) && validate_8_3_name(ext,3)) )
return(FALSE);
pc_ascii_mfile(sfn_buffer, name, ext);
return (pc_valid_sfn(sfn_buffer));
}
BOOLEAN pc_patcmp_8(byte *p, byte *pattern, BOOLEAN dowildcard) /* __fn__*/
{
int size = 8;
byte save_char;
byte *save_p;
BOOLEAN ret_val;
/* Kludge. never match a deleted file */
if (*p == PCDELETE)
return (FALSE);
save_p = p;
save_char = *p;
if(save_char == 0x05)
*p = 0xe5; /* JIS KANJI char */
ret_val = TRUE;
while (size > 0)
{
if(dowildcard)
{
if (*pattern == '*') /* '*' matches the rest of the name */
goto ret;
if (*pattern != '?' && !jis_compare_nc(pattern,p))
{
ret_val = FALSE;
goto ret;
}
}
else
{
if (!jis_compare_nc(pattern,p))
{
ret_val = FALSE;
goto ret;
}
}
size -= jis_char_length(p);
p = jis_increment(p);
pattern = jis_increment(pattern);
}
ret:
*save_p = save_char;
return(ret_val);
}
BOOLEAN pc_patcmp_3(byte *p, byte *pattern, BOOLEAN dowildcard) /* __fn__*/
{
int size = 3;
BOOLEAN ret_val;
ret_val = TRUE;
while (size > 0)
{
if(dowildcard)
{
if (*pattern == '*') /* '*' matches the rest of the name */
goto ret;
if (*pattern != '?' && !jis_compare_nc(pattern,p))
{
ret_val = FALSE;
goto ret;
}
}
else
{
if (!jis_compare_nc(pattern,p))
{
ret_val = FALSE;
goto ret;
}
}
size -= jis_char_length(p);
p = jis_increment(p);
pattern = jis_increment(pattern);
}
ret:
return(ret_val);
}
#endif
/* map_jis_input() - take an ascii input string and return a string with
containing the input but convert escaped values into hex in the output
escape <XX to 8 bit hex, >XXXX to 16 bit hex
Uses static storage, allows 3 buffers. More can be added
Used only in test programs.
MAPINPUT() calls this routine to convert input ASCII to JIS
*/
#define NJISINBUF 3
byte btoc(byte b)
{
byte c;
if (b >= '0' && b <= '9') c = (byte)(b - '0');
else if (b >= 'a' && b <= 'f') c = (byte)(10 + b - 'a');
else if (b >= 'A' && b <= 'F') c = (byte)(10 + b - 'A');
else c = 0; /* Default. bad input to zero */
return(c);}
byte btohex(byte *pb){
byte c;
c = btoc(*pb);
c <<= 4;
pb++;
c = (byte) (c + btoc(*pb));
return(c);
}
byte jis_in_buf[NJISINBUF][255];
int cur_jis_in_buf = 0;
byte *map_jis_input(byte *pin)
{
byte *pout;
pout = &jis_in_buf[cur_jis_in_buf][0];
while (*pin)
{
if (*pin == '<') /* 8 bit hex esc */
{
pin++;
*pout++ = btohex(pin);
pin+=2;
}
else if (*pin == '>') /* 16 bit hex esc */
{
pin++;
*pout++ = btohex(pin);
pin+=2;
*pout++ = btohex(pin);
pin+=2;
}
else
*pout++ = *pin++;
}
*pout = 0;
/* Set up return */
pout = &jis_in_buf[cur_jis_in_buf][0];
/* Increment the pointer */
cur_jis_in_buf += 1;
if (cur_jis_in_buf == NJISINBUF)
cur_jis_in_buf = 0;
return(pout);
}
#define NJISOUTBUF 3
byte btoal(byte c)
{byte a; c &= 0xf; if (c < 10) a = (byte) (c + '0'); else a = (byte) (c-10 + 'A');
return(a);}
byte btoah(byte c)
{byte a;a = (byte)((c>>4)&0xf); return(btoal(a));}
byte jis_out_buf[NJISOUTBUF][255];
int cur_jis_out_buf = 0;
byte *map_jis_output(byte *pin)
{
byte *pout;
int l;
pout = &jis_out_buf[cur_jis_out_buf][0];
while (*pin)
{
if (*pin & 0x80) /* JIS Character */
{
l = jis_char_length(pin);
*pout++='[';
*pout++ = btoah(*pin);
*pout++ = btoal(*pin++);
if (l == 2)
{
*pout++ = btoah(*pin);
*pout++ = btoal(*pin++);
}
*pout++=']';
}
else
*pout++ = *pin++;
}
*pout = 0;
/* Set up return */
pout = &jis_out_buf[cur_jis_out_buf][0];
/* Increment the pointer */
if (cur_jis_out_buf == NJISOUTBUF)
cur_jis_out_buf = 0;
return((byte *)pout);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,991 @@
#include <rtfs.h>
/* To preserve memory you may exclude strings from the string table
if the corresponding module is not being used. Set the definition
in this table to zero if you wish to exclude strings from the
from the corresponding module.
*/
#define INCLUDE_CHKDSK_STRINGS 1
#define INCLUDE_FLDRVER_STRINGS 1
#define INCLUDE_FLASHDRV_STRINGS 1
#define INCLUDE_FLASHEMU_STRINGS 1
#define INCLUDE_RTFSINIT_STRINGS 1
#define INCLUDE_IDEDRV_STRINGS 1
#define INCLUDE_PORTMAIN_STRINGS 1
#define INCLUDE_PORTKERN_STRINGS 1
#define INCLUDE_RTFSDEM_STRINGS 1 /* For APIRGRS.C */
#define INCLUDE_TSTSH_STRINGS 1
/* Set this value to 1 if strings are entered as ascii and we require
the unicode layer to expand them to 16 bit character strings
set it to zero if you replace the strrings in the table with
true UNICODE
*/
typedef struct rtfs_string_table {
int string_id;
byte *string_value;
} RTFS_STRING_TABLE;
KS_CONSTANT RTFS_STRING_TABLE prompt_table[] = {
#if (INCLUDE_CS_UNICODE)
{UPROMPT_CRITERR,(byte *)L"Type A to abort R to Retry"},
{UPROMPT_REGRESS,(byte *)L"Regression Test Error, press any key to exit" },
#else
{UPROMPT_CRITERR,(byte *)"Type A to abort R to Retry"},
{UPROMPT_REGRESS,(byte *)"Regression Test Error, press any key to exit" },
#endif
#if (INCLUDE_TSTSH_STRINGS)
#if (INCLUDE_CS_UNICODE)
{UPROMPT_TSTSH1,(byte *)L"CMD> " },
{UPROMPT_TSTSH2,(byte *)L"Press Return " },
{UPROMPT_TSTSH3,(byte *)L"Enter the drive to format as A:, B: etc " },
{UPROMPT_TSTSH4,(byte *)L"Invalid drive selection to format, press return" },
{UPROMPT_TSTSH5,(byte *)L"Format - check media failed. Press return" },
{UPROMPT_TSTSH6,(byte *)L"Format: get media geometry failed. Press return" },
{UPROMPT_TSTSH7,(byte *)L"Format: Press Y to format media " },
{UPROMPT_TSTSH8,(byte *)L"Format: Media format failed. Press return" },
{UPROMPT_TSTSH9,(byte *)L"Format: Press Y to partition media " },
{UPROMPT_TSTSH10,(byte *)L"Format: Press Y to USE LBA formatting, N to use CHS " },
{UPROMPT_TSTSH11,(byte *)L"Format: Select the number of lbas for the first partition :" },
{UPROMPT_TSTSH12,(byte *)L"Format: Select the number of lbas for the second partition :" },
{UPROMPT_TSTSH13,(byte *)L"Format: Bad input for partition values. Press return" },
{UPROMPT_TSTSH14,(byte *)L"Format: Select the number of cyls for the first partition :" },
{UPROMPT_TSTSH15,(byte *)L"Format: Select the number of cyls for the second partition :" },
{UPROMPT_TSTSH16,(byte *)L"Format: Media partition failed. Press return" },
{UPROMPT_TSTSH17,(byte *)L"Format: Press Y to format the volume " },
{UPROMPT_TSTSH18,(byte *)L"Format: Format volume failed. Press return" },
#else
{UPROMPT_TSTSH1,(byte *)"CMD> " },
{UPROMPT_TSTSH2,(byte *)"Press Return " },
{UPROMPT_TSTSH3,(byte *)"Enter the drive to format as A:, B: etc " },
{UPROMPT_TSTSH4,(byte *)"Invalid drive selection to format, press return" },
{UPROMPT_TSTSH5,(byte *)"Format - check media failed. Press return" },
{UPROMPT_TSTSH6,(byte *)"Format: get media geometry failed. Press return" },
{UPROMPT_TSTSH7,(byte *)"Format: Press Y to format media " },
{UPROMPT_TSTSH8,(byte *)"Format: Media format failed. Press return" },
{UPROMPT_TSTSH9,(byte *)"Format: Press Y to partition media " },
{UPROMPT_TSTSH10,(byte *)"Format: Press Y to USE LBA formatting, N to use CHS " },
{UPROMPT_TSTSH11,(byte *)"Format: Select the number of lbas for the first partition :" },
{UPROMPT_TSTSH12,(byte *)"Format: Select the number of lbas for the second partition :" },
{UPROMPT_TSTSH13,(byte *)"Format: Bad input for partition values. Press return" },
{UPROMPT_TSTSH14,(byte *)"Format: Select the number of cyls for the first partition :" },
{UPROMPT_TSTSH15,(byte *)"Format: Select the number of cyls for the second partition :" },
{UPROMPT_TSTSH16,(byte *)"Format: Media partition failed. Press return" },
{UPROMPT_TSTSH17,(byte *)"Format: Press Y to format the volume " },
{UPROMPT_TSTSH18,(byte *)"Format: Format volume failed. Press return" },
#endif
#endif /* (INCLUDE_TSTSH_STRINGS) */
#if (INCLUDE_CS_UNICODE)
{UPROMPT_WINSPLSH,(byte *)L"<return> for next, (P)<return> for Previous, (Q)<return> to run demo" },
{0,(byte *)L"Unkown User Prompt" }
#else
{UPROMPT_WINSPLSH,(byte *)"<return> for next, (P)<return> for Previous, (Q)<return> to run demo" },
{0,(byte *)"Unkown User Prompt" }
#endif
};
KS_CONSTANT RTFS_STRING_TABLE string_table[] = {
#if (INCLUDE_CS_UNICODE)
{USTRING_SYS_NULL,(byte *)L"" },
/* Note that USTRING_SYS_BADALIAS is not stored as a wide string. this
is processed as a string of 8 bit characters */
{USTRING_SYS_BADALIAS,(byte *)"\\/:*?\"<>| ,;=+[]" },
{USTRING_SYS_BADLFN,(byte *)L"\\/:*?\"<>|" },
/* Note that USTRING_SYS_UCRESERVED_NAMES and USTRING_SYS_LCRESERVED_NAMES
are not stored as a wide string. they are processed as strings of 8 bit characters */
{USTRING_SYS_UCRESERVED_NAMES,(byte *)"CON,PRN,NUL,AUX,LPT1,LPT2,LPT3,LPT4,COM1,COM2,COM3,COM4" },
{USTRING_SYS_LCRESERVED_NAMES,(byte *)"con,prn,nul,aux,lpt1,lpt2,lpt3,lpt4,com1,com2,com3,com4" },
{USTRING_SYS_VOLUME_LABEL,(byte *)L"VOLUMELABEL" }, /* 11 chars max (12th is NUL) */
{USTRING_SYS_OEMNAME,(byte *)L"EBS" },
{USTRING_SYS_TAB,(byte *)L" " },
#if (INCLUDE_FAILSAFE_CODE)
{USTRING_SYS_FSFILENAME,(byte *)L"\\FAILSAFE" },
#endif
#else
{USTRING_SYS_NULL,(byte *)"" },
{USTRING_SYS_BADALIAS,(byte *)"\\/:*?\"<>| ,;=+[]" },
{USTRING_SYS_BADLFN,(byte *)"\\/:*?\"<>|" },
{USTRING_SYS_UCRESERVED_NAMES,(byte *)"CON,PRN,NUL,AUX,LPT1,LPT2,LPT3,LPT4,COM1,COM2,COM3,COM4" },
{USTRING_SYS_LCRESERVED_NAMES,(byte *)"con,prn,nul,aux,lpt1,lpt2,lpt3,lpt4,com1,com2,com3,com4" },
{USTRING_SYS_VOLUME_LABEL,(byte *)"VOLUMELABE" }, /* 11 chars max (12th is NUL) */
{USTRING_SYS_OEMNAME,(byte *)"EBS" },
{USTRING_SYS_TAB,(byte *)" " },
#if (INCLUDE_FAILSAFE_CODE)
{USTRING_SYS_FSFILENAME,(byte *)"\\FAILSAFE" },
#endif
#endif
#if (INCLUDE_CHKDSK_STRINGS)
#if (INCLUDE_CS_UNICODE)
{USTRING_CHKDSK_01,(byte *)L"Error Accessing: " },
{USTRING_CHKDSK_02,(byte *)L"Failed Allocating Core To Run" },
{USTRING_CHKDSK_03,(byte *)L"Failed Scanning Disk Files" },
{USTRING_CHKDSK_04,(byte *)L"Failed Scanning Fat" },
{USTRING_CHKDSK_05,(byte *)L" Creating .CHK Files" },
{USTRING_CHKDSK_06,(byte *)L" Failed Creating .CHK Files" },
{USTRING_CHKDSK_07,(byte *)L" Use -f option to create .CHK files" },
{USTRING_CHKDSK_08,(byte *)L"Failed Scanning Crossed Files" },
{USTRING_CHKDSK_09,(byte *)L" Crossed Chains Were Found" },
{USTRING_CHKDSK_11,(byte *)L" user files in this many directories " },
{USTRING_CHKDSK_13,(byte *)L" Kbytes total disk space" },
{USTRING_CHKDSK_15,(byte *)L" Kbytes in " },
{USTRING_CHKDSK_16,(byte *)L" hidden files" },
{USTRING_CHKDSK_18,(byte *)L" KBytes in " },
{USTRING_CHKDSK_19,(byte *)L" directories" },
{USTRING_CHKDSK_21,(byte *)L" KBytes in " },
{USTRING_CHKDSK_22,(byte *)L" user files" },
{USTRING_CHKDSK_24,(byte *)L" KBytes in bad sectors" },
{USTRING_CHKDSK_26,(byte *)L" Free sectors available on disk" },
{USTRING_CHKDSK_29,(byte *)L" Bytes Per Allocation Unit" },
{USTRING_CHKDSK_30,(byte *)L" " },
{USTRING_CHKDSK_32,(byte *)L" Total Allocation Units On Disk" },
{USTRING_CHKDSK_35,(byte *)L" lost clusters found in " },
{USTRING_CHKDSK_36,(byte *)L" lost chains" },
{USTRING_CHKDSK_38,(byte *)L" bad long file name chains found" },
{USTRING_CHKDSK_39,(byte *)L" and deleted" },
{USTRING_CHKDSK_40,(byte *)L" that were not deleted" },
{USTRING_CHKDSK_41,(byte *)L" Chains Crossed at Cluster" },
{USTRING_CHKDSK_42,(byte *)L" " },
{USTRING_CHKDSK_43,(byte *)L" Lost Chains" },
{USTRING_CHKDSK_44,(byte *)L" A Lost Chain" },
{USTRING_CHKDSK_45,(byte *)L"Path too deep , directory == " },
{USTRING_CHKDSK_46,(byte *)L"Failed Scanning This Directory on LFN Pass -" },
{USTRING_CHKDSK_47,(byte *)L"Failed Scanning This Directory -" },
{USTRING_CHKDSK_48,(byte *)L"Failed Scanning This Directory -" },
{USTRING_CHKDSK_49,(byte *)L" " },
{USTRING_CHKDSK_50,(byte *)L"Failed Scanning This File " },
{USTRING_CHKDSK_51,(byte *)L"Failed Scanning This Directory -" },
{USTRING_CHKDSK_52,(byte *)L"Failed Writing This Adusted File: " },
{USTRING_CHKDSK_53,(byte *)L"Size Adusted, This File: " },
{USTRING_CHKDSK_54,(byte *)L"Size Needs Adusting This File: " },
{USTRING_CHKDSK_55,(byte *)L"Chkdsk Giving up. Too Many Lost Chains" },
{USTRING_CHKDSK_56,(byte *)L"Failed Scanning This Directory " },
{USTRING_CHKDSK_57,(byte *)L"Failed Scanning This Directory " },
{USTRING_CHKDSK_58,(byte *)L" " },
{USTRING_CHKDSK_59,(byte *)L"Failed Scanning This File " },
{USTRING_CHKDSK_60,(byte *)L"Failed Scanning This Directory " },
{USTRING_CHKDSK_61,(byte *)L"Chkdsk gives up, too many crossed Files" },
{USTRING_CHKDSK_62,(byte *)L"Chkdsk gives up, Too many crossed chains" },
#else
{USTRING_CHKDSK_01,(byte *)"Error Accessing: " },
{USTRING_CHKDSK_02,(byte *)"Failed Allocating Core To Run" },
{USTRING_CHKDSK_03,(byte *)"Failed Scanning Disk Files" },
{USTRING_CHKDSK_04,(byte *)"Failed Scanning Fat" },
{USTRING_CHKDSK_05,(byte *)" Creating .CHK Files" },
{USTRING_CHKDSK_06,(byte *)" Failed Creating .CHK Files" },
{USTRING_CHKDSK_07,(byte *)" Use -f option to create .CHK files" },
{USTRING_CHKDSK_08,(byte *)"Failed Scanning Crossed Files" },
{USTRING_CHKDSK_09,(byte *)" Crossed Chains Were Found" },
{USTRING_CHKDSK_11,(byte *)" user files in this many directories " },
{USTRING_CHKDSK_13,(byte *)" Kbytes total disk space" },
{USTRING_CHKDSK_15,(byte *)" Kbytes in " },
{USTRING_CHKDSK_16,(byte *)" hidden files" },
{USTRING_CHKDSK_18,(byte *)" KBytes in " },
{USTRING_CHKDSK_19,(byte *)" directories" },
{USTRING_CHKDSK_21,(byte *)" KBytes in " },
{USTRING_CHKDSK_22,(byte *)" user files" },
{USTRING_CHKDSK_24,(byte *)" KBytes in bad sectors" },
{USTRING_CHKDSK_26,(byte *)" Free sectors available on disk" },
{USTRING_CHKDSK_29,(byte *)" Bytes Per Allocation Unit" },
{USTRING_CHKDSK_30,(byte *)" " },
{USTRING_CHKDSK_32,(byte *)" Total Allocation Units On Disk" },
{USTRING_CHKDSK_35,(byte *)" lost clusters found in " },
{USTRING_CHKDSK_36,(byte *)" lost chains" },
{USTRING_CHKDSK_38,(byte *)" bad long file name chains found" },
{USTRING_CHKDSK_39,(byte *)" and deleted" },
{USTRING_CHKDSK_40,(byte *)" that were not deleted" },
{USTRING_CHKDSK_41,(byte *)" Chains Crossed at Cluster" },
{USTRING_CHKDSK_42,(byte *)" " },
{USTRING_CHKDSK_43,(byte *)" Lost Chains" },
{USTRING_CHKDSK_44,(byte *)" A Lost Chain" },
{USTRING_CHKDSK_45,(byte *)"Path too deep , directory == " },
{USTRING_CHKDSK_46,(byte *)"Failed Scanning This Directory on LFN Pass -" },
{USTRING_CHKDSK_47,(byte *)"Failed Scanning This Directory -" },
{USTRING_CHKDSK_48,(byte *)"Failed Scanning This Directory -" },
{USTRING_CHKDSK_49,(byte *)" " },
{USTRING_CHKDSK_50,(byte *)"Failed Scanning This File " },
{USTRING_CHKDSK_51,(byte *)"Failed Scanning This Directory -" },
{USTRING_CHKDSK_52,(byte *)"Failed Writing This Adusted File: " },
{USTRING_CHKDSK_53,(byte *)"Size Adusted, This File: " },
{USTRING_CHKDSK_54,(byte *)"Size Needs Adusting This File: " },
{USTRING_CHKDSK_55,(byte *)"Chkdsk Giving up. Too Many Lost Chains" },
{USTRING_CHKDSK_56,(byte *)"Failed Scanning This Directory " },
{USTRING_CHKDSK_57,(byte *)"Failed Scanning This Directory " },
{USTRING_CHKDSK_58,(byte *)" " },
{USTRING_CHKDSK_59,(byte *)"Failed Scanning This File " },
{USTRING_CHKDSK_60,(byte *)"Failed Scanning This Directory " },
{USTRING_CHKDSK_61,(byte *)"Chkdsk gives up, too many crossed Files" },
{USTRING_CHKDSK_62,(byte *)"Chkdsk gives up, Too many crossed chains" },
#endif
#endif /* (INCLUDE_CHKDSK_STRINGS) */
#if (INCLUDE_CS_UNICODE)
{USTRING_CRITERR_02,(byte *)L"BAD_FORMAT" },
{USTRING_CRITERR_03,(byte *)L"CRERR_NO_CARD" },
{USTRING_CRITERR_04,(byte *)L"CRERR_BAD_CARD" },
{USTRING_CRITERR_05,(byte *)L"CRERR_CHANGED_CARD" },
{USTRING_CRITERR_06,(byte *)L"CRERR_CARD_FAILURE" },
{USTRING_CRITERR_07,(byte *)L"Media status == " },
{USTRING_CRITERR_08,(byte *)L"Volume == " },
{USTRING_CRITERR_09,(byte *)L"Volume is dirty" },
{USTRING_CRITERR_10,(byte *)L"Volume is clean" },
#else
{USTRING_CRITERR_02,(byte *)"BAD_FORMAT" },
{USTRING_CRITERR_03,(byte *)"CRERR_NO_CARD" },
{USTRING_CRITERR_04,(byte *)"CRERR_BAD_CARD" },
{USTRING_CRITERR_05,(byte *)"CRERR_CHANGED_CARD" },
{USTRING_CRITERR_06,(byte *)"CRERR_CARD_FAILURE" },
{USTRING_CRITERR_07,(byte *)"Media status == " },
{USTRING_CRITERR_08,(byte *)"Volume == " },
{USTRING_CRITERR_09,(byte *)"Volume is dirty" },
{USTRING_CRITERR_10,(byte *)"Volume is clean" },
#endif
#if (INCLUDE_FLDRVER_STRINGS)
#if (INCLUDE_CS_UNICODE)
{USTRING_FLDRVER_01,(byte *)L"Formatting " },
{USTRING_FLDRVER_02,(byte *)L" of " },
{USTRING_FLDRVER_03,(byte *)L" total tracks " },
{USTRING_FLDRVER_04,(byte *)L"Format failed resid != 0" },
{USTRING_FLDRVER_06,(byte *)L"Abnormal Termination Error FLERR_ABN_TERM" },
{USTRING_FLDRVER_07,(byte *)L"Floppy controller not responding FLERR_CHIP_HUNG " },
{USTRING_FLDRVER_08,(byte *)L"Dma Error FLERR_DMA " },
{USTRING_FLDRVER_09,(byte *)L"Error during format FLERR_FORMAT " },
{USTRING_FLDRVER_10,(byte *)L"Invalid Interleave For Media Type FLERR_INVALID_INTERLEAVE" },
{USTRING_FLDRVER_11,(byte *)L"Sector Not Found FLERR_IO_SECTOR" },
{USTRING_FLDRVER_12,(byte *)L"Time out FLERR_IO_TMO " },
{USTRING_FLDRVER_13,(byte *)L"Can not determine Media FLERR_MEDIA " },
{USTRING_FLDRVER_14,(byte *)L"Error During Recal FLERR_RECAL " },
{USTRING_FLDRVER_15,(byte *)L"Error resetting drive FLERR_RESET " },
{USTRING_FLDRVER_16,(byte *)L"Error during seek FLERR_SEEK " },
{USTRING_FLDRVER_17,(byte *)L"Error during specify FLERR_SPECIFY" },
{USTRING_FLDRVER_18,(byte *)L"Unknown Drive type FLERR_UNK_DRIVE" },
{USTRING_FLDRVER_19,(byte *)L"Unspecified floppy error" },
#else
{USTRING_FLDRVER_01,(byte *)"Formatting " },
{USTRING_FLDRVER_02,(byte *)" of " },
{USTRING_FLDRVER_03,(byte *)" total tracks " },
{USTRING_FLDRVER_04,(byte *)"Format failed resid != 0" },
{USTRING_FLDRVER_06,(byte *)"Abnormal Termination Error FLERR_ABN_TERM" },
{USTRING_FLDRVER_07,(byte *)"Floppy controller not responding FLERR_CHIP_HUNG " },
{USTRING_FLDRVER_08,(byte *)"Dma Error FLERR_DMA " },
{USTRING_FLDRVER_09,(byte *)"Error during format FLERR_FORMAT " },
{USTRING_FLDRVER_10,(byte *)"Invalid Interleave For Media Type FLERR_INVALID_INTERLEAVE" },
{USTRING_FLDRVER_11,(byte *)"Sector Not Found FLERR_IO_SECTOR" },
{USTRING_FLDRVER_12,(byte *)"Time out FLERR_IO_TMO " },
{USTRING_FLDRVER_13,(byte *)"Can not determine Media FLERR_MEDIA " },
{USTRING_FLDRVER_14,(byte *)"Error During Recal FLERR_RECAL " },
{USTRING_FLDRVER_15,(byte *)"Error resetting drive FLERR_RESET " },
{USTRING_FLDRVER_16,(byte *)"Error during seek FLERR_SEEK " },
{USTRING_FLDRVER_17,(byte *)"Error during specify FLERR_SPECIFY" },
{USTRING_FLDRVER_18,(byte *)"Unknown Drive type FLERR_UNK_DRIVE" },
{USTRING_FLDRVER_19,(byte *)"Unspecified floppy error" },
#endif
#endif /* (INCLUDE_FLDRVER_STRINGS) */
#if (INCLUDE_FLASHDRV_STRINGS)
#if (INCLUDE_CS_UNICODE)
{USTRING_FLASHDRV_01,(byte *)L"DISK FULL" },
{USTRING_FLASHDRV_02,(byte *)L"DATA ERROR" },
{USTRING_FLASHDRV_03,(byte *)L"DEVICE RESOURCE ERROR" },
{USTRING_FLASHDRV_04,(byte *)L"INTERNAL ERROR" },
{USTRING_FLASHDRV_05,(byte *)L"Flash: Exception at line " },
{USTRING_FLASHDRV_06,(byte *)L"RTFSYSErrorExit() called at line " },
{USTRING_FLASHDRV_07,(byte *)L"Avail count messed up" },
{USTRING_FLASHDRV_08,(byte *)L"*** adjusting EraseCount by " },
{USTRING_FLASHDRV_09,(byte *)L"CopyBlock from " },
{USTRING_FLASHDRV_10,(byte *)L" To " },
{USTRING_FLASHDRV_11,(byte *)L"Replaced " },
{USTRING_FLASHDRV_12,(byte *)L" Copied " },
{USTRING_FLASHDRV_13,(byte *)L"Avail " },
{USTRING_FLASHDRV_14,(byte *)L" Recovered " },
{USTRING_FLASHDRV_15,(byte *)L"*** Wareleveling block " },
{USTRING_FLASHDRV_16,(byte *)L"spare block not found" },
{USTRING_FLASHDRV_17,(byte *)L"new spare block not found" },
{USTRING_FLASHDRV_18,(byte *)L"Writing Sector " },
{USTRING_FLASHDRV_19,(byte *)L" count " },
{USTRING_FLASHDRV_20,(byte *)L"flash driver: ca not find a free sector" },
{USTRING_FLASHDRV_21,(byte *)L"flash driver: ca not find sector to write" },
{USTRING_FLASHDRV_22,(byte *)L"flash media too large" },
{USTRING_FLASHDRV_23,(byte *)L"flash disk OK" },
{USTRING_FLASHDRV_24,(byte *)L"Fixing 1" },
{USTRING_FLASHDRV_25,(byte *)L"Fixing 2" },
{USTRING_FLASHDRV_26,(byte *)L"Fixing 3" },
{USTRING_FLASHDRV_27,(byte *)L"Invalid sector value in flash" },
{USTRING_FLASHDRV_28,(byte *)L"Sector found twice" },
{USTRING_FLASHDRV_29,(byte *)L"Invalid Sector status" },
{USTRING_FLASHDRV_30,(byte *)L"Fixing 4" },
{USTRING_FLASHDSK_01,(byte *)L"Flash device is formatted already." },
{USTRING_FLASHDSK_02,(byte *)L"Call again to override and format." },
#else
{USTRING_FLASHDRV_01,(byte *)"DISK FULL" },
{USTRING_FLASHDRV_02,(byte *)"DATA ERROR" },
{USTRING_FLASHDRV_03,(byte *)"DEVICE RESOURCE ERROR" },
{USTRING_FLASHDRV_04,(byte *)"INTERNAL ERROR" },
{USTRING_FLASHDRV_05,(byte *)"Flash: Exception at line " },
{USTRING_FLASHDRV_06,(byte *)"RTFSYSErrorExit() called at line " },
{USTRING_FLASHDRV_07,(byte *)"Avail count messed up" },
{USTRING_FLASHDRV_08,(byte *)"*** adjusting EraseCount by " },
{USTRING_FLASHDRV_09,(byte *)"CopyBlock from " },
{USTRING_FLASHDRV_10,(byte *)" To " },
{USTRING_FLASHDRV_11,(byte *)"Replaced " },
{USTRING_FLASHDRV_12,(byte *)" Copied " },
{USTRING_FLASHDRV_13,(byte *)"Avail " },
{USTRING_FLASHDRV_14,(byte *)" Recovered " },
{USTRING_FLASHDRV_15,(byte *)"*** Wareleveling block " },
{USTRING_FLASHDRV_16,(byte *)"spare block not found" },
{USTRING_FLASHDRV_17,(byte *)"new spare block not found" },
{USTRING_FLASHDRV_18,(byte *)"Writing Sector " },
{USTRING_FLASHDRV_19,(byte *)" count " },
{USTRING_FLASHDRV_20,(byte *)"flash driver: ca not find a free sector" },
{USTRING_FLASHDRV_21,(byte *)"flash driver: ca not find sector to write" },
{USTRING_FLASHDRV_22,(byte *)"flash media too large" },
{USTRING_FLASHDRV_23,(byte *)"flash disk OK" },
{USTRING_FLASHDRV_24,(byte *)"Fixing 1" },
{USTRING_FLASHDRV_25,(byte *)"Fixing 2" },
{USTRING_FLASHDRV_26,(byte *)"Fixing 3" },
{USTRING_FLASHDRV_27,(byte *)"Invalid sector value in flash" },
{USTRING_FLASHDRV_28,(byte *)"Sector found twice" },
{USTRING_FLASHDRV_29,(byte *)"Invalid Sector status" },
{USTRING_FLASHDRV_30,(byte *)"Fixing 4" },
{USTRING_FLASHDSK_01,(byte *)"Flash device is formatted already." },
{USTRING_FLASHDSK_02,(byte *)"Call again to override and format." },
#endif
#endif /* (INCLUDE_FLASHDRV_STRINGS) */
#if (INCLUDE_FLASHEMU_STRINGS)
#if (INCLUDE_CS_UNICODE)
{USTRING_FLASHEMU_01,(byte *)L"Curr > Base hit" },
{USTRING_FLASHEMU_02,(byte *)L"Flash emu hit trap" },
{USTRING_FLASHEMU_03,(byte *)L"flash emulator: called with file not open " },
{USTRING_FLASHEMU_04,(byte *)L"MapWindow beyond block" },
{USTRING_FLASHEMU_05,(byte *)L"EraseBlock: block not mapped" },
{USTRING_FLASHEMU_06,(byte *)L"ProgramData: outside Window" },
{USTRING_FLASHEMU_07,(byte *)L"attempt to unset bits in flash!" },
#else
{USTRING_FLASHEMU_01,(byte *)"Curr > Base hit" },
{USTRING_FLASHEMU_02,(byte *)"Flash emu hit trap" },
{USTRING_FLASHEMU_03,(byte *)"flash emulator: called with file not open " },
{USTRING_FLASHEMU_04,(byte *)"MapWindow beyond block" },
{USTRING_FLASHEMU_05,(byte *)"EraseBlock: block not mapped" },
{USTRING_FLASHEMU_06,(byte *)"ProgramData: outside Window" },
{USTRING_FLASHEMU_07,(byte *)"attempt to unset bits in flash!" },
#endif
#endif /* (INCLUDE_FLASHEMU_STRINGS) */
#if (INCLUDE_RTFSINIT_STRINGS)
#if (INCLUDE_CS_UNICODE)
{USTRING_RTFSINIT_01,(byte *)L"ERTFS Device List" },
{USTRING_RTFSINIT_02,(byte *)L"=================" },
{USTRING_RTFSINIT_03,(byte *)L"Name Logging Disabled" },
{USTRING_RTFSINIT_04,(byte *)L" = " },
{USTRING_RTFSINIT_05,(byte *)L"Autoformatting RAM Devices" },
{USTRING_RTFSINIT_06,(byte *)L"==========================" },
{USTRING_RTFSINIT_07,(byte *)L"Autoformatting Drive Id - " },
{USTRING_RTFSINIT_08,(byte *)L" as Device: " },
{USTRING_RTFSINIT_09,(byte *)L"Failed Autoformatting Drive Id - " },
{USTRING_RTFSINIT_10,(byte *)L" = " },
{USTRING_RTFSINIT_11,(byte *)L"NDRIVES is too small to mount all devices" },
{USTRING_RTFSINIT_12,(byte *)L"Device name : " },
{USTRING_RTFSINIT_13,(byte *)L" Is mounted on " },
#else
{USTRING_RTFSINIT_01,(byte *)"ERTFS Device List" },
{USTRING_RTFSINIT_02,(byte *)"=================" },
{USTRING_RTFSINIT_03,(byte *)"Name Logging Disabled" },
{USTRING_RTFSINIT_04,(byte *)" = " },
{USTRING_RTFSINIT_05,(byte *)"Autoformatting RAM Devices" },
{USTRING_RTFSINIT_06,(byte *)"==========================" },
{USTRING_RTFSINIT_07,(byte *)"Autoformatting Drive Id - " },
{USTRING_RTFSINIT_08,(byte *)" as Device: " },
{USTRING_RTFSINIT_09,(byte *)"Failed Autoformatting Drive Id - " },
{USTRING_RTFSINIT_10,(byte *)" = " },
{USTRING_RTFSINIT_11,(byte *)"NDRIVES is too small to mount all devices" },
{USTRING_RTFSINIT_12,(byte *)"Device name : " },
{USTRING_RTFSINIT_13,(byte *)" Is mounted on " },
#endif
#endif /* (INCLUDE_RTFSINIT_STRINGS) */
#if (INCLUDE_IDEDRV_STRINGS)
#if (INCLUDE_CS_UNICODE)
{USTRING_IDEDRV_01,(byte *)L"PIO Mode set succeed" },
{USTRING_IDEDRV_02,(byte *)L"PIO Mode set failed" },
{USTRING_IDEDRV_03,(byte *)L"Unknown ATAPI Command Issued" },
{USTRING_IDEDRV_04,(byte *)L"Get LBA VTOC failed" },
{USTRING_IDEDRV_05,(byte *)L"Read Audio Failed" },
#else
{USTRING_IDEDRV_01,(byte *)"PIO Mode set succeed" },
{USTRING_IDEDRV_02,(byte *)"PIO Mode set failed" },
{USTRING_IDEDRV_03,(byte *)"Unknown ATAPI Command Issued" },
{USTRING_IDEDRV_04,(byte *)"Get LBA VTOC failed" },
{USTRING_IDEDRV_05,(byte *)"Read Audio Failed" },
#endif
#endif /* (INCLUDE_IDEDRV_STRINGS) */
#if (INCLUDE_PORTMAIN_STRINGS)
#if (INCLUDE_CS_UNICODE)
{USTRING_PORTMAIN_01,(byte *)L"Spawn of main task failed. change priority ?" },
{USTRING_PORTMAIN_02,(byte *)L"Spawn of main task failed." },
#else
{USTRING_PORTMAIN_01,(byte *)"Spawn of main task failed. change priority ?" },
{USTRING_PORTMAIN_02,(byte *)"Spawn of main task failed." },
#endif
#endif /* (INCLUDE_PORTMAIN_STRINGS) */
#if (INCLUDE_PORTKERN_STRINGS)
#if (INCLUDE_CS_UNICODE)
{USTRING_PORTKERN_01,(byte *)L"Spawn of timer task failed. change priority " },
{USTRING_PORTKERN_02,(byte *)L"Spawn of timer task failed. " },
{USTRING_PORTKERN_03,(byte *)L"pc_report_error was called with error" },
{USTRING_PORTKERN_04,(byte *)L"Exitting and restoring interrupt vectors" },
#else
{USTRING_PORTKERN_01,(byte *)"Spawn of timer task failed. change priority " },
{USTRING_PORTKERN_02,(byte *)"Spawn of timer task failed. " },
{USTRING_PORTKERN_03,(byte *)"pc_report_error was called with error" },
{USTRING_PORTKERN_04,(byte *)"Exitting and restoring interrupt vectors" },
#endif
#endif /* (INCLUDE_PORTKERN_STRINGS) */
#if (INCLUDE_RTFSDEM_STRINGS)
#if (INCLUDE_CS_UNICODE)
{USTRING_RTFSDEM_01,(byte *)L"pc_ertfs_init failed" },
{USTRING_RTFSDEM_07,(byte *)L"Invalid Drive number" },
{USTRING_RTFSDEM_08,(byte *)L"Creating Subdirectory:" },
{USTRING_RTFSDEM_09,(byte *)L"Creating Subdirectory " },
{USTRING_RTFSDEM_10,(byte *)L"Creating Subdirectory " },
{USTRING_RTFSDEM_11,(byte *)L"Removing Directory " },
{USTRING_RTFSDEM_12,(byte *)L"-" },
{USTRING_RTFSDEM_13,(byte *)L"Performing File io test" },
{USTRING_RTFSDEM_14,(byte *)L"regress_error was called with error" },
{USTRING_RTFSDEM_15,(byte *)L"Performing long file name test" },
{USTRING_RTFSDEM_16,(byte *)L"Performing buffered file io test" },
{USTRING_RTFSDEM_17,(byte *)L"Performing Large (4Gig)File io test" },
#else
{USTRING_RTFSDEM_01,(byte *)"pc_ertfs_init failed" },
{USTRING_RTFSDEM_07,(byte *)"Invalid Drive number" },
{USTRING_RTFSDEM_08,(byte *)"Creating Subdirectory:" },
{USTRING_RTFSDEM_09,(byte *)"Creating Subdirectory " },
{USTRING_RTFSDEM_10,(byte *)"Creating Subdirectory " },
{USTRING_RTFSDEM_11,(byte *)"Removing Directory " },
{USTRING_RTFSDEM_12,(byte *)"-" },
{USTRING_RTFSDEM_13,(byte *)"Performing File io test" },
{USTRING_RTFSDEM_14,(byte *)"regress_error was called with error" },
{USTRING_RTFSDEM_15,(byte *)"Performing long file name test" },
{USTRING_RTFSDEM_16,(byte *)"Performing buffered file io test" },
{USTRING_RTFSDEM_17,(byte *)"Performing Large (4Gig)File io test" },
#endif
#endif /* (INCLUDE_RTFSDEM_STRINGS) */
#if (INCLUDE_TSTSH_STRINGS)
#if (INCLUDE_CS_UNICODE)
{USTRING_TSTSH_01,(byte *)L"CD Memory init failed" },
{USTRING_TSTSH_02,(byte *)L"Not implemented. See ide ioctl... " },
{USTRING_TSTSH_03,(byte *)L"Set Default Drive Failed" },
{USTRING_TSTSH_04,(byte *)L"Usage: DSKSELECT D: " },
{USTRING_TSTSH_05,(byte *)L"No more random file slots " },
{USTRING_TSTSH_06,(byte *)L"Cant open :" },
{USTRING_TSTSH_07,(byte *)L"Usage: RNDOP D:PATH RECLEN" },
{USTRING_TSTSH_08,(byte *)L"Cant find file" },
{USTRING_TSTSH_09,(byte *)L"Close failed" },
{USTRING_TSTSH_10,(byte *)L"Usage: CLOSE fd" },
{USTRING_TSTSH_11,(byte *)L"Cant find file" },
{USTRING_TSTSH_12,(byte *)L"Seek operation failed " },
{USTRING_TSTSH_13,(byte *)L"Usage: SEEK fd recordno" },
{USTRING_TSTSH_14,(byte *)L"Cant find file" },
{USTRING_TSTSH_15,(byte *)L"Read operation failed " },
{USTRING_TSTSH_16,(byte *)L"Usage: READ fd" },
{USTRING_TSTSH_17,(byte *)L"Cant find file" },
{USTRING_TSTSH_18,(byte *)L"Write operation failed " },
{USTRING_TSTSH_19,(byte *)L"Usage: WRITE fd data " },
{USTRING_TSTSH_20,(byte *)L"Usage: MKDIR D:PATH" },
{USTRING_TSTSH_21,(byte *)L"Usage: RMDIR D:PATH" },
{USTRING_TSTSH_22,(byte *)L"Usage: DELTREE D:PATH" },
{USTRING_TSTSH_23,(byte *)L"deleting --> " },
{USTRING_TSTSH_24,(byte *)L"Can not delete: " },
{USTRING_TSTSH_25,(byte *)L"Usage: DELETE D:PATH" },
{USTRING_TSTSH_26,(byte *)L"Usage: RENAME PATH NEWNAME" },
{USTRING_TSTSH_27,(byte *)L"Set cwd failed" },
{USTRING_TSTSH_28,(byte *)L"Get cwd failed" },
{USTRING_TSTSH_29,(byte *)L"PWD Failed " },
{USTRING_TSTSH_30,(byte *)L" " },
{USTRING_TSTSH_31,(byte *)L" File(s) " },
{USTRING_TSTSH_32,(byte *)L" Blocks Free " },
{USTRING_TSTSH_33,(byte *)L"Cant open " },
{USTRING_TSTSH_34,(byte *)L"Usage: CAT PATH" },
{USTRING_TSTSH_35,(byte *)L"Usage: CHKDSK DRIVE: WRITECHAINS" },
{USTRING_TSTSH_36,(byte *)L"Example:CHKDSK A: 1" },
{USTRING_TSTSH_37,(byte *)L"Runs chkdsk on A: writes lost chains" },
{USTRING_TSTSH_38,(byte *)L"Example:CHKDSK A: 0" },
{USTRING_TSTSH_39,(byte *)L"Runs chkdsk on A: does not write lost chains" },
{USTRING_TSTSH_40,(byte *)L"Cant open file: " },
{USTRING_TSTSH_41,(byte *)L"Change size function failed" },
{USTRING_TSTSH_42,(byte *)L"Usage: CHSIZE PATH NEWSIZE" },
{USTRING_TSTSH_43,(byte *)L"Cant open file: " },
{USTRING_TSTSH_44,(byte *)L"Cant open file" },
{USTRING_TSTSH_45,(byte *)L"Write failure " },
{USTRING_TSTSH_46,(byte *)L"Usage: COPY FROMPATH TOPATH" },
{USTRING_TSTSH_47,(byte *)L"Cant open file: " },
{USTRING_TSTSH_48,(byte *)L"Cant open file" },
{USTRING_TSTSH_49,(byte *)L"Files are different" },
{USTRING_TSTSH_50,(byte *)L"File: " },
{USTRING_TSTSH_51,(byte *)L" And File: " },
{USTRING_TSTSH_52,(byte *)L" are the same" },
{USTRING_TSTSH_53,(byte *)L"File: " },
{USTRING_TSTSH_54,(byte *)L" is larger than File: " },
{USTRING_TSTSH_55,(byte *)L"Usage: DIFF PATH PATH " },
{USTRING_TSTSH_56,(byte *)L"Cant open file" },
{USTRING_TSTSH_57,(byte *)L"Write failure" },
{USTRING_TSTSH_58,(byte *)L"Usage: FILLFILE PATH PATTERN NTIMES" },
{USTRING_TSTSH_59,(byte *)L"MODE BITS :" },
{USTRING_TSTSH_60,(byte *)L"S_IFDIR|" },
{USTRING_TSTSH_61,(byte *)L"S_IFREG|" },
{USTRING_TSTSH_62,(byte *)L"S_IWRITE|" },
{USTRING_TSTSH_63,(byte *)L"S_IREAD" },
{USTRING_TSTSH_65,(byte *)L"FSTAT failed" },
{USTRING_TSTSH_66,(byte *)L"Usage: FSTAT D:PATH" },
{USTRING_TSTSH_67,(byte *)L"Calling media format" },
{USTRING_TSTSH_68,(byte *)L"The drive is contains this many logical blocks " },
{USTRING_TSTSH_69,(byte *)L"This many logical blocks remain" },
{USTRING_TSTSH_70,(byte *)L"The drive contains this many cylinders" },
{USTRING_TSTSH_71,(byte *)L"There are this many cylinders remainng" },
{USTRING_TSTSH_72,(byte *)L"Attributes: " },
{USTRING_TSTSH_73,(byte *)L"ARDONLY|" },
{USTRING_TSTSH_74,(byte *)L"AHIDDEN|" },
{USTRING_TSTSH_75,(byte *)L"ASYSTEM|" },
{USTRING_TSTSH_76,(byte *)L"AVOLUME|" },
{USTRING_TSTSH_77,(byte *)L"ADIRENT|" },
{USTRING_TSTSH_78,(byte *)L"ARCHIVE|" },
{USTRING_TSTSH_79,(byte *)L"NORMAL FILE (No bits set)" },
{USTRING_TSTSH_81,(byte *)L"get attributes failed" },
{USTRING_TSTSH_82,(byte *)L"Usage: GETATTR D:PATH" },
{USTRING_TSTSH_83,(byte *)L"Can not get attributes" },
{USTRING_TSTSH_84,(byte *)L"RDONLY" },
{USTRING_TSTSH_85,(byte *)L"HIDDEN" },
{USTRING_TSTSH_86,(byte *)L"SYSTEM" },
{USTRING_TSTSH_87,(byte *)L"ARCHIVE" },
{USTRING_TSTSH_88,(byte *)L"NORMAL" },
{USTRING_TSTSH_89,(byte *)L"Set attributes failed" },
{USTRING_TSTSH_90,(byte *)L"Usage: SETATTR D:PATH RDONLY|HIDDEN|SYSTEM|ARCHIVE|NORMAL" },
{USTRING_TSTSH_91,(byte *)L"Can not open disk " },
{USTRING_TSTSH_92,(byte *)L"Usage: DSKOPEN D:" },
{USTRING_TSTSH_93,(byte *)L"Usage: DSKCLOSE D: " },
{USTRING_TSTSH_94,(byte *)L"cd_set_default failed" },
{USTRING_TSTSH_95,(byte *)L"Usage: DSKSELECT D: " },
{USTRING_TSTSH_96,(byte *)L"path error" },
{USTRING_TSTSH_97,(byte *)L"Cant open File" },
{USTRING_TSTSH_98,(byte *)L"Usage: CAT PATH" },
{USTRING_TSTSH_99,(byte *)L"Cant open :" },
{USTRING_TSTSH_100,(byte *)L"." },
{USTRING_TSTSH_102,(byte *)L"Usage: READ PATH" },
{USTRING_TSTSH_103,(byte *)L"Usage: COPY CDPATH OSPATH" },
{USTRING_TSTSH_104,(byte *)L"Cant open " },
{USTRING_TSTSH_105,(byte *)L"Cant creat " },
{USTRING_TSTSH_106,(byte *)L"." },
{USTRING_TSTSH_108,(byte *)L"Write error" },
{USTRING_TSTSH_110,(byte *)L"Usage: REGRESSTEST D:" },
#if (INCLUDE_FAILSAFE_CODE)
{USTRING_TSTSH_111, (byte *)L"Usage: FAILSAFEINIT D:"},
{USTRING_TSTSH_112, (byte *)L"Usage: FAILSAFECOMMIT D:"},
{USTRING_TSTSH_113,(byte *)L"Failsafe commit failed\n"},
{USTRING_TSTSH_114,(byte *)L"Failsafe init failed\n"},
{USTRING_TSTSH_115,(byte *)L"Failsafe already running on a drive\n"},
{USTRING_TSTSH_116,(byte *)L"Command shell only supports one failsafe session\n"},
{USTRING_TSTSH_117,(byte *)L"Usage: FAILSAFERESTORE D:"},
#endif
{USTRING_TSTSH_118,(byte *)L"Failsafe disabled"},
{USTRING_TSTSH_119,(byte *)L"Failsafe enabled with journaling "},
{USTRING_TSTSH_120,(byte *)L"Failsafe enabled with no journaling "},
{USTRING_TSTSH_121,(byte *)L"Total Number of Block Buffers "},
{USTRING_TSTSH_122,(byte *)L"Pending writes on Block Buffers "},
{USTRING_TSTSH_123,(byte *)L"Block Buffers available "},
{USTRING_TSTSH_124,(byte *)L"Block Buffer Cache Hits "},
{USTRING_TSTSH_125,(byte *)L"Block Buffer Cache Misses "},
{USTRING_TSTSH_126,(byte *)L"Block Buffer Low Water "},
{USTRING_TSTSH_127,(byte *)L"Block Allocation failures "},
{USTRING_TSTSH_128,(byte *)L"Total Number of FAT Buffers "},
{USTRING_TSTSH_129,(byte *)L"FAT Buffers never used "},
{USTRING_TSTSH_130,(byte *)L"FAT Buffer Primary Cache Hits "},
{USTRING_TSTSH_131,(byte *)L"FAT Buffer Secondary Cache Hits "},
{USTRING_TSTSH_132,(byte *)L"FAT Buffer Secondary Cache Loads "},
{USTRING_TSTSH_133,(byte *)L"FAT Buffer Secondary Cache Swaps "},
{USTRING_TSTSH_134,(byte *)L"Pending writes on FAT Buffers "},
{USTRING_TSTSH_135,(byte *)L"FAT Buffers available "},
{USTRING_TSTSH_136,(byte *)L"pro_failsafe_status failed"},
{USTRING_TSTSH_137,(byte *)L"USAGE: BUFFERSTAT D:"},
#if (INCLUDE_FAILSAFE_CODE)
{USTRING_TSTSH_138,(byte *)L"FAILSAFE: Volume up to date, no restore required"},
{USTRING_TSTSH_139,(byte *)L"FAILSAFE: no journal present"},
{USTRING_TSTSH_140,(byte *)L"FAILSAFE: bad journal file present"},
{USTRING_TSTSH_141,(byte *)L"FAILSAFE: journal file has checksum error"},
{USTRING_TSTSH_142,(byte *)L"FAILSAFE: IO error during restore"},
{USTRING_TSTSH_144,(byte *)L"FAILSAFE: Volume was restored sucessfully"},
{USTRING_TSTSH_145,(byte *)L"FAILSAFE: Restore required"},
{USTRING_TSTSH_146,(byte *)L"FAILSAFE: Restore unknown return code"},
#endif
{USTRING_TSTSH_147,(byte *)L"Failsafe file blocks consumed "},
{USTRING_TSTSH_148,(byte *)L"Failsafe file blocks still available "},
{USTRING_TSTSHHELP_01,(byte *)L"CAT PATH" },
{USTRING_TSTSHHELP_02,(byte *)L"CHSIZE FILENAME NEWSIZE" },
{USTRING_TSTSHHELP_03,(byte *)L"CD PATH or CD to display PWD " },
{USTRING_TSTSHHELP_04,(byte *)L"CDCAT PATH" },
{USTRING_TSTSHHELP_05,(byte *)L"CDCOPY PATH PATH" },
{USTRING_TSTSHHELP_06,(byte *)L"CDREAD PATH" },
{USTRING_TSTSHHELP_07,(byte *)L"CDCD PATH " },
{USTRING_TSTSHHELP_08,(byte *)L"CDDIR PATH" },
{USTRING_TSTSHHELP_09,(byte *)L"CDDSKCLOSE: D:" },
{USTRING_TSTSHHELP_10,(byte *)L"CDDSKOPEN: D:" },
{USTRING_TSTSHHELP_11,(byte *)L"CDDSKSEL D:" },
{USTRING_TSTSHHELP_12,(byte *)L"CHKDSK D: <0,1> 1 is write lost chains" },
{USTRING_TSTSHHELP_13,(byte *)L"CLOSE FDNO" },
{USTRING_TSTSHHELP_14,(byte *)L"COPY PATH PATH" },
{USTRING_TSTSHHELP_15,(byte *)L"DELETE PATH" },
{USTRING_TSTSHHELP_16,(byte *)L"DELTREE PATH" },
{USTRING_TSTSHHELP_17,(byte *)L"DEVINFO (Display Device Information)" },
{USTRING_TSTSHHELP_18,(byte *)L"DIFF PATH PATH" },
{USTRING_TSTSHHELP_19,(byte *)L"DIR PATH" },
{USTRING_TSTSHHELP_20,(byte *)L"DSKSEL D:" },
{USTRING_TSTSHHELP_21,(byte *)L"ECHO: [args]" },
{USTRING_TSTSHHELP_22,(byte *)L"EJECT (ejects LS-120)" },
{USTRING_TSTSHHELP_23,(byte *)L"FILLFILE PATH PATTERN NTIMES" },
{USTRING_TSTSHHELP_24,(byte *)L"FORMAT (routine will prompt for arguments)" },
{USTRING_TSTSHHELP_25,(byte *)L"GETATTR FILE" },
{USTRING_TSTSHHELP_26,(byte *)L"HELP:" },
{USTRING_TSTSHHELP_27,(byte *)L"LSTOPEN (lists all open file decscriptors) " },
{USTRING_TSTSHHELP_28,(byte *)L"MKDIR PATH" },
{USTRING_TSTSHHELP_29,(byte *)L"PCMCIAINT (Force a PCMCIA mgmt Interrupt)" },
{USTRING_TSTSHHELP_30,(byte *)L"QUIT" },
{USTRING_TSTSHHELP_31,(byte *)L"READ FDNO" },
{USTRING_TSTSHHELP_32,(byte *)L"RENAME PATH NEWNAME" },
{USTRING_TSTSHHELP_33,(byte *)L"RMDIR PATH" },
{USTRING_TSTSHHELP_34,(byte *)L"RNDOP PATH RECLEN" },
{USTRING_TSTSHHELP_35,(byte *)L"SEEK FDNO RECORD" },
{USTRING_TSTSHHELP_36,(byte *)L"SETATTR D:PATH RDONLY|HIDDEN|SYSTEM|ARCHIVE|NORMAL" },
{USTRING_TSTSHHELP_37,(byte *)L"STAT PATH" },
{USTRING_TSTSHHELP_38,(byte *)L"WRITE FDNO QUOTED DATA" },
{USTRING_TSTSHHELP_39,(byte *)L"REGRESSTEST D:"},
{USTRING_TSTSHHELP_40,(byte *)L"MKHOSTDISK win9xpath"},
{USTRING_TSTSHHELP_41 ,(byte *)L"MKROM"},
#if (INCLUDE_FAILSAFE_CODE)
{USTRING_TSTSHHELP_42 ,(byte *)L"FAILSAFEINIT D:"},
{USTRING_TSTSHHELP_43 ,(byte *)L"FAILSAFECOMMIT D:"},
{USTRING_TSTSHHELP_44 ,(byte *)L"FAILSAFERESTORE D:"},
{USTRING_TSTSHHELP_45 ,(byte *)L"BUFFERSTAT D:"},
{USTRING_TSTSHHELP_46 ,(byte *)L"FAILSAFETEST D: (must be hostdisk)"},
#endif /* (INCLUDE_FAILSAFE_CODE) */
{USTRING_TSTSHCMD_01,(byte *)L"CAT" },
{USTRING_TSTSHCMD_02,(byte *)L"CHSIZE" },
{USTRING_TSTSHCMD_03,(byte *)L"CD" },
{USTRING_TSTSHCMD_04,(byte *)L"CDCAT" },
{USTRING_TSTSHCMD_05,(byte *)L"CDCOPY" },
{USTRING_TSTSHCMD_06,(byte *)L"CDREAD" },
{USTRING_TSTSHCMD_07,(byte *)L"CDCD" },
{USTRING_TSTSHCMD_08,(byte *)L"CDDIR" },
{USTRING_TSTSHCMD_09,(byte *)L"CDDSKCLOSE" },
{USTRING_TSTSHCMD_10,(byte *)L"CDDSKOPEN" },
{USTRING_TSTSHCMD_11,(byte *)L"CDDSKSEL" },
{USTRING_TSTSHCMD_12,(byte *)L"CHKDSK" },
{USTRING_TSTSHCMD_13,(byte *)L"CLOSE" },
{USTRING_TSTSHCMD_14,(byte *)L"COPY" },
{USTRING_TSTSHCMD_15,(byte *)L"DELETE" },
{USTRING_TSTSHCMD_16,(byte *)L"DELTREE" },
{USTRING_TSTSHCMD_17,(byte *)L"DEVINFO" },
{USTRING_TSTSHCMD_18,(byte *)L"DIFF" },
{USTRING_TSTSHCMD_19,(byte *)L"DIR" },
{USTRING_TSTSHCMD_20,(byte *)L"DSKSEL" },
{USTRING_TSTSHCMD_21,(byte *)L"ECHO" },
{USTRING_TSTSHCMD_22,(byte *)L"EJECT" },
{USTRING_TSTSHCMD_23,(byte *)L"FILLFILE" },
{USTRING_TSTSHCMD_24,(byte *)L"FORMAT" },
{USTRING_TSTSHCMD_25,(byte *)L"GETATTR" },
{USTRING_TSTSHCMD_26,(byte *)L"HELP" },
{USTRING_TSTSHCMD_27,(byte *)L"LSTOPEN" },
{USTRING_TSTSHCMD_28,(byte *)L"MKDIR" },
{USTRING_TSTSHCMD_29,(byte *)L"PCMCIAINT" },
{USTRING_TSTSHCMD_30,(byte *)L"QUIT" },
{USTRING_TSTSHCMD_31,(byte *)L"READ" },
{USTRING_TSTSHCMD_32,(byte *)L"RENAME" },
{USTRING_TSTSHCMD_33,(byte *)L"RMDIR" },
{USTRING_TSTSHCMD_34,(byte *)L"RNDOP" },
{USTRING_TSTSHCMD_35,(byte *)L"SEEK" },
{USTRING_TSTSHCMD_36,(byte *)L"SETATTR" },
{USTRING_TSTSHCMD_37,(byte *)L"STAT" },
{USTRING_TSTSHCMD_38,(byte *)L"WRITE" },
{USTRING_TSTSHCMD_39,(byte *)L"REGRESSTEST"},
{USTRING_TSTSHCMD_40,(byte *)L"MKHOSTDISK"},
{USTRING_TSTSHCMD_41,(byte *)L"MKROM"},
#if (INCLUDE_FAILSAFE_CODE)
{USTRING_TSTSHCMD_42 ,(byte *)L"FAILSAFEINIT"},
{USTRING_TSTSHCMD_43 ,(byte *)L"FAILSAFECOMMIT"},
{USTRING_TSTSHCMD_44 ,(byte *)L"FAILSAFERESTORE"},
{USTRING_TSTSHCMD_45 ,(byte *)L"BUFFERSTAT"},
{USTRING_TSTSHCMD_46 ,(byte *)L"FAILSAFETEST"},
#endif /* (INCLUDE_FAILSAFE_CODE) */
#else
{USTRING_TSTSH_01,(byte *)"CD Memory init failed" },
{USTRING_TSTSH_02,(byte *)"Not implemented. See ide ioctl... " },
{USTRING_TSTSH_03,(byte *)"Set Default Drive Failed" },
{USTRING_TSTSH_04,(byte *)"Usage: DSKSELECT D: " },
{USTRING_TSTSH_05,(byte *)"No more random file slots " },
{USTRING_TSTSH_06,(byte *)"Cant open :" },
{USTRING_TSTSH_07,(byte *)"Usage: RNDOP D:PATH RECLEN" },
{USTRING_TSTSH_08,(byte *)"Cant find file" },
{USTRING_TSTSH_09,(byte *)"Close failed" },
{USTRING_TSTSH_10,(byte *)"Usage: CLOSE fd" },
{USTRING_TSTSH_11,(byte *)"Cant find file" },
{USTRING_TSTSH_12,(byte *)"Seek operation failed " },
{USTRING_TSTSH_13,(byte *)"Usage: SEEK fd recordno" },
{USTRING_TSTSH_14,(byte *)"Cant find file" },
{USTRING_TSTSH_15,(byte *)"Read operation failed " },
{USTRING_TSTSH_16,(byte *)"Usage: READ fd" },
{USTRING_TSTSH_17,(byte *)"Cant find file" },
{USTRING_TSTSH_18,(byte *)"Write operation failed " },
{USTRING_TSTSH_19,(byte *)"Usage: WRITE fd data " },
{USTRING_TSTSH_20,(byte *)"Usage: MKDIR D:PATH" },
{USTRING_TSTSH_21,(byte *)"Usage: RMDIR D:PATH" },
{USTRING_TSTSH_22,(byte *)"Usage: DELTREE D:PATH" },
{USTRING_TSTSH_23,(byte *)"deleting --> " },
{USTRING_TSTSH_24,(byte *)"Can not delete: " },
{USTRING_TSTSH_25,(byte *)"Usage: DELETE D:PATH" },
{USTRING_TSTSH_26,(byte *)"Usage: RENAME PATH NEWNAME" },
{USTRING_TSTSH_27,(byte *)"Set cwd failed" },
{USTRING_TSTSH_28,(byte *)"Get cwd failed" },
{USTRING_TSTSH_29,(byte *)"PWD Failed " },
{USTRING_TSTSH_30,(byte *)" " },
{USTRING_TSTSH_31,(byte *)" File(s) " },
{USTRING_TSTSH_32,(byte *)" Blocks Free " },
{USTRING_TSTSH_33,(byte *)"Cant open " },
{USTRING_TSTSH_34,(byte *)"Usage: CAT PATH" },
{USTRING_TSTSH_35,(byte *)"Usage: CHKDSK DRIVE: WRITECHAINS" },
{USTRING_TSTSH_36,(byte *)"Example:CHKDSK A: 1" },
{USTRING_TSTSH_37,(byte *)"Runs chkdsk on A: writes lost chains" },
{USTRING_TSTSH_38,(byte *)"Example:CHKDSK A: 0" },
{USTRING_TSTSH_39,(byte *)"Runs chkdsk on A: does not write lost chains" },
{USTRING_TSTSH_40,(byte *)"Cant open file: " },
{USTRING_TSTSH_41,(byte *)"Change size function failed" },
{USTRING_TSTSH_42,(byte *)"Usage: CHSIZE PATH NEWSIZE" },
{USTRING_TSTSH_43,(byte *)"Cant open file: " },
{USTRING_TSTSH_44,(byte *)"Cant open file" },
{USTRING_TSTSH_45,(byte *)"Write failure " },
{USTRING_TSTSH_46,(byte *)"Usage: COPY FROMPATH TOPATH" },
{USTRING_TSTSH_47,(byte *)"Cant open file: " },
{USTRING_TSTSH_48,(byte *)"Cant open file" },
{USTRING_TSTSH_49,(byte *)"Files are different" },
{USTRING_TSTSH_50,(byte *)"File: " },
{USTRING_TSTSH_51,(byte *)" And File: " },
{USTRING_TSTSH_52,(byte *)" are the same" },
{USTRING_TSTSH_53,(byte *)"File: " },
{USTRING_TSTSH_54,(byte *)" is larger than File: " },
{USTRING_TSTSH_55,(byte *)"Usage: DIFF PATH PATH " },
{USTRING_TSTSH_56,(byte *)"Cant open file" },
{USTRING_TSTSH_57,(byte *)"Write failure" },
{USTRING_TSTSH_58,(byte *)"Usage: FILLFILE PATH PATTERN NTIMES" },
{USTRING_TSTSH_59,(byte *)"MODE BITS :" },
{USTRING_TSTSH_60,(byte *)"S_IFDIR|" },
{USTRING_TSTSH_61,(byte *)"S_IFREG|" },
{USTRING_TSTSH_62,(byte *)"S_IWRITE|" },
{USTRING_TSTSH_63,(byte *)"S_IREAD" },
{USTRING_TSTSH_65,(byte *)"FSTAT failed" },
{USTRING_TSTSH_66,(byte *)"Usage: FSTAT D:PATH" },
{USTRING_TSTSH_67,(byte *)"Calling media format" },
{USTRING_TSTSH_68,(byte *)"The drive is contains this many logical blocks " },
{USTRING_TSTSH_69,(byte *)"This many logical blocks remain" },
{USTRING_TSTSH_70,(byte *)"The drive contains this many cylinders" },
{USTRING_TSTSH_71,(byte *)"There are this many cylinders remainng" },
{USTRING_TSTSH_72,(byte *)"Attributes: " },
{USTRING_TSTSH_73,(byte *)"ARDONLY|" },
{USTRING_TSTSH_74,(byte *)"AHIDDEN|" },
{USTRING_TSTSH_75,(byte *)"ASYSTEM|" },
{USTRING_TSTSH_76,(byte *)"AVOLUME|" },
{USTRING_TSTSH_77,(byte *)"ADIRENT|" },
{USTRING_TSTSH_78,(byte *)"ARCHIVE|" },
{USTRING_TSTSH_79,(byte *)"NORMAL FILE (No bits set)" },
{USTRING_TSTSH_81,(byte *)"get attributes failed" },
{USTRING_TSTSH_82,(byte *)"Usage: GETATTR D:PATH" },
{USTRING_TSTSH_83,(byte *)"Can not get attributes" },
{USTRING_TSTSH_84,(byte *)"RDONLY" },
{USTRING_TSTSH_85,(byte *)"HIDDEN" },
{USTRING_TSTSH_86,(byte *)"SYSTEM" },
{USTRING_TSTSH_87,(byte *)"ARCHIVE" },
{USTRING_TSTSH_88,(byte *)"NORMAL" },
{USTRING_TSTSH_89,(byte *)"Set attributes failed" },
{USTRING_TSTSH_90,(byte *)"Usage: SETATTR D:PATH RDONLY|HIDDEN|SYSTEM|ARCHIVE|NORMAL" },
{USTRING_TSTSH_91,(byte *)"Can not open disk " },
{USTRING_TSTSH_92,(byte *)"Usage: DSKOPEN D:" },
{USTRING_TSTSH_93,(byte *)"Usage: DSKCLOSE D: " },
{USTRING_TSTSH_94,(byte *)"cd_set_default failed" },
{USTRING_TSTSH_95,(byte *)"Usage: DSKSELECT D: " },
{USTRING_TSTSH_96,(byte *)"path error" },
{USTRING_TSTSH_97,(byte *)"Cant open File" },
{USTRING_TSTSH_98,(byte *)"Usage: CAT PATH" },
{USTRING_TSTSH_99,(byte *)"Cant open :" },
{USTRING_TSTSH_100,(byte *)"." },
{USTRING_TSTSH_102,(byte *)"Usage: READ PATH" },
{USTRING_TSTSH_103,(byte *)"Usage: COPY CDPATH OSPATH" },
{USTRING_TSTSH_104,(byte *)"Cant open " },
{USTRING_TSTSH_105,(byte *)"Cant creat " },
{USTRING_TSTSH_106,(byte *)"." },
{USTRING_TSTSH_108,(byte *)"Write error" },
{USTRING_TSTSH_110,(byte *)"Usage: REGRESSTEST D:" },
#if (INCLUDE_FAILSAFE_CODE)
{USTRING_TSTSH_111,(byte *)"Usage: FAILSAFEINIT D:"},
{USTRING_TSTSH_112,(byte *)"Usage: FAILSAFECOMMIT D:"},
{USTRING_TSTSH_113,(byte *)"Failsafe commit failed\n"},
{USTRING_TSTSH_114,(byte *)"Failsafe init failed\n"},
{USTRING_TSTSH_115,(byte *)"Failsafe already running on a drive\n"},
{USTRING_TSTSH_116,(byte *)"Command shell only supports one failsafe session\n"},
{USTRING_TSTSH_117,(byte *)"Usage: FAILSAFERESTORE D:"},
#endif
{USTRING_TSTSH_118,(byte *)"Failsafe disabled"},
{USTRING_TSTSH_119,(byte *)"Failsafe enabled with journaling "},
{USTRING_TSTSH_120,(byte *)"Failsafe enabled with no journaling"},
{USTRING_TSTSH_121,(byte *)"Total Number of Block Buffers "},
{USTRING_TSTSH_122,(byte *)"Pending writes on Block Buffers "},
{USTRING_TSTSH_123,(byte *)"Block Buffers available "},
{USTRING_TSTSH_124,(byte *)"Block Buffer Cache Hits "},
{USTRING_TSTSH_125,(byte *)"Block Buffer Cache Misses "},
{USTRING_TSTSH_126,(byte *)"Block Buffer Low Water "},
{USTRING_TSTSH_127,(byte *)"Block Allocation failures "},
{USTRING_TSTSH_128,(byte *)"Total Number of FAT Buffers "},
{USTRING_TSTSH_129,(byte *)"FAT Buffers never used "},
{USTRING_TSTSH_130,(byte *)"FAT Buffer Primary Cache Hits "},
{USTRING_TSTSH_131,(byte *)"FAT Buffer Secondary Cache Hits "},
{USTRING_TSTSH_132,(byte *)"FAT Buffer Secondary Cache Loads "},
{USTRING_TSTSH_133,(byte *)"FAT Buffer Secondary Cache Swaps "},
{USTRING_TSTSH_134,(byte *)"Pending writes on FAT Buffers "},
{USTRING_TSTSH_135,(byte *)"FAT Buffers available "},
{USTRING_TSTSH_136,(byte *)"pro_failsafe_status failed"},
{USTRING_TSTSH_137,(byte *)"USAGE: BUFFERSTAT D:"},
#if (INCLUDE_FAILSAFE_CODE)
{USTRING_TSTSH_138,(byte *)"FAILSAFE: Volume up to date, no restore required"},
{USTRING_TSTSH_139,(byte *)"FAILSAFE: no journal present"},
{USTRING_TSTSH_140,(byte *)"FAILSAFE: bad journal file present"},
{USTRING_TSTSH_141,(byte *)"FAILSAFE: journal file has checksum error"},
{USTRING_TSTSH_142,(byte *)"FAILSAFE: IO error during restore"},
{USTRING_TSTSH_144,(byte *)"FAILSAFE: Volume was restored sucessfully"},
{USTRING_TSTSH_145,(byte *)"FAILSAFE: Restore required"},
{USTRING_TSTSH_146,(byte *)"FAILSAFE: Restore unknown return code"},
#endif
{USTRING_TSTSH_147,(byte *)"Failsafe file blocks consumed "},
{USTRING_TSTSH_148,(byte *)"Failsafe file blocks still available "},
{USTRING_TSTSHHELP_01,(byte *)"CAT PATH" },
{USTRING_TSTSHHELP_02,(byte *)"CHSIZE FILENAME NEWSIZE" },
{USTRING_TSTSHHELP_03,(byte *)"CD PATH or CD to display PWD " },
{USTRING_TSTSHHELP_04,(byte *)"CDCAT PATH" },
{USTRING_TSTSHHELP_05,(byte *)"CDCOPY PATH PATH" },
{USTRING_TSTSHHELP_06,(byte *)"CDREAD PATH" },
{USTRING_TSTSHHELP_07,(byte *)"CDCD PATH " },
{USTRING_TSTSHHELP_08,(byte *)"CDDIR PATH" },
{USTRING_TSTSHHELP_09,(byte *)"CDDSKCLOSE: D:" },
{USTRING_TSTSHHELP_10,(byte *)"CDDSKOPEN: D:" },
{USTRING_TSTSHHELP_11,(byte *)"CDDSKSEL D:" },
{USTRING_TSTSHHELP_12,(byte *)"CHKDSK D: <0,1> 1 is write lost chains" },
{USTRING_TSTSHHELP_13,(byte *)"CLOSE FDNO" },
{USTRING_TSTSHHELP_14,(byte *)"COPY PATH PATH" },
{USTRING_TSTSHHELP_15,(byte *)"DELETE PATH" },
{USTRING_TSTSHHELP_16,(byte *)"DELTREE PATH" },
{USTRING_TSTSHHELP_17,(byte *)"DEVINFO (Display Device Information)" },
{USTRING_TSTSHHELP_18,(byte *)"DIFF PATH PATH" },
{USTRING_TSTSHHELP_19,(byte *)"DIR PATH" },
{USTRING_TSTSHHELP_20,(byte *)"DSKSEL D:" },
{USTRING_TSTSHHELP_21,(byte *)"ECHO: [args]" },
{USTRING_TSTSHHELP_22,(byte *)"EJECT (ejects LS-120)" },
{USTRING_TSTSHHELP_23,(byte *)"FILLFILE PATH PATTERN NTIMES" },
{USTRING_TSTSHHELP_24,(byte *)"FORMAT (routine will prompt for arguments)" },
{USTRING_TSTSHHELP_25,(byte *)"GETATTR FILE" },
{USTRING_TSTSHHELP_26,(byte *)"HELP:" },
{USTRING_TSTSHHELP_27,(byte *)"LSTOPEN (lists all open file decscriptors) " },
{USTRING_TSTSHHELP_28,(byte *)"MKDIR PATH" },
{USTRING_TSTSHHELP_29,(byte *)"PCMCIAINT (Force a PCMCIA mgmt Interrupt)" },
{USTRING_TSTSHHELP_30,(byte *)"QUIT" },
{USTRING_TSTSHHELP_31,(byte *)"READ FDNO" },
{USTRING_TSTSHHELP_32,(byte *)"RENAME PATH NEWNAME" },
{USTRING_TSTSHHELP_33,(byte *)"RMDIR PATH" },
{USTRING_TSTSHHELP_34,(byte *)"RNDOP PATH RECLEN" },
{USTRING_TSTSHHELP_35,(byte *)"SEEK FDNO RECORD" },
{USTRING_TSTSHHELP_36,(byte *)"SETATTR D:PATH RDONLY|HIDDEN|SYSTEM|ARCHIVE|NORMAL" },
{USTRING_TSTSHHELP_37,(byte *)"STAT PATH" },
{USTRING_TSTSHHELP_38,(byte *)"WRITE FDNO QUOTED DATA" },
{USTRING_TSTSHHELP_39,(byte *)"REGRESSTEST D:"},
{USTRING_TSTSHHELP_40,(byte *)"MKHOSTDISK win9xpath"},
{USTRING_TSTSHHELP_41 ,(byte *)"MKROM"},
#if (INCLUDE_FAILSAFE_CODE)
{USTRING_TSTSHHELP_42 ,(byte *)"FAILSAFEINIT D:"},
{USTRING_TSTSHHELP_43 ,(byte *)"FAILSAFECOMMIT D:"},
{USTRING_TSTSHHELP_44 ,(byte *)"FAILSAFERESTORE D:"},
{USTRING_TSTSHHELP_45 ,(byte *)"BUFFERSTAT D:"},
{USTRING_TSTSHHELP_46 ,(byte *)"FAILSAFETEST D: (must be hostdisk)"},
#endif /* (INCLUDE_FAILSAFE_CODE) */
{USTRING_TSTSHCMD_01,(byte *)"CAT" },
{USTRING_TSTSHCMD_02,(byte *)"CHSIZE" },
{USTRING_TSTSHCMD_03,(byte *)"CD" },
{USTRING_TSTSHCMD_04,(byte *)"CDCAT" },
{USTRING_TSTSHCMD_05,(byte *)"CDCOPY" },
{USTRING_TSTSHCMD_06,(byte *)"CDREAD" },
{USTRING_TSTSHCMD_07,(byte *)"CDCD" },
{USTRING_TSTSHCMD_08,(byte *)"CDDIR" },
{USTRING_TSTSHCMD_09,(byte *)"CDDSKCLOSE" },
{USTRING_TSTSHCMD_10,(byte *)"CDDSKOPEN" },
{USTRING_TSTSHCMD_11,(byte *)"CDDSKSEL" },
{USTRING_TSTSHCMD_12,(byte *)"CHKDSK" },
{USTRING_TSTSHCMD_13,(byte *)"CLOSE" },
{USTRING_TSTSHCMD_14,(byte *)"COPY" },
{USTRING_TSTSHCMD_15,(byte *)"DELETE" },
{USTRING_TSTSHCMD_16,(byte *)"DELTREE" },
{USTRING_TSTSHCMD_17,(byte *)"DEVINFO" },
{USTRING_TSTSHCMD_18,(byte *)"DIFF" },
{USTRING_TSTSHCMD_19,(byte *)"DIR" },
{USTRING_TSTSHCMD_20,(byte *)"DSKSEL" },
{USTRING_TSTSHCMD_21,(byte *)"ECHO" },
{USTRING_TSTSHCMD_22,(byte *)"EJECT" },
{USTRING_TSTSHCMD_23,(byte *)"FILLFILE" },
{USTRING_TSTSHCMD_24,(byte *)"FORMAT" },
{USTRING_TSTSHCMD_25,(byte *)"GETATTR" },
{USTRING_TSTSHCMD_26,(byte *)"HELP" },
{USTRING_TSTSHCMD_27,(byte *)"LSTOPEN" },
{USTRING_TSTSHCMD_28,(byte *)"MKDIR" },
{USTRING_TSTSHCMD_29,(byte *)"PCMCIAINT" },
{USTRING_TSTSHCMD_30,(byte *)"QUIT" },
{USTRING_TSTSHCMD_31,(byte *)"READ" },
{USTRING_TSTSHCMD_32,(byte *)"RENAME" },
{USTRING_TSTSHCMD_33,(byte *)"RMDIR" },
{USTRING_TSTSHCMD_34,(byte *)"RNDOP" },
{USTRING_TSTSHCMD_35,(byte *)"SEEK" },
{USTRING_TSTSHCMD_36,(byte *)"SETATTR" },
{USTRING_TSTSHCMD_37,(byte *)"STAT" },
{USTRING_TSTSHCMD_38,(byte *)"WRITE" },
{USTRING_TSTSHCMD_39,(byte *)"REGRESSTEST"},
{USTRING_TSTSHCMD_40,(byte *)"MKHOSTDISK"},
{USTRING_TSTSHCMD_41,(byte *)"MKROM"},
#if (INCLUDE_FAILSAFE_CODE)
{USTRING_TSTSHCMD_42 ,(byte *)"FAILSAFEINIT"},
{USTRING_TSTSHCMD_43 ,(byte *)"FAILSAFECOMMIT"},
{USTRING_TSTSHCMD_44 ,(byte *)"FAILSAFERESTORE"},
{USTRING_TSTSHCMD_45 ,(byte *)"BUFFERSTAT"},
{USTRING_TSTSHCMD_46 ,(byte *)"FAILSAFETEST"},
#endif /* (INCLUDE_FAILSAFE_CODE) */
#endif
#endif /* (INCLUDE_TSTSH_STRINGS) */
#if (INCLUDE_CS_UNICODE)
{0,(byte *)L"Unkown User String" }
#else
{0,(byte *)"Unkown User String" }
#endif
};
static byte *rtfs_strtab_string(KS_CONSTANT RTFS_STRING_TABLE *ptable, int string_id)
{
while (ptable->string_id != 0)
{
if (ptable->string_id == string_id)
break;
ptable++;
}
/* Return prompt. If lookup failed return Unkown User Prompt */
return((byte *)ptable->string_value);
}
byte *rtfs_strtab_user_prompt(int prompt_id)
{
return(rtfs_strtab_string(prompt_table, prompt_id));
}
byte *rtfs_strtab_user_string(int string_id)
{
return(rtfs_strtab_string(string_table, string_id));
}

View File

@ -0,0 +1,723 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 2002
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* UNICODE.C - Contains UNCICODE string manipulation and character conversion routines */
#include <rtfs.h>
#if (INCLUDE_CS_UNICODE)
BOOLEAN _illegal_alias_char(byte ch);
#if (KS_LITTLE_ENDIAN)
#define BYTE_LOW 1 /* Numeric low byte of a character */
#define BYTE_HIGH 0 /* Numeric high byte of a character */
#else
#define BYTE_LOW 0 /* Numeric low byte of a character */
#define BYTE_HIGH 1 /* Numeric high byte of a character */
#endif
void pc_ascii_byte2upper(byte *to, byte *from)
{
byte c;
c = *from;
if ((c >= 'a') && (c <= 'z'))
c = (byte) ('A' + c - 'a');
*to = c;
}
void pc_unicode_byte2upper(byte *to, byte *from) /* __fn__*/
{
byte c;
if (*(from+BYTE_LOW)==0)
{
c = *(from+BYTE_HIGH);
if ((c >= 'a') && (c <= 'z'))
c = (byte) ('A' + c - 'a');
*(to+BYTE_LOW)= 0;
*(to+BYTE_HIGH)= c;
}
else
{
*to++ = *from++;
*to = *from;
}
}
int unicode_ascii_index(byte *p, byte base)
{
byte c[2];
int index;
pc_unicode_byte2upper(c, p);
if (c[BYTE_LOW]==0)
{
index = (int) (c[BYTE_HIGH] - base);
}
else
{
index = c[BYTE_HIGH];
index <<= 8;
index += c[BYTE_LOW];
}
return(index);
}
int unicode_compare(byte *p1, byte *p2)
{
if (*p1 == *p2 && *(p1+1) == *(p2+1))
return(1);
else
return(0);
}
int ascii_compare_nc(byte *p1, byte *p2)
{
byte c,d;
if (*p1 == *p2)
return(1);
else
{
pc_ascii_byte2upper(&c, p1);
pc_ascii_byte2upper(&d, p2);
return(c == d);
}
}
int unicode_compare_nc(byte *p1, byte *p2)
{
byte cp1[2];
byte cp2[2];
pc_unicode_byte2upper(cp1,p1);
pc_unicode_byte2upper(cp2,p2);
if (unicode_compare(cp1, cp2))
return(1);
else
return(0);
}
byte *unicode_goto_eos(byte *p)
{
while ((*p) || *(p+1)) p+=2;
return(p);
}
void unicode_drno_to_letter(byte *p,int driveno)
{
driveno += (int) 'A';
*(p+BYTE_LOW) = 0;
*(p+BYTE_HIGH) = (byte) driveno;
}
int unicode_cmp_to_ascii_char(byte *p, byte c)
{
if (*(p+BYTE_LOW) == 0)
return ( c ==*(p+BYTE_HIGH) );
return(0);
}
void unicode_assign_ascii_char(byte *p, byte c)
{
*(p+BYTE_LOW) = 0;
*(p+BYTE_HIGH) = c;
}
void map_ascii_to_unicode(byte *unicode_to, byte *ascii_from)
{
byte *p;
p = unicode_to;
while (*ascii_from)
{
*(p+BYTE_LOW) = 0;
*(p+BYTE_HIGH) = *ascii_from++;
p+= 2;
}
*p++ = 0;
*p++ = 0;
}
void map_unicode_to_ascii(byte *to, byte *from)
{
while (*from || *(from+1))
{
if (*(from+BYTE_LOW) == 0)
*to++ = *(from+BYTE_HIGH);
else
*to++ = '_';
from += 2;
}
*to = 0;
}
void pc_ascii_strn2upper(byte *to, byte *from, int n) /* __fn__*/
{
int i;
byte c;
for (i = 0; i < n; i++)
{
c = *from++;
if ((c >= 'a') && (c <= 'z'))
c = (byte) ('A' + c - 'a');
*to++ = c;
}
}
void pc_ascii_str2upper(byte *to, byte *from) /* __fn__*/
{
byte c;
while(*from)
{
c = *from++;
if ((c >= 'a') && (c <= 'z'))
c = (byte) ('A' + c - 'a');
*to++ = c;
}
*to = '\0';
}
byte * rtfs_cs_strcat(byte * targ, byte * src) /*__fn__*/
{
byte *p;
p = unicode_goto_eos(targ);
rtfs_cs_strcpy(p, src);
return targ;
}
int rtfs_cs_strcmp(byte * s1, byte * s2)
{
word w1, w2;
while (CS_OP_IS_NOT_EOS(s1) && CS_OP_IS_NOT_EOS(s2) && unicode_compare(s1, s2))
{
s1 += 2;
s2 += 2;
}
w1 = (word)*(s1+BYTE_HIGH); w1 = (word) w1 << 8; w1 = (word)w1 + (word) *(s1+BYTE_LOW);
w2 = (word)*(s2+BYTE_HIGH); w2 = (word) w2 << 8; w2 = (word)w2 + (word) *(s2+BYTE_LOW);
if (w1 == w2) return 0;
else if (w1 < w2) return -1;
else return 1;
}
int rtfs_cs_strcpy(byte * targ, byte * src)
{
int loop_count = 0;
while (CS_OP_IS_NOT_EOS(src))
{
*targ++ = *src++;
*targ++ = *src++;
loop_count++;
}
*targ++ = 0;
*targ = 0;
return (loop_count);
}
/* return number of unicode chars in a string */
int rtfs_cs_strlen(byte * string) /*__fn__*/
{
int len;
len = 0;
while (CS_OP_IS_NOT_EOS(string))
{
len += 1;
string += 2;
}
return (len);
}
BOOLEAN validate_filename(byte * name, byte * ext)
{
int len;
byte *pa, *pu, uni_buffer[16], ascii_buffer[8];
RTFS_ARGSUSED_PVOID((void *) ext);
/* Check short filenames to see if they are reserved names, The test
is done in ascii because we use this for aliases */
len = 0;
pu = uni_buffer; pa = name;
/* Make a unicode string up to DOT or Zero */
while (CS_OP_IS_NOT_EOS(pa))
{
if (CS_OP_CMP_ASCII(pa,'.'))
break;
CS_OP_CP_CHR(pu, pa);
CS_OP_INC_PTR(pu);
CS_OP_INC_PTR(pa);
CS_OP_TERM_STRING(pu);
len += 1;
if (len > 4)
break;
}
if (len && len <= 4)
{
map_unicode_to_ascii(ascii_buffer, uni_buffer);
if(name_is_reserved(ascii_buffer)) return(FALSE);
}
if (*(name+BYTE_LOW)==0)
if (*(name+BYTE_HIGH) == ' ')
return(FALSE);
len = 1;
name += 2;
while (CS_OP_IS_NOT_EOS(name))
{
if (*(name+BYTE_LOW)==0)
if (_illegal_lfn_char(*(name+BYTE_HIGH)))
return(FALSE);
name += 2;
len += 1;
}
if(len > 255) return(FALSE);
return(TRUE);
}
BOOLEAN pc_ascii_malias(byte *alias, byte *input_file, int try);
/* UNICODE Version */
BOOLEAN pc_cs_malias(byte *alias, byte *input_file, int try) /*__fn__*/
{
BLKBUFF *scratch;
BLKBUFF *scratch1;
byte *ascii_input_file;
byte *ascii_alias;
BOOLEAN ret_val = FALSE;
/* We know UNICODE file names aren't legal aliases */
if(try == -1)
return(FALSE);
scratch = scratch1 = 0;
scratch = pc_scratch_blk();
scratch1 = pc_scratch_blk();
if (!scratch || !scratch1)
goto ex_it;
ascii_input_file = scratch->data;
ascii_alias = scratch1->data;
/* Map the unicode to ascii and create an ascii alias */
map_unicode_to_ascii(ascii_input_file, input_file);
if (!pc_ascii_malias(ascii_alias, ascii_input_file, try))
goto ex_it;
/* Now back to unicode */
map_ascii_to_unicode(alias, ascii_alias);
ret_val = TRUE;
ex_it:
if (scratch)
pc_free_scratch_blk(scratch);
if (scratch1)
pc_free_scratch_blk(scratch1);
return(ret_val);
}
BOOLEAN pc_patcmp_8(byte *p, byte *pattern, BOOLEAN dowildcard) /* __fn__*/
{
byte ascii_pattern[9];
int size = 8;
map_unicode_to_ascii(ascii_pattern, pattern);
pattern = ascii_pattern;
/* Kludge. never match a deleted file */
if (*p == PCDELETE)
return (FALSE);
else if (*pattern == PCDELETE) /* But E5 in the Pattern matches 0x5 */
{
if (*p == 0x5)
{
size -= 1;
p++;
pattern++;
}
else
return (FALSE);
}
while (size--)
{
if(dowildcard)
{
if (*pattern == '*') /* '*' matches the rest of the name */
return (TRUE);
if (*pattern != '?' && !ascii_compare_nc(pattern,p))
return (FALSE);
}
else
{
if (!ascii_compare_nc(pattern,p))
return (FALSE);
}
p++;
pattern++;
}
return (TRUE);
}
BOOLEAN pc_patcmp_3(byte *p, byte *pattern, BOOLEAN dowildcard) /* __fn__*/
{
byte ascii_pattern[9];
int size = 3;
map_unicode_to_ascii(ascii_pattern, pattern);
pattern = ascii_pattern;
while (size--)
{
if(dowildcard)
{
if (*pattern == '*') /* '*' matches the rest of the name */
return (TRUE);
if (*pattern != '?' && !ascii_compare_nc(pattern,p))
return (FALSE);
}
else
{
if (!ascii_compare_nc(pattern,p))
return (FALSE);
}
p++;
pattern++;
}
return (TRUE);
}
void lfn_chr_to_unicode(byte *to, byte *fr)
{
#if (KS_LITTLE_ENDIAN)
*to = *fr++;
*(to+1) = *fr;
#else /* make sure UNICODE str is in Intel byte order on disk */
*(to+1) = *fr++;
*to = *fr;
#endif
}
void unicode_chr_to_lfn(byte *to, byte *fr)
{
#if (KS_LITTLE_ENDIAN)
*to = *fr++;
*(to+1) = *fr;
#else /* make sure UNICODE str is in Intel byte order on disk */
*(to+1) = *fr++;
*to = *fr;
#endif
}
byte *pc_ascii_mfile(byte *to, byte *filename, byte *ext);
/* Version of MFILE that converts path from byte orientation to
native char set before returning. */
byte *pc_cs_mfile(byte *to, byte *filename, byte *ext)
{
byte temp_to[13];
pc_ascii_mfile(temp_to, filename, ext);
map_ascii_to_unicode(to, temp_to);
return(to);
}
/***************************************************************************
PC_FILEPARSE - Parse a file xxx.yyy into filename/pathname
Description
Take a file named XXX.YY and return SPACE padded NULL terminated
filename [XXX ] and fileext [YY ] components. If the name or ext are
less than [8,3] characters the name/ext is space filled and null termed.
If the name/ext is greater than [8,3] the name/ext is truncated. '.'
is used to seperate file from ext, the special cases of . and .. are
also handled.
Returns
Returns TRUE
****************************************************************************/
/* UNICODE - Called by pc_malias not by others if vfat - Okay as ascii */
/* UNICODE - pc_enum usage is probably incorrect */
/* Take a string xxx[.yy] and put it into filename and fileext */
/* Note: add a check legal later */
BOOLEAN pc_ascii_fileparse(byte *filename, byte *fileext, byte *p) /* __fn__*/
{
int i;
/* Defaults */
rtfs_memset(filename, ' ', 8);
filename[8] = '\0';
rtfs_memset(fileext, ' ', 3);
fileext[3] = '\0';
/* Special cases of . and .. */
if (*p == '.')
{
*filename = '.';
if (*(p+1) == '.')
{
*(++filename) = '.';
return (TRUE);
}
else if (*(p + 1) == '\0')
return (TRUE);
else
return (FALSE);
}
i = 0;
while (*p)
{
if (*p == '.')
{
p++;
break;
}
else
if (i++ < 8)
*filename++ = *p;
p++;
}
i = 0;
while (*p)
{
if (i++ < 3)
*fileext++ = *p;
p++;
}
return (TRUE);
}
/***************************************************************************
PC_MFILE - Build a file spec (xxx.yyy) from a file name and extension
Description
Fill in to with a concatenation of file and ext. File and ext are
not assumed to be null terminated but must be blank filled to [8,3]
chars respectively. 'to' will be a null terminated string file.ext.
ASCII character function only. Unicode not required
Returns
A pointer to 'to'.
This is byte oriented. See pc_cs_mfile() for unicode oriented.
****************************************************************************/
byte *pc_ascii_mfile(byte *to, byte *filename, byte *ext)
{
byte *p;
int i;
byte *retval = to;
p = filename;
i = 0;
while(*p)
{
if (*p == ' ')
break;
else
{
*to++ = *p++;
i++;
}
if (i == 8)
break;
}
if (p != filename)
{
p = ext;
if (*p && *p != ' ')
*to++ = '.';
i = 0;
while(p && *p)
{
if (*p == ' ')
break;
else
{
*to++ = *p++;
i++;
}
if (i == 3)
break;
}
}
*to = '\0';
return (retval);
}
BOOLEAN pc_valid_ascii_sfn(byte *filename);
BOOLEAN pc_ascii_malias(byte *alias, byte *input_file, int try)
{
int n,i,s;
byte filename[9],fileext[4];
/* Fill filename[8] with spaces before we start. */
rtfs_memset(filename, ' ', 8);
/* See if no change necessary! */
if(try == -1)
return(pc_valid_ascii_sfn((byte *)input_file));
/* Process the ASCII alias name */
while(*input_file=='.' || *input_file==' ') input_file++;
/* find extension start */
for(n=0,i=0; input_file[n]!=0; n++) /* i holds the position right */
{ /* after the last period */
if(input_file[n]=='.') i=n+1;
}
if(i>0 && input_file[i]!=0){
/* copy extension to fileext[] */
for(n=i,s=0; input_file[n]!=0 && s<3; n++)
{
if(input_file[n]!=' ')
{
if(_illegal_alias_char(input_file[n]))
{
fileext[s++] = '_';
}
else
fileext[s++] = input_file[n];
}
}
fileext[s]=0;} else { i=512; fileext[0]=0; } /* null terminate */
/* copy file name to filename[], filtering out spaces, periods and
replacing characters illegal in alias names with '_' */
for(n=0,s=0; n<i && input_file[n]!=0 && s<8; n++)
{
if(input_file[n]!=' ' && input_file[n]!='.')
{
if(_illegal_alias_char(input_file[n]) || input_file[n]>127)
{
filename[s++] = '_';
}
else
filename[s++] = input_file[n];
}
}
for(;s<8;s++) /* pad with spaces */
{
filename[s] = ' ';
}
filename[8]=0; /* null terminate filename[] */
pc_ascii_str2upper(filename,filename);
pc_ascii_str2upper(fileext,fileext);
/* append (TEXT[])i to filename[] */
for(n=7,s=try; s>0 && n>0; s/=10,n--)
{
filename[n] = (byte)(((byte)s%10)+'0');
}
if(n==0 && s>0)
return(FALSE);
else
filename[n]='~';
/* copy filename[] to alias[], filtering out spaces */
for(n=0,s=0; s<8; s++)
{
if(filename[s]!=' ')
alias[n++]=filename[s];
}
if(fileext[0] != 0)
{
alias[n++]='.'; /* insert separating period */
/* copy fileext[] to alias[] */
for(s=0; fileext[s]!=0; s++,n++)
{
alias[n]=fileext[s];
}
}
alias[n]=0; /* null terminate alias[] */
return(TRUE);
}
/***************************************************************************
PC_VALID_SFN - See if filename is a valid short file name
Description
Determines validity of a short file name based on the following criteria:
- the file name must be between 0 and 8 characters
- the file extension must be between 0 and 3 characters
- the file name must not begin with a period
- it must not be a reserved DOS file name
- it must not contain any characters that are illegal within sfn's
Returns
TRUE if filename is a valid sfn, FALSE otherwise
****************************************************************************/
BOOLEAN pc_valid_ascii_sfn(byte *filename)
{
int len,period_count,ext_start;
BOOLEAN badchar;
if(name_is_reserved(filename)) return(FALSE);
for(len=0,badchar=FALSE,period_count=0,ext_start=0; filename[len]!=0; len++)
{
if(_illegal_alias_char(filename[len])) badchar = TRUE;
if(filename[len] == '.')
{
ext_start = len+1;
period_count++;
}
}
if( (filename[0] == ' ') || /* 1st char is a space */
(len == 0) || /* no name */
badchar || /* contains illegal chars */
(period_count > 1) || /* contains more than one extension */
((len-ext_start)>3 && period_count>0) || /* extension is longer than 3 chars */
(period_count==0 && len > 8) || /* name is longer than 8 chars */
(ext_start > 9) || /* name is longer than 8 chars */
(ext_start==1) ) return(FALSE); /* no name; 1st char is a period */
return(TRUE);
}
byte print_buffer[132];
/* Take a string the may be either ASCI unicode '\0''C' or just asci 'C'
and return an asci printable version of the string */
byte *unicode_make_printable(byte *p)
{
int i;
byte c;
int is_unicode;
is_unicode = 0;
if (*(p+BYTE_LOW)!=0) /* Most likely it is ascii */
{
rtfs_strcpy(print_buffer, p);
return(&print_buffer[0]);
}
i = 0;
for (;;)
{
if (*(p+BYTE_LOW)==0)
{
c = *(p+BYTE_HIGH);
if (c == 0)
break;
else
print_buffer[i++] = c;
}
p += 2;
}
print_buffer[i] = 0;
return (&print_buffer[0]);
}
#endif

View File

@ -0,0 +1,158 @@
/*---------------------------------------------------------------------------*
Project: CTR - for RTFS
File: drdefault.c
2006 Nintendo.
*---------------------------------------------------------------------------*/
#include <twl.h>
#include <rtfs_target_os.h>
#include <rtfs.h>
#include <rtfsconf.h>
#if (RTFS_DEBUG_PRINT_ON == 1)
#if (CTR_DEF_ENVIRONMENT_DSEMU == 1)
#define PRINTDEBUG osTPrintf
#else
#include <ctr/vlink.h>
#define PRINTDEBUG vlink_dos_printf
#endif
#else
#define PRINTDEBUG i_no_print
static void i_no_print( const char *fmt, ... );
static void i_no_print( const char *fmt, ... ){ return; }
#endif
/*---------------------------------------------------------------------------*
Name: defaultRtfsIo
Description:
Arguments: driveno :
block :
buffer :
count :
reading : TRUE
Returns: TRUE/FALSE
*---------------------------------------------------------------------------*/
BOOL defaultRtfsIo( int driveno, dword block, void* buffer, word count, BOOLEAN reading)
{
if( reading) {
PRINTDEBUG( "DEVCTL_IO_READ ... block:%x, count:%x -> buf:%x\n", block, count, buffer);
}else{
PRINTDEBUG( "DEVCTL_IO_WRITE ... block:%x, count:%x <- buf:%x\n", block, count, buffer);
}
return FALSE;
}
/*---------------------------------------------------------------------------*
Name: defaultRtfsCtrl
Description:
Arguments: driveno :
opcode :
pargs :
Returns:
*---------------------------------------------------------------------------*/
int defaultRtfsCtrl( int driveno, int opcode, void* pargs)
{
DDRIVE *pdr;
DEV_GEOMETRY gc;
int heads, secptrack;
pdr = pc_drno_to_drive_struct( driveno);
switch( opcode) {
case DEVCTL_GET_GEOMETRY:
PRINTDEBUG( "DEVCTL_GET_GEOMETRY\n");
rtfs_memset( &gc, (byte)0, sizeof(gc));
gc.dev_geometry_lbas = 0;
gc.dev_geometry_heads = 0;
gc.dev_geometry_cylinders = 0;
gc.dev_geometry_secptrack = 0;
/**/
gc.fmt_parms_valid = FALSE;
OSAPI_CPUCOPY8( &gc, pargs, sizeof(gc));
return( -1); //fix
case DEVCTL_FORMAT:
PRINTDEBUG( "DEVCTL_FORMAT\n");
break;
case DEVCTL_REPORT_REMOVE:
pdr->drive_flags &= ~DRIVE_FLAGS_INSERTED;
break;
case DEVCTL_CHECKSTATUS:
PRINTDEBUG( "DEVCTL_CHECKSTATUS\n");
if (!(pdr->drive_flags & DRIVE_FLAGS_REMOVABLE)) { //リムーバブルでない場合
return(DEVTEST_NOCHANGE); //fix
}else{ //リムーバブルの場合
return(DEVTEST_NOMEDIA); //fix
}
case DEVCTL_WARMSTART:
PRINTDEBUG( "DEVCTL_WARMSTART\n");
pdr->drive_flags |= (/*DRIVE_FLAGS_VALID |*/ DRIVE_FLAGS_REMOVABLE);
pdr->partition_number = 0;
return( 0); //fix
case DEVCTL_POWER_RESTORE:
PRINTDEBUG( "DEVCTL_POWER_RESTORE\n");
break;
case DEVCTL_POWER_LOSS:
PRINTDEBUG( "DEVCTL_POWER_LOSS\n");
break;
default:
PRINTDEBUG( "DEVCTL_unknown\n");
break;
}
return( 0);
}
/*---------------------------------------------------------------------------*
Name: defaultRtfsAttach
Description: defaultドライバをドライブに割り当てる
Arguments: driveno :
Returns:
*---------------------------------------------------------------------------*/
/* rtfs_detachでdefaultドライバが割り当てられるため、このAPIは必要ない*/
/*
void defaultRtfsAttach( int driveno)
{
BOOLEAN result;
DDRIVE pdr;
pdr.dev_table_drive_io = defaultRtfsIo;
pdr.dev_table_perform_device_ioctl = defaultRtfsCtrl;
pdr.register_file_address = (dword) 0; // Not used
pdr.interrupt_number = 0; // Not used
pdr.drive_flags = 0; // DRIVE_FLAGS_VALID をセットしない
pdr.partition_number = 0; // Not used
pdr.pcmcia_slot_number = 0; // Not used
pdr.controller_number = 0;
pdr.logical_unit_number = 0;
//REMOVE扱い
pdr.drive_flags |= DRIVE_FLAGS_REMOVABLE;
pdr.drive_flags &= ~DRIVE_FLAGS_INSERTED;
result = rtfs_attach( driveno, &pdr, "DEFAULT"); //構造体がFSライブラリ側にコピーされる
if( !result) {
PRINTDEBUG( "fsEnableDevice failured\n");
}
}
*/

View File

@ -0,0 +1,11 @@
#ifndef __DRDEFAULT_H__
#define __DRDEFAULT_H__
void defaultRtfsAttach( int driveno);
BOOL defaultRtfsIo( int driveno, dword block, void* buffer, word count, BOOLEAN reading);
int defaultRtfsCtrl( int driveno, int opcode, void* pargs);
#endif /*__DRDEFAULT_H__*/

View File

@ -0,0 +1,295 @@
/*---------------------------------------------------------------------------*
Project: CTR - for RTFS
File: drfile.c
2006 Nintendo.
*---------------------------------------------------------------------------*/
#include <twl.h>
#include <rtfs_target_os.h>
#include <rtfs.h>
#include <rtfsconf.h>
#if (RTFS_DEBUG_PRINT_ON == 1)
#if (CTR_DEF_ENVIRONMENT_DSEMU == 1)
#define PRINTDEBUG osTPrintf
#else
#include <ctr/vlink.h>
#define PRINTDEBUG vlink_dos_printf
#endif
#else
#define PRINTDEBUG i_no_print
static void i_no_print( const char *fmt, ... );
static void i_no_print( const char *fmt, ... ){ return; }
#endif
/*---------------------------------------------------------------------------*
global変数
*---------------------------------------------------------------------------*/
PCFD fileDescList[26] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
u32 file_capacity;
u32 file_adjusted_capacity;
u16 file_heads;
u16 file_secptrack;
u16 file_cylinders;
/*---------------------------------------------------------------------------*
extern変数
*---------------------------------------------------------------------------*/
extern int rtfs_first_stat_flag[26];
/*---------------------------------------------------------------------------*
static関数
*---------------------------------------------------------------------------*/
static void file_get_CHS_params( u32 file_sector_num);
/*---------------------------------------------------------------------------*
Name: fileRtfsIo
Description:
Arguments: driveno :
block :
buffer :
count :
reading : TRUE
Returns: TRUE/FALSE
*---------------------------------------------------------------------------*/
BOOL fileRtfsIo( int driveno, dword block, void* buffer, word count, BOOLEAN reading)
{
int result;
unsigned long dmy;
po_ulseek( fileDescList[driveno], block*512, &dmy, PSEEK_SET);
if( reading) {
PRINTDEBUG( "DEVCTL_IO_READ ... block:%x, count:%x -> buf:%x\n", block, count, buffer);
result = po_read( fileDescList[driveno], buffer, 512*count);
}else{
PRINTDEBUG( "DEVCTL_IO_WRITE ... block:%x, count:%x <- buf:%x\n", block, count, buffer);
result = po_write( fileDescList[driveno], buffer, 512*count);
}
if( result < 0) {
return FALSE;
}else{
return TRUE;
}
}
/*---------------------------------------------------------------------------*
Name: fileRtfsCtrl
Description:
Arguments: driveno :
opcode :
pargs :
Returns:
*---------------------------------------------------------------------------*/
int fileRtfsCtrl( int driveno, int opcode, void* pargs)
{
DDRIVE *pdr;
DEV_GEOMETRY gc;
int heads, secptrack;
unsigned long file_size, dmy;
pdr = pc_drno_to_drive_struct( driveno);
switch( opcode) {
case DEVCTL_GET_GEOMETRY:
PRINTDEBUG( "%s : DEVCTL_GET_GEOMETRY\n", __FUNCTION__);
rtfs_memset( &gc, (byte)0, sizeof(gc));
po_ulseek( fileDescList[driveno], 0, &dmy, PSEEK_SET);
po_ulseek( fileDescList[driveno], 0, &file_size, PSEEK_END);
po_ulseek( fileDescList[driveno], 0, &dmy, PSEEK_SET);
file_capacity = file_size / 512; //セクタ単位にする
file_get_CHS_params( file_capacity);
PRINTDEBUG( "capacity : 0x%x\n", file_adjusted_capacity);
PRINTDEBUG( "heads : 0x%x\n", file_heads);
PRINTDEBUG( "cylinders : 0x%x\n", file_cylinders);
PRINTDEBUG( "secptrack : 0x%x\n", file_secptrack);
gc.dev_geometry_lbas = file_adjusted_capacity;
gc.dev_geometry_heads = file_heads;
gc.dev_geometry_cylinders = file_cylinders;
gc.dev_geometry_secptrack = file_secptrack;
/**/
gc.fmt_parms_valid = FALSE;
OSAPI_CPUCOPY8( &gc, pargs, sizeof(gc));
return( 0);
case DEVCTL_FORMAT:
{
/* u32 filebuf[512/4];
miCpuFill8( filebuf, 0, 512);
po_write( fileDescList[driveno], filebuf, 512);*/
PRINTDEBUG( "%s : DEVCTL_FORMAT\n", __FUNCTION__);
return( 0);
}
case DEVCTL_REPORT_REMOVE:
pdr->drive_flags &= ~DRIVE_FLAGS_INSERTED;
return( 0);
case DEVCTL_CHECKSTATUS:
PRINTDEBUG( "%s : DEVCTL_CHECKSTATUS\n", __FUNCTION__);
if (!(pdr->drive_flags & DRIVE_FLAGS_REMOVABLE)) { //リムーバブルでない場合
return(DEVTEST_NOCHANGE); //fix
}else{ //リムーバブルの場合
if( rtfs_first_stat_flag[driveno]) {
rtfs_first_stat_flag[driveno] = 0;
PRINTDEBUG( "CHANGED!\n");
pdr->drive_flags |= DRIVE_FLAGS_INSERTED;
return(DEVTEST_CHANGED);
}
pdr->drive_flags |= DRIVE_FLAGS_INSERTED;
return( DEVTEST_NOCHANGE);
}
case DEVCTL_WARMSTART:
PRINTDEBUG( "%s : DEVCTL_WARMSTART\n", __FUNCTION__);
pdr->drive_flags |= (DRIVE_FLAGS_VALID | DRIVE_FLAGS_REMOVABLE);
return( 0);
case DEVCTL_POWER_RESTORE:
PRINTDEBUG( "%s : DEVCTL_POWER_RESTORE\n", __FUNCTION__);
break;
case DEVCTL_POWER_LOSS:
PRINTDEBUG( "%s : DEVCTL_POWER_LOSS\n", __FUNCTION__);
break;
default:
PRINTDEBUG( "%s : DEVCTL_unknown\n", __FUNCTION__);
break;
}
return( 0);
}
/*SD File System Specification(仕様書)に基づいた値を出す*/
static void file_get_CHS_params( u32 file_sector_num)
{
int mbytes;
// mbytes = (sdmc_current_spec.card_capacity / (1024 * 1024)) * 512;
mbytes = (file_sector_num >> 11);
while( 1) {
if( mbytes <= 2) {
file_heads = 2;
file_secptrack = 16;
break;
}
if( mbytes <= 16) {
file_heads = 2;
file_secptrack = 32;
break;
}
if( mbytes <= 32) {
file_heads = 4;
file_secptrack = 32;
break;
}
if( mbytes <= 128) {
file_heads = 8;
file_secptrack = 32;
break;
}
if( mbytes <= 256) {
file_heads = 16;
file_secptrack = 32;
break;
}
if( mbytes <= 504) {
file_heads = 16;
file_secptrack = 63;
break;
}
if( mbytes <= 1008) {
file_heads = 32;
file_secptrack = 63;
break;
}
if( mbytes <= 2016) {
file_heads = 64;
file_secptrack = 63;
break;
}
if( mbytes <= 2048) {
file_heads = 128;
file_secptrack = 63;
break;
}
if( mbytes <= 4032) {
file_heads = 128;
file_secptrack = 63;
break;
}
if( mbytes <= 32768) {
file_heads = 255;
file_secptrack = 63;
break;
}
}
/*シリンダ数を計算*/
file_cylinders = (file_sector_num / (file_heads * file_secptrack));
/*memory_capacityを再計算してadjusted_memory_capacityに格納*/
file_adjusted_capacity = file_cylinders *
(file_heads * file_secptrack);
}
/*---------------------------------------------------------------------------*
Name: fileRtfsAttach
Description: fileドライバをドライブに割り当てる
Arguments: driveno :
Returns:
*---------------------------------------------------------------------------*/
BOOL fileRtfsAttach( PCFD fileDesc, int driveno)
{
BOOLEAN result;
DDRIVE pdr;
pdr.dev_table_drive_io = fileRtfsIo;
pdr.dev_table_perform_device_ioctl = fileRtfsCtrl;
pdr.register_file_address = (dword) 0; /* Not used */
pdr.interrupt_number = 0; /* Not used */
pdr.drive_flags = DRIVE_FLAGS_VALID;
pdr.partition_number = 0; /* Not used */
pdr.pcmcia_slot_number = 0; /* Not used */
pdr.controller_number = 0;
pdr.logical_unit_number = 0;
fileDescList[driveno] = fileDesc; /* file descripter セット */
result = rtfs_attach( driveno, &pdr, "FILE"); //構造体がFSライブラリ側にコピーされる
/**/
if( !result) {
PRINTDEBUG( "fsEnableDevice failured\n");
}
return( result);
}

View File

@ -0,0 +1,50 @@
/*****************************************************************************
*Filename: PORTCONF.H - RTFS porting layer tuning constants
*
*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc, 1993-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
* Description:
* This file contains porting layer tuning constants for configuring RTFS.
* It is included by rtfsconf.h.
*
****************************************************************************/
#ifndef __PORTCONF__
#define __PORTCONF__ 1
/* CPU Configuration section */
#define KS_LITTLE_ENDIAN 1 /* See porting reference guide for explanation */
#define KS_LITTLE_ODD_PTR_OK 0 /* See porting reference guide for explanation */
#define KS_CONSTANT const /* See porting reference guide for explanation */
#define KS_FAR /* See porting reference guide for explanation */
/* Compile time constants to control device inclusion
See the reference guide for an explanation
*/
#define INCLUDE_SD 0
#define INCLUDE_IDE 0 /* - Include the IDE driver */
#define INCLUDE_PCMCIA 0 /* - Include the pcmcia driver */
#define INCLUDE_PCMCIA_SRAM 0 /* - Include the pcmcia static ram card driver */
#define INCLUDE_COMPACT_FLASH 0 /* - Support compact flash (requires IDE and PCMCIA) */
#define INCLUDE_FLASH_FTL 0 /* - Include the linear flash driver */
#define INCLUDE_ROMDISK 0 /* - Include the rom disk driver */
#define INCLUDE_RAMDISK 0 /* - Include the rom disk driver */
#define INCLUDE_MMCCARD 0 /* - Include the multi media flash card driver */
#define INCLUDE_SMARTMEDIA 0 /* - Include the smart media flash card driver */
#define INCLUDE_FLOPPY 0 /* - Include the floppy disk driver */
#define INCLUDE_HOSTDISK 0 /* - Include the host disk disk simulator */
#define INCLUDE_UDMA 0 /* - Include ultra dma support for the ide driver */
#define INCLUDE_82365_PCMCTRL 0 /* - Include the 82365 pcmcia controller driver */
#endif /* __PORTCONF__ */

View File

@ -0,0 +1,418 @@
/*
* portio.c
*
* ERTFS Porting layer peripheral input output functions. The user must port
* some or all of the routines in this file to his CPU environment according
* to the rules set forth in the ERTFS porting specification.
*
* Copyright EBS Inc , 1993-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
* Generic implementation of IO porting layer
* Modify these routnes for your target environment.
* Note: Not all routines must be implemented. Only implement
* those routines that are required for your selected set of devices.
*/
#include <twl.h>
#include <rtfs.h>
#include <rtfs_target_os.h>
/*--- ctr modified ---*/
#include <rtfsconf.h>
#if (RTFS_DEBUG_PRINT_ON == 1)
#if (CTR_DEF_ENVIRONMENT_DSEMU == 1)
#define PRINTDEBUG osTPrintf
#else
#include <ctr/vlink.h>
#define PRINTDEBUG vlink_dos_printf
#endif
#else
#define PRINTDEBUG i_no_print
static void i_no_print( const char *fmt, ... );
static void i_no_print( const char *fmt, ... ){ return; }
#endif
/*--------------------*/
/* All of the IO in and out functions in this file call one of these four
macros to write or read the apprpriate IO location. If t is convenient
to use this scheme and it will work for you then please modify these
macros to do the appropriate IO operation for the register. If this can't
be accomplished just modfy the appropriate routines manually.
*/
#define RTFS_OUTBYTE(ADDRESS,VALUE)
#define RTFS_INBYTE(ADDRESS) 0
#define RTFS_OUTWORD(ADDRESS,VALUE)
#define RTFS_INWORD(ADDRESS) 0
#define RTFS_OUTDWORD(ADDRESS,VALUE)
/* The code below must be implemented for all targets */
/*rtfs_port_disable() and rtfs_port_enable()
Used by a few device drivers, floppy, flash chip and pcmctrl,
you may ignore it if not being called, but first check to see
if floppy, flash chip and pcmctrl are still the only drivers
using the functions */
/*This function must disable interrupts and return. */
void rtfs_port_disable(void)
{ /* ctr modified */
PRINTDEBUG( "fatfs : rtfs_port_disable) is called.\n");
OSAPI_DISABLEINTR();
}
/*This function must re-disable interrupts that were disabled via a call to
rtfs_port_disable(). */
void rtfs_port_enable(void)
{ /* ctr modified */
PRINTDEBUG( "rtfs_port_enable is called.\n");
OSAPI_ENABLEINTR();
}
#if (INCLUDE_82365_PCMCTRL)
/* These routines are required only if the 82365 pcmcia controller driver
is included (pcmctrl.c)
phys82365_to_virtual(byte * * virt, dword phys)
write_82365_index_register(byte value)
write_82365_data_register(byte value)
read_82365_data_register(void)
*/
/* This routine must take a physical linear 32 bit bus address passed in
the "phys" argument and convert it to an address adressable in the logical
space of the CPU, returning that value in "virt". Two sample methods are
provided, a flat version where the virtual address is simply the "phys"
address cast to a pointer and a second segmented version for X86
segmented applications.
*/
void phys82365_to_virtual(byte * * virt, dword phys)
{
*virt = (byte *) phys; /* example for flat unmapped address space */
}
/*
These routines write and read the 82365's index and data registers which,
in a standard PC environment, are located in IO space at address 0x3E0 and
0x3E1. Non PC architectures typically map these as memory mapped locations
somewhere high in memory such as 0xB10003E0 and 0xB10003E1.
*/
void write_82365_index_register(byte value)
{
RTFS_OUTBYTE(0x3e0,value); /* Defined for X86. Replace with your own */
}
void write_82365_data_register(byte value)
{
RTFS_OUTBYTE(0x3e1,value); /* Defined for X86. Replace with your own */
}
byte read_82365_data_register(void)
{
byte v;
v = RTFS_INBYTE(0x3e1); /* Defined for X86. Replace with your own */
return (v);
}
#endif /* (INCLUDE_82365_PCMCTRL) */
/*
These routines are only required if INCLUDE_IDE is turned on (ide_drv.c)
byte ide_rd_status(dword register_file_address)
byte ide_rd_sector_count(dword register_file_address)
byte ide_rd_alt_status(dword register_file_address,int contiguous_io_mode)
byte ide_rd_error(dword register_file_address)
byte ide_rd_sector_number(dword register_file_address)
byte ide_rd_cyl_low(dword register_file_address)
byte ide_rd_cyl_high(dword register_file_address)
byte ide_rd_drive_head(dword register_file_address)
byte ide_rd_drive_address(dword register_file_address,int contiguous_io_mode)
void ide_wr_dig_out(dword register_file_address, int contiguous_io_mode, byte value);
void ide_wr_sector_count(dword register_file_address, byte value)
void ide_wr_sector_number(dword register_file_address, byte value)
void ide_wr_cyl_low(dword register_file_address, byte value)
void ide_wr_cyl_high(dword register_file_address, byte value)
void ide_wr_drive_head(dword register_file_address, byte value)
void ide_wr_command(dword register_file_address, byte value)
void ide_wr_feature(dword register_file_address, byte value)
unsigned long rtfs_port_bus_address(void * p)
void ide_insw(dword register_file_address, unsigned short *p, int nwords)
void ide_outsw(dword register_file_address, unsigned short *p, int nwords)
These routines are only required if INCLUDE_IDE
and INCLUDE_UDMA are turned on
dword rtfs_port_ide_bus_master_address(int controller_number)
byte ide_rd_udma_status(dword bus_master_address)
void ide_wr_udma_status(dword bus_master_address, byte value)
byte ide_rd_udma_command(dword bus_master_address)
void ide_wr_udma_command(dword bus_master_address, byte value)
void ide_wr_udma_address(dword bus_master_address, dword bus_address)
*/
#if (INCLUDE_IDE)
/* These routines are required only if using the IDE device driver */
/* This function must return the byte in location 7 (IDE_OFF_STATUS)
of the ide register file at register_file_address */
byte ide_rd_status(dword register_file_address)
{
return(RTFS_INBYTE((word) (register_file_address + 7)));
}
/* This function must return the word in location 0 (IDE_OFF_DATA)
of the ide register file at register_file_address */
word ide_rd_data(dword register_file_address)
{
return(RTFS_INWORD((word)register_file_address));
}
/* This function must return the byte in location 2 (IDE_OFF_SECTOR_COUNT)
of the ide register file at register_file_address */
byte ide_rd_sector_count(dword register_file_address)
{
return(RTFS_INBYTE((word) (register_file_address + 2)));
}
/* This function must return the byte in location 0x206 (IDE_OFF_ALT_STATUS)
of the ide register file at register_file_address If the value of the
argument contiguous_io_mode is 1 then the register must be 14 rather
than 0x206.
*/
byte ide_rd_alt_status(dword register_file_address, int contiguous_io_mode)
{
if (contiguous_io_mode)
return(RTFS_INBYTE((word) (register_file_address + 14)));
else
return(RTFS_INBYTE((word) (register_file_address + 0x206)));
}
/* This function must return the byte in location 1 (IDE_OFF_ERROR)
of the ide register file at register_file_address.
*/
byte ide_rd_error(dword register_file_address)
{
return(RTFS_INBYTE((word) (register_file_address + 1)));
}
/* This function must return the byte in location 3 (IDE_OFF_SECTOR_NUMBER)
of the ide register file at register_file_address
*/
byte ide_rd_sector_number(dword register_file_address)
{
return(RTFS_INBYTE((word) (register_file_address + 3)));
}
/* This function must return the byte in location 4 (IDE_OFF_CYL_LOW)
of the ide register file. register_file_address
*/
byte ide_rd_cyl_low(dword register_file_address)
{
return(RTFS_INBYTE((word) (register_file_address + 4)));
}
/* This function must return the byte in location 5 (IDE_OFF_CYL_HIGH)
of the ide register file. register_file_address
*/
byte ide_rd_cyl_high(dword register_file_address)
{
return(RTFS_INBYTE((word) (register_file_address + 5)));
}
/* This function must return the byte in location 6 (IDE_OFF_DRIVE_HEAD)
of the ide register file. register_file_address
*/
byte ide_rd_drive_head(dword register_file_address)
{
return(RTFS_INBYTE((word) (register_file_address + 6)));
}
/* This function must return the byte in location 0x207 (IDE_OFF_DRIVE_ADDRESS)
of the ide register file at register_file_address.
If the value of the argument contiguous_io_mode is 1 then the register
must be 15 rather than 0x207.
*/
byte ide_rd_drive_address(dword register_file_address,int contiguous_io_mode)
{
if (contiguous_io_mode)
return(RTFS_INBYTE((word) (register_file_address + 15)));
else
return(RTFS_INBYTE((word) (register_file_address + 0x207)));
}
/* This function must place the byte in value at location
0x206 (IDE_OFF_ALT_STATUS) of the ide register file at
register_file_address. If the value of the argument contiguous_io_mode
is 1 then the register must be 14 rather than 0x206.
*/
void ide_wr_dig_out(dword register_file_address, int contiguous_io_mode, byte value)
{
if (contiguous_io_mode)
RTFS_OUTBYTE((word) (register_file_address + 14), value);
else
RTFS_OUTBYTE((word) (register_file_address + 0x206), value);
}
/* This function must place the word in location 0 (IDE_OFF_DATA)
of the ide register file at register_file_address */
void ide_wr_data(dword register_file_address, word value)
{
RTFS_OUTWORD((word)register_file_address, value);
}
/* This function must place the byte in value at location
2 (IDE_OFF_SECTOR_COUNT) of the ide register file at
register_file_address
*/
void ide_wr_sector_count(dword register_file_address, byte value)
{
RTFS_OUTBYTE((word) (register_file_address + 2), value);
}
/* This function must place the byte in value at location
3 (IDE_OFF_SECTOR_NUMBER) of the ide register file at
register_file_address
*/
void ide_wr_sector_number(dword register_file_address, byte value)
{
RTFS_OUTBYTE((word) (register_file_address + 3), value);
}
/* This function must place the byte in value at location
4 (IDE_OFF_CYL_LOW) of the ide register file at
register_file_address
*/
void ide_wr_cyl_low(dword register_file_address, byte value)
{
RTFS_OUTBYTE((word) (register_file_address + 4), value);
}
/* This function must place the byte in value at location
5 (IDE_OFF_CYL_HIGH) of the ide register file at register_file_address
*/
void ide_wr_cyl_high(dword register_file_address, byte value)
{
RTFS_OUTBYTE((word) (register_file_address + 5), value);
}
/* This function must place the byte in value at location
6 (IDE_OFF_DRIVE_HEAD) of the ide register file at register_file_address
*/
void ide_wr_drive_head(dword register_file_address, byte value)
{
RTFS_OUTBYTE((word) (register_file_address + 6), value);
}
/* This function must place the byte in value at location
7 (IDE_OFF_COMMAND) of the ide register file at register_file_address */
void ide_wr_command(dword register_file_address, byte value)
{
RTFS_OUTBYTE((word) (register_file_address + 7), value);
}
/* This function must place the byte in value at location
1 (IDE_OFF_FEATURE) of the ide register file at register_file_address
*/
void ide_wr_feature(dword register_file_address, byte value)
{
RTFS_OUTBYTE((word) (register_file_address + 1), value);
}
/* This function must read nwords 16 bit values from the data
register at offset 0 of the the ide register file and place
them in succesive memory locations starting at p. Since large
blocks of data are transferred from the drive in this way this
routine should be optimized. On x86 based systems the repinsw
instruction should be used, on non x86 platforms the loop should
be as tight as possible.
*/
void ide_insw(dword register_file_address, unsigned short *p, int nwords)
{
while (nwords--)
*p++ = (word)RTFS_INWORD(register_file_address);
}
/*
This function must write nwords 16 bit values to the data
register at offset 0 of the the ide register file. The data is
taken from succesive memory locations starting at p. Since large
blocks of data are transferred from the drive in this way this
routine should be optimized. On x86 based systems the repoutsw
instruction should be used, on non x86 platforms the loop should
be as tight as possible.
*/
void ide_outsw(dword register_file_address, unsigned short *p, int nwords)
{
while (nwords--)
RTFS_OUTWORD(register_file_address, *p++);
}
#if (INCLUDE_UDMA)
/* These routines are required only if using an ultra-dma controller. */
/* This function must determine if the specified controller is a PCI bus
mastering IDE controller and if so return the location of the
control and status region for that controller. If it is not a bus
bus master controller it should return zero.
*/
dword rtfs_port_ide_bus_master_address(int controller_number)
{
RTFS_ARGSUSED_INT(controller_number);
return (0); /* Must be implemented. 0 return val disables UDMA */
}
/* This function must read the status byte value at location
2 the bus master control region
*/
byte ide_rd_udma_status(dword bus_master_address)
{
byte value;
value = RTFS_INBYTE((word) (bus_master_address + 2));
return (value);
}
/* This function must write the byte value to location
2 of the bus master control region
*/
void ide_wr_udma_status(dword bus_master_address, byte value)
{
RTFS_OUTBYTE((word) (bus_master_address + 2), value);
}
/* This function must read the command byte value at location
0 of the bus master control region
*/
byte ide_rd_udma_command(dword bus_master_address)
{
byte value;
value = RTFS_INBYTE((word) bus_master_address);
return (value);
}
/* This function must write the byte value to location
0 of the bus master control region
*/
void ide_wr_udma_command(dword bus_master_address, byte value)
{
RTFS_OUTBYTE((word) bus_master_address, value);
}
/* This function must write the byte dword to location
4 of the bus master control region
*/
void ide_wr_udma_address(dword bus_master_address, dword bus_address)
{
RTFS_OUTDWORD((word)(bus_master_address+4), bus_address);
}
/* This function must take a logical pointer and convert it to an
unsigned long representation of its address on the system bus */
unsigned long rtfs_port_bus_address(void * p)
{
dword laddress;
laddress = (dword) p;
return(laddress);
}
#endif /* (INCLUDE_UDMA) */
#endif /* (INCLUDE_IDE) */

View File

@ -0,0 +1,636 @@
/*
* portrtfs.c
*
* ERTFS Porting layer. The user must port some or all of the routines
* in this file to his RTOS and hardware environment according to the
* rules set forth in the ERTFS porting specification.
*
* Copyright EBS Inc , 1993-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
* Generic RTOS porting layer template.
*
* This file contains the RTOS/KERNEL porting layer as described in
* the porting guide. If you are porting to a real time operating
* system environment you must modify most of the routines in this
* file for your RTOS. If you are not porting to an RTOS but are rather
* bringing ERTFS up in polling mode then read the following section.
*
*
* If you are using POLLED mode then this file is actually quite portable.
* Several reference ports are provided for x86 environments. To port
* it to a non supported environment you must provide the following
* functions and macros.
* unsigned long rtfs_port_get_ticks();
* #define MILLISECONDS_PER_TICK
*
*
* And depending on what drivers are required one or more of the following
*
* void hook_82365_pcmcia_interrupt(int irq)
* void hook_ide_interrupt(int irq, int controller_number)
* void hook_ide_interrupt(int irq, int controller_number)
* void hook_floppy_interrupt(int irq)
*
*/
#include <twl.h> /* ctr modified */
//#include <ctr/rtc/rtc.h> /* ctr modified */
//#include <kernel.h>
#include <rtfs.h>
#include <portconf.h> /* For included devices */
/*--- ctr modified ---*/
#include <rtfsconf.h>
#if (RTFS_DEBUG_PRINT_ON == 1)
#if (CTR_DEF_ENVIRONMENT_DSEMU == 1)
#define PRINTDEBUG osTPrintf
#else
#include <ctr/vlink.h>
#define PRINTDEBUG vlink_dos_printf
#endif
#else
#define PRINTDEBUG i_sdmc_no_print
static void i_sdmc_no_print( const char *fmt, ... );
static void i_sdmc_no_print( const char *fmt, ... ){ return; }
#endif
/*--------------------*/
/* This routine takes no arguments and returns an unsigned long. The routine
must return a tick count from the system clock. The macro named
MILLISECONDS_PER_TICK must be defined in such a way so that it returns
the rate at which the tick increases in milliseconds per tick */
/* This routine is declared as static to emphasize that its use is local
to the portkern.c file only */
#if (TARGET_OS_CTR == 1)
#define MILLISECONDS_PER_TICK 1 /* Change this to your environment */
#else
#define MILLISECONDS_PER_TICK 33520 /* Change this to your environment */
#endif
static dword rtfs_port_get_ticks(void)
{
#if (TARGET_OS_CTR == 1)
SYSTIM systim; /* ctr modified */
systim = get_tim( &systim);
PRINTDEBUG( "fatfs : rtfs_port_get_ticks(%d).\n", systim);
return( (dword)(systim)); /* Return the real periodic clock tick value here */
#else
OSTick systim;
systim = OS_GetTick();
return( (dword)(systim));
#endif
}
/*
This routine takes no arguments and returns an unsigned long. The routine
must allocate and initialize a Mutex, setting it to the "not owned" state. It
must return an unsigned long value that will be used as a handle. ERTFS will
not interpret the value of the return value. The handle will only used as
an argument to the rtfs_port_claim_mutex() and rtfs_port_release_mutex()
calls. The handle may be used as an index into a table or it may be cast
internally to an RTOS specific pointer. If the mutex allocation function
fails this routine must return 0 and the ERTFS calling function will return
failure.
*/
/*メモapicnfig.cの定義「NDRIVES」の数 + 1個ぶんの回数呼ばれる*/
dword rtfs_port_alloc_mutex(void)
{ /* ctr modified */
/* POLLED mode does not require mutexes */
/* Otherwise implement it */
#if (TARGET_OS_CTR == 1)
// ID mytskid;
T_CMTX cmtx;
ER_ID mtxid;
// get_tid( &mytskid);
// setup mutex generate info.
cmtx.mtxatr = TA_INHERIT; // set attribution : inherit priority
cmtx.ceilpri= TMAX_MPRI; // set max priority : no effect when mtxatr is without TA_CEILING
mtxid = acre_mtx( &cmtx); //mutexの生成
if( mtxid < 0) {
PRINTDEBUG("fatfs : ERROR! Cannot create new mutex.\n");
return 0;
}
// PRINTDEBUG( "fatfs : task[%d] create new mutex(%d).\n", mytskid, mtxid);
return( (dword)(mtxid));
#else
OSMutex* my_mtx;
my_mtx = (OSMutex*)OS_Alloc( sizeof( OSMutex));
if( my_mtx == NULL) {
return 0;
}
OS_InitMutex( my_mtx);
return( (dword)my_mtx);
#endif
}
/* This routine takes as an argument a mutex handle that was returned by
rtfs_port_alloc_mutex(). If the mutex is already claimed it must wait for
it to be released and then claim the mutex and return.
*/
void rtfs_port_claim_mutex(dword handle)
{ /* ctr modified */
/* POLLED mode does not require mutexes */
/* Otherwise implement it */
#if ( TARGET_OS_CTR == 1)
// ID mytskid;
ER ercd;
// ercd = get_tid( &mytskid);
ercd = loc_mtx( handle); //mutexのロック
if( ercd == E_OK) {
// PRINTDEBUG( "fatfs : task[%d] lock mutex(%d).\n", mytskid, handle);
}
#else
OS_LockMutex( (OSMutex*)handle);
#endif
}
/* This routine takes as an argument a mutex handle that was returned by
rtfs_port_alloc_mutex() that was previously claimed by a call to
rtfs_port_claim_mutex(). It must release the handle and cause a caller
blocked in rtfs_port_claim_mutex() for that same handle to unblock.
*/
void rtfs_port_release_mutex(dword handle)
{ /* ctr modified */
/* POLLED mode does not require mutexes */
/* Otherwise implement it */
#if ( TARGET_OS_CTR == 1)
// ID mytskid;
ER ercd;
// ercd = get_tid( &mytskid);
ercd = unl_mtx( handle); //mutexのリリース
if( ercd == E_OK) {
// PRINTDEBUG( "fatfs : task[%d] release mutex(%d).\n", mytskid, handle);
}
#else
OS_UnlockMutex( (OSMutex*)handle);
OS_Free( (OSMutex*)handle);
#endif
}
/* Note: Currently ERTFS only requires these functions if the floppy disk device
driver is being used or if the IDE device driver is being used in interrupt
mode rather than polled mode. Additional user supplied device drivers may
opt to use these calls or they may implement their own native signalling
method at the implementor's discretion. If you are not using the floppy
disk driver or the IDE driver in interrupt mode please skip this section.
The signalling code is abstracted into four functions that must be modified
by the user to support the target RTOS. The required functions are:
rtfs_port_alloc_signal(), rtfs_port_clear_signal(), rtfs_port_test_signal()
and rtfs_port_set_signal(). The requirements of each of these functions is
defined below.
*/
/* This routine takes no arguments and returns an unsigned long. The routine
must allocate and initialize a signalling device (typically a counting
semaphore) and set it to the "not signalled" state. It must return an
unsigned long value that will be used as a handle. ERTFS will
not interpret the value of the return value. The handle will only used as
an argument to the rtfs_port_clear_signal(), rtfs_port_test_signal()
and rtfs_port_set_signal() calls.
Only required for the supplied floppy disk and ide device driver if the
ide driver is running in interrupt mode. Otherwise leave this function as
it is, it will not be used. */
dword rtfs_port_alloc_signal(void)
{
/* Polled mode has only one global signal */
/* Otherwise implement it */
PRINTDEBUG( "not implemented function ( rtfs_port_alloc_signal) is called\n");
return(1);
}
/* This routine takes as an argument a handle that was returned by
rtfs_port_alloc_signal(). It must place the signal in an unsignalled state
such that a subsequant call to rtfs_port_test_signal() will not return
success until rtfs_port_set_signal() has been called. This clear function
is neccessary since it is possible although unlikely that an interrupt
service routine could call rtfs_port_set_signal() after the intended call
to rtfs_port_test_signal() timed out. A typical implementation of this
function for a counting semaphore is to set the count value to zero or
to poll it until it returns failure. */
int polled_signal = 0; /* We only need one signal for polled mode since it
is single threaded */
void rtfs_port_clear_signal(dword handle)
{
/* Polled mode has only one global signal */
/* Otherwise implement clear of the signal specified by handle */
PRINTDEBUG( "not implemented function ( rtfs_port_clear_signal) is called\n");
RTFS_ARGSUSED_PVOID((void *) handle);
polled_signal = 0;
}
/* This routine takes as an argument a handle that was returned by
rtfs_port_alloc_signal() and a timeout value in milliseconds. It must
block until timeout milliseconds have elapsed or rtfs_port_set_signal()
has been called. If the test succeeds must return 0, if it times out it
must return a non-zero value.
Only required for the supplied floppy disk and ide device driver if the
ide driver is running in interrupt mode. Otherwise leave this function as
it is, it will not be used. */
int rtfs_port_test_signal(dword handle, int timeout)
{
PRINTDEBUG( "not implemented function ( rtfs_port_test_signal) is called\n");
#if (!POLLED_MODE)
/* Implement timed test of the signal specified by handle here
otherwise use the polled mode code provided below */
return (-1);
#else
/* This will work in polled mode */
dword last_time, end_time, curr_time;
/* Polled mode signal wait with timeout. This is portable but the
user must implement the routine rtfs_port_get_ticks(void)
and the macro MILLISECONDS_PER_TICK. */
/* polled mode only ever uses one signal at a time so we
ignore the handle argument */
RTFS_ARGSUSED_PVOID((void *) handle);
if (timeout)
{
/* Covert milliseconds to ticks. If 0 set it to 2 ticks */
timeout = timeout/MILLISECONDS_PER_TICK;
if (!timeout)
timeout = 2;
last_time = end_time = 0; // keep compiler happy
curr_time = rtfs_port_get_ticks();
end_time = curr_time + (dword) timeout;
// Check for a wrap
if (end_time < curr_time)
{
end_time = (dword) 0xffffffffL;
}
last_time = curr_time;
do
{
// See if we timed out
curr_time = rtfs_port_get_ticks();
if (curr_time > end_time)
break;
// if wrap or clearing of clock then start count over
if (curr_time < last_time)
end_time = curr_time + (dword) timeout;
last_time = curr_time;
} while (polled_signal == 0);
}
if (polled_signal)
{
polled_signal -= 1;
return(0);
}
else
{
return(-1);
}
#endif
}
/*
This routine takes as an argument a handle that was returned by
rtfs_port_alloc_signal(). It must set the signal such that a subsequant
call to rtfs_port_test_signal() or a call currently blocked in
rtfs_port_test_signal() will return success.
This routine is always called from the device driver interrupt service
routine while the processor is executing in the interrupt context.
Only required for the supplied floppy disk and ide device driver if the
ide driver is running in interrupt mode. Otherwise leave this function as
it is, it will not be used. */
void rtfs_port_set_signal(dword handle)
{
/* Implement set of the signal specified by handle here */
/* This simple implemetation is for polled mode */
PRINTDEBUG( "not implemented function ( rtfs_port_set_signal) is called\n");
RTFS_ARGSUSED_PVOID((void *) handle);
polled_signal += 1;
}
/*
This routine takes as an argument a sleeptime value in milliseconds. It
must not return to the caller until at least sleeptime milliseconds have
elapsed. In a mutitasking environment this call should yield the task cpu.
*/
void rtfs_port_sleep(int sleeptime)
{
/* Implement simple task sleep call here */
/* This simple implemetation is for polled mode */
/* Call the signalling system to timeout. This will in effect sleep */
#if (TARGET_OS_CTR == 1)
dly_tsk( (RELTIM)sleeptime);
#else
OS_Sleep( (u32)sleeptime);
#endif
PRINTDEBUG( "fatfs : port_sleep (time : %d). \n", sleeptime);
rtfs_port_clear_signal(0);
rtfs_port_test_signal(0, sleeptime);
}
/* This routine takes no arguments and returns an unsigned long. The routine
must return an unsigned long value that will later be passed to
rtfs_port_elapsed_check() to test if a given number of milliseconds or
more have elapsed. A typical implementation of this routine would read the
system tick counter and return it as an unsigned long. ERTFS makes no
assumptions about the value that is returned.
*/
dword rtfs_port_elapsed_zero(void)
{
PRINTDEBUG( "fatfs : rtfs_port_elapsed_zero\n");
return(rtfs_port_get_ticks());
}
/* This routine takes as arguments an unsigned long value that was returned by
a previous call to rtfs_port_elapsed_zero() and a timeout value in
milliseconds. If "timeout" milliseconds have not elapsed it should return
0. If "timeout" milliseconds have elapsed it should return 1. A typical
implementation of this routine would read the system tick counter, subtract
the zero value, scale the difference to milliseconds and compare that to
timeout. If the scaled difference is greater or equal to timeout it should
return 1, if less than timeout it should return 0.
*/
int rtfs_port_elapsed_check(dword zero_val, int timeout)
{
dword curr_time;
PRINTDEBUG( "not implemented function ( rtfs_port_elapsed_check) is called\n");
timeout = timeout/MILLISECONDS_PER_TICK;
if (!timeout)
timeout = 2;
curr_time = rtfs_port_get_ticks();
if ( (curr_time - zero_val) > (dword) timeout)
return(1);
else
return(0);
}
/*
This function must return an unsigned long number that is unique to the
currently executing task such that each time this function is called from
the same task it returns this same unique number. A typical implementation
of this function would get address of the current task control block, cast
it to a long, and return it.
*/
dword rtfs_port_get_taskid(void)
{ /* ctr modified */
/* For an RTOS environment return a dword that is unique to this
task. For example the address of its task control block */
/* Otherwise always return 1 For POLLOS */
#if (TARGET_OS_CTR == 1)
ID tskid;
get_tid( &tskid);
return( (dword)(tskid));
#else
OSThread* my_tsk;
my_tsk = OS_GetCurrentThread();
return( (dword)my_tsk);
#endif
}
/*
This routine requires porting if you wish to use the interactive test shell.
It must provide a line of input from the terminal driver. The line must be
NULL terminated and it must not contain ending newline or carriage return
characters.
*/
void rtfs_port_tm_gets(byte *buffer)
{
/* Use Get's or some other console input function. If you have no console
input function then leave it blank */
/* gets(buffer); */
}
/*
This routine requires porting if you wish to display messages to your console
This routine must print a line of text from the supplied buffer to
the console. The output routine must not issue a carriage or linefeed
command unless the text is terminated with the appropriate control
character (\n or \r).
*/
void rtfs_port_puts(byte *buffer)
{
PRINTDEBUG( "%s\n", buffer); //ctr modified
/* Use cputs or some other console output function. If you have no console
output function then leave it blank */
/* cputs(buffer); */
}
/*
This function must exit the RTOS session and return to the user prompt. It
is only necessary when an RTOS is running inside a shell environment like
Windows. This function must be implemented if you are using the ERTFS command library
in an environment that will ever exit, for example if ERTFS is running with
an RTOS in a Dos/Windows or Unix environment you should put a call to your
RTOS's exit code.
Note: Most embedded systems never exit. If your application never exits then
please skip this section.
*/
void rtfs_port_exit(void)
{
/* Exit your application here. If you never exit then leave it blank. */
/* exit(0); */
PRINTDEBUG( "not implemented function ( rtfs_port_exit) is called\n");
}
/*
When the system needs to date stamp a file it will call this routine
to get the current time and date. YOU must modify the shipped routine
to support your hardware's time and date routines.
*/
DATESTR *pc_getsysdate(DATESTR * pd)
{
word year; /* relative to 1980 */
word month; /* 1 - 12 */
word day; /* 1 - 31 */
word hour;
word minute;
word sec; /* Note: seconds are 2 second/per. ie 3 == 6 seconds */
#if (TARGET_OS_CTR == 1)
RtcDate rtfs_base_date; //ctr modified
RtcTime rtfs_base_time; //ctr modified
#endif
PRINTDEBUG( "not implemented function ( pc_getsysdate) is called\n");
#if (0)
/* This code will work if yoiu have ANSI time functions. otherwise get
rid of it and look below where the time is wired to 3/28/8.
You may modify that code to work in your environment. */
struct tm *timeptr;
time_t timer;
time(&timer);
timeptr = localtime(&timer);
hour = (word) timeptr->tm_hour;
minute = (word) timeptr->tm_min;
sec = (word) (timeptr->tm_sec/2);
/* Date comes back relative to 1900 (eg 93). The pc wants it relative to
1980. so subtract 80 */
year = (word) (timeptr->tm_year-80);
month = (word) (timeptr->tm_mon+1);
day = (word) timeptr->tm_mday;
#else
#if (TARGET_OS_CTR == 1)
/* This code is useless but very generic */
/* Hardwire for now */
/* 7:37:28 PM */
// hour = 19;
// minute = 37;
// sec = 14;
/* 3-28-88 */
// year = 8; /* relative to 1980 */
// month = 3; /* 1 - 12 */
// day = 28; /* 1 - 31 */
/*----- ctr modified -----*/
rtcGetDateTimeSync( &rtfs_base_date, &rtfs_base_time);
hour = rtfs_base_time.hour;
minute = rtfs_base_time.minute;
sec = rtfs_base_time.second / 2;
year = rtfs_base_date.year - 1980;
month = rtfs_base_date.month;
day = rtfs_base_date.day;
/*------------------------*/
#else
#endif
#endif
pd->time = (word) ( (hour << 11) | (minute << 5) | sec);
pd->date = (word) ( (year << 9) | (month << 5) | day);
return (pd);
}
/*--- ctr modified ---*/
/*SDK_WEAK_SYMBOL BOOL rtcGetDateTimeSync(RtcDate *pDate, RtcTime *pTime)
{
pTime->hour = 0;
pTime->minute = 0;
pTime->second = 0;
pDate->year = 2007;
pDate->month = 1;
pDate->day = 1;
return( FALSE);
}*/
/*--------------------*/
/* This routine must establish an interrupt handler that will call the
plain 'C' routine void mgmt_isr(void) when the the chip's management
interrupt event occurs. The value of the argument 'irq' is the interrupt
number that was put into the 82365 management interrupt selection register
and is between 0 and 15. This is controlled by the constant
"MGMT_INTERRUPT" which is defined in pcmctrl.c
*/
#if (INCLUDE_82365_PCMCTRL)
/* The routine mgmt_isr(0) must execute when the PCMCIA controller interrupts
this a sample interrupt service routne that will do this, modify it
to match your system's interrupt behavior */
void mgmt_isr(int);
void pcmcia_isr()
{
PRINTDEBUG( "not implemented function ( pcmcia_isr) is called\n");
mgmt_isr(0);
}
/* This routine must "hook" the interrupt so the above code is jumped to
when the PCMCIA controller interrupts */
void hook_82365_pcmcia_interrupt(int irq)
{
PRINTDEBUG( "not implemented function ( hook_82365_pcmcia_interrupt) is called\n");
}
#endif /* (INCLUDE_82365_PCMCTRL) */
#if (INCLUDE_IDE)
/* The routine ide_isr(controller_number) must execute when the IDE
controller associated with that contoller number interrupts.
these are sample interrupt service routines that will do this, modify
them to match your system's interrupt behavior */
void ide_isr(int);
/* This is a sample interrupt service routine for controller 0 */
void ide_isr_0()
{
PRINTDEBUG( "not implemented function ( ide_isr_0) is called\n");
ide_isr(0);
}
/* This is a sample interrupt service routine for controller 1 */
void ide_isr_1()
{
PRINTDEBUG( "not implemented function ( ide_isr_1) is called\n");
ide_isr(1);
}
/* hook_ide_interrupt() is called with the interrupt number in the argument
irq taken from the user's setting of pdr->interrupt_number in pc_ertfs_init().
Controller number is taken from the pdr->controller_number field as set in
pc_ertfs_init() by the user. Hook_ide_interrupt() must establish an interrupt
handler such that the plain 'C' function "void ide_isr(int controller_number)"
is called when the IDE interrupt occurs. The argument to ide_isr() must be
the controller number that was passed to hook_ide_interrupt(), this value
is typically zero for single controller system.
hook_ide_interrupt()pc_ertfs_init()pdr->interrupt_number
(irq)
controller_numberはpc_ertfs_init()pdr->controller_numberとして定義され
*/
void hook_ide_interrupt(int irq, int controller_number)
{
PRINTDEBUG( "not implemented function ( hook_ide_interrupt) is called\n");
}
#endif /* (INCLUDE_IDE) */
/* This routine is called by the floppy disk device driver. It must
establish an interrupt handler such that the plain 'C' function void
floppy_isr(void) is called when the floppy disk interrupt occurs.
The value in "irq" is always 6, this is the PC's standard mapping of
the floppy interrupt. If this is not correct for your system just ignore
the irq argument.
*/
#if (INCLUDE_FLOPPY)
/* This is a sample floppy disk interrupt handler. Modify it to match
your target system */
void floppy_isr(int);
void floppy_interrupt()
{
PRINTDEBUG( "not implemented function ( floppy_interrupt) is called\n");
floppy_isr(0);
}
void hook_floppy_interrupt(int irq)
{
PRINTDEBUG( "not implemented function ( hook_floppy_interrupt) is called\n");
}
#endif /* (INCLUDE_FLOPPY) */

View File

@ -0,0 +1,52 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright Peter Van Oudenaren , 1993
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
*
* Implementation for the generic porting layer
*/
/*
*****************************************************************************
Portmain.c - Main entry point RTOS specific
This file contains the main entry point for the executable. It is
required only if building a stand alone application like our demo.
Several examples of entry point are provided for different operating
systems. The only requirement of the startup module is to call
rtfs_app_entry() from within the contents of a thread. (or of the
main thread for OS's like DOS or UNIX. (see rtfsdemo.c for rtfs_app_entry)
Note: All that is required to use ERTFS is to call pc_rtfs_init() before
using the API This file is required only if building the RTFS DEMO
program as a stand alone application.
If you wish to use the RTFS DEMO program from your existing framework
from your existing simply call rtfs_app_entry().
If you wish to use the RTFS library from your existing framework
from your existing simply call pc_rtfs_init() and then make calls
to the ERTFS API.
*****************************************************************************/
#include <rtfs.h>
// ********************************************************************
// THIS TASK IS THE MAIN PROGRAM
// ********************************************************************
void rtfs_app_entry(void);
/*
void main()
{
rtfs_app_entry();
}
*/
int main()
{
rtfs_app_entry();
return( 0);
}

View File

@ -0,0 +1,309 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* APIPRO.C - Contains user api level source code for ERTFS-Pro functions.
The following routines are included:
pro_buffer_status - Return disk, failsafe and buffer status.
pro_assign_buffer_pool - Assign a private buffer pool to a drive.
*/
#include <rtfs.h>
/* pro_buffer_status - Return disk and failsafe status.
*
* Summary:
* BOOLEAN pro_buffer_status(byte *drive_name, struct pro_buffer_stats *pstat)
*
* Description:
*
* This routine returns status information about failsafe, the block buffer
* pools and the fat buffer pools.
* The information is returned to the user in the structure of type
* pro_buffer_stats that must be passed to the routine.
*
* If the routine succeeds it will return 0 and the following fields in
* pstat will be poulated:
*
* int failsafe_mode - Failsafe operating mode.
* 0 - Failsafe disabled
* 1 - Failsafe enabled
* dword failsafe_blocks_used
* If failsafe is enabled this the number of blocks currently
* journalled in the FailSafe file. If FailSafe is disabled this
* value is zero.
* dword failsafe_blocks_free
* If failsafe is enabled this the number of blocks still available
* in the FailSafe file for use. If FailSafe is disabled this
* value is zero.
* dword total_block_buffers;
* Total number of directory buffers available.
* dword block_buffers_pending
* Total number of directory blocks scheduled to write but not yet written
* If directory writeback mode is not enabled this value will be zero.
* dword block_buffers_available;
* Number of directory blocks still available to hold pending writes.
* If directory writeback mode is not enabled this value will be zero.
* dword block_buffers_cache_hits;
* Number of block reads so far that were in the cache when the request
* was made.
* dword block_buffers_cache_misses;
* Number of block reads so far that were not in the cache when the request
* was made.
* dword block_buffers_low
* The low water mark or lowest number of block buffers that have been
* available for allocation so far.
* If directory writeback mode is not enabled this value will be zero.
* dword block_buffers_fail
* The number of block allocation failures that have occured due to
* insufficient buffer pool space
* If directory writeback mode is not enabled this value will be zero.
* dword block_buffers_cache_hits;
* Number of block reads so far that were in the cache when the request
* was made.
* dword block_buffers_cache_misses;
* Number of block reads so far that were not in the cache when the request
* was made.
* dword fat_buffer_primary_cache_hits
* Number of fat block accesses so far that were in the fat primary cache
* when the request was made.
* dword fat_buffer_secondary_cache_hits
* Number of fat block accesses so far that were in the fat secondary cache
* when the request was made.
* dword fat_buffer_cache_misses;
* Number of fat block accesses so far that were in the fat secondary cache
* when the request was made.
* dword total_fat_buffers
* Total number of fat directory buffers for this drive. This value is
* determined by the value assigned to prtfs_cfg->cfg_FAT_BUFFER_SIZE[driveno] in apiconfig.c
* dword fat_buffers_pending
* Total number of fat blocks scheduled to write but not yet written
* If FAT writeback mode is not enabled this value will be zero.
* dword fat_buffers_available
* Number of fat blocks still available to store pending writes.
* If FAT writeback mode is not enabled this value will be zero.
* dword fat_buffers_free
* Number of fat buffer blocks that have never been used. If this value
* is non-zero it means no fat swapping has occured.
* dword fat_buffer_cache_loads
* Number of fat block reads so far that were not in the cache when
* the request was made.
* dword fat_buffer_cache_swaps;
* Number of fat block swaps so far. Blocks that were written because they
* contained changed data but the buffer was required in order to load
* another block.
*
* Returns:
* TRUE - Success
* FALSE - Failure
* If FALSE is return errno will be set to one of the following.
*
* PEINVALIDDRIVEID - Drive argument invalid
*/
BOOLEAN pro_buffer_status(byte *drive_name, struct pro_buffer_stats *pstat)
{
#if (INCLUDE_FAILSAFE_CODE)
FAILSAFECONTEXT *pfscntxt;
#endif
int driveno;
DDRIVE *pdr;
FATBUFF *pfblk;
driveno = pc_parse_raw_drive(drive_name);
if (driveno < 0)
{
inval:
rtfs_set_errno(PEINVALIDDRIVEID);
return(FALSE);
}
pdr = pc_drno_to_drive_struct(driveno);
if (!pdr || !(pdr->drive_flags&DRIVE_FLAGS_VALID) )
goto inval;
OS_CLAIM_LOGDRIVE(driveno) /* pro_buffer_status Register drive in use */
rtfs_set_errno(0);
#if (INCLUDE_FAILSAFE_CODE)
pfscntxt = (FAILSAFECONTEXT *) pdr->pfscntxt;
if (!pfscntxt)
{
pstat->failsafe_mode = 0;
pstat->failsafe_blocks_used = 0;
pstat->failsafe_blocks_free = 0;
}
else if (pfscntxt->configuration_flags & FS_MODE_JOURNALING)
{
pstat->failsafe_mode = 1;
pstat->failsafe_blocks_used = pfscntxt->total_blocks_mapped;
pstat->failsafe_blocks_free = pfscntxt->num_remap_blocks -
pfscntxt->total_blocks_mapped;
}
else
{
pstat->failsafe_mode = 2;
pstat->failsafe_blocks_used = pfscntxt->total_blocks_mapped;
pstat->failsafe_blocks_free = pfscntxt->num_remap_blocks -
pfscntxt->total_blocks_mapped;
}
#else
pstat->failsafe_mode = 0;
pstat->failsafe_blocks_used = 0;
pstat->failsafe_blocks_free = 0;
#endif
OS_CLAIM_FSCRITICAL()
/* Critical since block buffers may be shared among drives */
pstat->total_block_buffers = pdr->pbuffcntxt->num_blocks;
pstat->block_buffers_pending = 0;
/* for (pblk = pdr->pbuffcntxt->ppopulated_blocks; pblk; pblk = pblk->pnext) */
/* { */
/* if (pblk->block_state == DIRBLOCK_COMMITTED) */
/* pstat->block_buffers_pending += 1; */
/* } */
pstat->block_buffers_available = pstat->total_block_buffers -
pstat->block_buffers_pending;
pstat->block_buffers_cache_hits = pdr->pbuffcntxt->stat_cache_hits;
pstat->block_buffers_cache_misses = pdr->pbuffcntxt->stat_cache_misses;
pstat->block_buffers_low = pdr->pbuffcntxt->low_water;
pstat->block_buffers_fail = pdr->pbuffcntxt->num_alloc_failures;
OS_RELEASE_FSCRITICAL()
pstat->total_fat_buffers
= pdr->fatcontext.num_blocks;
pstat->fat_buffer_primary_cache_hits
= pdr->fatcontext.stat_primary_cache_hits;
pstat->fat_buffer_secondary_cache_hits
= pdr->fatcontext.stat_secondary_cache_hits;
pstat->fat_buffer_cache_loads
= pdr->fatcontext.stat_secondary_cache_loads;
pstat->fat_buffer_cache_swaps
= pdr->fatcontext.stat_secondary_cache_swaps;
pstat->fat_buffers_free = 0;
for (pfblk = pdr->fatcontext.pfree_blocks;pfblk;pfblk=pfblk->pnext)
pstat->fat_buffers_free += 1;
pstat->fat_buffers_pending = 0;
for (pfblk = pdr->fatcontext.pcommitted_blocks;pfblk;pfblk=pfblk->pnext)
pstat->fat_buffers_pending += 1;
pstat->fat_buffers_available
= pstat->total_fat_buffers - pstat->fat_buffers_pending;
OS_RELEASE_LOGDRIVE(driveno) /* pro_buffer_status release */
return(TRUE);
}
/* pro_assign_buffer_pool - Assign a private buffer pool to a drive.
*
* Summary:
* BOOLEAN pro_assign_buffer_pool(byte *drive_name,
* int block_hashtable_size,
* BLKBUFF **block_hash_table,
* int block_buffer_pool_size,
* BLKBUFF *block_buffer_pool_data)
*
* Description:
*
* This routine provides a way to assign a private block
* buffer pool to a named drive. Normally block buffer space
* is shared among all drives in the system, but this function
* allows the caller to assign block buffers that are private to
* the drive.
*
* This function may improve performance by reducing the amount
* of buffer swapping that occurs when multiple drives compete for
* buffers in the common pool.
*
* It is advisable to assign a private buffer pool to a drive
* if writeback block buffering mode is being used. Failure to do so
* may result in block allocation failures occuring when using other
* drives because blocks are being consumed by pending writes.
*
*
* Inputs:
* drive_name - Null terminated drive designator, for example "A:"
* block_buffer_context - User supplied memory for the block buffer context
* block that will be assigned to the drive to be used
* as a private buffer pool management structure.
* This must be a pointer to a structure of type
* BLKBUFFCNTXT that must remain valid for the whole
* session and may not be deallocated.
* block_hashtable_size - You must set this to the size of the block hash
* table. Each entry in the table takes up 4 bytes.
* This value must be a power of two.
* block_hash_table - User supplied memory for the block hash table.
* This must be a pointer to an array of data of type
* BLKBUF *, containing block_hashtable_size elements.
* It must remain valid for the whole session and must
* not be deallocated.
* block_buffer_pool_size-You must set this to the size of the block buffer
* pool. Each entry in buffer pool requires
* approximately 540 bytes.
* block_buffer_pool_data - User supplied memory for the block buffer pool.
* This must be a pointer to an array of data of type
* BLKBUF, containing block_buffer_pool_size elements.
* It must remain valid for the whole session and must
* not be deallocated.
*
* Returns:
* TRUE - Success
* FALSE - Error
*
* If it returns FALSE errno will be set to one of the following:
*
* PEINVALIDPARMS - Invalid parameters either no context block was passed
* or the fields were not initialized correctly.
* PEINVALIDDRIVEID - Invalid drive
* An ERTFS system error
*
*/
BOOLEAN pro_assign_buffers(byte *drivename,
BLKBUFFCNTXT *block_buffer_context,
int block_hashtable_size,
BLKBUFF **block_hash_table,
int block_buffer_pool_size,
BLKBUFF *block_buffer_pool_data)
{
DDRIVE *pdrive;
int driveno;
if (!pc_parsedrive( &driveno, drivename))
return (-1);
OS_CLAIM_LOGDRIVE(driveno) /* pro_assign_buffers register drive in use */
if ( (block_hashtable_size & 0x3) ||
(block_buffer_pool_size < 2) ||
(!block_hash_table) ||
(!block_buffer_pool_data) ||
(!block_buffer_context) )
{
goto bad_args;
}
/* Initialize the block buffer pool */
if (!pc_initialize_block_pool(
block_buffer_context,
block_buffer_pool_size,
block_buffer_pool_data,
block_hashtable_size,
block_hash_table))
{
bad_args:
OS_RELEASE_LOGDRIVE(driveno) /* pro_assign_buffers release */
rtfs_set_errno(PEINVALIDPARMS);
return (-1);
}
/* Assign a private block buffer pool to the drive */
pdrive = pc_drno_to_drive_struct(driveno);
/* Make sure no blocks are buffered for this drive */
pc_free_all_blk(pdrive);
pdrive->pbuffcntxt = block_buffer_context;
OS_RELEASE_LOGDRIVE(driveno)
return(0);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,484 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* PRFSAPI.C - Contains user api level source code for ERTFS-Pro
failsafe functions.
The following routines are included:
pro_failsafe_init - Initiate a failsafe session
pro_failsafe_commit - Commit failsafe buffers to disk
pro_failsafe_restore - Check or restore from the failsafe journal
pro_failsafe_auto_init - Automatically enable failsafe for a device at boot
pro_failsafe_shutdown - Close or abort FailSafe mode
*/
#include <rtfs.h>
#if (INCLUDE_FAILSAFE_CODE)
#define INCLUDE_FAILSAFE_AUTO_INIT 1
/* pro_failsafe_init - Initiate a failsafe session
*
* Summary:
* BOOLEAN pro_failsafe_init(byte *drive_name,
* FAILSAFECONTEXT *pfscntxt,
* int configuration_flags)
*
* Description:
*
* This routine checks the user supplied parameters, initializes the
* failsafe context structure and places the drive in failsafe mode.
* Once the device is in failsafe mode directory block and FAT block
* writes will be held in a journal file pro_failsafe_commit() is called.
*
* Inputs:
* drive_name - Null terminated drive designator, for example "A:"
* pfscntxt - The address of a block of data that will be used as a
* context block for failsafe. This block must remain valid for the whole
* session and may not be deallocated.
* journal_size - If this is non-zero a journal file is created containing
* this many blocks. If this value is zero the journal file will be created
* using default size calculations. The default size is calculated to be the
* size of the File Allocation table plus
* value in blocks
* configuration_flags - You can optionally enable these features by oring
* these values into the configuration_flags field.
* FS_MODE_AUTORESTORE- If removable media is reinserted and the
* journal file indicates that restore is needed,
* automatically restore and continue.
* If this flag is not set when this condition occurs
* the mount of the volume fails and the errno is set
* to PEFSRESTORENEEDED, the application must then
* handle this errno setting and call the pro_failsafe_restore
* FS_MODE_AUTORECOVER- If AUTORESTORE is set and the restore fails, ignore
* ignore the error and continue. Attempt to create
* the journal file. If AUTORECOVER is not set the
* disk mount fails, with errno set to PEFSRESTOREERROR.
* FS_MODE_AUTOCOMMIT- If AUTOCOMMIT is enabled the FailSafe commit operation
* will be performed automatically be ERTFS at the
* completion of each API call. With AUTOCOMMIT enabled
* the FailSafe operation is transparent to the user
* and it is not necessary to call pro_failsafe_commit().
*
*
* Additional inputs - Several fields in the FailSafe context block may be
* initialized before pro_failsafe_init() is called. user_journal_size may
* be set under certain special circumstances. blockmap_freelist and
* blockmap_size should be initialized under most circumstance.
*
* user_journal_size - This field in the context block may be assigned with
* a value that prescribes the size of the FailSafe file in blocks. If this
* field is left at zero the FailSafe file will be sized according to the
* algorithm described in the compile time configuration section.
*
* Blockmaps - FailSafe will utilize an optional block map cache if you
* provide it with the necessary ram resources. Even though FailSafe will
* execute properly if no block mapping is provided its performance will be
* significantly diminished. It is therefore highly recommended that you
* enable block mapping. If the number of blocks written to the FailSafe
* file exceeds the number of block map elements FailSafe performance will
* be reduced drastically. Each caching structure requires approximately
* 32 bytes. In the examples provided with ERTFS we provide 128 mapping
* structures.
*
* blockmap_freelist - This field in the context block may be assigned
* a pointer to an array of structures of type FSBLOCKMAP. for example:
* context.blockmap_freelist = &blockmap_array[0];
*
* blockmap_size - This field may be filled in with the number of elements
* contained in the array assigned to blockmap_freelist.
*
* Returns:
* TRUE - Success
* FALSE - Error
*
* If it returns FALSE errno will be set to one of the following:
*
* PEFSREINIT - Failsafe already initialized
* PEINVALIDPARMS - Invalid parameters either no context block was passed
* the journal size parameter is too small
* PEINVALIDDRIVEID - Invalid drive
* An ERTFS system error
*
*/
BOOLEAN pro_failsafe_init(byte *drivename, FAILSAFECONTEXT *pfscntxt)
{
DDRIVE *pdrive;
int driveno;
BOOLEAN ret_val;
if (!pc_parsedrive( &driveno, drivename))
return (FALSE);
OS_CLAIM_LOGDRIVE(driveno) /* pro_failsafe_init register drive in use */
pdrive = pc_drno_to_drive_struct(driveno);
if (pdrive->pfscntxt)
{
rtfs_set_errno(PEFSREINIT);
OS_RELEASE_LOGDRIVE(driveno)
return(FALSE);
}
/* If the drive is open now, flush all buffers and close the disk.
When the drive is reopened it will re-open in failsafe mode */
if (pdrive->mount_valid)
{
/* Flush any FAT buffers */
if (!FATOP(pdrive)->fatop_flushfat(driveno))
{
OS_RELEASE_LOGDRIVE(driveno)
return(FALSE);
}
/* Flush any directory buffers */
/*HEREHERE - Need an API */
pc_dskfree(driveno);
}
ret_val = pro_failsafe_init_internal(pdrive, pfscntxt);
OS_RELEASE_LOGDRIVE(driveno)
return(ret_val);
}
/* pro_failsafe_commit - Commit failsafe buffers to disk
*
* Summary:
* int pro_failsafe_commit(FAILSAFECONTEXT *pfscntxt)
*
* Description:
*
* This routine updates the disk from the in-memory fat and block buffers.
* If FS_MODE_JOURNALING is enabled the journal file is completed before the
* buffer flush operation begins.
*
* When pro_failsafe_commit completes succesfully, the changes made to
* the volume structure since the previous succesful call to
* pro_failsafe_commit are guaranteed to be committed to disk. If
* the disk volume was correct when failsafe was started it will
* still be correct.
*
* If pro_failsafe_commit is unsuccessful, those changes made to
* the volume structure since the last call to pro_failsafe_commit
* may be partially committed to disk. This causes inconsistencies such as
* lost cluster chains and incorrect file lengtths. If JOURNALING is
* enabled, pro_failsafe_restore may be called to restore the disk volume
* back to it's state after the last successful call to pro_failsafe_init.
*
*
* Returns:
* TRUE - Success
* FALSE - Failure
* If FALSE is returned errno will be set to one of the following.
*
* PEINVALIDDRIVEID - Drive argument invalid
* PENOINIT - pro_failsafe_init must be called first
* PEJOURNALOPENFAIL - journal file or vram init call failed
* PEIOERRORREAD - Error reading FAT or buffer area
* PEIOERRORWRITEJOURNAL - Error writing journal file or NVRAM section
* PEIOERRORREADJOURNAL - Error writing journal file or NVRAM section
* PEIOERRORWRITEFAT - Error writing fat area
* PEIOERRORWRITEBLOCK - Error writing directory area
* PEINTERNAL - internal error, only occurs if ERTFS is not configured.
* PEIOERRORREAD - Error reading FAT or buffer area
* PEIOERRORWRITEJOURNAL - Error writing journal file or NVRAM section
* PEIOERRORWRITEFAT - Error writing fat area
* PEIOERRORWRITEBLOCK - Error writing directory area
* An ERTFS system error
*/
BOOLEAN pro_failsafe_commit(byte *path) /* __apifn__ */
{
FAILSAFECONTEXT *pfscntxt;
int driveno;
BOOLEAN ret_val;
DDRIVE *pdr;
driveno = check_drive_name_mount(path);
if (driveno < 0)
return(FALSE); /* Check_drive set errno */
pdr = pc_drno_to_drive_struct(driveno);
rtfs_set_errno(0);
pfscntxt = (FAILSAFECONTEXT *) pdr->pfscntxt;
if (!pfscntxt || !(pfscntxt->configuration_flags & FS_MODE_JOURNALING))
{
release_drive_mount(driveno);/* Release lock, unmount if aborted */
rtfs_set_errno(PENOINIT);
return (FALSE);
}
/* Flush any directory buffers */
if (pro_failsafe_commit_internal(pfscntxt) == 0)
ret_val = TRUE;
else
ret_val = FALSE;
release_drive_mount(driveno);/* Release lock, unmount if aborted */
return (ret_val);
}
/* pro_failsafe_restore - Check or restore from the failsafe journal
*
* Summary:
* int pro_failsafe_restore(byte *drive_name,
* FAILSAFECONTEXT *fscntxt,
* BOOLEAN dorestore,
* BOOLEAN doclear)
*
* Description:
*
* This routine tests the status of the failsafe journal file and returns the
* status of the drive. If dorestore is requested and restore is required
* the disk volume is restored from the journal file.
* If doclear Failsafe will clear any errors in the failsafe file
*
* Note: pro_failsafe_restore() requires a FAILSAFE CONTEXT structure to
* operate. If Failsafe is already initialized it will already have
* this context block, otherwise
*
* Returns:
* FS_STATUS_OK - No restore required
* FS_STATUS_NO_JOURNAL - No journal file present
* FS_STATUS_BAD_JOURNAL - Journal present but has invalid fields
* FS_STATUS_BAD_CHECKSUM - Journal data doesn't match stored checksum.
* FS_STATUS_IO_ERROR - IO error during restore
* FS_STATUS_RESTORED - Restore was required and completed
* FS_STATUS_MUST_RESTORE - Disk must be restored from the journal file
* because flushing of FAT and disk blocks was
* interrupted
* FS_STATUS_NO_INIT - Failsafe init must be called or a context
* structure must be provided
*
* Example:
* int s;
* s = pro_failsafe_restore("A:", 0, FALSE);
* if (s==FS_STATUS_OK) printf("No restore required\n");
* else if (s==FS_STATUS_OK) printf("No restore needed\n");
* else if (s==FS_STATUS_NO_JOURNAL) printf("No journal file present\n");
* else if (s==FS_STATUS_BAD_JOURNAL) printf("Journal contains bad data\n");
* else if (s==FS_STATUS_BAD_CHECKSUM) printf("Journal contains bad data\n");
* else if (s==FS_STATUS_OUT_OF_DATE) printf("Journal out of sync\n");
* else if (s==FS_STATUS_NO_INIT) printf("Failsafe not initialized\n");
* else if (s==FS_STATUS_IO_ERROR) printf("IO error accessing journal\n");
* else if (s==FS_STATUS_MUST_RESTORE)
* {
* printf("Restoring disk from the journal file\n");
* s = pro_failsafe_restore("A:", 0, TRUE);
* if (s==FS_STATUS_RESTORED)
* printf("Restore was completed sucesfully\n");
* else if (s==FS_STATUS_BAD_CHECKSUM)
* printf("Journal file corrupted\n");
* else if (s==FS_STATUS_IO_ERROR)
* printf("IO error during restore\n");
* }
* }
*
*/
int pro_failsafe_restore(byte *drive_name, FAILSAFECONTEXT *fscntxt, BOOLEAN dorestore, BOOLEAN doclear)
{
int ret_val,driveno;
FAILSAFECONTEXT *savedcontext;
DDRIVE *pdr;
savedcontext = 0;
/* Get the drive and make sure it has a context block */
if (!pc_parsedrive( &driveno, drive_name))
return(FS_STATUS_NO_INIT);
pdr = pc_drno_to_drive_struct(driveno);
if (!pdr)
return(FS_STATUS_NO_INIT);
if (!pdr->pfscntxt && !fscntxt)
return(FS_STATUS_NO_INIT);
OS_CLAIM_LOGDRIVE(driveno) /* check_drive_name_mount Register drive in use */
pc_dskfree(driveno); /* make sure buffers are free */
savedcontext = (FAILSAFECONTEXT *)pdr->pfscntxt; /* Kill failsafe */
pdr->pfscntxt = 0;
OS_RELEASE_LOGDRIVE(driveno) /* check_drive_name_mount release */
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(drive_name);
if (driveno < 0)
{
ret_val = -1; /* check_drive set errno */
}
else
{
if (fscntxt)
{
rtfs_memset((void *) fscntxt, 0, sizeof(*fscntxt));
fscntxt->pdrive = pdr;
pdr->pfscntxt = (void *) fscntxt;
}
else
pdr->pfscntxt = (void *) savedcontext;
ret_val = failsafe_restore_internal((FAILSAFECONTEXT *) pdr->pfscntxt, dorestore, doclear);
if (dorestore || doclear)
pc_dskfree(driveno);
}
pdr->pfscntxt = (void *) savedcontext;
OS_RELEASE_LOGDRIVE(driveno) /* pro+failsafe_restore, release claim by check_drive_name_mount() */
return(ret_val);
}
/* pro_failsafe_auto_init - Automatically enable failsafe for a device at boot
* time
*
* The user must modify this code if he wishes to auto configure failsafe
* features for a given device.
*
*
* Summary:
* BOOLEAN pro_failsafe_auto_init(DDRIVE *pdrive)
*
* Description:
*
* If in pc_ertfs_init() the DRIVE_FLAGS_FAILSAFE bit is set in
* pdr->drive_flags then this routine is called
* to automatically enable Failsafe mode for that drive.
* If failsafe is initialized this way there is no need to call
* pro_failsafe_init() from the API layer.
*
* Note: pro_failsafe_auto_init() is implemented inside the file
* prapifs.c.
* To use this feature, INCLUDE_FAILSAFE_AUTO_INIT must be set to
* 1 in the source file, the routine should be modified to fit
* your needs and then be recompiled. By default the
* INCLUDE_FAILSAFE_AUTO_INIT is set to zero.
*
*
*
* Inputs:
* pdrive - A pointer to the drive structure for the device.
*
* Returns:
* TRUE - (default) If the user returns TRUE, ERTFS will allow mounts
* to occur on the drive.
* FALSE - If the user returns FALSE, ERTFS will not allow mounts
* to occur on the drive.
*
*/
#if (INCLUDE_FAILSAFE_AUTO_INIT)
FAILSAFECONTEXT auto_fscontext;
#define AUTO_BLOCKMAPSIZE 128
FSBLOCKMAP auto_failsafe_blockmap_array[AUTO_BLOCKMAPSIZE];
#endif
BOOLEAN pro_failsafe_auto_init(DDRIVE *pdrive)
{
#if (!INCLUDE_FAILSAFE_AUTO_INIT)
return(FALSE);
#else
/* In this example we set up failsafe mode for one device
This code may be modified to enable failsafe on multiple
devices and to modify FailSafe settings according to the
documentation provided for pro_failsafe_init().
*/
if (auto_fscontext.pdrive) /* Only one device supported int this */
return (FALSE); /* Example. Add more contexts */
rtfs_memset((void *) &auto_fscontext, 0, sizeof(auto_fscontext));
/* Run fully automated */
auto_fscontext.configuration_flags =
// (FS_MODE_AUTORESTORE|FS_MODE_AUTORECOVER/*|FS_MODE_AUTOCOMMIT*/);
(FS_MODE_AUTORESTORE|FS_MODE_AUTORECOVER|FS_MODE_AUTOCOMMIT); // ctr modified
auto_fscontext.blockmap_size = AUTO_BLOCKMAPSIZE;
auto_fscontext.blockmap_freelist = &auto_failsafe_blockmap_array[0];
/* Our parameters are correct so we know that the routine will not
fail but to demonstrate the principle we return FALSE if the
call does fail. */
if (!pro_failsafe_init_internal(pdrive, &auto_fscontext))
return(FALSE);
return(TRUE);
#endif /* (INCLUDE_FAILSAFE_AUTO_INIT) */
}
/* pro_failsafe_shutdown - Close or abort FailSafe mode
*
* Summary:
* BOOLEAN pro_failsafe_shutdown(byte *drive_name, BOOLEAN abort)
*
* Description:
*
* This routine allows the applications layer to disable Failsafe.
* FailSafe. The opcode field determines what operation to perform.
*
*
* If the parameter abort is TRUE then FailSafe is unilaterally disabled
* for the specified drive.
*
* If the parameter abort is FALSE then a FailSafe commit is performed and
* if it is succesful then FailSafe is disabled. If the commit is unsucessful
* FailSafe is not disabled and errno will contain the reason for the failure.
*
* Returns:
* TRUE - If Success
* FALSE - Failure
*
* If FALSE is returned errno will be set to one of the following.
*
* PEINVALIDDRIVEID - Drive argument invalid
* PEJOURNALOPENFAIL - journal file or vram init call failed
* PEINTERNAL - internal error, only occurs if ERTFS is not configured.
* PEIOERRORREAD - Error reading FAT or buffer area
* PEIOERRORWRITEJOURNAL - Error writing journal file or NVRAM section
* PEIOERRORREADJOURNAL - Error writing journal file or NVRAM section
* PEIOERRORWRITEFAT - Error writing fat area
* PEIOERRORWRITEBLOCK - Error writing directory area
* An ERTFS system error
*
*/
BOOLEAN pro_failsafe_shutdown(byte *drive_name, BOOLEAN abort)
{
BOOLEAN ret_val;
int driveno;
DDRIVE *pdr;
FAILSAFECONTEXT *pfscntxt;
if (abort) /* unilaterally suspend */
{
if (!pc_parsedrive( &driveno, drive_name))
return (FALSE);
pdr = pc_drno_to_drive_struct(driveno);
if (!pdr)
return (FALSE);
OS_CLAIM_LOGDRIVE(driveno) /* check_drive_name_mount Register drive in use */
pdr->pfscntxt = 0; /* Shutdown just unlinks it */
if (pdr->mount_valid) /* already mounted */
pc_dskfree(pdr->driveno);
OS_RELEASE_LOGDRIVE(driveno)
return(TRUE);
}
else
{
/* Get the drive and make sure it is mounted */
driveno = check_drive_name_mount(drive_name);
if (driveno < 0)
return(FALSE); /* check_drive set errno */
rtfs_set_errno(0);
pdr = pc_drno_to_drive_struct(driveno);
ret_val = TRUE;
pfscntxt = (FAILSAFECONTEXT *) pdr->pfscntxt;
if (pfscntxt)
{
if (pro_failsafe_commit_internal(pfscntxt) != 0)
ret_val = FALSE;
else
pdr->pfscntxt = 0; /* Shutdown just unlinks it */
}
release_drive_mount(driveno);
return(ret_val);
}
}
#endif /* (INCLUDE_FAILSAFE_CODE) */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,406 @@
/* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* PRFSNVIO.C - ERTFS-PRO FailSafe journal file routines */
/* Contains source code to implement journal file accesses read, write,
open and create.
The following routines are exported:
failsafe_reopen_nv_buffer()
failsafe_create_nv_buffer()
failsafe_write_nv_buffer()
failsafe_read_nv_buffer()
Note: These routines create and maintains a journal file on the
disk. If you have a closed system and you prefer to use system non
volatile ram instead please modify these for functions to use that
resource instead of a disk based file.
*/
#include <rtfs.h>
#if (INCLUDE_FAILSAFE_CODE)
static BOOLEAN open_failsafe_file(FAILSAFECONTEXT *pfscntxt, BOOLEAN create);
/*
* failsafe_reopen_nv_buffer - Open the failsafe buffer.
*
* Summary:
* BOOLEAN failsafe_reopen_nv_buffer(FAILSAFECONTEXT *pfscntxt)
*
* Description:
*
* This routine must check for the existence of a failsafe buffer on the
* current disk or in system non volatile ram and return TRUE if one exists,
* or FALSE if one does not.
* It may use the field nv_buffer_handle in the structure pointed to
* by pfscntxt to store a handle for later access by failsafe_read_nv_buffer()
* and failsafe_write_nv_buffer().
*
*/
BOOLEAN failsafe_reopen_nv_buffer(FAILSAFECONTEXT *pfscntxt)
{
return(open_failsafe_file(pfscntxt, FALSE));
}
/*
* failsafe_create_nv_buffer - Create the failsafe buffer.
*
* Summary:
* BOOLEAN failsafe_create_nv_buffer(FAILSAFECONTEXT *pfscntxt)
*
* Description:
*
* This routine must create a failsafe buffer on the current disk or
* in system NV ram and return TRUE if successful, FALSE if it is
* unsuccessful.
* It may use the field nv_buffer_handle in the sructure pointed to
* by pfscntxt to store a handle for later access by failsafe_read_nv_buffer()
* and failsafe_write_nv_buffer().
*
* The failsafe buffer must contain space for:
* (pfscntxt->num_remap_blocks + pfscntxt->num_index_blocks)
* 512 byte blocks.
*
* The source code in prfailsf.c implements the failsafe buffer in a hidden
* file named \FAILSAFE on the disk.
* The reference implementation is convenient and should be adequate for
* most applications. If it is more desirable to implement the failsafe
* buffer in flash or NVRAM then these functions should be modified to access
* that media instead.
*
*/
BOOLEAN failsafe_create_nv_buffer(FAILSAFECONTEXT *pfscntxt)
{
/* Set the journal file size to zero to force the open routine to
open the file. If the first open succeeds and the size is as big
as pfscntxt->correct_journal_size then we won't have to reopen it
in subsequant calls to restore and create */
pfscntxt->journal_file_size = 0;
return(open_failsafe_file(pfscntxt, TRUE));
}
/*
* failsafe_read_nv_buffer - Write a block to the failsafe buffer.
*
* Summary:
* BOOLEAN failsafe_write_nv_buffer(
* FAILSAFECONTEXT *pfscntxt,
* dword block_no,
* byte *pblock)
*
* Description:
*
* This routine must write one block to the block at offset block_no
* in the failsafe buffer on the current disk or in system NV ram and
* return TRUE if successful, FALSE if it is unsuccessful.
*
*/
BOOLEAN failsafe_write_nv_buffer(FAILSAFECONTEXT *pfscntxt, dword block_no, byte *pblock)
{
if (!pfscntxt->nv_buffer_handle || (pfscntxt->journal_file_size <= block_no))
{
rtfs_set_errno(PEIOERRORWRITEJOURNAL);
return(FALSE);
}
return (devio_write(pfscntxt->pdrive->driveno,
pfscntxt->nv_buffer_handle+block_no, pblock,
(word)1, TRUE));
}
/*
* failsafe_read_nv_buffer - Read a block from the failsafe buffer.
*
* Summary:
* BOOLEAN failsafe_read_nv_buffer(
* FAILSAFECONTEXT *pfscntxt,
* dword block_no,
* byte *pblocks)
*
* Description:
*
* This routine must read one block from the block at offset block_no
* in the failsafe buffer on the current disk or in system NV ram and
* return TRUE if successful, FALSE if it is unsuccessful.
*
*/
BOOLEAN failsafe_read_nv_buffer(FAILSAFECONTEXT *pfscntxt, dword block_no, byte *pblock)
{
if (!pfscntxt->nv_buffer_handle || (pfscntxt->journal_file_size <= block_no))
{
rtfs_set_errno(PEIOERRORREADJOURNAL);
return(FALSE);
}
return(devio_read(pfscntxt->pdrive->driveno,
pfscntxt->nv_buffer_handle+block_no, pblock,
(word)1, TRUE));
}
/*
* open_failsafe_file - low level open/create of failsafe journal file
*
* Summary:
* BOOLEAN open_failsafe_file(FAILSAFECONTEXT *pfscntxt, BOOLEAN create)
*
* Description:
*
* This opens the failsafe file and check if it contains enough contiguous
* blocks to hold a worst case journal file. If create is not requested and
* it can't find the file or the file is too small then it fails.
* If create is requested then it creates and extends the file as necessary.
*
* This routine is called when from ERTFS with the drive already locked, it
* uses low level access routines to create or open a contiguous file
*
* returns TRUE if successful, FALSE if it is unsuccessful.
*
*/
static BOOLEAN validate_failsafe_blocks(FAILSAFECONTEXT *pfscntxt, BOOLEAN fix_errors);
static BOOLEAN open_failsafe_file(FAILSAFECONTEXT *pfscntxt, BOOLEAN create)
{
DROBJ *proot, *pobj;
byte path[32]; /* leave room for "FAILSAFE" 32 is plenty */
byte filename[32];
byte fileext[4];
dword first_cluster, contig_clusters, n_clusters,next_cluster,required_journal_file_size,first_hit;
int end_of_chain;
DDRIVE *pdrive;
FAILSAFECONTEXT *saved_pfscntxt;
BOOLEAN doupdate = FALSE;
BOOLEAN doflush = FALSE;
pfscntxt->nv_buffer_handle = 0;
pdrive = pfscntxt->pdrive;
if (!pdrive)
return(FALSE);
saved_pfscntxt = (FAILSAFECONTEXT *) pdrive->pfscntxt;
pdrive->pfscntxt = (void *) 0;
proot = pc_get_root(pdrive);
if (!proot ||
!pc_parsepath((byte *)&path[0],(byte *)&filename[0],fileext,
rtfs_strtab_user_string(USTRING_SYS_FSFILENAME)))
{
return_error:
pdrive->pfscntxt = (void *) saved_pfscntxt;
return(FALSE);
}
/* See if it exists */
pobj = pc_get_inode( 0, proot, filename, fileext, GET_INODE_MATCH);
if (!pobj)
{
if (!create)
goto return_error;
else
{
/* Create a file entry in the root, hidden, readonly */
pobj = pc_mknode( proot, (byte *)filename, fileext, ARDONLY|AHIDDEN, 0);
if (!pobj)
{
goto return_error;
}
doupdate = TRUE;
}
}
first_cluster = pc_finode_cluster(pobj->pdrive,pobj->finode);
if (first_cluster)
n_clusters = FATOP(pdrive)->fatop_get_chain(pdrive, first_cluster,&next_cluster, 0xffffffff, &end_of_chain);
else
n_clusters = 0;
pfscntxt->journal_file_size = n_clusters * pdrive->secpalloc;
if (create)
{ /* Creating or extend or truncate to the correct size */
n_clusters = (CLUSTERTYPE)
((pfscntxt->num_remap_blocks +
pfscntxt->num_index_blocks +
pdrive->secpalloc-1) >> pdrive->log2_secpalloc);
required_journal_file_size = n_clusters * pdrive->secpalloc;
if (pfscntxt->journal_file_size != required_journal_file_size)
{
doupdate = TRUE;
doflush = TRUE;
/* Truncate if necessary */
if (first_cluster)
{
FATOP(pdrive)->fatop_freechain(pdrive, first_cluster, 0, 0xffffffff);
pc_pfinode_cluster(pdrive,pobj->finode,0);
pobj->finode->fsize = 0;
}
/* Allocate */
first_cluster = 0;
#if (defined(AF_CONTIGUOUS_MODE_FORCE)) /* Should be true for version 5.0 and up */
contig_clusters = FATOP(pdrive)->fatop_alloc_chain(pdrive, &first_cluster, n_clusters, AF_CONTIGUOUS_MODE_FORCE);
#else
contig_clusters = 0;
first_hit = 0;
/* Bug fix Nan 9, 2006
fatop_alloc_chain - allocates clusters starting from
pdrive->free_contig_pointer. or from first_cluster, if
first_cluster is not zero.
The problem is that if first_cluster is not zero
we link it to the newly allocated cluster chain, which is
not what we want. So the code has been modified to advance
pdrive->free_contig_pointer and always have first_cluster == 0 */
pdrive->free_contig_pointer = pdrive->free_contig_base;
while (contig_clusters < n_clusters)
{ /* alloc chain can't guarantee n_clusters contiguous so
loop and free until we get contig_clusters == n_clusters */
first_cluster = 0; /* must be zero or it will be linked. */
contig_clusters = FATOP(pobj->pdrive)->fatop_alloc_chain(pobj->pdrive, &first_cluster, n_clusters, FALSE);
if (!first_hit)
first_hit = first_cluster;
else if (first_hit == first_cluster)
{
FATOP(pdrive)->fatop_freechain(pdrive, first_cluster, 0, 0xffffffff);
break;
}
if (contig_clusters == 0)
break;
if (contig_clusters < n_clusters)
{
FATOP(pdrive)->fatop_freechain(pdrive, first_cluster, 0, 0xffffffff);
pdrive->free_contig_pointer = first_cluster+contig_clusters;
}
}
pdrive->free_contig_pointer = pdrive->free_contig_base; /* restore pointer */
#endif
if (contig_clusters < n_clusters)
{
pfscntxt->journal_file_size = 0;
pobj->finode->fsize = 0;
pc_pfinode_cluster(pdrive,pobj->finode,0);
pc_rmnode(pobj);
doupdate = FALSE;
}
else
{
pfscntxt->journal_file_size = contig_clusters * pdrive->secpalloc;
pc_pfinode_cluster(pdrive,pobj->finode,first_cluster);
pobj->finode->fsize = pfscntxt->journal_file_size * 512;
}
}
if ((doflush && !FATOP(pdrive)->fatop_flushfat(pdrive->driveno)) ||
(doupdate && !pc_update_inode(pobj, TRUE, TRUE)) )
{
pfscntxt->journal_file_size = 0;
}
}
if (pfscntxt->journal_file_size == 0)
{
pfscntxt->nv_buffer_handle = 0;
pc_freeobj(pobj);
pc_free_all_blk(pdrive);
pc_free_all_fat_blocks(&pdrive->fatcontext);
goto return_error;
}
else
{
pfscntxt->nv_buffer_handle =
pobj->pdrive->partition_base +
pc_cl2sector(pobj->pdrive, first_cluster);
pc_freeobj(pobj);
/* Clear buffer pool and fat buffer pool */
pc_free_all_blk(pdrive);
pc_free_all_fat_blocks(&pdrive->fatcontext);
#if (CFG_VALIDATE_JOURNAL)
if (!validate_failsafe_blocks(pfscntxt, TRUE))
{
pfscntxt->journal_file_size = 0;
pfscntxt->nv_buffer_handle = 0;
/* Tell the upper levels that an IO error occured.
This is unrecoverable */
pfscntxt->open_status = FS_STATUS_IO_ERROR;
pdrive->pfscntxt = (void *) saved_pfscntxt;
return(FALSE);
}
#endif
pdrive->pfscntxt = (void *) saved_pfscntxt;
return(TRUE);
}
}
#if (CFG_VALIDATE_JOURNAL)
static byte static_validate_buffer[CFG_VALIDATE_BUFFER_SIZE*512];
byte *get_validate_buffer(word *pblocks_per_buffer)
{
*pblocks_per_buffer = CFG_VALIDATE_BUFFER_SIZE;
return(&static_validate_buffer[0]);
}
static BOOLEAN validate_failsafe_blocks(FAILSAFECONTEXT *pfscntxt, BOOLEAN fix_errors)
{
dword block_no,n_blocks_left;
word blocks_per_buffer, blocks_this_access;
byte *pbuffer;
int driveno;
driveno = pfscntxt->pdrive->driveno;
pbuffer = get_validate_buffer(&blocks_per_buffer);
if (blocks_per_buffer > 128)
blocks_per_buffer = 128;
/* Read the journal file */
block_no = pfscntxt->nv_buffer_handle;
n_blocks_left = pfscntxt->journal_file_size;
while (n_blocks_left)
{
if (n_blocks_left > (dword) blocks_per_buffer)
blocks_this_access = blocks_per_buffer;
else
blocks_this_access = (word) n_blocks_left;
if (!devio_read(driveno, block_no, pbuffer,blocks_this_access,TRUE))
break;
block_no += blocks_this_access;
n_blocks_left -= blocks_this_access;
}
if (n_blocks_left == 0)
return(TRUE); /* Read all blocks without failure */
if (!fix_errors)
return(FALSE);
/* We got here because a read error occured
Write all zeroes to the file to see if we can correct it. */
/* Write the journal file */
block_no = pfscntxt->nv_buffer_handle;
n_blocks_left = pfscntxt->journal_file_size;
while (n_blocks_left)
{
if (n_blocks_left > (dword) blocks_per_buffer)
blocks_this_access = blocks_per_buffer;
else
blocks_this_access = (word) n_blocks_left;
/* Zero the buffer every time we use it. This takes a little
extra time but in the unlikely event other threads are using it
for reads we will zero it before we write each time */
rtfs_memset((void *)pbuffer, 0, (int)(blocks_this_access*512));
if (!devio_write(driveno, block_no, pbuffer,blocks_this_access,TRUE))
break;
block_no += blocks_this_access;
n_blocks_left -= blocks_this_access;
}
if (n_blocks_left != 0)
return(FALSE); /* Fail because We could not write the file.. */
else
{
/* We overwrote, now revalidate */
return(validate_failsafe_blocks(pfscntxt, FALSE));
}
}
#endif /* (CFG_VALIDATE_JOURNAL) */
#endif /* (INCLUDE_FAILSAFE_CODE) */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
以下は追加したファイル。
RTFS製品には含まれていない。
RTFSをバージョンアップ等で差し替える際に注意
attach.c
attach.h
drdefault.c
drdefault.h
drfile.c
drfile.h

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,533 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* rtdevio.c - Media check functions and device io wrapper functions
*
*
*/
#include <rtfs.h>
static BOOLEAN check_media_entry(int driveno);
static BOOLEAN check_media_io(DDRIVE *pdr, BOOLEAN raw);
static BOOLEAN check_media(DDRIVE *pdr, BOOLEAN ok_to_automount, BOOLEAN raw_access_requested, BOOLEAN call_crit_err);
static int card_failed_handler(DDRIVE *pdr);
/* Check if a drive id is valid and mount the drive. This is an internal
routine that is called by other api calls
If it fails, return -1 with the drive not claimed.
If it succeeds return the drive number with the drive claimed.
The caller will call release_drive_mount(driveno) to release it
*/
int check_drive_name_mount(byte *name) /*__fn__*/
{
int driveno;
/* Get the drive and make sure it is mounted */
if (pc_parsedrive( &driveno, name))
{
OS_CLAIM_LOGDRIVE(driveno) /* check_drive_name_mount Register drive in use */
if (!check_media_entry(driveno))
{
OS_RELEASE_LOGDRIVE(driveno) /* check_drive_name_mount release */
return(-1);
}
return(driveno);
}
else
{
rtfs_set_errno(PEINVALIDDRIVEID); /* Check drive called with bad drive name */
return(-1);
}
}
/* Check if a drive id is valid and mount the drive. This is an internal
routine that is called by other api calls
If it fails, return -1 with the drive not claimed.
If it succeeds return the drive number with the drive claimed.
The caller will call release_drive_mount(driveno) to release it
*/
BOOLEAN check_drive_number_mount(int driveno) /*__fn__*/
{
if (!pc_validate_driveno(driveno))
{
rtfs_set_errno(PEINVALIDDRIVEID); /* Check drive called with bad drive name */
return(FALSE);
}
else
{
/* Get the drive and make sure it is mounted */
OS_CLAIM_LOGDRIVE(driveno) /* check_drive_number_mount Register drive in use */
if (!check_media_entry(driveno))
{
OS_RELEASE_LOGDRIVE(driveno) /* check_drive_number_mount release */
return(FALSE);
}
return(TRUE);
}
}
/* Release a drive that was claimed by a succesful call to
check_drive_name_mount, or check_drive_number_mount
If the the operation queued an abort request then
free the drive an all it's structures
*/
void release_drive_mount(int driveno)
{
DDRIVE *pdr;
pdr = pc_drno_to_drive_struct(driveno);
if (pdr && pdr->mount_abort)
{
pc_dskfree(driveno);
}
OS_RELEASE_LOGDRIVE(driveno) /* release_drive_mount release */
}
BOOLEAN release_drive_mount_write(int driveno)
{
DDRIVE *pdr;
BOOLEAN ret_val;
ret_val = TRUE;
pdr = pc_drno_to_drive_struct(driveno);
if (pdr)
{
if (pdr->mount_abort)
pc_dskfree(driveno);
#if (INCLUDE_FAILSAFE_CODE) /* Call failsafe autocommit */
else
ret_val = pro_failsafe_autocommit(pdr);
#endif
}
OS_RELEASE_LOGDRIVE(driveno) /* release_drive_mount release */
return(ret_val);
}
/* BOOLEAN check_drive_number_present(int driveno)
*
* Called from the apps layer when formatting
* Ignore and clear DISKCHANGED status
* Return TRUE if the device is UP.
*
* Inputs:
* int driveno; Drive number 0 .. prtfs_cfg->cfg_NDRIVES
*
* Outputs:
* TRUE if is is okay to proceed with IO
* FALSE If we can not proceed with IO
*
*
*/
BOOLEAN check_drive_number_present(int driveno) /*__fn__*/
{
int media_status;
DDRIVE *pdr;
pdr = pc_drno_to_drive_struct(driveno);
if (!pdr || !(pdr->drive_flags&DRIVE_FLAGS_VALID) )
{
rtfs_set_errno(PEDEVICEINIT); /* device not initialized in pc_ertfs_init().*/
return(FALSE);
}
media_status = DEVTEST_NOCHANGE;
if (pdr->drive_flags & DRIVE_FLAGS_REMOVABLE)
{
media_status = pdr->dev_table_perform_device_ioctl(driveno, DEVCTL_CHECKSTATUS, 0);
/* Call it again to clear media change */
if (media_status == DEVTEST_CHANGED)
media_status = pdr->dev_table_perform_device_ioctl(driveno, DEVCTL_CHECKSTATUS, 0);
}
if (media_status == DEVTEST_NOCHANGE)
return(TRUE);
else if (media_status == DEVTEST_NOMEDIA)
rtfs_set_errno(PEDEVICENOMEDIA);
else if (media_status == DEVTEST_UNKMEDIA)
rtfs_set_errno(PEDEVICEUNKNOWNMEDIA);
else
rtfs_set_errno(PEDEVICEFAILURE);
/* Queue the drive for disk free and remount */
if (pdr->mount_valid)
pdr->mount_abort = TRUE;
return(FALSE);
}
/* BOOLEAN check_media_entry(int driveno)
*
* Called from the top of the API
* Return TRUE if the drive is mounted and it is okay to proceed with IO on
* a drive
*
* This routine is called from the top of the io layer. If the drive is
* Not mounted it may be (re)mounted as a result of this call and the call
* will return TRUE (it is okay to proceed). A similar call, check_media_io(),
* is called from a lower layer. It will succeed if raw IO is requested
* and the device is ok or if the device is mounted and ok
*
* Note: The the logical drive must be claimed before this routine is
* called and later released by the caller.
*
* Inputs:
* int driveno; Drive number 0 .. prtfs_cfg->cfg_NDRIVES
*
* Outputs:
* TRUE if is mounted and it is okay to proceed with IO
* FALSE if the drive ca not be used and the user did not
* replace it with a usable disk
*
*
*/
static BOOLEAN check_media_entry(int driveno) /*__fn__*/
{
DDRIVE *pdr;
/* Call media check
If dev is OK and mounted proceed
If dev is OK and not mounted try to mount.
If dev is changed and mounted but buffers are not dirty then
unmount and remount.
If dev is changed and mounted but buffers are dirty then unmount and fail
*/
pdr = pc_drno_to_drive_struct(driveno);
if (!pdr || !(pdr->drive_flags&DRIVE_FLAGS_VALID) )
{
rtfs_set_errno(PEDEVICEINIT); /* device not initialized in pc_ertfs_init().*/
return(FALSE);
}
return(check_media(pdr, TRUE, FALSE, TRUE));
}
/* BOOLEAN check_media_io(DDRIVE *pdr, BOOLEAN raw)
*
* Called from the IO layer
* Return TRUE if the device is UP and either raw IO is requested
* or the drive is mounted.
*
* Note: The the logical drive must be claimed before this routine is
* called and later released by the caller.
*
* Inputs:
* int driveno; Drive number 0 .. prtfs_cfg->cfg_NDRIVES
*
* Outputs:
* TRUE if is is okay to proceed with IO
* FALSE If we ca not proceed with IO
*
*
*/
static BOOLEAN check_media_io(DDRIVE *pdr, BOOLEAN raw) /*__fn__*/
{
/* Call media check
If dev is OK and mounted or raw proceed
If dev is changed and not mounted and raw then proceed
If dev is changed and mounted then unmount and fail
*/
if (!pdr || !(pdr->drive_flags&DRIVE_FLAGS_VALID) )
{
rtfs_set_errno(PEDEVICEINIT); /* device not initialized in pc_ertfs_init().*/
return(FALSE);
}
return(check_media(pdr, FALSE, raw, TRUE));
}
/* BOOLEAN check_media(DDRIVE *pdr, BOOLEAN ok_to_automount, BOOLEAN raw_access_requested, BOOLEAN call_crit_err)
*
* Return TRUE is it is okay to proceed with IO on a drive
*
* Note: The the logical drive must be claimed before this routine is
* called and later released by the caller.
**
* Inputs:
* int driveno; Drive number 0 .. prtfs_cfg->cfg_NDRIVES
* BOOLEAN ok_to_automount Automount the drive
* BOOLEAN raw_access_requested Mount not needed but device must
* be functional
* BOOLEAN call_crit_err If true call error handler
*/
static BOOLEAN check_media(DDRIVE *pdr, BOOLEAN ok_to_automount, BOOLEAN raw_access_requested, BOOLEAN call_crit_err) /*__fn__*/
{
int media_status;
int crit_err_media_status;
int drive_is_dirty;
/* If an abort request is pending, executed it */
if (ok_to_automount && pdr->mount_valid && pdr->mount_abort)
{
pc_dskfree(pdr->driveno);
}
/* If the device is removable check status to see if we must recover or remount */
if (pdr->drive_flags & DRIVE_FLAGS_REMOVABLE)
media_status = pdr->dev_table_perform_device_ioctl(pdr->driveno, DEVCTL_CHECKSTATUS, 0);
else
media_status = 0;
crit_err_media_status = 0;
if (media_status==0) /* Device is up */
{
if (pdr->mount_valid) /* already mounted */
{
goto status_is_ok;
}
else
{
if (raw_access_requested) /* Mount not required */
goto status_is_ok;
else if (ok_to_automount)
{
/* Mount the drive if we can -
. Read partition table if required
. Read block zero
*/
if (pc_i_dskopen(pdr->driveno))
{
#if (INCLUDE_FAILSAFE_CODE) /* Call failsafe autorestore and open routines */
if (!pro_failsafe_autorestore(pdr) ||
!pro_failsafe_dskopen(pdr) )
{ /* Failsafe set errno */
crit_err_media_status = 0;
goto status_is_bad;
}
#endif
goto status_is_ok;
}
else
{
/* Tell the user it is unformatted */
/* pc_i_dskopen() sets errno */
crit_err_media_status = CRERR_BAD_FORMAT;
goto status_is_bad;
}
}
else
{
/* The drive is not mounted. and ok_to_automount is false */
rtfs_set_errno(PEDEVICECHANGED);
goto status_is_bad;
}
}
}
else if (media_status == DEVTEST_CHANGED)
{
drive_is_dirty = (pdr->mount_valid && (pdr->fat_is_dirty || pc_test_all_fil(pdr)));
/* If the drive is dirty the user must explicitly abort */
if (drive_is_dirty)
{
rtfs_set_errno(PEDEVICECHANGED);
crit_err_media_status = CRERR_CHANGED_CARD;
goto status_is_bad;
}
else
{
/* If automount is requested then close the existing
mount and continue. */
if (ok_to_automount)
{
pc_dskfree((int)pdr->driveno);
/* Mount the drive if we can */
if (pc_i_dskopen(pdr->driveno))
{
#if (INCLUDE_FAILSAFE_CODE) /* Call failsafe autorestore and open routines */
if (!pro_failsafe_autorestore(pdr) ||
!pro_failsafe_dskopen(pdr) )
{ /* Failsafe set errno */
crit_err_media_status = 0;
goto status_is_bad;
}
#endif
goto status_is_ok;
}
else
{
/* pc_i_dskopen() sets errno */
crit_err_media_status = CRERR_BAD_FORMAT;
goto status_is_bad;
}
}
else
{
rtfs_set_errno(PEDEVICECHANGED);
crit_err_media_status = CRERR_CHANGED_CARD;
goto status_is_bad;
}
}
}
else
{
if (media_status == DEVTEST_NOMEDIA)
{
rtfs_set_errno(PEDEVICENOMEDIA);
crit_err_media_status = CRERR_NO_CARD;
}
else if (media_status == DEVTEST_UNKMEDIA)
{
rtfs_set_errno(PEDEVICEUNKNOWNMEDIA);
crit_err_media_status = CRERR_BAD_CARD;
}
else
{
rtfs_set_errno(PEDEVICEFAILURE);
crit_err_media_status = CRERR_CARD_FAILURE;
}
goto status_is_bad;
}
status_is_ok:
return(TRUE);
status_is_bad:
if (crit_err_media_status)
{
if (call_crit_err)
critical_error_handler(pdr->driveno, crit_err_media_status, 0);
}
/* Queue the drive for disk free and remount */
pdr->mount_abort = TRUE;
return(FALSE);
}
static int card_failed_handler(DDRIVE *pdr) /* __fn__ */
{
int ret_val;
ret_val = critical_error_handler(pdr->driveno,CRERR_CARD_FAILURE, 0);
if (ret_val == CRITICAL_ERROR_ABORT)
{
/* Queue the drive for disk free and remount */
if (pdr->mount_valid)
{
pdr->mount_abort = TRUE;
}
}
return(ret_val);
}
/*
* Note: The the logical drive must be claimed before this routine is
* called and later released by the caller.
*/
BOOLEAN devio_read(int driveno, dword blockno, byte * buf, word n_to_read, BOOLEAN raw) /* __fn__ */
{
DDRIVE *pdr;
pdr = pc_drno_to_drive_struct(driveno);
/* Bug Fix. 1-28-02 thanks to Kerry Krouse. This code was inside the
loop, which caused retries to fail
*/
if (pdr->drive_flags & DRIVE_FLAGS_PARTITIONED)
{
if (!raw)
blockno += pdr->partition_base;
}
for(;;)
{
/* Check if disk is accessable and has not changed since mounted */
if (!(pdr->drive_flags & DRIVE_FLAGS_VALID))
return(FALSE);
if (!check_media_io(pdr, raw))
return(FALSE);
if (pdr->dev_table_drive_io(driveno, blockno, buf, n_to_read, TRUE))
{
return(TRUE);
}
else
{
if (card_failed_handler(pdr) != CRITICAL_ERROR_RETRY)
break;
}
}
return(FALSE);
}
#if (RTFS_WRITE)
/* This is a special version of devio_write that is used by the format utility
It is the same as devio_write except that it does not automount the
drive or load the partition table. If non-raw IO is requested the
caller must first be sure that the partition table is loaded
*/
/*
* Note: The the logical drive must be claimed before this routine is
* called and later released by the caller.
*/
BOOLEAN devio_write_format(int driveno, dword blockno, byte * buf, word n_to_write, BOOLEAN raw) /* __fn__ */
{
DDRIVE *pdr;
pdr = pc_drno_to_drive_struct(driveno);
if (pdr->drive_flags & DRIVE_FLAGS_PARTITIONED)
{
if (!raw)
blockno += pdr->partition_base;
}
for (;;)
{
/* Check if disk is accessable and has not changed since mounted */
if (!check_media_io(pdr, TRUE))
return(FALSE);
if (pdr->dev_table_drive_io(driveno, blockno, buf, n_to_write, FALSE))
{
return(TRUE);
}
else
{
if (card_failed_handler(pdr) != CRITICAL_ERROR_RETRY)
break;
}
}
rtfs_set_errno(PEIOERRORWRITE);/* devio_write_format: write failed */
return(FALSE);
}
/*
* Note: The the logical drive must be claimed before this routine is
* called and later released by the caller.
*/
BOOLEAN devio_write(int driveno, dword blockno, byte * buf, word n_to_write, BOOLEAN raw) /* __fn__ */
{
DDRIVE *pdr;
pdr = pc_drno_to_drive_struct(driveno);
if (pdr->drive_flags & DRIVE_FLAGS_PARTITIONED)
{
if (!raw)
blockno += pdr->partition_base;
}
for (;;)
{
/* Check if disk is accessable and has not changed since mounted */
if (!check_media_io(pdr, raw))
return(FALSE);
if (pdr->dev_table_drive_io(driveno, blockno, buf, n_to_write, FALSE))
{
return(TRUE);
}
else
{
if (card_failed_handler(pdr) != CRITICAL_ERROR_RETRY)
break;
}
}
return(FALSE);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,360 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* RTFAT16.C - FAT16 management routines */
#include <rtfs.h>
CLUSTERTYPE fatxx_clalloc(DDRIVE *pdr, CLUSTERTYPE clhint);
CLUSTERTYPE fatxx_clgrow(DDRIVE *pdr, CLUSTERTYPE clno);
CLUSTERTYPE fatxx_clalloc(DDRIVE *pdr, CLUSTERTYPE clhint);
CLUSTERTYPE fatxx_clgrow(DDRIVE *pdr, CLUSTERTYPE clno);
BOOLEAN pc_init_drv_fat_info16(DDRIVE *pdr, struct pcblk0 *pbl0)
{
pdr->secpfat = (CLUSTERTYPE) pbl0->secpfat; /* sectors / fat */
pdr->numfats = pbl0->numfats; /* Number of fat copies */
pdr->fatblock = (BLOCKT) pbl0->secreserved;
pdr->rootblock = pdr->fatblock + pdr->secpfat * pdr->numfats;
pdr->secproot = (int)((pdr->numroot + INOPBLOCK - 1)/INOPBLOCK);
/* The first block of the cluster area is just past the root */
/* Round up if we have to */
pdr->firstclblock = pdr->rootblock +
(pdr->numroot + INOPBLOCK - 1)/INOPBLOCK;
/* Calculate the largest index in the file allocation table.
Total # block in the cluster area)/Blockpercluster == s total
Number of clusters. Entries 0 & 1 are reserved so the highest
valid fat index is 1 + total # clusters.
*/
pdr->maxfindex = (long)(1 + ((pdr->numsecs - pdr->firstclblock)/pdr->secpalloc));
/* Nibbles/fat entry if < 4087 clusters then 12 bit else 16 */
pdr->fasize = (int) ((pdr->maxfindex < 4087) ? 3 : 4);
{
/* Make sure the calculated index doesn't overflow the fat sectors */
dword max_index;
/* For FAT16 Each block of the fat holds 256 entries so the maximum index is
(pdr->secpfat * 256)-1; */
max_index = (dword) pdr->secpfat;
if (pdr->fasize == 3)
{/* Max clusters in FAT12.. 1024 per 3 blocks plus 341 per residual block */
/* Modified 8-16-06 to distinguish between FAT12 and FAT16 */
dword max_index3,div3,ltemp,residual;
max_index3 = max_index;
div3 = max_index3/3;
max_index = div3 * 1024;
ltemp = div3 * 3;
residual = max_index3-ltemp;
max_index += (residual * 341);
}
else
{
max_index *= 256;
}
max_index -= 1;
if (pdr->maxfindex > max_index)
pdr->maxfindex = max_index;
}
/* if calculated size > fff0 set it to one less. fff0 to ffff are
reserved values. */
if (pdr->maxfindex >= 0xfff0 && pdr->maxfindex <= 0xffff)
pdr->maxfindex = 0xffef;
/* Create a hint for where we should write file data. We do this
because directories are allocated in one cluster chunks while
file may allocate larger chunks. We Try to put directory
data at the beginning of the disk in a seperate region so we
do not break the contiguous space further out */
/* guess that 1/32nd of the disk will store directory info and the
rest will be data. */
pdr->free_contig_base = (word) (pdr->maxfindex >> 5);
if (pdr->free_contig_base < 2)
pdr->free_contig_base = 2;
/* set the pointer to where to look for free clusters to the contiguous
area. On the first call to write this will hunt for the real free
blocks. */
pdr->free_contig_pointer = pdr->free_contig_base;
pdr->infosec = 0;
return(TRUE);
}
BOOLEAN pc_mkfs16(int driveno, FMTPARMS *pfmt, BOOLEAN use_raw) /*__fn__*/
{
byte *b;
BLKBUFF *buf;
dword ltotsecs;
word totsecs;
word nclusters;
dword lnclusters;
dword ldata_area;
int fausize;
word i,j;
BLOCKT blockno;
BOOLEAN ret_val;
if (use_raw) /* check media and clear change conditions */
check_drive_number_present(driveno);
ret_val = FALSE;
buf = pc_scratch_blk();
if (!buf)
{
return(FALSE);
}
b = buf->data;
/* Build up a block 0 */
rtfs_memset(&b[0], 0, 512);
b[0] = (byte) 0xe9; /* Jump vector. Used to id MS-DOS disk */
b[1] = (byte) 0x00;
b[2] = (byte) 0x00;
/* Copy the OEM name */
pc_cppad(&b[3], pfmt->oemname, 8);
/* bytes per sector */
fr_WORD ( &(b[11]), 512); /*X*/
/* sectors / cluster */
b[13] = pfmt->secpalloc;
/* Number of reserved sectors. (Including block 0) */
fr_WORD ( &(b[14]), pfmt->secreserved); /*X*/
/* number of dirents in root */
fr_WORD ( &(b[17]), pfmt->numroot); /*X*/
/* total sectors in the volume */
/* Set totsecs to 0 if size > 64k. This triggers sensing huge 4.0
partitions. */
ltotsecs = pfmt->numcyl;
ltotsecs *= pfmt->secptrk;
ltotsecs *= pfmt->numhead;
ltotsecs -= pfmt->numhide; //ctr modified
if (ltotsecs > 0xffffL)
{
/* HUGE partition the 3.xx totsecs field is zeroed */
totsecs = 0;
}
else
{
totsecs = (word) ltotsecs;
}
fr_WORD ( &(b[19]), totsecs); /*X*/
/* Media descriptor */
b[21] = pfmt->mediadesc;
/* sectors per trak */
fr_WORD ( &(b[24]), pfmt->secptrk); /*X*/
/* number heads */
fr_WORD ( &(b[26]), pfmt->numhead); /*X*/
/* number hidden sectors */
fr_WORD ( &(b[28]), pfmt->numhide); /*X*/ //ctr modified
/* number of duplicate fats */
b[16] = pfmt->numfats;
fr_WORD ( &(b[22]), (word)pfmt->secpfat); /*X*/
/* Now fill in 4.0 specific section of the boot block */
if (ltotsecs > 0xffffL)
{
/* HUGE partition */
fr_DWORD ( &(b[32]), ltotsecs); /*X*/
}
else
{
fr_DWORD ( &(b[32]), 0L); /*X*/
}
b[36] = pfmt->physical_drive_no;
b[38] = 0x29; /* extended boot signature */
fr_DWORD(&(b[39]) , pfmt->binary_volume_label); /*X*/
pc_cppad( &(b[43]), pfmt->text_volume_label, 11);
fr_WORD(&(b[0x01fe]), (word)0xaa55);
/* Count the size of the area managed by the fat. */
ldata_area = ltotsecs;
ldata_area -= pfmt->numfats * pfmt->secpfat;
ldata_area -= pfmt->secreserved;
/* Note: numroot must be an even multiple op INOPBLOCK */
ldata_area -= pfmt->numroot/INOPBLOCK;
/* Nibbles/fat entry if < 4087 clusters then 12 bit else 16 */
lnclusters = ldata_area/pfmt->secpalloc;
if (lnclusters > 0xffffL)
{
rtfs_set_errno(PEINVALIDPARMS); /* pc_mkfs16: volume too large */
goto errex;
}
else
{
nclusters = (word) lnclusters;
}
fausize = (int) ( (nclusters < 4087) ? 3 : 4 );
/* Check the FAT.
if ( (nibbles needed) > (nibbles if fatblocks)
trouble;
*/
{
long ltotnibbles;
long lnibsinfatbls;
/* Total nibbles = (# clusters * nibbles/cluster) */
ltotnibbles = lnclusters;
ltotnibbles *= fausize;
/* How many nibbles are available. */
lnibsinfatbls = pfmt->secpfat;
lnibsinfatbls <<= 10; /* 1024 nibbles/block */
if (ltotnibbles > lnibsinfatbls)
{
rtfs_set_errno(PEINVALIDPARMS); /* pc_mkfs16: volume too large */
goto errex;
}
}
if (pfmt->numroot % INOPBLOCK)
{
rtfs_set_errno(PEINVALIDPARMS); /* pc_mkfs16: numroot incorrect */
goto errex;
}
if (!devio_write_format(driveno, (dword) 0 + pfmt->numhide, &(b[0]), 1, use_raw) )
{
goto errex;
}
/* Now write the fats out */
for (i = 0; i < pfmt->numfats; i++)
{
rtfs_memset(&b[0], 0, 512);
/* The first 3(4) bytes of a fat are MEDIADESC,FF,FF,(FF) */
b[0] = pfmt->mediadesc;
b[1] = (byte) 0xff;
b[2] = (byte) 0xff;
if (fausize == 4)
b[3] = (byte) 0xff;
blockno = pfmt->numhide + pfmt->secreserved + (i * pfmt->secpfat); //ctr modified
for ( j = 0; j < pfmt->secpfat; j++)
{
/* WRITE */
if (!devio_write_format(driveno, blockno, &(b[0]), 1, use_raw) )
{
goto errex;
}
blockno += 1;
rtfs_memset(&b[0], 0, 512);
}
}
/* Now write the root sectors */
blockno = pfmt->numhide + pfmt->secreserved + pfmt->numfats * pfmt->secpfat; //ctr modified
rtfs_memset(&b[0], 0, 512);
for ( j = 0; j < (pfmt->numroot/INOPBLOCK) ; j++)
{
if (!devio_write_format(driveno, blockno, &(b[0]), 1, use_raw) )
{
goto errex;
}
blockno += 1;
}
ret_val = TRUE;
errex: /* Not only errors return through here. Everything does. */
pc_free_scratch_blk(buf);
return(ret_val);
}
#if (!FAT32)
BOOLEAN pc_init_drv_fat_info(DDRIVE *pdr, struct pcblk0 *pbl0)
{
return (pc_init_drv_fat_info16(pdr, pbl0));
}
CLUSTERTYPE pc_get_parent_cluster(DDRIVE *pdrive, DROBJ *pobj)
{
return(pc_sec2cluster(pdrive,pobj->blkinfo.my_frstblock));
}
/* Grab a cluster for a new directory entry.
To minimize fragmentation give a hint where to start looking for new
clusters based on the position of the parent directory */
CLUSTERTYPE pc_alloc_dir(DDRIVE *pdrive, DROBJ *pmom)
{
CLUSTERTYPE clbase,cluster;
if (pc_isroot(pmom))
clbase = 0;
else
clbase = pc_finode_cluster(pmom->pdrive,pmom->finode);
/*Grab a cluster for the new dir */
cluster = fatxx_clalloc(pdrive, clbase);
return(cluster);
}
CLUSTERTYPE pc_grow_dir(DDRIVE *pdrive, DROBJ *pobj)
{
CLUSTERTYPE cluster;
if (pc_isroot(pobj))
{
rtfs_set_errno(PENOSPC);
cluster = 0;
}
else
cluster = fatxx_clgrow(pdrive, pc_finode_cluster(pdrive,pobj->finode));
return(cluster);
}
void pc_truncate_dir(DDRIVE *pdrive, DROBJ *pobj, CLUSTERTYPE cluster)
{
FATOP(pdrive)->fatop_cl_truncate_dir(pdrive, pc_finode_cluster(pdrive,pobj->finode), cluster);
}
BOOLEAN pc_mkfs32(int driveno, FMTPARMS *pfmt, BOOLEAN use_raw) /*__fn__*/
{
RTFS_ARGSUSED_INT(driveno);
RTFS_ARGSUSED_PVOID((void *) pfmt);
RTFS_ARGSUSED_INT((int) use_raw);
return(FALSE);
}
CLUSTERTYPE pc_finode_cluster(DDRIVE *pdr, FINODE *finode) /* __fn__ */
{
RTFS_ARGSUSED_PVOID((void *) pdr);
return ( (CLUSTERTYPE)finode->fcluster );
}
void pc_pfinode_cluster(DDRIVE *pdr, FINODE *finode, CLUSTERTYPE value) /*__fn__ */
{
finode->fcluster = (word)value;
RTFS_ARGSUSED_PVOID((void *) pdr);
}
BOOLEAN pc_gblk0_32(word driveno, struct pcblk0 *pbl0, byte *b) /*__fn__*/
{
RTFS_ARGSUSED_INT((int) driveno);
RTFS_ARGSUSED_PVOID((void *) pbl0);
RTFS_ARGSUSED_PVOID((void *) b);
return(FALSE);
}
BOOLEAN pc_validate_partition_type(byte p_type)
{
if ( (p_type == 0x01) || (p_type == 0x04) || (p_type == 0x06) || (p_type == 0x0E))
return(TRUE);
else
return(FALSE);
}
BOOLEAN fat_flushinfo(DDRIVE *pdr)
{
RTFS_ARGSUSED_PVOID((void *) pdr);
return(TRUE);
}
#endif

View File

@ -0,0 +1,502 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* RTFAT32.C - FAT32 specific managment routines */
#include <rtfs.h>
CLUSTERTYPE fatxx_clalloc(DDRIVE *pdr, CLUSTERTYPE clhint);
CLUSTERTYPE fatxx_clgrow(DDRIVE *pdr, CLUSTERTYPE clno);
#if (FAT32)
struct fat32_info {
dword fs_sig; /* Signature of FAT32 (0x61417272) */
#define FSINFOSIG 0x61417272ul
dword free_alloc; /* Free clusters on drive (-1 if unknown) */
dword next_alloc; /* Most recently allocated cluster */
dword reserved; /* Reserved - ignore */
};
BOOLEAN pc_init_drv_fat_info(DDRIVE *pdr, struct pcblk0 *pbl0)
{
if (pdr->numroot!=0) /* Drive is not FAT32 */
return (pc_init_drv_fat_info16(pdr, pbl0));
pdr->secpfat = (CLUSTERTYPE) pbl0->secpfat; /* sectors / fat */
pdr->numfats = pbl0->numfats; /* Number of fat copies */
if (pdr->secpfat == 0L)
pdr->secpfat = pbl0->secpfat2;
if (pbl0->flags & NOFATMIRROR)
{
pdr->fatblock = (BLOCKT) pbl0->secreserved +
((pbl0->flags & ACTIVEFAT) * pdr->secpfat);
pdr->numfats = 1;
}
else
pdr->fatblock = (BLOCKT) pbl0->secreserved;
/* The first block of the root is just past the fat copies */
pdr->firstclblock = pdr->fatblock + pdr->secpfat * pdr->numfats;
/* DM: 7-6-99: BUG FIX: */
pdr->rootblock = (pbl0->rootbegin-2) * pdr->secpalloc + pdr->firstclblock;
/* WRONG: pdr->rootblock = pbl0->rootbegin-2 + pdr->firstclblock; */
/* Calculate the largest index in the file allocation table.
Total # block in the cluster area)/Blockpercluster == s total
Number of clusters. Entries 0 & 1 are reserved so the highest
valid fat index is 1 + total # clusters.
*/
pdr->maxfindex = (long) (1 + ((pdr->numsecs - pdr->firstclblock)/pdr->secpalloc));
{
/* Make sure the calculated index doesn't overflow the fat sectors */
dword max_index;
/* For FAT32 Each block of the fat holds 128 entries so the maximum index is
(pdr->secpfat * 128)-1; */
max_index = (dword) pdr->secpfat;
max_index *= 128;
max_index -= 1;
if (pdr->maxfindex > max_index)
pdr->maxfindex = max_index;
}
/* Create a hint for where we should write file data. We do this
because directories are allocated in one cluster chunks while
file may allocate larger chunks. We Try to put directory
data at the beginning of the disk in a seperate region so we
do not break the contiguous space further out */
pdr->known_free_clusters = pbl0->free_alloc;
pdr->free_contig_base = pbl0->next_alloc;
pdr->free_contig_pointer = pdr->free_contig_base;
pdr->infosec = pbl0->infosec;
pdr->fasize = 8;
return(TRUE);
}
CLUSTERTYPE pc_get_parent_cluster(DDRIVE *pdrive, DROBJ *pobj) /* __fatfn__ */
{
if ((pdrive->fasize == 8) &&
(pobj->blkinfo.my_frstblock == pdrive->rootblock))
return(0);
else
return(pc_sec2cluster(pdrive,pobj->blkinfo.my_frstblock));
}
/* Grab a cluster for a new directory entry.
To minimize fragmentation give a hint where to start looking for new
clusters based on the position of the parent directory */
CLUSTERTYPE pc_alloc_dir(DDRIVE *pdrive, DROBJ *pmom) /* __fatfn__ */
{
CLUSTERTYPE clbase,cluster;
if ( pdrive->fasize != 8 && pc_isroot(pmom))
clbase = 0;
else
clbase = pc_finode_cluster(pmom->pdrive,pmom->finode);
/*Grab a cluster for the new dir */
cluster = fatxx_clalloc(pdrive, clbase);
return(cluster);
}
CLUSTERTYPE pc_grow_dir(DDRIVE *pdrive, DROBJ *pobj) /* __fatfn__ */
{
CLUSTERTYPE tmpcl, cluster;
if ( pdrive->fasize != 8 && pc_isroot(pobj))
{
rtfs_set_errno(PENOSPC);
cluster = 0;
}
else
{
tmpcl = pc_finode_cluster(pdrive,pobj->finode);
if ( (pdrive->fasize == 8) && (tmpcl == 0) )
tmpcl = pc_sec2cluster(pdrive, pdrive->rootblock);
cluster = fatxx_clgrow(pdrive, tmpcl);
}
return(cluster);
}
void pc_truncate_dir(DDRIVE *pdrive, DROBJ *pobj, CLUSTERTYPE cluster) /* __fatfn__ */
{
if (pdrive->fasize == 8)
{
dword tmpcl = pc_finode_cluster(pdrive,pobj->finode);
if (tmpcl == 0)
tmpcl = pc_sec2cluster(pdrive, pdrive->rootblock);
FATOP(pdrive)->fatop_cl_truncate_dir(pdrive, tmpcl, cluster);
}
else
FATOP(pdrive)->fatop_cl_truncate_dir(pdrive, pc_finode_cluster(pdrive,pobj->finode), cluster);
}
BOOLEAN pc_mkfs32(int driveno, FMTPARMS *pfmt, BOOLEAN use_raw) /*__fn__*/
{
byte *b;
BLKBUFF *buf;
dword ltotsecs;
word totsecs;
dword lnclusters;
dword ldata_area;
int fausize;
word i,j,k;
BLOCKT blockno;
BOOLEAN ret_val;
if (use_raw) /* check media and clear change conditions */
check_drive_number_present(driveno);
ret_val = FALSE;
buf = pc_scratch_blk();
if (!buf)
return(FALSE);
b = buf->data;
/* Build up a block 0 */
rtfs_memset(&b[0], 0, 512);
for (i=0;i<pfmt->secreserved;i++)
{
/* WRITE */
if (!devio_write_format(driveno, pfmt->numhide + (dword) i, &(b[0]), 1, use_raw) ) //ctr modified
{
goto errex;
}
}
#if (INCLUDE_FAT32_BOOT_CODE)
copybuff(&b[0],&FAT32_BOOT_CODE[512],512);
if (!devio_write_format(driveno, pfmt->numhide + (dword) 8, &(b[0]), 1, use_raw) ) //ctr modified
{
goto errex;
}
if (!devio_write_format(driveno, pfmt->numhide + (dword) 2, &(b[0]), 1, use_raw) ) //ctr modified
{
goto errex;
}
copybuff(&b[0],&FAT32_BOOT_CODE[0],512);
#else
rtfs_memset(&b[0], 0, 512);
#endif
b[0] = (byte) 0xe9; /* Jump vector. Used to id MS-DOS disk */
b[1] = (byte) 0x00;
b[2] = (byte) 0x00;
b[0x40] = 0x80;
b[0x41] = 0x00;
b[0x42] = 0x29;
#if (INCLUDE_FAT32_BOOT_CODE)
b[0] = (byte) 0xeb; /* Jump vector. Used to id MS-DOS disk */
b[1] = (byte) 0x58;
b[2] = (byte) 0x90;
#endif
/* Copy the OEM name */
pc_cppad(&b[3], pfmt->oemname, 8);
/* bytes per sector */
fr_WORD ( &(b[11]), 512); /*X*/
/* sectors / cluster */
b[13] = pfmt->secpalloc;
/* Number of reserved sectors. (Including block 0) */
fr_WORD ( &(b[14]), pfmt->secreserved); /*X*/
/* number of dirents in root */
fr_WORD ( &(b[17]), pfmt->numroot); /*X*/
/* total sectors in the volume */
/* Set totsecs to 0 if size > 64k. This triggers sensing huge 4.0
partitions. */
ltotsecs = pfmt->numcyl;
ltotsecs *= pfmt->secptrk;
ltotsecs *= pfmt->numhead;
ltotsecs -= pfmt->numhide;
if (ltotsecs > 0xffffL)
{
/* HUGE partition the 3.xx totsecs field is zeroed */
totsecs = 0;
}
else
{
totsecs = (word) ltotsecs;
}
fr_WORD ( &(b[19]), totsecs); /*X*/
/* if secpfat was not provided calculate it here */
/* TONY - Bug fix 6/23/98 */
if (!pfmt->secpfat)
{
pfmt->secpfat = (ltotsecs + 128*pfmt->secpalloc)
/(128*pfmt->secpalloc + 1);
}
/* Media descriptor */
b[21] = pfmt->mediadesc;
/* sectors per trak */
fr_WORD ( &(b[24]), pfmt->secptrk);
/* number heads */
fr_WORD ( &(b[26]), pfmt->numhead);
/* number hidden sectors */
fr_DWORD ( &(b[28]), pfmt->numhide);
/* number of duplicate fats */
b[16] = pfmt->numfats;
fr_WORD ( &(b[22]), (word)0);
fr_DWORD ( &(b[36]), (dword)pfmt->secpfat);
fr_DWORD ( &(b[40]), (dword)0); /* flags and version */
fr_DWORD ( &(b[44]), (dword)2); /* root dir starting cluster */
fr_WORD ( &(b[48]), (word)1); /* info sector */
fr_WORD ( &(b[50]), (word)6); /* backup boot sector */
/* Now fill in 4.0 specific section of the boot block */
if (ltotsecs > 0xffffL)
{
/* HUGE partition */
fr_DWORD ( &(b[32]), ltotsecs); /*X*/
}
else
{
fr_DWORD ( &(b[32]), 0L); /*X*/
}
fr_DWORD( &(b[0x43]), pfmt->binary_volume_label);
pc_cppad( &(b[0x47]), (byte*)pfmt->text_volume_label, 11);
pc_cppad( &(b[0x52]), (byte*)"FAT32",8);
fr_WORD(&(b[0x01fe]), (word)0xaa55);
/* Count the size of the area managed by the fat. */
ldata_area = ltotsecs;
ldata_area -= pfmt->numfats * pfmt->secpfat;
ldata_area -= pfmt->secreserved;
/* Note: numroot must be an even multiple op INOPBLOCK */
ldata_area -= pfmt->numroot/INOPBLOCK;
/* Nibbles/fat entry if < 4087 clusters then 12 bit else 16 */
lnclusters = ldata_area/pfmt->secpalloc;
fausize = 8;
/* Check the FAT.
if ( (nibbles needed) > (nibbles if fatblocks)
trouble;
*/
{
long ltotnibbles;
long lnibsinfatbls;
/* Total nibbles = (# clusters * nibbles/cluster) */
ltotnibbles = lnclusters;
ltotnibbles *= fausize;
/* How many nibbles are available. */
lnibsinfatbls = pfmt->secpfat;
lnibsinfatbls <<= 10; /* 1024 nibbles/block */
if (ltotnibbles > lnibsinfatbls)
{
rtfs_set_errno(PEINVALIDPARMS);
goto errex;
}
}
if (pfmt->numroot % INOPBLOCK)
{
rtfs_set_errno(PEINVALIDPARMS);
goto errex;
}
if (!devio_write_format(driveno, (dword) 0 + pfmt->numhide, &(b[0]), 1, use_raw) )
{
goto errex;
}
/* Put the initial free cluster value in right */
rtfs_memset(&b[0], 0, 512);
fr_DWORD( &(b[0]), (dword) 0x41615252ul);
fr_DWORD( &(b[0x01e4]), (dword) FSINFOSIG);
fr_DWORD( &(b[0x01e8]), (dword)(lnclusters-1));
fr_DWORD( &(b[0x01ec]), (dword)0x00000003);
fr_WORD( &(b[0x01fe]), (word)0xaa55);
if (!devio_write_format(driveno, pfmt->numhide + (dword) 7, &(b[0]), 1, use_raw) ) //ctr modified
{
goto errex;
}
if (!devio_write_format(driveno, pfmt->numhide + (dword) 1, &(b[0]), 1, use_raw) ) //ctr modified
{
goto errex;
}
/* Now write the fats out */
for (i = 0; i < pfmt->numfats; i++)
{
rtfs_memset(&b[0], 0, 512);
/* The first 3(4) bytes of a fat are MEDIADESC,FF,FF,(FF) */
b[0] = pfmt->mediadesc;
b[1] = (byte) 0xff;
b[2] = (byte) 0xff;
j = (word) fausize;
if (j==8) j=12;
while(j > 3)
{
if (j%4 == 0 && fausize == 8)
b[--j] = (byte) 0x0f;
else
b[--j] = (byte) 0xff;
}
blockno = pfmt->numhide + pfmt->secreserved + (i * pfmt->secpfat); //ctr modified
for ( j = 0; j < pfmt->secpfat; j++)
{
/* WRITE */
if (!devio_write_format(driveno, blockno, &(b[0]), 1, use_raw) )
{
goto errex;
}
blockno += 1;
rtfs_memset(&b[0], 0, 512);
}
}
/* Now write the root sectors */
blockno = pfmt->numhide + pfmt->secreserved + pfmt->numfats * pfmt->secpfat; //ctr modified
rtfs_memset(&b[0], 0, 512);
/* Bug fix 11-22-99 use <pfmt->secpalloc instead of 8 */
for(k=0;k<pfmt->secpalloc;k++) /* Is 8 blocks per cluster? */
{
if (!devio_write_format(driveno, blockno+k, &(b[0]), 1, use_raw) )
goto errex;
}
ret_val = TRUE;
errex: /* Not only errors return through here. Everything does. */
pc_free_scratch_blk(buf);
return(ret_val);
}
CLUSTERTYPE pc_finode_cluster(DDRIVE *pdr, FINODE *finode) /* __fatfn__ */
{
if (pdr->fasize == 8)
return ( (dword)finode->fcluster | ((dword)finode->fclusterhi << 16) );
else
return ( (CLUSTERTYPE)finode->fcluster );
}
void pc_pfinode_cluster(DDRIVE *pdr, FINODE *finode, CLUSTERTYPE value) /*__fatfn__ */
{
finode->fcluster = (word)value;
if (pdr->fasize == 8)
finode->fclusterhi = (word)(value >> 16);
}
BOOLEAN pc_gblk0_32(word driveno, struct pcblk0 *pbl0, byte *b) /*__fn__*/
{
word i;
if (pbl0->numroot == 0)
{
pbl0->secpfat2 = to_DWORD(b+0x24);
pbl0->flags = to_WORD(b+0x28);
pbl0->fs_version = to_WORD(b+0x2a);
pbl0->rootbegin = to_DWORD(b+0x2c);
pbl0->infosec = to_WORD(b+0x30);
pbl0->backup = to_WORD(b+0x32);
copybuff( &pbl0->vollabel[0],b+0x47,11); /* Volume label FAT32 */
if (!devio_read(driveno,(BLOCKT)(pbl0->infosec) ,b,1, FALSE))
{
return(FALSE);
}
for (i=0; to_DWORD((void *)b) != FSINFOSIG && i<512; b++,i++);
pbl0->free_alloc = to_DWORD((void *)&((struct fat32_info *)b)->free_alloc);
pbl0->next_alloc = to_DWORD((void *)&((struct fat32_info *)b)->next_alloc);
}
return(TRUE);
}
BOOLEAN pc_validate_partition_type(byte p_type)
{
if ( (p_type == 0x01) || (p_type == 0x04) || (p_type == 0x06) ||
(p_type == 0x0E) || /* Windows FAT16 Partition */
(p_type == 0x0B) || /* FAT32 Partition */
(p_type == 0x0C) || /* FAT32 Partition */
(p_type == 0x55) ) /* FAT32 Partition */
return(TRUE);
else
return(FALSE);
}
/* Update a fat32 voulme s info sector */
BOOLEAN fat_flushinfo(DDRIVE *pdr) /*__fn__*/
{
byte *pf;
int j;
BLKBUFF *buf;
if (pdr->fasize == 8)
{
/* Use read_blk, to take advantage of the failsafe cache */
buf = pc_read_blk(pdr, (dword) pdr->infosec);
if(!buf)
{
rtfs_set_errno(PEIOERRORREADINFO32); /* fat_flushinfo: failed writing info block */
goto info_error;
}
/* Merge in the new values */
pf = buf->data; /* Now we do not have to use the stack */
for (j=0; to_DWORD(pf)!=FSINFOSIG && j<512; pf++,j++);
fr_DWORD((byte *) (&((struct fat32_info *)pf)->free_alloc), pdr->known_free_clusters );
fr_DWORD((byte *) (&((struct fat32_info *)pf)->next_alloc), pdr->free_contig_pointer );
/* Use write_blk, to take advantage of the failsafe cache */
if (!pc_write_blk(buf))
{
rtfs_set_errno(PEIOERRORWRITEINFO32); /* fat_flushinfo: failed writing info block */
pc_discard_buf(buf);
info_error:
pc_report_error(PCERR_FAT_FLUSH);
return(FALSE);
}
pc_release_buf(buf); /* Leave it cached */
}
return (TRUE);
}
#if (RTFS_WRITE)
BOOLEAN fatxx_pfaxxterm(DDRIVE *pdr, CLUSTERTYPE clno);
byte * fatxx_pfswap(DDRIVE *pdr, CLUSTERTYPE index, BOOLEAN for_write);
/* Put a DWORD value into the fat at index */
BOOLEAN fatxx_pfpdword(DDRIVE *pdr, dword index, dword *pvalue) /*__fatfn__*/
{
dword *ppage;
dword offset;
/* Make sure we have access to the page. Mark it for writing */
ppage = (dword *)fatxx_pfswap(pdr,index,TRUE);
if (!ppage)
return(FALSE);
else
{
/* there are 128 entries per page */
offset = (dword) (index & 0x7f);
ppage[(int)offset] = *pvalue;
}
return(TRUE);
}
#endif
/* Get a DWORD value from the fat at index */
BOOLEAN fatxx_pfgdword(DDRIVE *pdr, dword index, dword *value) /*__fatfn__*/
{
dword *ppage;
dword offset;
/* Make sure we have access to the page. Do not Mark it for writing */
ppage = (dword *)fatxx_pfswap(pdr,index,FALSE);
if (!ppage)
return(FALSE);
else
{
/* there are 128 entries per page */
offset = (dword) (index & 0x7f);
*value = ppage[(int)offset];
}
return(TRUE);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,522 @@
/*
* rtkernfn.c - Miscelaneous portable functions
*
* ERTFS portable process management and other functions.
* This file is portable but it requires interaction with the
* porting layer functions in portrtfs.c.
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
*/
#include <rtfs.h>
BOOLEAN rtfs_resource_init(void) /*__fn__*/
{
prtfs_cfg->critical_semaphore = rtfs_port_alloc_mutex();
if (!prtfs_cfg->critical_semaphore)
return(FALSE);
/* Note: cfg_NDRIVES semaphores are allocated and assigned to the individual
drive structure within routine pc_ertfs_init() */
/* Initialize a user table */
rtfs_memset((byte *)prtfs_cfg->rtfs_user_table, 0, sizeof(RTFS_SYSTEM_USER)*prtfs_cfg->cfg_NUM_USERS);
return(TRUE);
}
PRTFS_SYSTEM_USER rtfs_get_system_user(void)
{
int i;
dword t;
t = rtfs_port_get_taskid();
if (prtfs_cfg->cfg_NUM_USERS == 1)
return(&prtfs_cfg->rtfs_user_table[0]);
for (i = 0; i < prtfs_cfg->cfg_NUM_USERS; i++)
{
if (t == prtfs_cfg->rtfs_user_table[i].task_handle)
return(&prtfs_cfg->rtfs_user_table[i]);
}
/* Did not find one.. so assign one from between 1 and n */
for (i = 1; i < prtfs_cfg->cfg_NUM_USERS; i++)
{
if (!prtfs_cfg->rtfs_user_table[i].task_handle)
{
return_it:
rtfs_memset((byte *)&prtfs_cfg->rtfs_user_table[i], 0, sizeof(RTFS_SYSTEM_USER));
prtfs_cfg->rtfs_user_table[i].task_handle = t;
return(&prtfs_cfg->rtfs_user_table[i]);
}
}
/* We are out of user structures so use element 0 */
i = 0;
goto return_it;
}
void pc_free_user(void) /*__fn__*/
{
int i;
PRTFS_SYSTEM_USER s;
s = rtfs_get_system_user();
if (s)
{
for (i = 0; i < prtfs_cfg->cfg_NDRIVES; i++)
{
if (s->lcwd[i])
{
pc_freeobj((DROBJ *) s->lcwd[i]);
s->lcwd[i] = 0;
}
}
rtfs_memset((byte *)s, 0, sizeof(*s));
}
}
/* pc_free_all_users() - Run down the user list releasing drive resources
*
* This routine is called by RTFS when it closes a drive.
* The routine must release the current directory object for that drive
* for each user. If a user does not have a CWD for the drive it should
* not call pc_freeobj.
*
* In the reference port we cycle through our array of user structures
* to provide the enumeration. Other implementations are equally valid.
*/
void pc_free_all_users(int driveno) /*__fn__*/
{
int i;
if (prtfs_cfg->cfg_NUM_USERS == 1)
{
if (prtfs_cfg->rtfs_user_table[0].lcwd[driveno])
{
pc_freeobj((DROBJ *)prtfs_cfg->rtfs_user_table[0].lcwd[driveno]);
prtfs_cfg->rtfs_user_table[0].lcwd[driveno] = 0;
}
}
else
{
for (i = 0; i < prtfs_cfg->cfg_NUM_USERS; i++)
{
if (prtfs_cfg->rtfs_user_table[i].task_handle && prtfs_cfg->rtfs_user_table[i].lcwd[driveno])
{
pc_freeobj((DROBJ *)prtfs_cfg->rtfs_user_table[i].lcwd[driveno]);
prtfs_cfg->rtfs_user_table[i].lcwd[driveno] = 0;
}
}
}
}
/* int rtfs_set_driver_errno() - set device driver errno for the calling task
Saves driver errno for the calling task in array based on callers taskid.
Note: This routine must not be called from the interrupt service layer
Returns nothing
*/
void rtfs_set_driver_errno(dword error) /*__fn__*/
{
rtfs_get_system_user()->rtfs_driver_errno = error;
}
/* ********************************************************************
dword rtfs_get_driver_errno() - get device driver errno for the calling task
Returns device driver errno for the calling task in array based on
callers taskid.
*/
dword rtfs_get_driver_errno(void) /*__fn__*/
{
return(rtfs_get_system_user()->rtfs_driver_errno);
}
/* int rtfs_set_errno() - set errno for the calling task
Saves errno for the calling task in array based on callers taskid.
Returns -1
*/
int rtfs_set_errno(int error) /*__fn__*/
{
rtfs_get_system_user()->rtfs_errno = error;
return(-1);
}
/* ********************************************************************
int get_errno() - get errno for the calling task
Returns errno for the calling task in array based on callers taskid.
*/
int get_errno(void) /*__fn__*/
{
return(rtfs_get_system_user()->rtfs_errno);
}
/* Miscelaneous functions */
void pc_report_error(int error_number) /*__fn__*/
{
RTFS_PRINT_STRING_1(USTRING_PORTKERN_03, 0); /* "pc_report_error was called with error" */
RTFS_PRINT_LONG_1((dword) error_number, PRFLG_NL);
}
/* This routine will be called if an IO error occurs. It must return
either CRITICAL_ERROR_ABORT to have the operation aborted and
the drive to be unmounted or CRITICAL_ERROR_RETRY to force a retry
of the operation.
This routine prompts the user to Abort or Retry. If console input
is not implemented it return Abort. This routine may be modified
to take corrective action (such as ask the user to reinsert the media)
before return Retry or Abort
*/
KS_CONSTANT int med_st[] =
{
USTRING_SYS_NULL, /* "" */
USTRING_CRITERR_02, /* "BAD_FORMAT" */
USTRING_CRITERR_03, /* "CRERR_NO_CARD" */
USTRING_CRITERR_04, /* "CRERR_BAD_CARD" */
USTRING_CRITERR_05, /* "CRERR_CHANGED_CARD" */
USTRING_CRITERR_06, /* "CRERR_CARD_FAILURE" */
};
int critical_error_handler(int driveno, int media_status, dword sector)
{
byte inbuf[20];
byte *p;
DDRIVE *pdr;
BOOLEAN needs_flush;
/* If you do not have console input you may return abort unconditionally */
/* return (CRITICAL_ERROR_ABORT); */
RTFS_ARGSUSED_PVOID((void *) sector);
pdr = pc_drno_to_drive_struct(driveno);
if (pdr->fat_is_dirty || pc_test_all_fil(pdr))
needs_flush = TRUE;
else
needs_flush = FALSE;
RTFS_PRINT_STRING_1(USTRING_CRITERR_07,0); /* "Media status == " */
RTFS_PRINT_STRING_1(med_st[media_status],PRFLG_NL);
RTFS_PRINT_STRING_2(USTRING_CRITERR_08, pdr->volume_label, PRFLG_NL); /* "Volume == " */
if (needs_flush)
RTFS_PRINT_STRING_1(USTRING_CRITERR_09, PRFLG_NL); /* "Volume is dirty" */
else
RTFS_PRINT_STRING_1(USTRING_CRITERR_10, PRFLG_NL); /* "Volume is clean" */
/* default to ABORT. If rtfs_print_prompt_user() is not implemented
then ABORT will be the default behavior */
p = inbuf;
CS_OP_ASSIGN_ASCII(p,'A');
CS_OP_INC_PTR(p);
CS_OP_TERM_STRING(p);
return (CRITICAL_ERROR_ABORT); /* ctr modified */
// for (;;)
// {
// /* "Type A to abort R to Retry" */
// rtfs_print_prompt_user(UPROMPT_CRITERR, inbuf);
// if (CS_OP_CMP_ASCII(inbuf,'A') || CS_OP_CMP_ASCII(inbuf,'a'))
// return (CRITICAL_ERROR_ABORT);
// if (CS_OP_CMP_ASCII(inbuf,'R') || CS_OP_CMP_ASCII(inbuf,'r'))
// return (CRITICAL_ERROR_RETRY);
// }
}
/**************************************************************************
PC_NUM_DRIVES - Return total number of drives in the system
Description
This routine returns the number of drives in the system
Returns
The number
*****************************************************************************/
int pc_num_drives(void) /* __fn__ */
{
return(prtfs_cfg->cfg_NDRIVES);
}
/**************************************************************************
PC_NUSERFILES - Return total number of uses allowed in the system
Description
This routine returns the number of user in the system
Returns
The number
*****************************************************************************/
int pc_num_users(void) /* __fn__ */
{
return(prtfs_cfg->cfg_NUM_USERS);
}
/**************************************************************************
PC_NUSERFILES - Return total number of userfiles alloed in the system
Description
This routine returns the number of user files in the system
Returns
The number
*****************************************************************************/
int pc_nuserfiles(void) /* __fn__ */
{
return(prtfs_cfg->cfg_NUSERFILES);
}
/**************************************************************************
PC_VALIDATE_DRIVENO - Verify that a drive number is <= prtfs_cfg->cfg_NDRIVES
Description
This routine is called when a routine is handed a drive number and
needs to know if it is within the number of drives set during
the congiguration.
Returns
TRUE if the drive number is valid or FALSE.
*****************************************************************************/
BOOLEAN pc_validate_driveno(int driveno) /* __fn__ */
{
if ((driveno < 0) || (driveno > 25) || (!prtfs_cfg->drno_to_dr_map[driveno]) )
return(FALSE);
else
return(TRUE);
}
/**************************************************************************
PC_MEMORY_INIT - Initialize and allocate File system structures.
THIS ROUTINE MUST BE CALLED BEFORE ANY FILE SYSTEM ROUTINES !!!!!!
IT IS CALLED BY THE PC_ERTFS_INIT() Function
Description
This routine must be called before any file system routines. Its job
is to allocate tables needed by the file system. We chose to implement
memory management this way to provide maximum flexibility for embedded
system developers. In the reference port we use malloc to allocate the
various chunks of memory we need, but we could just have easily comiled
the tables into the BSS section of the program.
Use whatever method makes sense in you system.
Note the total number of bytes allocated by this routine is:
(sizeof(DDRIVE) * prtfs_cfg->cfg_NDRIVES) + (sizeof(PC_FILE)*NUSERFILES) +
(sizeof(BLKBUFF)*NBLKBUFFS)+ (sizeof(DROBJ)*NDROBJS) +
(sizeof(FINODE)*NFINODES)
Returns
TRUE on success or no ON Failure.
*****************************************************************************/
BOOLEAN pc_memory_init(void) /*__fn__*/
{
int i,j,l;
DROBJ *pobj;
FINODE *pfi;
DDRIVE *pdrive;
/* Call the kernel level initialization code */
if (!rtfs_resource_init())
return(FALSE);
/*
=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=
We simply assign our pointers to the placeholders in
the BSS
=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=
*/
/* Initialize the drive structures */
l =sizeof(DDRIVE); l *= prtfs_cfg->cfg_NDRIVES;
rtfs_memset(prtfs_cfg->mem_drives_structures, (byte) 0, (int)l);
/* Initialize the directory block buffer array */
if (!pc_initialize_block_pool(
&prtfs_cfg->buffcntxt, prtfs_cfg->cfg_NBLKBUFFS,
prtfs_cfg->mem_block_pool, prtfs_cfg->cfg_BLK_HASHTBLE_SIZE,
prtfs_cfg->mem_block_hash_table))
return(FALSE);
/* Initialize buffer pools for each drive */
for (pdrive=prtfs_cfg->mem_drives_structures,i = 0;
i < prtfs_cfg->cfg_NDRIVES; i++, pdrive++)
{
/* Use the globally shared block buffer pool.
this can be overriden through the API to assign a private buffer pool to the drive */
pdrive->pbuffcntxt = &prtfs_cfg->buffcntxt;
/* Initialize the fat block buffer array */
if (!pc_initialize_fat_block_pool(
&pdrive->fatcontext,
prtfs_cfg->cfg_FAT_BUFFER_SIZE[i], prtfs_cfg->fat_buffers[i],
prtfs_cfg->cfg_FAT_HASHTBL_SIZE[i], prtfs_cfg->fat_hash_table[i],
prtfs_cfg->fat_primary_cache[i], prtfs_cfg->fat_primary_index[i]))
return(FALSE);
}
/* make a NULL terminated freelist of the DROBJ pool using
pdrive as the link. This linked freelist structure is used by the
DROBJ memory allocator routine. */
pobj = prtfs_cfg->mem_drobj_freelist = prtfs_cfg->mem_drobj_pool;
pobj->is_free = TRUE;
for (i = 0,j = 1; i < prtfs_cfg->cfg_NDROBJS-1; i++, j++)
{
pobj = prtfs_cfg->mem_drobj_freelist + j;
pobj->is_free = TRUE;
prtfs_cfg->mem_drobj_freelist[i].pdrive = (DDRIVE *) pobj;
}
prtfs_cfg->mem_drobj_freelist[prtfs_cfg->cfg_NDROBJS-1].pdrive = 0;
/* Make a NULL terminated FINODE freelist using
pnext as the link. This linked freelist is used by the FINODE
memory allocator routine */
pfi = prtfs_cfg->mem_finode_freelist = prtfs_cfg->mem_finode_pool;
for (i = 0; i < prtfs_cfg->cfg_NFINODES-1; i++)
{
pfi->is_free = TRUE;
pfi++;
prtfs_cfg->mem_finode_freelist->pnext = pfi;
prtfs_cfg->mem_finode_freelist++;
prtfs_cfg->mem_finode_freelist->pnext = 0;
}
/* Mark all user files free */
for (i = 0; i < prtfs_cfg->cfg_NUSERFILES; i++)
prtfs_cfg->mem_file_pool[i].is_free = TRUE;
prtfs_cfg->mem_finode_freelist = prtfs_cfg->mem_finode_pool;
return(TRUE);
}
/**************************************************************************
PC_MEMORY_DROBJ - Allocate a DROBJ structure
Description
If called with a null pointer, allocates and zeroes the space needed to
store a DROBJ structure. If called with a NON-NULL pointer the DROBJ
structure is returned to the heap.
Returns
If an ALLOC returns a valid pointer or NULL if no more core. If a free
the return value is the input.
*****************************************************************************/
DROBJ *pc_memory_drobj(DROBJ *pobj) /*__fn__*/
{
DROBJ *preturn;
preturn = 0;
if (pobj)
{
OS_CLAIM_FSCRITICAL()
if (!pobj->is_free)
{
pobj->is_free = TRUE;
/* Free it by putting it at the head of the freelist
NOTE: pdrive is used to link the freelist */
pobj->pdrive = (DDRIVE *) prtfs_cfg->mem_drobj_freelist;
prtfs_cfg->mem_drobj_freelist = pobj;
}
OS_RELEASE_FSCRITICAL()
}
else
{
/* Alloc: return the first structure from the freelist */
OS_CLAIM_FSCRITICAL()
preturn = prtfs_cfg->mem_drobj_freelist;
if (preturn)
{
prtfs_cfg->mem_drobj_freelist = (DROBJ *) preturn->pdrive;
rtfs_memset(preturn, (byte) 0, sizeof(DROBJ));
OS_RELEASE_FSCRITICAL()
}
else
{
OS_RELEASE_FSCRITICAL()
rtfs_set_errno(PERESOURCE); /* pc_memory_drobj: out drobj of resources */
pc_report_error(PCERR_DROBJALLOC);
}
}
return(preturn);
}
/**************************************************************************
PC_MEMORY_FINODE - Allocate a FINODE structure
Description
If called with a null pointer, allocates and zeroes the space needed to
store a FINODE structure. If called with a NON-NULL pointer the FINODE
structure is returned to the heap.
Returns
If an ALLOC returns a valid pointer or NULL if no more core. If a free
the return value is the input.
*****************************************************************************/
FINODE *pc_memory_finode(FINODE *pinode) /*__fn__*/
{
FINODE *preturn;
BLKBUFF *pfile_buffer;
if (pinode)
{
pfile_buffer = 0;
OS_CLAIM_FSCRITICAL()
if (!pinode->is_free)
{
/* Free it by putting it at the head of the freelist */
pfile_buffer = pinode->pfile_buffer;
pinode->pfile_buffer = 0;
pinode->is_free = TRUE;
pinode->pnext = prtfs_cfg->mem_finode_freelist;
prtfs_cfg->mem_finode_freelist = pinode;
}
OS_RELEASE_FSCRITICAL()
if (pfile_buffer)
pc_free_scratch_blk(pfile_buffer);
preturn = pinode;
}
else
{
/* Alloc: return the first structure from the freelist */
OS_CLAIM_FSCRITICAL()
preturn = prtfs_cfg->mem_finode_freelist;
if (preturn)
{
prtfs_cfg->mem_finode_freelist = preturn->pnext;
/* Zero the structure */
rtfs_memset(preturn, (byte) 0, sizeof(FINODE));
OS_RELEASE_FSCRITICAL()
}
else
{
OS_RELEASE_FSCRITICAL()
rtfs_set_errno(PERESOURCE); /* pc_memory_finode: out finode of resources */
pc_report_error(PCERR_FINODEALLOC);
}
}
return(preturn);
}

View File

@ -0,0 +1,711 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* RTLOWL.C - Low level functions that don't directly manipulate the fat.
Routines in this file include:
pc_i_dskopen - Mount a drive if you can
pc_read_partition_table
- Load a drive structure with partition info
pc_gblk0 - Read block zero and set up internal structures.
pc_clzero - Write zeroes to a cluster on disk.
pc_drno2dr - Convert a drive number to a drive structure.
pc_dskfree - Free resources associated with a drive.
pc_sec2cluster - Convert a sector number to a cluster value.
pc_sec2index - Convert a sector number to a cluster offset.
pc_cl2sector - Convert a cluster value to a sector number.
pc_pfinode_cluster - Assign a cluster value to a finode
pc_finode_cluster - Get the cluster value from a finode
*/
#include <rtfs.h>
/******************************************************************************
PC_I_DSKOPEN - Open a disk for business.
Description
Called by lower level code in chkmedia to open the disk
Returns
Returns TRUE if the disk was successfully initialized.
****************************************************************************/
int pc_log_base_2(word n) /*__fn__*/
{
int log;
log = 0;
if (n <= 1)
return(log);
while(n)
{
log += 1;
n >>= 1;
}
return((int)(log-1));
}
/*
* Note: This routine is called with the drive already locked so
* in several cases there is no need for critical section code handling
* This is a helper function for pc_i_dskopen()
*/
BOOLEAN pc_init_drv_fat_info(DDRIVE *pdr, struct pcblk0 *pbl0);
BOOLEAN pc_i_dskopen(int driveno) /*__fn__*/
{
DDRIVE *pdr;
struct pcblk0 bl0;
BOOLEAN ret_val;
int partition_status;
if (!prtfs_cfg)
{
/* Failed: pc_meminit() must not have been called */
pc_report_error(PCERR_INITCORE);
return (FALSE);
}
/* Check drive number */
if (!pc_validate_driveno(driveno))
{
rtfs_set_errno(PEINVALIDDRIVEID);
return(FALSE);
}
pdr = pc_drno_to_drive_struct(driveno);
/* Do not do anything on reopens */
if (pdr->mount_valid)
{
return(TRUE);
}
else
{
/* Zero the structure so all of our initial values are right */
OS_CLAIM_FSCRITICAL()
{
byte *p1, *p2;
p1 = (byte *) pdr;
p2 = (byte *) &pdr->begin_user_area;
while(p1 < p2) *p1++ = 0;
/* Set driveno now because we overwrote it */
pdr->driveno = (word)driveno;
}
OS_RELEASE_FSCRITICAL()
}
/* Set this to true now so check media does not try to mount */
pdr->mount_valid = TRUE;
partition_status = 0;
if (pdr->drive_flags & DRIVE_FLAGS_PARTITIONED)
{
partition_status = pc_read_partition_table(driveno, pdr);
if (partition_status != READ_PARTION_OK)
{
/* If we read a block but didn't see a partition table signature
and this drive structure is for the first partition number
then fall through and see if there is a BPB at block 0. */
if (partition_status == READ_PARTION_NO_TABLE && pdr->partition_number == 0)
{
rtfs_set_errno(0); /* Clear errno, we'll set it later */
pdr->partition_base = 0; /* Is BPB at 0 ? */
}
else
{
pc_report_error(PCERR_INITDEV);
return_error:
pdr->mount_valid = FALSE;
return(FALSE);
}
}
}
/* Read block 0 */
if (!pc_gblk0((word) driveno, &bl0 ))
{
/* pc_gblk0 set errno */
pc_report_error(PCERR_INITREAD);
goto return_error;
}
/* Verify that we have a good dos formatted disk */
if ( (bl0.jump != (byte) 0xE9) && (bl0.jump !=(byte) 0xEB) )
{
/* If we were checking for an MBR at physical block 0 with a driver
set for partitioned devices, set PEINVALIDMBR, otherwise
set PEINVALIDBPB */
if (pdr->drive_flags & DRIVE_FLAGS_PARTITIONED && partition_status == READ_PARTION_NO_TABLE)
rtfs_set_errno(PEINVALIDMBR);
else
rtfs_set_errno(PEINVALIDBPB); /* pc_i_dskopen Unkown values in Bios Parameter block */
pc_report_error(PCERR_INITMEDI);
goto return_error;
}
/* set up the drive structur from block 0 */
pdr->bytspsector = bl0.bytspsector; /* bytes/sector */
pdr->secpalloc = bl0.secpalloc; /* sectors / cluster */
pdr->numroot = bl0.numroot; /* Maximum number of root entries */
pdr->numsecs = (BLOCKT) bl0.numsecs; /* Total sectors on the disk */
pdr->mediadesc = bl0.mediadesc; /* Media descriptor byte */
pdr->secreserved = bl0.secreserved; /* sectors reserved */
pdr->secptrk = bl0.secptrk; /* sectors per track */
pdr->numhead = bl0.numhead; /* number of heads */
pdr->numhide =bl0.numhide; /* # hidden sectors */
copybuff(pdr->volume_label, &bl0.vollabel[0], 11);
pdr->volume_label[11] = 0;
pdr->volume_serialno = bl0.volid;
/* Check if running on a DOS (4.0) huge partition */
/* If traditional total # sectors is zero, use value in extended BPB */
if (pdr->numsecs == 0L)
pdr->numsecs = bl0.numsecs2; /* (4.0) */
/* derive some things */
pdr->bytespcluster = (int) (512 * pdr->secpalloc);
/* bits to mask in to calculate byte offset in cluster from file pointer.
AND file pointer with this to get byte offset in cluster a shift right
9 to get block offset in cluster */
pdr->byte_into_cl_mask = (dword) pdr->bytespcluster;
pdr->byte_into_cl_mask -= 1L;
/* save away log of sectors per alloc */
pdr->log2_secpalloc = (int)pc_log_base_2((word)pdr->secpalloc);
/* Get
pdr->secpfat pdr->numfats pdr->fatblock
pdr->rootblock pdr->secproot pdr->firstclblock
pdr->maxfindex pdr->infosec pdr->fasize
pdr->free_contig_base
pdr->free_contig_pointer
pdr->known_free_clusters
*/
pc_init_drv_fat_info(pdr, &bl0);
/* Load the fat driver functions and initilialize the fat */
/* Init_fat will set errno */
if (pdr->fasize == 8)
ret_val = init_fat32(pdr);
else if (pdr->fasize == 4)
ret_val = init_fat16(pdr);
else if (pdr->fasize == 3)
ret_val = init_fat12(pdr);
else
{
rtfs_set_errno(PEINVALIDBPB); /* pc_i_dskopen Unkown values in Bios Parameter block */
ret_val = 0;
}
if (!ret_val)
{
pc_report_error(PCERR_FATREAD);
goto return_error;
}
pdr->mount_valid = TRUE;
/* Save Unique id for this mount */
prtfs_cfg->drive_opencounter += 1;
pdr->drive_opencounter = prtfs_cfg->drive_opencounter;
return(TRUE);
}
/******************************************************************************
pc_read_partition_table() - Load a drive structure with partition info
Description
Read the partition table from a disk. If one is found then check the
entry in the table that is specified by pdr->partition_number. If the
entry is valid then load the fields
pdr->partition_base,pdr->partition_size and pdr->partition_type;
Returns
The following values.
READ_PARTION_OK Partition read succesfully
READ_PARTION_ERR Internal error (could not allocate buffers ?)
READ_PARTION_NO_TABLE No partition table found
READ_PARTION_NO_ENTRY Request entry not found
READ_PARTION_IOERROR Device IO error
****************************************************************************/
int pc_read_partition_table(int driveno, DDRIVE *pdr)
{
PTABLE *ppart;
BLKBUFF *buf;
byte *pbuf;
word i;
int ret_val;
/* Grab some working space */
buf = pc_scratch_blk();
if (!buf)
{
return(READ_PARTION_ERR);
}
/* Read block zero */
if (!devio_read(driveno, 0 , buf->data , 1, TRUE))
{
/* Failed reading Master boot record */
rtfs_set_errno(PEIOERRORREADMBR);
ret_val = READ_PARTION_IOERROR;
goto done;
}
/* Copy the table to a word alligned buffer */
pbuf = buf->data;
pbuf += 0x1be; /* The info starts at buf[1be] */
/* Don't use sizeof here since the structure does not pack to exact size */
copybuff(buf->data, pbuf, 0x42);
ppart = (PTABLE *) buf->data;
if (to_WORD((byte *) &ppart->signature) != 0xAA55) /*X*/
{
rtfs_set_errno(PEINVALIDMBR);
ret_val = READ_PARTION_NO_TABLE;
goto done;
}
#if (SUPPORT_EXTENDED_PARTITIONS)
{
/* Special code to support extended partitions */
/* since most applications don't use these we compile it
conditionally to save code space */
dword extended_base, ltemp;
int j, skip_count;
for (j = 0; j < 4; j++)
{
if (ppart->ents[j].p_typ == 0x5 || ppart->ents[j].p_typ == 0xF)
{
if (j <= (int)pdr->partition_number)
{
/* the partition is inside an extended partition */
/* Get the relative start and size */
pdr->partition_base = to_DWORD ((byte *) &ppart->ents[j].r_sec);
extended_base = pdr->partition_base;
pdr->partition_size = to_DWORD ((byte *) &ppart->ents[j].p_size);
skip_count = (int)pdr->partition_number - j;
for (;;)
{
/* Read the partition information in the extended partition */
if (!devio_read(driveno, pdr->partition_base , buf->data , 1, TRUE))
{
/* Failed reading Master boot record */
rtfs_set_errno(PEIOERRORREADMBR);
ret_val = READ_PARTION_IOERROR;
goto done;
}
/* Copy the table to a word alligned buffer */
pbuf = buf->data;
pbuf += 0x1be; /* The info starts at buf[1be] */
/* Don't use sizeof here since the structure does not pack to exact size */
copybuff(buf->data, pbuf, 0x42);
ppart = (PTABLE *) buf->data;
if (to_WORD((byte *) &ppart->signature) != 0xAA55) /*X*/
{
rtfs_set_errno(PEINVALIDMBR);
ret_val = READ_PARTION_NO_TABLE;
goto done;
}
if (skip_count==0)
{
if (pc_validate_partition_type(ppart->ents[0].p_typ))
{
pdr->partition_type = ppart->ents[0].p_typ;
ltemp = pdr->partition_base;
pdr->partition_base = ltemp + to_DWORD ((byte *) &ppart->ents[0].r_sec);
pdr->partition_size = to_DWORD ((byte *) &ppart->ents[0].p_size);
ret_val = READ_PARTION_OK;
goto done;
}
else
{
rtfs_set_errno(PEINVALIDMBROFFSET);
ret_val = READ_PARTION_NO_TABLE;
goto done;
}
}
else
{
if (ppart->ents[1].p_typ != 0x5 && ppart->ents[1].p_typ != 0xF)
{
rtfs_set_errno(PEINVALIDMBROFFSET);
ret_val = READ_PARTION_NO_TABLE;
goto done;
}
pdr->partition_base = extended_base + to_DWORD ((byte *) &ppart->ents[1].r_sec);
pdr->partition_size = to_DWORD ((byte *) &ppart->ents[1].p_size);
skip_count -= 1;
}
}
}
}
}
}
/* Fall through to here if not in an extended partition */
#endif /* (SUPPORT_EXTENDED_PARTITIONS) */
i = (word)pdr->partition_number;
if (pc_validate_partition_type(ppart->ents[i].p_typ))
{
/* Get the relative start and size */
pdr->partition_base = to_DWORD ((byte *) &ppart->ents[i].r_sec);
pdr->partition_size = to_DWORD ((byte *) &ppart->ents[i].p_size);
pdr->partition_type = ppart->ents[i].p_typ;
ret_val = READ_PARTION_OK;
}
else
{
rtfs_set_errno(PEINVALIDMBROFFSET);
ret_val = READ_PARTION_NO_TABLE;
}
done:
pc_free_scratch_blk(buf);
return(ret_val);
}
/****************************************************************************
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 TRUE if all went well.
****************************************************************************/
/* read block zero */
BOOLEAN pc_gblk0(word driveno, struct pcblk0 *pbl0) /*__fn__*/
{
BLKBUFF *buf;
byte *b;
/* Zero fill pbl0 so we do not get any surprises */
rtfs_memset(pbl0, (byte) 0,sizeof(struct pcblk0));
/* Grab a buffer to play with */
buf = pc_scratch_blk();
if (!buf)
{
rtfs_set_errno(PERESOURCEBLOCK); /* pc_gblk0 couldn't allocate a buffer */
return(FALSE);
}
b = buf->data; /* Now we do not have to use the stack */
/* get 1 block starting at 0 from driveno */
/* READ */
if (!devio_read(driveno, 0L ,b,1, FALSE))
{
rtfs_set_errno(PEIOERRORREADBPB); /* pc_gblk0 failed reading Bios Parameter block */
pc_free_scratch_blk(buf);
return(FALSE);
}
/* Now load the structure from the buffer */
pbl0->jump = b[0];
copybuff( &pbl0->oemname[0],b+3,8);
pbl0->oemname[8] = CS_OP_ASCII('\0');
pbl0->secpalloc = b[0xd];
pbl0->numfats = b[0x10];
pbl0->mediadesc = b[0x15];
pbl0->physdrv = b[0x24]; /* Physical Drive No. (4.0) */
pbl0->xtbootsig = b[0x26]; /* Extended signt 29H if 4.0 stuf valid */
/* BUG FIX 12-1-99 - Add KS_LITTLE_ODD_PTR_OK flag to split between
big endian and little endian system. The top section works on little
endian systems that do not require even alligned word accesses like
the x86 but for example on Little endian ARM systems these assignments
derefrencing a pointer to word at an odd address which gives bad data .*/
pbl0->bytspsector = to_WORD(b+0xb); /*X*/
pbl0->secreserved = to_WORD(b+0xe); /*X*/
pbl0->numroot = to_WORD(b+0x11); /*X*/
pbl0->numsecs = to_WORD(b+0x13); /*X*/
pbl0->secpfat = to_WORD(b+0x16); /*X*/
pbl0->secptrk = to_WORD(b+0x18); /*X*/
pbl0->numhead = to_WORD(b+0x1a); /*X*/
pbl0->numhide = to_WORD(b+0x1c); /*X*/
pbl0->numhide2 = to_WORD(b+0x1e); /*X*/
pbl0->numsecs2 = to_DWORD(b+0x20);/*X*/ /* # secs if > 32M (4.0) */
pbl0->volid = to_DWORD(b+0x27);/*X*/ /* Unique number per volume (4.0) */
copybuff( &pbl0->vollabel[0],b+0x2b,11); /* Volume label (4.0) */
if (pbl0->numroot == 0 && !pc_gblk0_32(driveno, pbl0, b))
{
pc_free_scratch_blk(buf);
rtfs_set_errno(PEIOERRORREADINFO32); /* pc_gblk0_32 failed reading Bios Parameter block */
return(FALSE);
}
pc_free_scratch_blk(buf);
return(TRUE);
}
#if (RTFS_WRITE)
#if (RTFS_SUBDIRS)
/***************************************************************************
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 FALSE on a write erro.
****************************************************************************/
/* Write zeros to all blocks in a cluster */
BOOLEAN pc_clzero(DDRIVE *pdrive, CLUSTERTYPE cluster) /*__fn__*/
{
BLKBUFF *pbuff;
CLUSTERTYPE i;
BLOCKT currbl;
currbl = pc_cl2sector(pdrive , cluster);
if (!currbl)
return (FALSE);
/*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 (FALSE);
}
if (!pc_write_blk ( pbuff ) )
{
pc_discard_buf(pbuff);
return (FALSE);
}
pc_release_buf(pbuff);
}
return (TRUE);
}
#endif
#endif
/****************************************************************************
PC_DRNO2DR - Convert a drive number to a pointer to DDRIVE
Description
Given a drive number look up the DDRIVE structure associated with it.
Returns
Returns NULL if driveno is not an open drive.
****************************************************************************/
DDRIVE *pc_drno_to_drive_struct(int driveno) /*__fn__*/
{
DDRIVE *pdr;
pdr = 0;
/* Check drive number */
if (pc_validate_driveno(driveno))
{
pdr = prtfs_cfg->drno_to_dr_map[driveno];
}
return(pdr);
}
DDRIVE *pc_drno2dr(int driveno) /*__fn__*/
{
DDRIVE *pdr;
DDRIVE *pretval;
pdr = pc_drno_to_drive_struct(driveno);
pretval = 0;
OS_CLAIM_FSCRITICAL()
/* Check drive number */
if (pdr)
{
if (pdr->mount_valid)
{
pretval = pdr;
}
}
OS_RELEASE_FSCRITICAL()
return(pretval);
}
/***************************************************************************
PC_DSKFREE - Deallocate all core associated with a disk structure
Description
Given a valid drive number. If the drive open count goes to zero, free the
file allocation table and the block zero information associated with the
drive. If unconditional is true, ignore the open count and release the
drive.
If open count reaches zero or unconditional, all future accesses to
driveno will fail until re-opened.
Returns
Returns FALSE if driveno is not an open drive.
****************************************************************************/
/* free up all core associated with the drive
called by close. A drive restart would consist of
pc_dskfree(driveno, TRUE), pc_dskopen() */
BOOLEAN pc_dskfree(int driveno) /*__fn__*/
{
DDRIVE *pdr;
/* Note this will fail unless mount_valid is true */
pdr = pc_drno2dr(driveno);
if (!pdr)
{
return(FALSE);
}
if (pdr->mount_valid)
{
/* Free the current working directory for this drive for all users */
pc_free_all_users(driveno);
/* Free all files, finodes & blocks associated with the drive */
pc_free_all_fil(pdr);
pc_free_all_i(pdr);
/* Free all drobj structures that have not yet been accessed */
pc_free_all_drobj(pdr);
pc_free_all_blk(pdr);
/* Clear the fat cache */
pc_free_all_fat_blocks(&pdr->fatcontext);
}
pdr->mount_valid = FALSE;
pdr->mount_abort = FALSE;
return (TRUE);
}
/****************************************************************************
PC_SEC2CLUSTER - Convert a block number to its cluster representation.
Description
Convert blockno to its cluster representation if it is in cluster space.
Returns
Returns 0 if the block is not in cluster space, else returns the
cluster number associated with block.
****************************************************************************/
#if (RTFS_SUBDIRS)
/* Cluster<->sector conversion routines */
/* Convert sector to cluster. 0 == s error */
CLUSTERTYPE pc_sec2cluster(DDRIVE *pdrive, BLOCKT blockno) /*__fn__*/
{
BLOCKT ltemp;
BLOCKT answer;
if ((blockno >= pdrive->numsecs) || (pdrive->firstclblock > blockno))
return (0);
else
{
/* (2 + (blockno - pdrive->firstclblock)/pdrive->secpalloc) */
ltemp = blockno - pdrive->firstclblock;
answer = ltemp;
answer = (BLOCKT) answer >> pdrive->log2_secpalloc;
answer += 2;
return ((CLUSTERTYPE)answer);
}
}
#endif
/****************************************************************************
PC_SEC2INDEX - Calculate the offset into a cluster for a block.
Description
Given a block number offset from the beginning of the drive, calculate
which block number within a cluster it will be. If the block number
coincides with a cluster boundary, the return value will be zero. If it
coincides with a cluster boundary + 1 block, the value will be 1, etc.
Returns
0,1,2 upto blockspcluster -1.
***************************************************************************/
#if (RTFS_SUBDIRS)
/* Convert sector to index into a cluster . No error detection */
word pc_sec2index(DDRIVE *pdrive, BLOCKT blockno) /*__fn__*/
{
BLOCKT answer;
/* ((blockno - pdrive->firstclblock) % pdrive->secpalloc) ); */
answer = blockno - pdrive->firstclblock;
answer = answer % pdrive->secpalloc;
return ( (word) answer);
}
#endif
/***************************************************************************
PC_CL2SECTOR - Convert a cluster number to block number representation.
Description
Convert cluster number to a blocknumber.
Returns
Returns 0 if the cluster is out of range. else returns the
block number of the beginning of the cluster.
****************************************************************************/
/* Convert cluster. to sector */
BLOCKT pc_cl2sector(DDRIVE *pdrive, CLUSTERTYPE cluster) /*__fn__*/
{
BLOCKT blockno;
dword t;
if (cluster < 2)
return (BLOCKEQ0);
else
{
t = cluster - 2;
t = t << pdrive->log2_secpalloc;
blockno = pdrive->firstclblock + t;
}
if (blockno >= pdrive->numsecs)
return (BLOCKEQ0);
else
return (blockno);
}
/* Round a size up to it's next cluster boundary and return
the length in clusters */
dword pc_chain_length(DDRIVE *pdrive, dword byte_length)
{
dword ltemp,chain_length;
ltemp = byte_length + pdrive->byte_into_cl_mask;
if (ltemp > byte_length)
{
chain_length = ltemp & ~(pdrive->byte_into_cl_mask);
chain_length >>= (int) (pdrive->log2_secpalloc + 9);
}
else
{
ltemp = (byte_length - pdrive->bytespcluster)+ pdrive->byte_into_cl_mask;
chain_length = ltemp & ~(pdrive->byte_into_cl_mask);
chain_length >>= (int) (pdrive->log2_secpalloc + 9);
chain_length += 1;
}
return(chain_length);
}

View File

@ -0,0 +1,441 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* RTNVFAT.C - Contains routines specific to the non-vfat implementation */
#include <rtfs.h>
#if (!VFAT)
/***************************************************************************
PC_FINDIN - Find a filename in the same directory as the argument.
Description
Look for the next match of filename or pattern filename:ext in the
subdirectory containing pobj. If found update pobj to contain the
new information (essentially getnext.) Called by pc_get_inode().
Note: Filename and ext must be right filled with spaces to 8 and 3 bytes
respectively. Null termination does not matter.
Note the use of the action variable. This is used so we do not have to
use match patterns in the core code like *.* and ..
GET_INODE_MATCH Must match the pattern exactly
GET_INODE_WILD Pattern may contain wild cards
GET_INODE_STAR Like he passed *.* (pattern will be null)
GET_INODE_DOTDOT Like he past .. (pattern will be null
Returns
Returns TRUE if found or FALSE.
****************************************************************************/
/* Find filename in the directory containing pobj. If found, load the inode
section of pobj. If the inode is already in the inode buffers we free the current inode
and stitch the existing one in, bumping its open count */
BOOLEAN pc_findin( DROBJ *pobj, byte *filename, byte *fileext, int action) /*__fn__*/
{
BLKBUFF *rbuf;
DIRBLK *pd;
DOSINODE *pi;
FINODE *pfi;
BOOLEAN matchfound;
BOOLEAN dowildcard;
if (action == GET_INODE_WILD)
dowildcard = TRUE;
else
dowildcard = FALSE;
rtfs_set_errno(0); /* Clear it here just in case */
/* For convenience. We want to get at block info here */
pd = &pobj->blkinfo;
/* Read the data */
pobj->pblkbuff = rbuf = pc_read_blk(pobj->pdrive, pobj->blkinfo.my_block);
while (rbuf)
{
pi = (DOSINODE *) &rbuf->data[0];
/* Look at the current inode */
pi += pd->my_index;
/* And look for a match */
while ( pd->my_index < INOPBLOCK )
{
matchfound = FALSE;
/* End of dir if name is 0 */
if (!pi->fname[0])
{
rtfs_set_errno(PENOENT); /* pc_findin: file or dir not found */
pc_release_buf(rbuf);
return(FALSE);
}
if (pi->fattribute != CHICAGO_EXT && pi->fname[0] != PCDELETE)
{
if (action == GET_INODE_STAR)
matchfound = TRUE;
else if (action == GET_INODE_DOTDOT)
{
if (pi->fname[0] == CS_OP_ASCII('.') && pi->fname[1] == CS_OP_ASCII('.'))
matchfound = TRUE; /* 8.3, not lfn */
}
else
{
matchfound =
( pc_patcmp_8(pi->fname, (byte*) filename, dowildcard) &&
pc_patcmp_3(pi->fext, (byte*) fileext, dowildcard ) );
}
if (matchfound && pi->fattribute & AVOLUME &&
action != GET_INODE_STAR && action != GET_INODE_WILD)
{
/* Don't match volume labels if we are finding a specific match. */
matchfound = FALSE;
}
}
if (matchfound)
{
/* We found it */
/* See if it already exists in the inode list.
If so.. we use the copy from the inode list */
pfi = pc_scani(pobj->pdrive, rbuf->blockno, pd->my_index);
if (pfi)
{
pc_freei(pobj->finode);
pobj->finode = pfi;
}
else /* No inode in the inode list. Copy the data over
and mark where it came from */
{
pfi = pc_alloci();
if (pfi)
{
pc_freei(pobj->finode); /* Release the current */
pobj->finode = pfi;
pc_dos2inode(pobj->finode , pi );
pc_marki(pobj->finode , pobj->pdrive , pd->my_block,
pd->my_index );
}
else
{
pc_release_buf(rbuf);
return (FALSE);
}
}
/* Free, no error */
pc_release_buf(rbuf);
return (TRUE);
} /* if (match) */
pd->my_index++;
pi++;
}
/* Not in that block. Try again */
pc_release_buf(rbuf);
/* Update the objects block pointer */
if (!pc_next_block(pobj))
break;
pd->my_index = 0;
pobj->pblkbuff = rbuf = pc_read_blk(pobj->pdrive, pobj->blkinfo.my_block);
}
if (!get_errno())
rtfs_set_errno(PENOENT); /* pc_findin: file or dir not found */
return (FALSE);
}
/***************************************************************************
PC_INSERT_INODE - Insert a new inode into an existing directory inode.
Description
Take mom , a fully defined DROBJ, and pobj, a DROBJ with a finode
containing name, ext, etc, but not yet stitched into the inode buffer
pool, and fill in pobj and its inode, write it to disk and make the inode
visible in the inode buffer pool. (see also pc_mknode() )
Returns
Returns TRUE if all went well, FALSE on a write error, disk full error or
root directory full.
**************************************************************************/
/* Note: the parent directory is locked before this routine is called */
BOOLEAN pc_insert_inode(DROBJ *pobj , DROBJ *pmom, byte attr, CLUSTERTYPE initcluster, byte *filename, byte *fileext)
{
BLKBUFF *pbuff;
DIRBLK *pd;
DOSINODE *pi;
int i;
CLUSTERTYPE cluster;
DDRIVE *pdrive;
DATESTR crdate;
pc_init_inode( pobj->finode, filename, fileext,
attr, initcluster, /*size*/ 0L ,pc_getsysdate(&crdate) );
/* Set up pobj */
pdrive = pobj->pdrive = pmom->pdrive;
pobj->isroot = FALSE;
pd = &pobj->blkinfo;
/* Now get the start of the dir */
pd->my_block = pd->my_frstblock = pc_firstblock(pmom);
if (!pd->my_block)
{
rtfs_set_errno(PEINVALIDBLOCKNUMBER); /* pc_insert_inode: Internal error, invalid block id */
return (FALSE);
}
else
pd->my_index = 0;
/* Read the data */
pobj->pblkbuff = pbuff = pc_read_blk(pobj->pdrive, pobj->blkinfo.my_block);
if (!pbuff)
return(FALSE);
while (pbuff)
{
i = pd->my_index = 0;
pi = (DOSINODE *) &pbuff->data[0];
/* look for a slot */
while ( i < INOPBLOCK )
{
/* End of dir if name is 0 */
if ( (pi->fname[0] == CS_OP_ASCII('\0')) || (pi->fname[0] == PCDELETE) )
{
pd->my_index = (word)i;
/* Update the DOS disk */
pc_ino2dos( pi, pobj->finode );
/* Write the data */
if (pc_write_blk(pbuff))
{
/* Mark the inode in the inode buffer */
pc_marki(pobj->finode , pobj->pdrive , pd->my_block,
pd->my_index );
pc_release_buf(pbuff);
return(TRUE);
}
else
{
pc_discard_buf(pbuff);
return(FALSE);
}
}
i++;
pi++;
}
/* Not in that block. Try again */
pc_release_buf(pbuff);
/* Update the objects block pointer */
rtfs_set_errno(0); /* Clear errno to be safe */
if (!pc_next_block(pobj))
{
if (get_errno())
return(FALSE);
else
break;
}
pobj->pblkbuff = pbuff = pc_read_blk(pobj->pdrive, pobj->blkinfo.my_block);
}
cluster = pc_grow_dir(pdrive, pmom);
if (!cluster)
return (FALSE);
/* Do not forget where the new item is */
pd->my_block = pc_cl2sector(pobj->pdrive , cluster);
pd->my_index = 0;
/* Zero out the cluster */
if (!pc_clzero( pobj->pdrive , cluster ) )
goto clean_and_fail;
/* Copy the item into the first block */
pbuff = pc_init_blk( pobj->pdrive , pd->my_block);
if (!pbuff)
goto clean_and_fail;
pc_ino2dos ( (DOSINODE *) &pbuff->data[0] , pobj->finode ) ;
/* Write it out */
if ( !pc_write_blk ( pbuff ) )
{
pc_discard_buf(pbuff);
goto clean_and_fail;
}
/* We made a new slot. Mark the inode as belonging there */
pc_marki(pobj->finode , pobj->pdrive , pd->my_block, pd->my_index );
pc_release_buf(pbuff);
return (TRUE);
clean_and_fail:
pc_truncate_dir(pdrive, pmom, cluster);
return (FALSE);
}
/****************************************************************************
PC_NIBBLEPARSE - Nibble off the left most part of a pathspec
Description
Take a pathspec (no leading D:). and parse the left most element into
filename and files ext. (SPACE right filled.).
Returns
Returns a pointer to the rest of the path specifier beyond file.ext
****************************************************************************/
/* Parse a path. Return NULL if problems or a pointer to the next */
byte *pc_nibbleparse(byte *filename, byte *fileext, byte *path) /* __fn__*/
{
byte *p;
BLKBUFF *scratch;
byte *tbuf;
byte *t;
p = path;
if (!p) /* Path must exist */
return (0);
scratch = pc_scratch_blk();
if (!scratch)
return(0);
tbuf = scratch->data;
t = tbuf;
while (CS_OP_IS_NOT_EOS(p))
{
if (CS_OP_CMP_ASCII(p,'\\'))
{
CS_OP_INC_PTR(p);
break;
}
else
{
CS_OP_CP_CHR(t, p);
CS_OP_INC_PTR(t);
CS_OP_INC_PTR(p);
}
}
CS_OP_TERM_STRING(t);
if (pc_ascii_fileparse(filename, fileext, tbuf))
{
pc_free_scratch_blk(scratch);
return (p);
}
else
{
pc_free_scratch_blk(scratch);
return (0);
}
}
BOOLEAN pc_parsepath(byte *topath, byte *filename, byte *fileext, byte *path) /*__fn__*/
{
byte *pfile, *pto, *pfr, *p, *pslash, *pcolon;
int i;
/* Check the path length - compare the string length in bytes
against the max path in chars. This is correct since in
ASCII charlen==bytelen, in JIS charlen does not equal bytelen
but we don't want the string to be > the char len */
if (rtfs_cs_strlen_bytes(path) > EMAXPATH_CHARS)
return(FALSE);
pslash = pcolon = 0;
pfr = path;
pto = topath;
/* Copy input path to output keep note colon and backslash positions */
for (i = 0; CS_OP_IS_NOT_EOS(pfr); i++,CS_OP_INC_PTR(pfr),CS_OP_INC_PTR(pto))
{
CS_OP_CP_CHR(pto, pfr);
if (CS_OP_CMP_ASCII(pto,'\\'))
pslash = pto;
else if (CS_OP_CMP_ASCII(pto,':'))
{
if (i != 1) /* A: B: C: .. x: y: z: only */
return (FALSE);
pcolon = pto;
CS_OP_INC_PTR(pcolon); /* Look one past */
}
}
CS_OP_TERM_STRING(pto);
if (pslash)
{
pfile = pslash;
CS_OP_INC_PTR(pfile);
}
else if (pcolon)
pfile = pcolon;
else
pfile = topath;
if (!pc_ascii_fileparse(filename, fileext, pfile))
return (FALSE);
/* Terminate path:
If X:\ or \ leave slash on. Else zero it
*/
p = topath; /* Default */
if (!pslash)
{
if (pcolon) p = pcolon;
}
else /* if slash. and at 0 or right after colon leave else zero it */
{
p = pslash;
/* \ or A:\ */
if (p == topath || p == pcolon)
{
CS_OP_INC_PTR(p); /* (leave it in path) */
}
}
CS_OP_TERM_STRING(p);
return(TRUE);
}
/* Byte oriented */
BOOLEAN _illegal_lfn_char(byte ch)
{
RTFS_ARGSUSED_INT((int) ch);
return(FALSE);
}
static BOOLEAN pc_allspace(byte *p, int i) /* __fn__*/
{while (i--) if (*p++ != ' ') return (FALSE); return (TRUE); }
BOOLEAN pc_isdot(byte *fname, byte *fext) /* __fn__*/
{
return (BOOLEAN)((*fname == '.') &&
pc_allspace(fname+1,7) && pc_allspace(fext,3) );
}
BOOLEAN pc_isdotdot(byte *fname, byte *fext) /* __fn__*/
{
return (BOOLEAN)( (*fname == '.') && (*(fname+1) == '.') &&
pc_allspace(fname+2,6) && pc_allspace(fext,3) );
}
BOOLEAN pc_delete_lfn_info(DROBJ *pobj)
{
RTFS_ARGSUSED_PVOID((void *) pobj);
return(TRUE);
}
void pc_zero_lfn_info(FINODE *pdir)
{
RTFS_ARGSUSED_PVOID((void *) pdir);
}
BOOLEAN pc_get_lfn_filename(DROBJ *pobj, byte *path)
{
RTFS_ARGSUSED_PVOID((void *) pobj);
RTFS_ARGSUSED_PVOID((void *) path);
return(FALSE);
}
dword scan_for_bad_lfns(DROBJ *pmom, int delete_bad_lfn) /*__fn__*/
{
RTFS_ARGSUSED_PVOID((void *) pmom);
RTFS_ARGSUSED_INT(delete_bad_lfn);
return(0);
}
#endif /* #if (!VFAT) */

View File

@ -0,0 +1,235 @@
/*
* rttermin.c - Portable portion of terminal IO routines
*
* EBS - ERTFS
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
*
* Module description:
* This file contains terminal IO routines used by the sample programs
* and by routines that print diagnostics.
*
*
* The rest of the routines in this module are portable with the possible
* exception of these two routines:
*
* void rtfs_print_format_dir
* void rtfs_print_format_stat
*
* These routines may require porting if sprintf() is not available to you.
* They are called only by the test shell prgram (tstsh.c) and are used to create attractive
* formatted output for the DIR and STAT commands. They rely on sprintf to format the output
* to provide a system specific console output routine. A define is provided
* in this file named SYS_SUPPORTS_SPRINTF, if this is set to one the routines format the output
* using sprintf, otherwise they print a fixd string. If sprintf is not available to you set
* SYS_SUPPORTS_SPRINTF to zero.
*
*
* The following portable routines are also provided in this file.
*
* rtfs_print_string_1(int stringid,int flags)
* rtfs_print_string_2(int stringid,byte *pstr2, int flags)
*
* These two routines are used to print string values to the console. They are portable,
* relying on the routine rtfs_port_puts(() to provide a system specific console output routine.
* If no output is desired define the macros RTFS_PRINT_STRING_1 and RTFS_PRINT_STRING_2 as
* no-ops in portterm.h.
*
* rtfs_print_long_1
*
* This routine is used to print long integers values to the console. It relies on
* rtfs_port_puts(() to provide a system specific console output routine. If no output
* is desired define the macro RTFS_PRINT_LONG_1 as a no-op in portterm.h.
*
*
* rtfs_print_prompt_user() -
*
* This routine is called when the ERTFS demo programs and critical error handlr routine
* requires console input from the user. It takes as input a prompt id (this is a numeric
* handle to the prompt strings in the prompts string table prompt_table[]
* in portstr.c and the address of a buffer where to place the console
* input.
*
* This routine displays the prompt by calling rtfs_print_one_string() and then
* calls the target specific routine tm_gets_rtfs() to recieve the console
* input.
*
* Note: If in your system console input is not available you may still
* use the demo and test applications by modifying this routine so that
* it returns specific strings to simulate user input. The values to return
* must be relevant to the value of prompt_id. Here are several prompt_id
* values that should be responded to if no console input is available.
*
*
* UPROMPT_CRITERR - This is the prompt_id argument when a drive IO error
* occurs. You should return "A" in the return buffer. This will cause the
* IO operation to fail and return an error to the API.
*
* UPROMPT_TSTSH - If you returned "S" for UPROMPT_RTFSDEM1 then this
* prompt will be called after the test shell starts and repeatedly
* thereafter. Return strings for this prompt as if you were typing
* input to the command shell.
*
* For example a sequence of strings might fill.
*
* FILLFILE TEST.DAT MYPATTERN 100
* CAT TEST.DAT
* DELETE TEST.BAT
*
* If you do not wish to use the interactive test programs you need
* not implement this function.
* If sprintf is not available to you set SYS_SUPPORTS_SPRINTF to zero.
*/
#define SYS_SUPPORTS_SPRINTF 0
#include <rtfs.h>
#if (SYS_SUPPORTS_SPRINTF)
#include <stdio.h> /* For sprintf */
#endif
void rtfs_print_one_string(byte *pstr,int flags);
byte *pc_ltoa(dword num, byte *dest);
void rtfs_print_string_1(int stringid,int flags)
{
rtfs_print_one_string(rtfs_strtab_user_string(stringid),flags);
}
void rtfs_print_string_2(int stringid,byte *pstr2, int flags)
{
rtfs_print_string_1(stringid,0);
rtfs_print_one_string(pstr2,flags);
}
void rtfs_print_long_1(dword l,int flags)
{
byte buffer[16];
rtfs_print_one_string(pc_ltoa(l, buffer),flags);
}
void rtfs_print_prompt_user(int prompt_id, byte *buf)
{
byte inbuff[80];
rtfs_print_one_string(rtfs_strtab_user_prompt(prompt_id),0);
rtfs_port_tm_gets(inbuff);
#if (INCLUDE_CS_UNICODE)
map_ascii_to_unicode(buf, inbuff);
#else
rtfs_strcpy(buf, inbuff);
#endif
}
/* Porting may be required */
static byte *gotoeos(byte *p) { while(*p) p++; return(p);}
void rtfs_print_format_dir(byte *display_buffer, DSTAT *statobj)
{
#if (SYS_SUPPORTS_SPRINTF)
byte *dirstr;
byte *p;
int year;
if (statobj->fattribute & AVOLUME)
dirstr = (byte *)"<VOL>";
else if (statobj->fattribute & ADIRENT)
dirstr = (byte *)"<DIR>";
else
dirstr = (byte *)" ";
p = display_buffer;
*p = 0;
sprintf((char *)p,"%-8s.", (char *)&(statobj->fname[0]));
sprintf((char *)gotoeos(p),"%-3s", (char *)&(statobj->fext[0]));
// sprintf((char *)gotoeos(p)," %10lu ", statobj->fsize);
sprintf((char *)gotoeos(p)," %10u ", statobj->fsize);
sprintf((char *)gotoeos(p),"%5s", dirstr);
sprintf((char *)gotoeos(p)," %02d",(statobj->fdate >> 5 ) & 0xf); /* Month */
sprintf((char *)gotoeos(p),"-%02d",(statobj->fdate & 0x1f)); /* Day */
year = 80 +(statobj->fdate >> 9) & 0xff; /* Year */
if (year >= 100)
year -= 100;
sprintf((char *)gotoeos(p),"-%02d", year); /* Year */
sprintf((char *)gotoeos(p)," %02d",(statobj->ftime >> 11) & 0x1f); /* Hour */
sprintf((char *)gotoeos(p),":%02d",(statobj->ftime >> 5) & 0x3f); /* Minute */
/* if lfnmae is null we know that the first two bytes are both 0 */
if (statobj->lfname[0] || statobj->lfname[1])
{
/* For vfat systems display the attributes and the long file name
seperately. This is a trick since the attribute are ASCII and the
LFN is UNICODE. If we print seperately we will see them both correctly */
sprintf((char *)gotoeos(p), " - ");
rtfs_print_one_string(display_buffer, 0);
rtfs_print_one_string(statobj->lfname,PRFLG_NL);
}
else
rtfs_print_one_string(display_buffer,PRFLG_NL);
#else /* #if (SYS_SUPPORTS_SPRINTF) */
rtfs_print_one_string((byte*)"SPRINTF NOT SUPPORTED",PRFLG_NL);
#endif
}
/* Porting may be required */
void rtfs_print_format_stat(byte *display_buffer, ERTFS_STAT *st)
{
#if (SYS_SUPPORTS_SPRINTF)
byte *p;
p = display_buffer;
*p = 0;
sprintf((char *)gotoeos(p),"DRIVENO: %02d SIZE: %7ld", st->st_dev, st->st_size);
sprintf((char *)gotoeos(p)," DATE:%02d-%02d",(st->st_atime.date >> 5 ) & 0xf,/* Month */(st->st_atime.date & 0x1f)/* Day */);
sprintf((char *)gotoeos(p),"-%02d",80 +(st->st_atime.date >> 9) & 0xff); /* Year */
sprintf((char *)gotoeos(p)," TIME:%02d:%02d\n",(st->st_atime.time >> 11) & 0x1f,/* Hour */(st->st_atime.time >> 5) & 0x3f); /* Minute */
sprintf((char *)gotoeos(p),"OPTIMAL BLOCK SIZE: %7ld FILE size (BLOCKS): %7ld",st->st_blksize,st->st_blocks);
rtfs_print_one_string(display_buffer,PRFLG_NL);
#else /* #if (SYS_SUPPORTS_SPRINTF) */
rtfs_print_one_string((byte*)"SPRINTF NOT SUPPORTED",PRFLG_NL);
#endif
}
void rtfs_print_one_string(byte *pstr,int flags)
{
rtfs_port_puts(CS_OP_FORMAT_OUTPUT(pstr));
if (flags & PRFLG_NL)
rtfs_port_puts((byte *)"\n");
if (flags & PRFLG_CR)
rtfs_port_puts((byte *)"\r");
}
/* Portable */
byte *pc_ltoa(dword num, byte *dest) /*__fn__*/
{
byte buffer[33]; /* MAXINT can have 32 digits max, base 2 */
int digit;
byte *olddest = dest;
byte * p;
p = &(buffer[32]);
*p = '\0';
/* Convert num to a string going from dest[31] backwards */
/* Nasty little ItoA algorithm */
do
{
digit = (int) (num % 10);
*(--p) =
(byte)(digit<10 ? (byte)(digit + '0') : (byte)((digit-10) + 'a'));
num /= 10;
}
while (num);
/* Now put the converted string at the beginning of the buffer */
while((*dest++=*p++)!='\0');
return (olddest);
}

View File

@ -0,0 +1,121 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* rtutbyte.c - Character set independent string manipulation routines */
#include <twl.h>
#include <rtfs.h>
#include <rtfs_target_os.h>
/* Byte oriented */
byte *pc_strchr(byte *string, byte ch)
{
for(;string && *string!=0; string++)
{
if(ch == *string) return(string);
}
return(0);
}
BOOLEAN _illegal_alias_char(byte ch) /*__fn__*/
{
if (pc_strchr(rtfs_strtab_user_string(USTRING_SYS_BADALIAS), ch))
return(TRUE);
else
return(FALSE);
}
/* Byte oriented */
int rtfs_strcpy(byte * targ, byte * src) /*__fn__*/
{
int loop_cnt=0;
do
{
targ[loop_cnt] = src[loop_cnt];
} while(src[loop_cnt++]);
return loop_cnt;
}
/* Byte oriented */
/* compares 2 strings; returns 0 if they match */
int rtfs_strcmp(byte * s1, byte * s2) /*__fn__*/
{
int index=0;
while (s1[index] && s2[index] && s1[index] == s2[index])
{
index++;
}
if (!s1[index] && !s2[index]) return 0;
if (s1[index] < s2[index]) return -1;
else return 1;
}
/* Byte oriented */
int rtfs_strlen(byte * string) /*__fn__*/
{
int len=0;
while (string[len] != 0) len++;
return len;
}
/* Byte oriented string functions character set independent */
/****************************************************************************
COPYBUF - Copy one buffer to another
Description
Essentially strncpy. Copy size BYTES from from to to.
Returns
Nothing
****************************************************************************/
void copybuff(void *vto, void *vfrom, int size) /* __fn__*/
{
OSAPI_CPUCOPY8( vfrom, vto, size);
/* byte *to = (byte *) vto;
byte *from = (byte *) vfrom;
while (size--)
*to++ = *from++;*/
}
/******************************************************************************
PC_CPPAD - Copy one buffer to another and right fill with spaces
Description
Copy up to size characters from from to to. If less than size
characters are transferred before reaching \0 fill to with SPACE
characters until its length reaches size.
Note: to is NOT ! Null terminated.
ASCII character function only. Unicode not required
Returns
Nothing
*****************************************************************************/
/* Byte oriented */
void pc_cppad(byte *to, byte *from, int size) /* __fn__*/
{
rtfs_memset(to, ' ', size);
while (size--)
if (*from)
*to++ = *from++;
}
/* ******************************************************************** */
/* Byte oriented */
void rtfs_memset(void *pv, byte b, int n) /*__fn__*/
{ byte *p; p = (byte *) pv; while(n--) {*p++=b;} }
/* Byte oriented see rtfs_cs_strcat for char oriented */
byte * rtfs_strcat(byte * targ, byte * src) /*__fn__*/
{
int ret_val;
ret_val = rtfs_strlen(targ);
rtfs_strcpy(targ + ret_val, src);
return targ;
}

View File

@ -0,0 +1,304 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* RTUTIL.C - String manipulation and byte order conversion routines */
#include <rtfs.h>
/******************************************************************************
PC_PARSEDRIVE - Get a drive number from a path specifier
Description
Take a path specifier in path and extract the drive number from it.
If the second character in path is ':' then the first char is assumed
to be a drive specifier and 'A' is subtracted from it to give the
drive number. If the drive number is valid, driveno is updated and
a pointer to the text just beyond ':' is returned. Otherwise null
is returned.
If the second character in path is not ':' then the default drive number
is put in driveno and path is returned.
Unicode character function. Unicode is required
Returns
Returns NULL on a bad drive number otherwise a pointer to the first
character in the rest of the path specifier.
***************************************************************************/
/* Get the drive number form the path. Make sure one is provided */
/* and that it is valid. */
/* returns -1 if not valid otherwise return the driveno */
/* UNICODE/ASCI/JIS Version */
int pc_path_to_driveno(byte *path) /* __fn__*/
{
byte *p;
int drivenumber;
p = path;
if (CS_OP_IS_EOS(p))
return(-2);
CS_OP_INC_PTR(p);
if (CS_OP_CMP_ASCII(p,':'))
{
drivenumber = CS_OP_ASCII_INDEX(path,'A');
if (drivenumber < 0 || drivenumber > 25)
{
rtfs_set_errno(PEINVALIDDRIVEID); /* pc_path_to_driveno: invalid drive number */
drivenumber = -1;
}
}
else
drivenumber = -2;
return(drivenumber);
}
/* Parse drive part from a string - return -2 if no 'A:' -1 if A:
and not valid drive id */
int pc_parse_raw_drive(byte *path) /* __fn__*/
{
int dno;
dno = pc_path_to_driveno(path);
if (dno < 0 || !pc_validate_driveno(dno))
return (-1);
else
return(dno);
}
/* Extract drive no from D: or use defualt. return the rest of the string
or NULL if a bad drive no is requested */
byte *pc_parsedrive(int *driveno, byte *path) /* __fn__*/
{
byte *p = path;
int dno;
/* get drive no */
dno = pc_path_to_driveno(path);
if (dno == -2) /* D: Not specified. Use current default */
{
dno = pc_getdfltdrvno();
/* Make sure default drive number is valid */
if (!pc_validate_driveno(dno))
return(0);
}
else if (dno == -1) /* D: specified but bogus */
return(0);
else /* D: Specified. validate */
{
if (!pc_validate_driveno(dno))
return(0);
/* SKIP D and : */
CS_OP_INC_PTR(p);
CS_OP_INC_PTR(p);
}
*driveno = dno;
return (p);
}
/***************************************************************************
PC_MPATH - Build a path sppec from a filename and pathname
Description
Fill in to with a concatenation of path and filename. If path
does not end with a path separator, one will be placed between
path and filename.
TO will be null terminated.
Returns
A pointer to 'to'.
*****************************************************************************/
byte *pc_mpath(byte *to, byte *path, byte *filename) /* __fn__*/
{
byte *retval = to;
byte *p;
byte c[2];
c[0] = c[1] = 0;
p = path;
while (CS_OP_IS_NOT_EOS(p))
{
if (CS_OP_CMP_ASCII(p,' '))
break;
else
{
CS_OP_CP_CHR(c, p);
CS_OP_CP_CHR(to, p);
CS_OP_INC_PTR(p);
CS_OP_INC_PTR(to);
}
}
/* Put \\ on the end f not there already, but not if path was null */
if (p != path && !CS_OP_CMP_ASCII(c,'\\'))
{
CS_OP_ASSIGN_ASCII(to,'\\');
CS_OP_INC_PTR(to);
}
p = filename;
while (CS_OP_IS_NOT_EOS(p))
{
CS_OP_CP_CHR(to, p);
CS_OP_INC_PTR(p);
CS_OP_INC_PTR(to);
}
CS_OP_TERM_STRING(to);
return (retval);
}
/* Byte oriented - search comma separated list in set for filename */
BOOLEAN pc_search_csl(byte *set, byte *string)
{
byte *p;
if (!set || !string)
return(FALSE);
while(*set)
{
p = string;
while (*set && *p && (*set == *p))
{
set++;
p++;
}
if ((*set == 0 || *set == ',') && *p == 0)
return(TRUE);
while (*set && *set != ',') set++;
while (*set == ',') set++;
if (!(*set))
break;
}
return(FALSE);
}
BOOLEAN name_is_reserved(byte *filename) /* __fn__*/
{
return (
pc_search_csl(rtfs_strtab_user_string(USTRING_SYS_UCRESERVED_NAMES), filename) ||
pc_search_csl(rtfs_strtab_user_string(USTRING_SYS_LCRESERVED_NAMES), filename)
);
}
/* ******************************************************************** */
/* KEEP COMPILER HAPPY ROUTINES */
/* ******************************************************************** */
/* Used to keep the compiler happy */
void RTFS_ARGSUSED_PVOID(void * p) /*__fn__*/
{
p = p;
}
/* Used to keep the compiler happy */
void RTFS_ARGSUSED_INT(int i) /*__fn__*/
{
i = i;
}
/*****************************************************************************
PC_CNVRT - Convert intel byte order to native byte order.
Summary
#include <rtfs.h>
dword to_DWORD (from) Convert intel style 32 bit to native 32 bit
byte *from;
word to_WORD (from) Convert intel style 16 bit to native 16 bit
byte *from;
void fr_WORD (to,from) Convert native 16 bit to 16 bit intel
byte *to;
word from;
void fr_DWORD (to,from) Convert native 32 bit to 32 bit intel
byte *to;
dword from;
Description
This code is known to work on 68K and 808x machines. It has been left
as generic as possible. You may wish to hardwire it for your CPU/Code
generator to shave off a few bytes and microseconds, be careful though
the addresses are not guaranteed to be word aligned in fact to_WORD AND
fr_WORD's arguments are definately NOT word alligned when working on odd
number indeces in 12 bit fats. (see pc_faxx and pc_pfaxx().
Note: Optimize at your own peril, and after everything else is debugged.
Bit shift operators are used to convert intel ordered storage
to native. The host byte ordering should not matter.
Returns
Example:
See other sources.
*****************************************************************************
*/
/* Convert a 32 bit intel item to a portable 32 bit */
dword to_DWORD ( byte *from) /*__fn__*/
{
dword res;
#if (KS_LITTLE_ENDIAN && KS_LITTLE_ODD_PTR_OK)
res = ((dword) *((dword *)from));
#else
dword t;
t = ((dword) *(from + 3)) & 0xff;
res = (t << 24);
t = ((dword) *(from + 2)) & 0xff;
res |= (t << 16);
t = ((dword) *(from + 1)) & 0xff;
res |= (t << 8);
t = ((dword) *from) & 0xff;
res |= t;
#endif
return(res);
}
/* Convert a 16 bit intel item to a portable 16 bit */
word to_WORD ( byte *from) /*__fn__*/
{
word nres;
#if (KS_LITTLE_ENDIAN && KS_LITTLE_ODD_PTR_OK)
nres = ((word) *((word *)from));
#else
word t;
t = (word) (((word) *(from + 1)) & 0xff);
nres = (word) (t << 8);
t = (word) (((word) *from) & 0xff);
nres |= t;
#endif
return(nres);
}
/* Convert a portable 16 bit to a 16 bit intel item */
void fr_WORD ( byte *to, word from) /*__fn__*/
{
#if (KS_LITTLE_ENDIAN && KS_LITTLE_ODD_PTR_OK)
*((word *)to) = from;
#else
*to = (byte) (from & 0x00ff);
*(to + 1) = (byte) ((from >> 8) & 0x00ff);
#endif
}
/* Convert a portable 32 bit to a 32 bit intel item */
void fr_DWORD ( byte *to, dword from) /*__fn__*/
{
#if (KS_LITTLE_ENDIAN && KS_LITTLE_ODD_PTR_OK)
*((dword *)to) = from;
#else
*to = (byte) (from & 0xff);
*(to + 1) = (byte) ((from >> 8) & 0xff);
*(to + 2) = (byte) ((from >> 16) & 0xff);
*(to + 3) = (byte) ((from >> 24) & 0xff);
#endif
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,452 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright Peter Van Oudenaren , 1993
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* winhdisk.c - Simulate disk drive in a file on the host operating system
Summary
Description
Provides a device driver that reads and writes data to a file on the
host disk. This version of the driver creates a file named
HOSTDISK.DAT. This is targeted for hosts runnig Win95/NT but it can
be migrated to other hosts.
The format routine requires an initialized external variable
named:
extern word host_disk_size;
that tells it what size in blocks the file should be formatted to.
This driver is used primarilly for the MKROM utility but it is
fully functional and can be used for other purposes.
*/
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <sys\types.h>
#include <stdlib.h>
#include <string.h>
#include "rtfs.h"
#include "portconf.h" /* For included devices */
#if (INCLUDE_HOSTDISK)
/* hostdisk - Device driver that uses a DOS file as a virtual disk.
Description
Provides a virtual volume that resides in a (host) DOS file. This
volume can be used to prototype applications. It can also be used to build
the image of a rom disk which can then be accessed through the
rom disk driver. (see winmkrom.c)
To enable this driver set INCLUDE_HOSTDISK to 1 in portconf.h
*/
#define DEFAULT_HOST_DISK_SIZE 10240 /* 5M, FAT16 */
#define WINDOWS_HOSTDISK_PRINTF printf
#define WINDOWS_HOSTDISK_SPRINTF sprintf
void calculate_hcn(long n_blocks, PDEV_GEOMETRY pgeometry);
#define MAXSEGMENTS_PER_UNIT 16
#define MAX_UNITS 8
struct file64 {
char basename[255];
int num_segments;
HANDLE segment_handles[MAXSEGMENTS_PER_UNIT];
};
BOOLEAN flush_all_writes;
struct file64 sixty_four_bit_volumes[MAX_UNITS];
/* there are 0x200000 blokcs per gigabyte segment */
#define BLOCKS_PER_GIG 0x200000
int alloc_64bit_unit()
{
int i;
for (i = 0 ;i < MAX_UNITS; i++)
{
if (!sixty_four_bit_volumes[i].num_segments)
return(i);
}
return(-1);
}
int open_64bit_volume(int unit, byte *basename)
{
dword i;
char segment_file_name[256];
rtfs_strcpy((byte *) &(sixty_four_bit_volumes[unit].basename[0]), basename);
sixty_four_bit_volumes[unit].num_segments = 0;
for (i = 0;;i++)
{
WINDOWS_HOSTDISK_SPRINTF(segment_file_name,"%s_SEGMENT_%x.HDK",basename,i);
/* reopen the file segments */
sixty_four_bit_volumes[unit].segment_handles[i] =
CreateFile(TEXT(segment_file_name), // file to open
GENERIC_READ|GENERIC_WRITE,
0, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING,
NULL); // no attr. template
if (sixty_four_bit_volumes[unit].segment_handles[i] == INVALID_HANDLE_VALUE)
{
if (i == 0)
return(-1); /* Nothing there */
else
return(0);
}
else
sixty_four_bit_volumes[unit].num_segments += 1;
}
}
int create_64bit_volume(int unit, byte *basename, dword nblocks)
{
dword i;
char segment_file_name[256];
rtfs_strcpy((byte *)sixty_four_bit_volumes[unit].basename, (byte *)basename);
sixty_four_bit_volumes[unit].num_segments = (nblocks + BLOCKS_PER_GIG - 1)/BLOCKS_PER_GIG;
for (i = 0 ;i < (dword)sixty_four_bit_volumes[unit].num_segments; i++)
{
WINDOWS_HOSTDISK_SPRINTF(segment_file_name,"%s_SEGMENT_%x.HDK",basename,i);
sixty_four_bit_volumes[unit].segment_handles[i] =
CreateFile(TEXT(segment_file_name), // file to open
GENERIC_READ|GENERIC_WRITE,
0, // share for reading
NULL, // default security
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING,
NULL); // no attr. template
if (sixty_four_bit_volumes[unit].segment_handles[i] == INVALID_HANDLE_VALUE)
return(-1);
}
return(0);
}
void close_64bit_volume(int unit)
{
dword i;
for (i = 0 ;i < (dword)sixty_four_bit_volumes[unit].num_segments; i++)
CloseHandle(sixty_four_bit_volumes[unit].segment_handles[i]);
}
dword size_64bit_volume(int unit)
{
DWORD size, s;
if (!sixty_four_bit_volumes[unit].num_segments)
return(0);
size = (sixty_four_bit_volumes[unit].num_segments-1) * BLOCKS_PER_GIG;
s = SetFilePointer(sixty_four_bit_volumes[unit].segment_handles[sixty_four_bit_volumes[unit].num_segments-1],
0,0, FILE_END);
if (s == INVALID_SET_FILE_POINTER)
return(0);
size += s/512;
return((dword)size);
}
BOOLEAN hostdisk_io_64(int unit, dword block, void *buffer, word _count, BOOLEAN reading) /*__fn__*/
{
dword segment_number;
dword max_count,block_offset,count;
dword s,ltemp;
HANDLE hFile;
dword nbytes,nblocks;
byte *bbuffer;
bbuffer = (byte *) buffer;
count = (dword) _count;
// if (reading)
// printf("%d,", block);
//else
// printf("%d;", block);
//if (block < 2000)
// printf("\n");
while (count)
{
segment_number = block/BLOCKS_PER_GIG;
block_offset = block%BLOCKS_PER_GIG;
hFile = sixty_four_bit_volumes[unit].segment_handles[segment_number];
ltemp = (dword)(block_offset * 512);
s = SetFilePointer(hFile,
ltemp,0, FILE_BEGIN);
if (s == INVALID_SET_FILE_POINTER)
return(FALSE);
if (s != ltemp)
{
return(FALSE);
}
max_count = (BLOCKS_PER_GIG - block_offset);
if (count > max_count)
{
nblocks = max_count;
}
else
{
nblocks = (int) count;
}
block += (dword)nblocks;
count -= (dword)nblocks;
nbytes = nblocks*512;
if (reading)
{
dword nread;
if (!ReadFile(hFile,bbuffer,nbytes,&nread,0) || nread != nbytes)
return(FALSE);
}
else
{
dword nwrote;
if (!WriteFile(hFile,bbuffer,nbytes,&nwrote,0) || nwrote != nbytes)
return(FALSE);
}
bbuffer += nbytes;
}
return(TRUE);
}
/*
*
* Perform io to and from the hostdisk.
*
* If the reading flag is true copy data from the hostdisk (read).
* else copy to the hostdisk. (write).
*
*/
extern dword simulate_disk_latency;
dword decrement(dword l);
BOOLEAN hostdisk_io(int driveno, dword block, void *buffer, word count, BOOLEAN reading) /*__fn__*/
{
DDRIVE *pdr;
pdr = pc_drno_to_drive_struct(driveno);
if (!pdr)
return(FALSE);
return(hostdisk_io_64(pdr->logical_unit_number, block, buffer, count, reading));
}
/* file is already truncated, this just expands it to correct size */
static BOOLEAN hostdisk_make_file(int driveno, dword numblocks)
{
dword block;
BLKBUFF *buf;
BOOLEAN saved_flush_all_writes;
dword segment;
buf = pc_scratch_blk();
if (!buf)
return(FALSE);
rtfs_memset(buf->data, 0, 512);
block = 0;
/* seek to the end of each one gig segment of the file and write one block
(this will extend the file) */
saved_flush_all_writes = flush_all_writes;
flush_all_writes = TRUE; /* don't change.. experimental doesn't speed things up */
segment = 1;
while (block < numblocks-1)
{
dword ltemp;
ltemp = (segment * BLOCKS_PER_GIG) -1;
if (ltemp >= numblocks)
block = numblocks - 1;
else
block = ltemp;
if (!hostdisk_io(driveno, block, buf->data, 1, FALSE))
{
flush_all_writes = saved_flush_all_writes;
pc_free_scratch_blk(buf);
return(FALSE);
}
segment += 1;
}
flush_all_writes = saved_flush_all_writes;
pc_free_scratch_blk(buf);
return(TRUE);
}
int hostdisk_perform_device_ioctl(int driveno, int opcode, void * pargs)
{
DDRIVE *pdr;
pdr = pc_drno_to_drive_struct(driveno);
if (!pdr)
return (-1);
switch (opcode)
{
case DEVCTL_GET_GEOMETRY:
{
DEV_GEOMETRY gc;
rtfs_memset(&gc, 0, sizeof(gc));
if (pdr->logical_unit_number < 0)
return(-1);
/* Now set the geometry section */
/* This is a simple default condition. It is overriden by
code in MKROM when the hostdisk is being populated from
a disk sub-tree */
gc.dev_geometry_lbas = size_64bit_volume(pdr->logical_unit_number);
if (!gc.dev_geometry_lbas)
return(-1);
calculate_hcn(gc.dev_geometry_lbas, &gc);
copybuff(pargs, &gc, sizeof(gc));
return (0);
}
case DEVCTL_FORMAT:
{
/* Fill the file with zeroes */
dword l;
int fd, answer;
PDEV_GEOMETRY pgc;
byte buf[20];
pgc = (PDEV_GEOMETRY) pargs;
fd = pdr->logical_unit_number;
/* The file should be open already */
if (fd < 0)
return(-1);
l = (dword) pgc->dev_geometry_heads;
l = (dword) l * pgc->dev_geometry_cylinders;
l = (dword) l * pgc->dev_geometry_secptrack;
if (pgc->dev_geometry_lbas)
l = pgc->dev_geometry_lbas;
answer = '1';
do
{
if (answer != '1')
{
WINDOWS_HOSTDISK_PRINTF("I didn't understand your choice.\n");
}
/* Here we want to prompt the user so that he or she can
change the size of the hostdisk to several presets. */
WINDOWS_HOSTDISK_PRINTF("What size do you want the hostdisk '%s' to be?\n", (char*)pdr->device_name);
WINDOWS_HOSTDISK_PRINTF(" 1) FAT12 (4M)\n"); /* 8192 blocks */
WINDOWS_HOSTDISK_PRINTF(" 2) FAT16 (16M)\n"); /* 32768 blocks */
WINDOWS_HOSTDISK_PRINTF(" 3) FAT32 (1G)\n"); /* 2097152 blocks */
WINDOWS_HOSTDISK_PRINTF(" 4) Current (~%iM)\n", l/2048);
WINDOWS_HOSTDISK_PRINTF(" 5) Custom\n");
WINDOWS_HOSTDISK_PRINTF(" 6) FAT32 (16G)\n"); /* 33554432 blocks */
WINDOWS_HOSTDISK_PRINTF(": ");
rtfs_port_tm_gets(buf);
if (strlen((char*)buf) == 1)
answer = buf[0];
else
answer = 'X'; /* wrong */
}
while (answer < '1' || answer > '6');
if (answer == '5')
{
l = 1;
do
{
if (l == 0)
{
WINDOWS_HOSTDISK_PRINTF("I didn't understand your choice.\n");
}
WINDOWS_HOSTDISK_PRINTF("How many megabytes would you like the hostdisk to contain?\n");
WINDOWS_HOSTDISK_PRINTF(": ");
rtfs_port_tm_gets(buf);
l = atoi((char*)buf);
}
while (l == 0);
l *= 2048;
}
switch (answer)
{
case '1': l = 8192; break;
case '2': l = 32768; break;
case '3': l = 2097152; break;
case '6': l = 33554432; break;
case '4': /* fall through */
case '5': /* fall through */
default: /* shouldn't happen */
break;
}
WINDOWS_HOSTDISK_PRINTF("Making disk %iM.\n", l/2048);
close_64bit_volume(fd);
if (create_64bit_volume(fd, pdr->device_name, l) != 0)
return(-1);
if (!hostdisk_make_file(driveno, l))
return(-1);
/* Update caller's idea of geometry */
pgc->dev_geometry_lbas = l;
calculate_hcn(pgc->dev_geometry_lbas, pgc);
return(0);
}
break;
case DEVCTL_REPORT_REMOVE:
pdr->drive_flags &= ~DRIVE_FLAGS_INSERTED;
return(0);
case DEVCTL_CHECKSTATUS:
if (pdr->drive_flags & DRIVE_FLAGS_INSERTED)
return(DEVTEST_NOCHANGE);
else
{
pdr->drive_flags |= DRIVE_FLAGS_INSERTED;
return(DEVTEST_CHANGED);
}
case DEVCTL_WARMSTART:
{
flush_all_writes = TRUE; /* Enable flush after each write by default */
pdr->logical_unit_number = alloc_64bit_unit();
if (pdr->logical_unit_number < 0)
return(-1);
/* See if it already exists */
if (open_64bit_volume(pdr->logical_unit_number, pdr->device_name) < 0)
{
pdr->drive_flags |= DRIVE_FLAGS_FORMAT;
if (create_64bit_volume(pdr->logical_unit_number, pdr->device_name, DEFAULT_HOST_DISK_SIZE) != 0)
return(-1);
if (!hostdisk_make_file(driveno, DEFAULT_HOST_DISK_SIZE))
return(-1);
}
pdr->drive_flags |= (DRIVE_FLAGS_VALID|DRIVE_FLAGS_INSERTED|DRIVE_FLAGS_REMOVABLE);
return(0);
}
/* Fall through */
case DEVCTL_POWER_RESTORE:
/* Fall through */
case DEVCTL_POWER_LOSS:
/* Fall through */
default:
break;
}
return(0);
}
#endif /* (INCLUDE_HOSTDISK) */

View File

@ -0,0 +1,661 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc, 1993-2002
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/*
*****************************************************************************
MKROM.C - Create a rom disk from an MS-DOS sudirectory
Summary
MKROM subdir
Description
Traverses the subdirectory "subdir" and make an exact image of that
subdirectory in a file named romdisk.dat. The file romdisk.dat
can be placed directly into a rom and accessed via the rom disk
device driver.
Example:
mkrom c:\dev\romimage
*****************************************************************************
*/
#include <rtfs.h>
#include <portconf.h> /* For included devices */
#if (INCLUDE_HOSTDISK)
/* Host disk is required to use the MKROM utility */
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <conio.h>
#include <dos.h>
#include <io.h>
#include <direct.h>
#include <string.h>
/* Write your own routines to create these. */
#define BIN_VOL_LABEL 0x12345678L
#define STR_VOL_LABEL "VOLUMELABE" /* 11 chars max */
typedef struct _finddata_t statobj_t;
#define MKROM_MAX_PATH_LEN 260
#define FIXED_BLOCKS 2 /* Block zero and 1 reserved + 2 fudge */
#define CLUSTER_FUDGE 2
void drno_to_string(byte *pname, int drno); /* See rtfsinit.c */
int traverse(byte *name, int level);
int copy_files(byte *name, int level);
int make_directories(byte *name, int level);
byte imagepath[MKROM_MAX_PATH_LEN];
int root_path_len = 0; /* remember how much of each path is the root */
long required_volume_size = 0; /* Derived in calculate_format_parms */
int n_subdirectories = 0; /* Total number of subdirectories */
int n_files = 0; /* Total number of files */
int n_root_entries = 0; /* Entries in the root */
int n_sub_entries = 0; /* Entries in subdirectories */
long file_cluster_count[33]; /* Count of files with */
long subdir_cluster_count[33]; /* Count of subdirs with */
BOOLEAN calculate_format_parms(DDRIVE *pdr, PDEV_GEOMETRY pgeometry);
BOOLEAN hostdisk_io(int driveno, dword block, void *buffer, word count, BOOLEAN reading);
int domkhostdisk(int agc, byte **agv) /*__fn__*/
{
int j,driveno;
byte drname[8];
byte inbuff[80];
DDRIVE *pdr;
DEV_GEOMETRY geometry;
if (agc != 1)
{
printf("Usage MKHOSTDISK path\n");
return(0);
}
else /* Get the path */
{
#if (INCLUDE_CS_UNICODE)
/* Convert unicode string to ASCII fro accessing win9x file system */
map_unicode_to_ascii((byte *)&imagepath[0], (byte *) *agv);
#else
strcpy((char *)&imagepath[0],(char *)*agv);
#endif
}
n_subdirectories = 0;
n_files = 0;
n_root_entries = 0;
n_sub_entries = 0;
for (j = 0; j< 33; j++)
{
file_cluster_count[j] = 0;
subdir_cluster_count[j] = 0;
}
driveno = -1;
pdr= prtfs_cfg->mem_drives_structures;
for (j = 0; j < prtfs_cfg->cfg_NDRIVES; j++, pdr++)
{
if (pdr->dev_table_drive_io == hostdisk_io)
{
drno_to_string(drname, pdr->driveno);
driveno = pdr->driveno;
break;
}
}
if (driveno == -1 || !(pdr->drive_flags&DRIVE_FLAGS_VALID) )
{
printf("Fail: No host disk device is available\n");
return 0;
}
/* Prepare to format the hostdisk */
/* check media and clear change conditions */
if (!check_drive_number_present(driveno))
{
printf("Check media failed can't format hostdisk.\n");
return(0);
}
/* Get media parms, but override in next section */
if (!pc_get_media_parms(drname, &geometry))
{
printf("Drive %s get media failed.\n", drname);
return(0);
}
/* How long is the path to the root.. We'll strip this off of the
front of the strings when we build RTFS files in the file image */
root_path_len = rtfs_strlen(imagepath);
printf("Populating host disk at %s from native subdirectory %s\n", drname, imagepath);
traverse(imagepath, 0);
if (!calculate_format_parms(pdr, &geometry))
return(0);
printf("\n");
printf("\n");
printf("Host Disk Image Will Contain\n");
printf("\t %10.10d Files\n", n_files);
printf("\t %10.10d Subdirectories\n", n_subdirectories);
printf("\t requiring %10.10ld blocks\n", required_volume_size);
printf("\n");
printf("\n");
printf("Type Y to create the Host Disk Image, any other key to exit\n");
gets((char *)inbuff);
printf("\n");
if (inbuff[0] != 'Y' && inbuff[0] != 'y')
return (0);
if (!pc_format_media(drname, &geometry))
{
printf("Media format failed\n");
return(0);
}
if (!pc_format_volume(drname, &geometry))
{
printf("Format volume failed\n");
return(0);
}
pc_set_default_drive(drname);
printf("Creating subdirectories\n");
if (make_directories(imagepath, 0) < 0)
{
printf("Can not create subdirectories \n");
return(0);
}
printf("Copying files\n");
if (copy_files(imagepath, 0) < 0)
{
printf("Can not copy files\n");
printf("Try adding extra blocks to the comand line\n");
printf("Increment extra blocks untill it works\n");
printf("For example: mkrom \\romdata 4\n");
return(0);
}
printf("Host disk at %s is populated from native subdirectory %s\n", drname, imagepath);
return(0);
}
/* Calculate number of clusters needed given cluster size */
long calc_n_clusters(long clsize)
{
long n_cl = 0;
int i;
i = (int)clsize;
n_cl += file_cluster_count[i];
n_cl += subdir_cluster_count[i];
return(n_cl);
}
long calc_best_cluster_size(void)
{
long min_clusters;
long best_size;
long try_size;
long l;
best_size = 1;
min_clusters = calc_n_clusters(best_size);
for (try_size = 2; try_size <= 32; try_size *= 2)
{
l = calc_n_clusters(try_size);
/* Take the minimum but limit it so we don't generate huge cluster
sizes on small volumes. We need at least a block anyway */
if (l < min_clusters && min_clusters > 256)
{
min_clusters = l;
best_size = try_size;
}
}
return(best_size);
}
void calculate_hcn(long n_blocks, PDEV_GEOMETRY pgeometry)
{
long cylinders; /*- Must be < 1024 */
long heads; /*- Must be < 256 */
long secptrack; /*- Must be < 64 */
long residual_h;
long residual_s;
secptrack = 1;
while (n_blocks/secptrack > (1023L*255L))
secptrack += 1;
residual_h = (n_blocks+secptrack-1)/secptrack;
heads = 1;
while (residual_h/heads > 1023L)
heads += 1;
residual_s = (residual_h+heads-1)/heads;
cylinders = residual_s;
pgeometry->dev_geometry_cylinders = (dword) cylinders;
pgeometry->dev_geometry_heads = (int) heads;
pgeometry->dev_geometry_secptrack = (int) secptrack;
printf("n_blocks == %ld hcn == %ld\n", n_blocks, (cylinders*heads*secptrack) );
}
BOOLEAN calculate_format_parms(DDRIVE *pdr, PDEV_GEOMETRY pgeometry)
{
long sec_p_alloc;
long n_clusters;
long nibs_p_cluster;
long nibs_p_fat;
long blocks_p_fat;
long blocks_p_root;
long blocks_p_heap;
long blocks_p_volume;
rtfs_memset(pgeometry, 0, sizeof(*pgeometry));
sec_p_alloc = calc_best_cluster_size();
n_clusters = calc_n_clusters(sec_p_alloc);
n_clusters += CLUSTER_FUDGE;
blocks_p_heap = n_clusters * sec_p_alloc;
if (n_clusters > 0xffffL)
{
nibs_p_cluster = 8;
printf("Fat32 not supported for this function\n");
return(FALSE);
}
else if (n_clusters < 4087)
nibs_p_cluster = 3;
else
nibs_p_cluster = 4;
nibs_p_fat = nibs_p_cluster * (n_clusters+2); /* Plus 2 for two reserved entries */
blocks_p_fat = (nibs_p_fat+1023)/1024;
blocks_p_root = (n_root_entries + 15)/16;
n_root_entries = blocks_p_root*16;
blocks_p_volume = FIXED_BLOCKS + blocks_p_heap + blocks_p_root + (2*blocks_p_fat);
required_volume_size = blocks_p_volume;
calculate_hcn(blocks_p_volume, pgeometry);
rtfs_strcpy(&pgeometry->fmt.oemname[0],
rtfs_strtab_user_string(USTRING_SYS_OEMNAME) );
pgeometry->fmt.physical_drive_no = (byte) pdr->driveno;
pgeometry->fmt.binary_volume_label = BIN_VOL_LABEL;
rtfs_strcpy(pgeometry->fmt.text_volume_label,
rtfs_strtab_user_string(USTRING_SYS_VOLUME_LABEL) );
pgeometry->fmt.secpalloc = (byte) sec_p_alloc;
pgeometry->fmt.numfats = (byte) 2;
pgeometry->fmt.secptrk = (word) pgeometry->dev_geometry_secptrack;
pgeometry->fmt.numhead = (word) pgeometry->dev_geometry_heads;
pgeometry->fmt.numcyl = (word) pgeometry->dev_geometry_cylinders;
pgeometry->fmt.mediadesc = (byte) 0xF8;
pgeometry->fmt.secreserved = (word) 1;
pgeometry->fmt.numhide = 0;
pgeometry->fmt.secpfat = (word) blocks_p_fat;
pgeometry->fmt.numroot = (word) n_root_entries;
pgeometry->fmt.mediadesc = (byte) 0xF8;
pgeometry->fmt_parms_valid = TRUE;
return(TRUE);
}
int traverse(byte *name, int level)
{
statobj_t statobj;
byte path[MKROM_MAX_PATH_LEN];
byte *pkind;
long n_blocks;
long n_clusters;
int i;
int entries;
long dd;
for (i = 0; i < level; i++)
printf(" ");
printf("Processing directory %s\n", name);
strcpy((char *)path, (char *)name);
strcat((char *)path, "\\*.*");
/* Print them all */
if ((dd = _findfirst((char *)path, &statobj)) < 0)
{
return(0);
}
else
{
entries = 0;
do
{
entries++;
#if (VFAT) /* Small piece of compile time VFAT vs's NONVFAT code */
entries += (rtfs_strlen((byte *)statobj.name) + 12)/13; /* Account for lfn data */
#endif
if ( (strcmp(".", statobj.name)==0) ||
(strcmp("..", statobj.name)==0) )
pkind = (byte *)"d";
else if( statobj.attrib & _A_SUBDIR )
{
n_subdirectories += 1;
pkind = (byte *)"d";
}
else
{
n_files += 1;
n_blocks = (statobj.size+511)/512;
for (i = 1; i <= 32; i *= 2)
{
n_clusters = (n_blocks+i-1)/i;
file_cluster_count[i] += n_clusters;
}
pkind = (byte *)"-";
}
/* matches unix output. */
for (i = 0; i < level; i++)
printf(" ");
printf("%s %8ld %-12s\r", pkind, statobj.size,statobj.name);
} while (_findnext(dd, &statobj) == 0);
_findclose(dd);
}
/* Track root entries and blocks used by dir ents */
if (level == 0)
n_root_entries += entries;
else
{
n_sub_entries += entries;
n_blocks = (entries + 15)/16; /* Blocks occupied */
for (i = 1; i <= 32; i *= 2)
{
n_clusters = (n_blocks+i-1)/i;
subdir_cluster_count[i] += n_clusters;
}
}
/* Now traverse */
if ((dd=_findfirst((char *)path, &statobj))<0)
{
return(0);
}
else
{
do
{
if( statobj.attrib & _A_SUBDIR )
{
if ( (strcmp(".", statobj.name)!=0) &&
(strcmp("..", statobj.name)!=0) )
{
strcpy((char *)path, (char *)name);
strcat((char *)path, "\\");
strcat((char *)path, statobj.name);
traverse(path, level+1);
strcpy((char *)path, (char *)name);
strcat((char *)path, "\\*.*");
}
}
} while (_findnext(dd, &statobj) == 0);
_findclose(dd);
}
return(1);
}
int make_directories(byte *name, int level)
{
statobj_t statobj;
byte path[MKROM_MAX_PATH_LEN];
byte *p;
long dd;
#if (INCLUDE_CS_UNICODE || !VFAT)
byte newpath[MKROM_MAX_PATH_LEN];
#endif
if (level)
{
p = name + root_path_len;
#if (!VFAT) /* Small piece of compile time VFAT vs's NONVFAT code */
/* USE upper case for 8.3 */
pc_str2upper(newpath, p);
p = newpath;
#endif
printf("Creating directory %s\n", p);
#if (INCLUDE_CS_UNICODE)
map_ascii_to_unicode(newpath, p);
if (!pc_mkdir(newpath) )
#else
if (!pc_mkdir(p) )
#endif
{
printf("Failed creating directory %s\n", p);
return(-1);
}
}
strcpy((char *)path, (char *)name);
strcat((char *)path, (char *)"\\*.*");
if ((dd = _findfirst((char *)path, &statobj))<0)
{
return(0);
}
else
{
do
{
if( statobj.attrib & _A_SUBDIR )
{
if ( (strcmp(".", statobj.name)!=0) &&
(strcmp("..", statobj.name)!=0) )
{
strcpy((char *)path, (char *)name);
strcat((char *)path, (char *)"\\");
strcat((char *)path, (char *)statobj.name);
if (make_directories(path, level+1) != 0)
return(-1);
strcpy((char *)path, (char *)name);
strcat((char *)path, (char *)"\\*.*");
}
}
} while (_findnext(dd, &statobj) == 0);
_findclose(dd);
}
return(0);
}
/* Copy Native file *from to dos path *to */
BOOLEAN copy_one_file(byte *path, byte *filename) /* __fn__ */
{
static byte dos_path[MKROM_MAX_PATH_LEN];
static byte buf[1024];
PCFD fd;
int res,res2;
int fi;
BOOLEAN retval = TRUE;
byte *to;
#if (INCLUDE_CS_UNICODE || !VFAT)
byte newpath[MKROM_MAX_PATH_LEN];
#endif
strcpy((char *)dos_path, (char *)path);
strcat((char *)dos_path, (char *)"\\");
strcat((char *)dos_path, (char *)filename);
/* Strip the leading path when we go to rtfs */
to = &dos_path[root_path_len];
#if (!VFAT)/* Small piece of compile time VFAT vs's NONVFAT code */
/* USE upper case for 8.3 */
pc_str2upper(newpath, to);
to = newpath;
#endif
printf("Copying %s to %s\n", dos_path, to);
if ( (fi = open((char *)dos_path,O_RDONLY|O_BINARY)) < 0) /* Open binary read */
{
printf("Cant open %s\n",dos_path);
return (FALSE);
}
else
{
/* Open the PC disk file for write */
#if (INCLUDE_CS_UNICODE)
map_ascii_to_unicode(newpath, to);
if ((fd = po_open(newpath,(PO_BINARY|PO_RDWR|PO_CREAT|PO_TRUNC),
(PS_IWRITE | PS_IREAD) ) ) < 0)
#else
if ((fd = po_open(to,(PO_BINARY|PO_RDWR|PO_CREAT|PO_TRUNC),
(PS_IWRITE | PS_IREAD) ) ) < 0)
#endif
{
printf("Cant open %s error = %i\n",to, -1);
return (FALSE);
}
else
{
/* Read from host until EOF */
while ( (res = read(fi,&buf[0],1024)) > 0)
{
/* Put to the drive */
if ( (res2 = (int)po_write(fd,buf,(word)res)) != res)
{
printf("Cant write %x %x \n",res,res2);
retval = FALSE;
break;
}
}
/* Close the pc file flush buffers & and de-allocate structure */
po_close(fd);
/* close the native file */
/* PORT-ME */
close(fi);
return (retval);
}
}
}
int copy_files(byte *name, int level)
{
statobj_t statobj;
byte path[MKROM_MAX_PATH_LEN];
long dd;
printf("Processing directory %s\n", name);
strcpy((char *)path, (char *)name);
strcat((char *)path, (char *)"\\*.*");
if ((dd = _findfirst((char *)path, &statobj))>=0)
{
do
{
if(!(statobj.attrib & (_A_SUBDIR) ))
{
if (!copy_one_file(name, (byte *)statobj.name))
return(-1);
}
} while (_findnext(dd, &statobj) == 0);
_findclose(dd);
}
/* Now traverse */
if ((dd = _findfirst((char *)path, &statobj)) < 0)
{
return(0);
}
else
{
do
{
if( statobj.attrib & _A_SUBDIR )
{
if ( (strcmp(".", statobj.name)!=0) &&
(strcmp("..", statobj.name)!=0) )
{
strcpy((char *)path, (char *)name);
strcat((char *)path, (char *)"\\");
strcat((char *)path, statobj.name);
if (copy_files((byte *)path, level+1) < 0)
return(-1);
strcpy((char *)path, (char *)name);
strcat((char *)path, (char *)"\\*.*");
}
}
} while (_findnext(dd, &statobj) == 0);
_findclose(dd);
}
return(0);
}
int domkrom(int agc, byte **agv) /*__fn__*/
{
FILE *infile, *outc;
int c, linecount=0;
long count=0;
printf("\n MKROM - Creating drromdsk.h from hostdisk.dat\n");
RTFS_ARGSUSED_INT(agc);
RTFS_ARGSUSED_PVOID((void *) agv);
infile = fopen("hostdisk.dat", "rb");
if (infile == NULL)
{
printf("MKROM could not open hostdisk.dat\n");
return(0);
}
outc = fopen("drromdsk.h", "wt");
if (outc == NULL)
{
printf("MKROM could not open drromdsk.h\n");
fclose(infile);
return(0);
}
fprintf(outc, "/* %s */\n", "drromdsk.h");
fprintf(outc, "/* Automatically Created from %s using MKROM */\n", "hostdisk.dat");
fprintf(outc, "\nbyte KS_FAR %s[]=\n{\n", "romdisk_data");
/* write the C file */
while ((c=fgetc(infile)) != EOF)
{
if (linecount < 16)
{
fprintf(outc, " 0x%02x, ",c);
linecount++;
}
else
{
fprintf(outc, " 0x%02x,\n", c);
linecount=0;
}
count++;
}
fprintf(outc, "};\n");
fclose(infile);
fclose(outc);
return(0);
}
#endif /* (INCLUDE_HOSTDISK) */

View File

@ -0,0 +1,378 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1996
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* WINSPLSH.C - Introductory text and display engine for windows based demo */
#include <rtfs.h>
#include <portconf.h> /* For included devices */
#if (INCLUDE_HOSTDISK)
#include <stdio.h>
#include <stdlib.h>
void display_introduction(void);
void display_text(char * readme[])
{
int nlines;
int current_line;
int break_line;
int i,j;
byte buf[32];
#define LINES_PER_PAGE 20
/* Count number of lines */
nlines = 0;
while (readme[nlines])
nlines++;
current_line = 0;
for (;;)
{
j = current_line;
break_line = 0;
for (i = 0; i < LINES_PER_PAGE; i++)
{
if (readme[j])
{
if (*readme[j] == '.')/* CDFS */
break_line = j;
if (break_line)
printf("\n");
else
printf("%s\n", readme[j++]);
}
else
printf("\n");
}
printf(" \n");
/* "<return> for next, (P)<return> for Previous, (Q)<return> to run demo" */
rtfs_print_prompt_user(UPROMPT_WINSPLSH, buf);
if (CS_OP_CMP_ASCII(buf,'Q') || CS_OP_CMP_ASCII(buf,'q'))
break;
if (CS_OP_CMP_ASCII(buf,'P') || CS_OP_CMP_ASCII(buf,'p'))
{
current_line -= LINES_PER_PAGE;
if (current_line < 0)
current_line = 0;
}
else
{
if (break_line)
current_line = break_line + 1;
else
{
if ((current_line + LINES_PER_PAGE) <= nlines)
current_line += LINES_PER_PAGE;
}
}
}
}
char * rtfsdemo_introduction[] = {
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ==================================================",
" = Thank you for your interest in ERTFS. =",
" = =",
" = Please Page through the following introduction =",
" = At any time press Q to run the Demo. =",
" = == =",
" = The DEMO is safe to execute on your workstation=",
" = it uses only ram disks, rom disks and a simple =",
" = user file. It does NOT bypass windows to access=",
" = your hard disk directly =",
" ==================================================",
" ",
" ",
" ",
" ",
" ERTFS is a DOS and WINDOWS compatible file system library for ",
" embedded systems. ERTFS supports all versions of DOS, 12, 16 ",
" and 32 bit File Allocation Tables. ERFTS even supports WIN95 long ",
" file names, and large FAT32 partions of 80 gigabytes and more. ",
" ",
" ",
" ERTFS has provided high performance reliable solutions for demanding ",
" embedded Applications since 1988. It is used in hundreds of applications",
" including medical devices, avionics, military, set-tops, digital cameras",
" scientific instruments and many other devices. ",
" ",
" ERTFS is portable, easy to use and has a familiar file system interface ",
" but it is also a high performance disk subsystem that has been used in ",
" many demanding and sophisticated applications including demanding video ",
" audio and scientific applications.",
" ",
/* ". page break", */
" Advanced Features of ERTFS",
" ",
" . Callable check disk . Callable format and fdisk functions",
" . Contiguous Files . Automounts removable media ",
" . Direct device driver access . Query file extents",
" . User control over block placement. Mountable device drivers",
" . Extensive device support . Multiple partition support",
" . Supports very large volumes . CD ISO 9660 supported (optional)",
" . Includes PCMCIA Support . Clean RTOS and CPU porting layer",
" . User placement of file extents . Complete access to free space ",
" . Full Posix style API",
" ",
" Devices Supported by ERTFS",
" ",
" . ATA hard drives. Drives as large as 80 GigaBytes have been tested",
" . Linear flash. FTL is provided with ram emulation of flash",
" . PCMCIA Ram cards . RAM disk . Floppy disk . Smart Media ",
" . PCMCIA ATA disks and compact flash",
" . ROM disk, includes tool to create a rom disk image from MS-Windows ",
" . Table driven device interface supports user supplied device drivers,",
" user devices may be removable and may have partitions. ERTFS handles",
" all devices the same way.",
" ",
" ",
/* ". page break", */
" API Calls provided with ERTFS",
" ",
" -- Initilaization --",
" pc_ertfs_init() - mount devices from device driver table. ",
" ",
" -- File Operations --",
" po_open - Open a file.",
" po_read - Read bytes from a file.",
" po_write - Write Bytes to a file.",
" po_lseek - Move the file pointer.",
" po_close - Close a file and flush the file allocation table.",
" po_flush - Flush an open file",
" po_trunc - Truncate an open file",
" pc_mv - Rename a file.",
" pc_unlink - Delete a file.",
" po_chsize - Truncate or extend an open file.",
" pc_set_attributes - Set File Attributes ",
" pc_get_attributes - Get File Attributes ",
" pc_stat - Obtain statistics on a path.",
" pc_fstat - Obtain statistics on an open file",
" ",
" -- Directory Operations --",
" pc_mkdir - Create a directory.",
" pc_rmdir - Delete a directory.",
" pc_deltree - Delete an entire directory tree.",
" pc_gfirst - Get stats on the first file to match a pattern.",
" pc_gnext - Get stats on the next file to match a pattern.",
" pc_gdone - Free resources used by pc_gfirst/pc_gnext.",
" ",
" -- Miscelaneous Functions -- ",
" chkdsk - check file system integrity",
" pc_fat_size - Calculate blocks required for a volume's FAT",
" pc_free - Calculate and return the free space on a disk.",
" pc_set_default_drive - Set the default drive number.",
" pc_set_cwd - Set the current working directory.",
" pc_isdir - Determine if a path is a directory.",
" pc_isvol - Determine if a path is a volume",
" pc_pwd - Get string representation of current working dir.",
" pc_set_pwd - Set current working directory for this user",
" pc_setdfltfrvno - Set the current default drive for this user.",
" pc_enumerate - Select all directory entries that match rules and",
" call a user callback on each. (like the unix print",
" utility)",
" ",
" ",
" -- Advanced High performance Functions -- ",
" pc_cluster_size - Get the cluster size of a drive",
" pc_find_contig_clusters",
" - Find contiguous clusters in the freelist",
" pc_get_free_list - Get a list free cluster segments on the drive",
" pc_raw_write - Write blocks directly to a disk",
" pc_raw_read - Read blocks directly from a disk",
" pc_get_file_extents- Get the list of block segments that make up a file",
" po_extend_file - Extend a file with contiguous clusters. Also ",
" supports direct assignment blocks to a file",
" ",
" -- Formatting routines -- ",
" pc_get_media_parms - Get media parameters.",
" pc_format_media - Device level format",
" pc_partition_media - Write partition table",
" pc_format_volume - Format a volume",
" ",
/* ". page break", */
" Sample utilities provided with ERTFS",
" ",
" Test Shell - An interactive test shell is provided. This test",
" shell is an excellent demontration of how to use the API as well ",
" as a useful tool itself. The console IO needs of the test shell are ",
" minimal and can be accomplished from a simple RS232 connection.",
" ",
" Regression Test - This program tests the ERTFS API and is a good test ",
" prgram for checking out ports of the library to new environments.",
" ",
" Check disk - This is a utility and callable function that performs",
" the check disk functionality.",
" ",
/* ". page break", */
" This demo program",
" ",
" ",
" This demo program is built with the ERTFS library. It contains the ",
" interactive test shell, the regression test module, and the check",
" disk utility. ",
" The demo runs from inside a \"DOS Box\" and it is safe to run it on your ",
" workstation. All devices are simulated in ram or in simple disk files ",
" in the current directory.",
" ",
/* ". page break", */
" ",
" When the program starts you will see the following diagnostics.",
" ",
"ERTFS Device List",
"=================",
"Drive: A Device: HOST DISK HOSTDISK.DAT:256K",
"Drive: B Device: STATIC RAM DISK",
"Drive: C Device: FLASH DISK",
"Drive: D Device: STATIC ROM DISK",
" ",
"Notes:",
"1. Host disk is a 256 K disk volume simulated in a disk file",
"2. Flash Disk is the FTL driver running on a flsh disk simulation in ram",
"3. The Static Rom disk was initialized with the MKROM tool.",
" ",
" = ",
" ",
/* ". page break", */
" ",
"The program will then print:",
" ",
"Autoformatting RAM Devices",
"==========================",
"Autoformatting Drive: A Device: HOST DISK HOSTDISK.DAT:256K",
"Autoformatting Drive: B Device: STATIC RAM DISK",
"Autoformatting Drive: C Device: FLASH DISK",
" = ",
"The devices are autoformatted at initialization, an attribute in the ",
"device record tells ERTFS to format the device. Other attributes",
"flag the device as removable and partitioned.",
" ",
"Note that the ROM disk is not autoformatted at initialization time.",
" ",
" ",
/* ". page break", */
" ",
"The program next enters the test shell.",
"The test shell is like the DOS or Unix command shell. ",
"The Static ROM disk D: is already populated",
"so running informations commands on D: is a the most interesting",
"until you use the shell to populate the other volumes.",
" ",
"The test shell commands are listed on the next page.",
" ",
/* ". page break", */
" ",
"These commands are avaliable from the test shell: ",
"HELP",
"CAT PATH",
"CHSIZE FILENAME NEWSIZE",
"CD PATH or CD to display PWD ",
"CHKDSK D: <0,1> 1 is write lost chains",
"CLOSE FDNO",
"COPY PATH PATH",
"DELETE PATH",
"DELTREE PATH",
"DEVINFO (Display Device Information)",
"DIFF PATH PATH",
"DIR PATH",
"DSKSEL D:",
"ECHO: [args]",
"EJECT (ejects LS-120)",
"FILLFILE PATH PATTERN NTIMES",
"FORMAT (routine will prompt for arguments)",
/* ". page break", */
"GETATTR FILE",
"HELP:",
"LSTOPEN (lists all open file decscriptors) ",
"MKDIR PATH",
"PCMCIAINT (Force a PCMCIA mgmt Interrupt)",
"QUIT",
"READ FDNO",
"RENAME PATH NEWNAME",
"RMDIR PATH",
"RNDOP PATH RECLEN",
"SEEK FDNO RECORD",
"SETATTR D:PATH RDONLY|HIDDEN|SYSTEM|ARCHIVE|NORMAL",
"STAT PATH",
"WRITE FDNO QUOTED DATA",
"REGRESSTEST D: (perform regression test)",
">: ",
" ",
" ",
" ",
" ",
" Notes about using the demo test shell. ",
" 1. Since the D: drive is populated running chkdsk on it is most",
" interesting. ",
" 2. To create a file on one of the other drives (A: to C:) ",
" use fillfile, rndop or copy files from the rom disk ",
" Example: ",
" >: FILLFILE mydatafile.dat \"This is my story\" 100 ",
" >: CAT mydatafile.dat ",
" Will produce a list of 100 lines of \"This is my story\"",
" Example: ",
" >: rndop myfile.dat 100",
" >: lstopen",
" 0: myfile.dat",
" >: dir *.*",
" myfile .dat 0 03-28-88 19:37 ",
" 1 File(s) 252 KBytes free",
" >: write 0 \"this is record zero\"",
" >: write 0 \"this is record one\"",
" >: write 0 \"this is record two\"",
" >: seek 0 1",
" >: read 0",
" this is record one :",
" >: close 0",
" >: dir *.*",
" myfile .dat 300 03-28-88 19:37 ",
" 1 File(s) 252 KBytes free",
" >: copy myfile.dat COPY.DAT",
" >: dir *.*",
" myfile .dat 300 03-28-88 19:37 ",
" COPY .DAT 300 03-28-88 19:37 ",
" 2 File(s) 251 KBytes free",
" >:",
" ",
" ",
"Thanks again for your interest in ERTFS.",
0,
};
void display_introduction(void)
{
display_text(rtfsdemo_introduction);
}
void winexit(void)
{
printf("========================================\n");
printf("========================================\n");
printf("========================================\n");
printf("Thanks for trying ERTFS. Please Call If \n");
printf(" You Have Any Questions \n");
printf("========================================\n");
printf("========================================\n");
printf("========================================\n");
printf("========================================\n");
exit(0);
}
#endif /* USEWIN32 - End readme display package */

View File

@ -0,0 +1,34 @@
#! make -f
#----------------------------------------------------------------------------
# Project: TwlSDK - libraries - spi
# File: Makefile
#
# Copyright 2007 Nintendo. All rights reserved.
#
# These coded instructions, statements, and computer programs contain
# proprietary information of Nintendo of America Inc. and/or Nintendo
# Company Ltd., and are protected by Federal copyright law. They may
# not be disclosed to third parties or copied or duplicated in any form,
# in whole or in part, without the prior written consent of Nintendo.
#
# $Log: $
# $NoKeywords: $
#----------------------------------------------------------------------------
include $(TWLSDK_ROOT)/build/buildtools/commondefs
#----------------------------------------------------------------------------
# SUBDIRS = ARM9
ifdef TWL_WITH_ARM7
SUBDIRS += ARM7
endif
#----------------------------------------------------------------------------
include $(TWLSDK_ROOT)/build/buildtools/modulerules
#===== End of Makefile =====

View File

@ -0,0 +1,108 @@
#ifndef __SDMC_H__
#define __SDMC_H__
#include <twl.h>
#include <rtfs.h>
#ifdef __cplusplus
extern "C" {
#endif
/*********************************************
SDCARD_ErrStatusに対して
*********************************************/
typedef enum {
SDMC_NORMAL = 0, /* 正常終了 */
SDMC_ERR_COMMAND = 0x0001, /* CMDエラー */
SDMC_ERR_CRC = 0x0002, /* CRCエラー */
SDMC_ERR_END = 0x0004, /* 実行エラー */
SDMC_ERR_TIMEOUT = 0x0008, /* コマンドタイムアウト */
SDMC_ERR_FIFO_OVF = 0x0010, /* FIFO オーバーフローエラー(INFO2のIllegal write access to buffer) */
SDMC_ERR_FIFO_UDF = 0x0020, /* FIFO アンダーフローエラー(INFO2のIllegal read access to buffer) */
SDMC_ERR_WP = 0x0040, /* WriteProtectによる書き込みエラー */
SDMC_ERR_FPGA_TIMEOUT = 0x0100, /* FPGA アクセスタイムアウト */
SDMC_ERR_PARAM = 0x0200, /* コマンドパラメータエラー */
SDMC_ERR_R1_STATUS = 0x0800, /* Normal response command カードステータス エラー */
SDMC_ERR_NUM_WR_SECTORS = 0x1000, /* 書き込み完了セクタ数 エラー */
SDMC_ERR_RESET = 0x2000, /* 初期化カードリセットコマンド時1.5秒タイムアウトエラー */
SDMC_ERR_ILA = 0x4000, /* イリーガルアクセスエラー */
SDMC_ERR_INFO_DETECT = 0x8000 /* カード排出時判別エラービット(IO3) */
}SDMC_ERR_CODE;
/*********************************************
SDドライバ処理結果通知情報構造体
*********************************************/
typedef struct {
u16 b_flags; /* 処理内容 */
u16 result; /* 実行結果 */
u32 resid; /* 読み(書き)サイズ */
} SdmcResultInfo;
/*********************************************
SDスペック構造体
*********************************************/
typedef struct {
u32 csd_ver2_flag; //CSDフォーマットバージョン(SDHCのときは1)
u32 memory_capacity; //data areaのサイズ(512Byte単位)
u32 protected_capacity; //protected areaのサイズ(512Byte単位)
u32 card_capacity; //カード全体のサイズ(512Byte単位)
u32 adjusted_memory_capacity; //memory_capacityをシリンダ(heads*secptrack)の倍数に調整したサイズ(cylinders*heads*secptrackになる)
u16 heads;
u16 secptrack;
u16 cylinders;
u16 SC; //sectors per cluster
u16 BU;
u16 RDE; //number of root dir entries(512 fix)
u32 SS; //sector size(512 fix)
u32 RSC; //reserved sector count(1 fix)
// u32 TS; //total sectors
u16 FATBITS; //16 or 32
u16 SF; //sectors per FAT
u32 SSA; //sectors in system area
u32 NOM; //sectors in master boot record
} SdmcSpec;
/*********************************************
RTFS用ドライバインタフェース
*********************************************/
BOOL sdmcRtfsIo( int driveno, dword block, void* buffer, word count, BOOLEAN reading);
int sdmcRtfsCtrl( int driveno, int opcode, void* pargs);
BOOL sdmcRtfsAttach( int driveno);
BOOL sdmcCheckMedia( void);
/*********************************************
API
*********************************************/
SDMC_ERR_CODE sdmcInit(void (*func1)(void),void (*func2)(void)); /* カードドライバ初期化 */
SDMC_ERR_CODE sdmcReset( void); /* カードリセット */
SDMC_ERR_CODE sdmcGetStatus(u16 *status); /* カードドライバの現在の状態を取得する */
u32 sdmcGetCardSize(void); /* カード全サイズの取得 */
/*SD I/FのFIFOを使ってリードする高速*/
SDMC_ERR_CODE sdmcReadFifo(void* buf,u32 bufsize,u32 offset,void(*func)(void),SdmcResultInfo *info);/* テスト用カードリード */
/*リードする*/
SDMC_ERR_CODE sdmcRead(void* buf,u32 bufsize,u32 offset,void(*func)(void),SdmcResultInfo *info); /* テスト用カードリード */
/*SD I/FのFIFOを使ってライトする高速*/
SDMC_ERR_CODE sdmcWriteFifo(void* buf,u32 bufsize,u32 offset,void(*func)(void),SdmcResultInfo *info);/* テスト用カードライト */
/*ライトする*/
SDMC_ERR_CODE sdmcWrite(void* buf,u32 bufsize,u32 offset,void(*func)(void),SdmcResultInfo *info); /* テスト用カードライト */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*__SDMC_H__*/

View File

@ -0,0 +1,25 @@
/*---------------------------------------------------------------------------*
Project: CTR - for RTFS
File: attach.h
2006 Nintendo.
*---------------------------------------------------------------------------*/
#ifndef __ATTACH_H__
#define __ATTACH_H__
#include <twl.h>
#include <rtfs.h>
/*---------------------------------------------------------------------------*
API
*---------------------------------------------------------------------------*/
BOOLEAN rtfs_attach( int driveno, DDRIVE* pdr, char* dev_name);
BOOLEAN rtfs_detach( int driveno);
#endif /*__ATTACH_H__*/

View File

@ -0,0 +1,446 @@
byte *rtfs_strtab_user_prompt(int prompt_id);
byte *rtfs_strtab_user_string(int string_id);
#define USTRING_SYS_NULL 100
#define USTRING_SYS_BADALIAS 101
#define USTRING_SYS_BADLFN 102
#define USTRING_SYS_UCRESERVED_NAMES 103
#define USTRING_SYS_LCRESERVED_NAMES 104
#define USTRING_SYS_VOLUME_LABEL 105
#define USTRING_SYS_OEMNAME 106
#define USTRING_SYS_TAB 107
#define USTRING_SYS_FSFILENAME 108
#define USTRING_CHKDSK_01 200
#define USTRING_CHKDSK_02 201
#define USTRING_CHKDSK_03 202
#define USTRING_CHKDSK_04 203
#define USTRING_CHKDSK_05 204
#define USTRING_CHKDSK_06 205
#define USTRING_CHKDSK_07 206
#define USTRING_CHKDSK_08 207
#define USTRING_CHKDSK_09 208
#define USTRING_CHKDSK_10 209
#define USTRING_CHKDSK_11 210
#define USTRING_CHKDSK_12 211
#define USTRING_CHKDSK_13 212
#define USTRING_CHKDSK_14 213
#define USTRING_CHKDSK_15 214
#define USTRING_CHKDSK_16 215
#define USTRING_CHKDSK_17 216
#define USTRING_CHKDSK_18 217
#define USTRING_CHKDSK_19 218
#define USTRING_CHKDSK_20 219
#define USTRING_CHKDSK_21 220
#define USTRING_CHKDSK_22 221
#define USTRING_CHKDSK_23 222
#define USTRING_CHKDSK_24 223
#define USTRING_CHKDSK_25 224
#define USTRING_CHKDSK_26 225
#define USTRING_CHKDSK_27 226
#define USTRING_CHKDSK_28 227
#define USTRING_CHKDSK_29 228
#define USTRING_CHKDSK_30 229
#define USTRING_CHKDSK_31 230
#define USTRING_CHKDSK_32 231
#define USTRING_CHKDSK_33 232
#define USTRING_CHKDSK_34 233
#define USTRING_CHKDSK_35 234
#define USTRING_CHKDSK_36 235
#define USTRING_CHKDSK_37 236
#define USTRING_CHKDSK_38 237
#define USTRING_CHKDSK_39 238
#define USTRING_CHKDSK_40 239
#define USTRING_CHKDSK_41 240
#define USTRING_CHKDSK_42 241
#define USTRING_CHKDSK_43 242
#define USTRING_CHKDSK_44 243
#define USTRING_CHKDSK_45 244
#define USTRING_CHKDSK_46 245
#define USTRING_CHKDSK_47 246
#define USTRING_CHKDSK_48 247
#define USTRING_CHKDSK_49 248
#define USTRING_CHKDSK_50 249
#define USTRING_CHKDSK_51 250
#define USTRING_CHKDSK_52 251
#define USTRING_CHKDSK_53 252
#define USTRING_CHKDSK_54 253
#define USTRING_CHKDSK_55 254
#define USTRING_CHKDSK_56 255
#define USTRING_CHKDSK_57 256
#define USTRING_CHKDSK_58 257
#define USTRING_CHKDSK_59 258
#define USTRING_CHKDSK_60 259
#define USTRING_CHKDSK_61 260
#define USTRING_CHKDSK_62 261
#define USTRING_CRITERR_01 400
#define USTRING_CRITERR_02 401
#define USTRING_CRITERR_03 402
#define USTRING_CRITERR_04 403
#define USTRING_CRITERR_05 404
#define USTRING_CRITERR_06 405
#define USTRING_CRITERR_07 406
#define USTRING_CRITERR_08 407
#define USTRING_CRITERR_09 408
#define USTRING_CRITERR_10 409
#define USTRING_FLDRVER_01 600
#define USTRING_FLDRVER_02 601
#define USTRING_FLDRVER_03 602
#define USTRING_FLDRVER_04 603
#define USTRING_FLDRVER_05 604
#define USTRING_FLDRVER_06 605
#define USTRING_FLDRVER_07 606
#define USTRING_FLDRVER_08 607
#define USTRING_FLDRVER_09 608
#define USTRING_FLDRVER_10 609
#define USTRING_FLDRVER_11 610
#define USTRING_FLDRVER_12 611
#define USTRING_FLDRVER_13 612
#define USTRING_FLDRVER_14 613
#define USTRING_FLDRVER_15 614
#define USTRING_FLDRVER_16 615
#define USTRING_FLDRVER_17 616
#define USTRING_FLDRVER_18 617
#define USTRING_FLDRVER_19 618
#define USTRING_FLASHDRV_01 800
#define USTRING_FLASHDRV_02 801
#define USTRING_FLASHDRV_03 802
#define USTRING_FLASHDRV_04 803
#define USTRING_FLASHDRV_05 804
#define USTRING_FLASHDRV_06 805
#define USTRING_FLASHDRV_07 806
#define USTRING_FLASHDRV_08 807
#define USTRING_FLASHDRV_09 808
#define USTRING_FLASHDRV_10 809
#define USTRING_FLASHDRV_11 810
#define USTRING_FLASHDRV_12 811
#define USTRING_FLASHDRV_13 812
#define USTRING_FLASHDRV_14 813
#define USTRING_FLASHDRV_15 814
#define USTRING_FLASHDRV_16 815
#define USTRING_FLASHDRV_17 816
#define USTRING_FLASHDRV_18 817
#define USTRING_FLASHDRV_19 818
#define USTRING_FLASHDRV_20 819
#define USTRING_FLASHDRV_21 820
#define USTRING_FLASHDRV_22 821
#define USTRING_FLASHDRV_23 822
#define USTRING_FLASHDRV_24 823
#define USTRING_FLASHDRV_25 824
#define USTRING_FLASHDRV_26 825
#define USTRING_FLASHDRV_27 826
#define USTRING_FLASHDRV_28 827
#define USTRING_FLASHDRV_29 828
#define USTRING_FLASHDRV_30 829
#define USTRING_FLASHDSK_01 1000
#define USTRING_FLASHDSK_02 1001
#define USTRING_FLASHEMU_01 1200
#define USTRING_FLASHEMU_02 1201
#define USTRING_FLASHEMU_03 1202
#define USTRING_FLASHEMU_04 1203
#define USTRING_FLASHEMU_05 1204
#define USTRING_FLASHEMU_06 1205
#define USTRING_FLASHEMU_07 1206
#define USTRING_RTFSINIT_01 1400
#define USTRING_RTFSINIT_02 1401
#define USTRING_RTFSINIT_03 1402
#define USTRING_RTFSINIT_04 1403
#define USTRING_RTFSINIT_05 1404
#define USTRING_RTFSINIT_06 1405
#define USTRING_RTFSINIT_07 1406
#define USTRING_RTFSINIT_08 1407
#define USTRING_RTFSINIT_09 1408
#define USTRING_RTFSINIT_10 1409
#define USTRING_RTFSINIT_11 1410
#define USTRING_RTFSINIT_12 1411
#define USTRING_RTFSINIT_13 1412
#define USTRING_IDEDRV_01 1600
#define USTRING_IDEDRV_02 1601
#define USTRING_IDEDRV_03 1602
#define USTRING_IDEDRV_04 1603
#define USTRING_IDEDRV_05 1604
#define USTRING_PORTMAIN_01 1800
#define USTRING_PORTMAIN_02 1801
#define USTRING_PORTKERN_01 2000
#define USTRING_PORTKERN_02 2001
#define USTRING_PORTKERN_03 2002
#define USTRING_PORTKERN_04 2003
#define USTRING_RTFSDEM_01 2200
#define USTRING_RTFSDEM_02 2201
#define USTRING_RTFSDEM_03 2202
#define USTRING_RTFSDEM_04 2203
#define USTRING_RTFSDEM_05 2204
#define USTRING_RTFSDEM_06 2205
#define USTRING_RTFSDEM_07 2206
#define USTRING_RTFSDEM_08 2207
#define USTRING_RTFSDEM_09 2208
#define USTRING_RTFSDEM_10 2209
#define USTRING_RTFSDEM_11 2210
#define USTRING_RTFSDEM_12 2211
#define USTRING_RTFSDEM_13 2212
#define USTRING_RTFSDEM_14 2213
#define USTRING_RTFSDEM_15 2214
#define USTRING_RTFSDEM_16 2215
#define USTRING_RTFSDEM_17 2216
#define USTRING_TSTSH_01 2400
#define USTRING_TSTSH_02 2401
#define USTRING_TSTSH_03 2402
#define USTRING_TSTSH_04 2403
#define USTRING_TSTSH_05 2404
#define USTRING_TSTSH_06 2405
#define USTRING_TSTSH_07 2406
#define USTRING_TSTSH_08 2407
#define USTRING_TSTSH_09 2408
#define USTRING_TSTSH_10 2409
#define USTRING_TSTSH_11 2410
#define USTRING_TSTSH_12 2411
#define USTRING_TSTSH_13 2412
#define USTRING_TSTSH_14 2413
#define USTRING_TSTSH_15 2414
#define USTRING_TSTSH_16 2415
#define USTRING_TSTSH_17 2416
#define USTRING_TSTSH_18 2417
#define USTRING_TSTSH_19 2418
#define USTRING_TSTSH_20 2419
#define USTRING_TSTSH_21 2420
#define USTRING_TSTSH_22 2421
#define USTRING_TSTSH_23 2422
#define USTRING_TSTSH_24 2423
#define USTRING_TSTSH_25 2424
#define USTRING_TSTSH_26 2425
#define USTRING_TSTSH_27 2426
#define USTRING_TSTSH_28 2427
#define USTRING_TSTSH_29 2428
#define USTRING_TSTSH_30 2429
#define USTRING_TSTSH_31 2430
#define USTRING_TSTSH_32 2431
#define USTRING_TSTSH_33 2432
#define USTRING_TSTSH_34 2433
#define USTRING_TSTSH_35 2434
#define USTRING_TSTSH_36 2435
#define USTRING_TSTSH_37 2436
#define USTRING_TSTSH_38 2437
#define USTRING_TSTSH_39 2438
#define USTRING_TSTSH_40 2439
#define USTRING_TSTSH_41 2440
#define USTRING_TSTSH_42 2441
#define USTRING_TSTSH_43 2442
#define USTRING_TSTSH_44 2443
#define USTRING_TSTSH_45 2444
#define USTRING_TSTSH_46 2445
#define USTRING_TSTSH_47 2446
#define USTRING_TSTSH_48 2447
#define USTRING_TSTSH_49 2448
#define USTRING_TSTSH_50 2449
#define USTRING_TSTSH_51 2450
#define USTRING_TSTSH_52 2451
#define USTRING_TSTSH_53 2452
#define USTRING_TSTSH_54 2453
#define USTRING_TSTSH_55 2454
#define USTRING_TSTSH_56 2455
#define USTRING_TSTSH_57 2456
#define USTRING_TSTSH_58 2457
#define USTRING_TSTSH_59 2458
#define USTRING_TSTSH_60 2459
#define USTRING_TSTSH_61 2460
#define USTRING_TSTSH_62 2461
#define USTRING_TSTSH_63 2462
#define USTRING_TSTSH_64 2463
#define USTRING_TSTSH_65 2464
#define USTRING_TSTSH_66 2465
#define USTRING_TSTSH_67 2466
#define USTRING_TSTSH_68 2467
#define USTRING_TSTSH_69 2468
#define USTRING_TSTSH_70 2469
#define USTRING_TSTSH_71 2470
#define USTRING_TSTSH_72 2471
#define USTRING_TSTSH_73 2472
#define USTRING_TSTSH_74 2473
#define USTRING_TSTSH_75 2474
#define USTRING_TSTSH_76 2475
#define USTRING_TSTSH_77 2476
#define USTRING_TSTSH_78 2477
#define USTRING_TSTSH_79 2478
#define USTRING_TSTSH_80 2479
#define USTRING_TSTSH_81 2480
#define USTRING_TSTSH_82 2481
#define USTRING_TSTSH_83 2482
#define USTRING_TSTSH_84 2483
#define USTRING_TSTSH_85 2484
#define USTRING_TSTSH_86 2485
#define USTRING_TSTSH_87 2486
#define USTRING_TSTSH_88 2487
#define USTRING_TSTSH_89 2488
#define USTRING_TSTSH_90 2489
#define USTRING_TSTSH_91 2490
#define USTRING_TSTSH_92 2491
#define USTRING_TSTSH_93 2492
#define USTRING_TSTSH_94 2493
#define USTRING_TSTSH_95 2494
#define USTRING_TSTSH_96 2495
#define USTRING_TSTSH_97 2496
#define USTRING_TSTSH_98 2497
#define USTRING_TSTSH_99 2498
#define USTRING_TSTSH_100 2499
#define USTRING_TSTSH_101 2500
#define USTRING_TSTSH_102 2501
#define USTRING_TSTSH_103 2502
#define USTRING_TSTSH_104 2503
#define USTRING_TSTSH_105 2504
#define USTRING_TSTSH_106 2505
#define USTRING_TSTSH_107 2506
#define USTRING_TSTSH_108 2507
#define USTRING_TSTSH_109 2508
#define USTRING_TSTSH_110 2509
#define USTRING_TSTSH_111 2510
#define USTRING_TSTSH_112 2511
#define USTRING_TSTSH_113 2512
#define USTRING_TSTSH_114 2513
#define USTRING_TSTSH_115 2514
#define USTRING_TSTSH_116 2515
#define USTRING_TSTSH_117 2516
#define USTRING_TSTSH_118 2517
#define USTRING_TSTSH_119 2518
#define USTRING_TSTSH_120 2519
#define USTRING_TSTSH_121 2520
#define USTRING_TSTSH_122 2521
#define USTRING_TSTSH_123 2522
#define USTRING_TSTSH_124 2523
#define USTRING_TSTSH_125 2524
#define USTRING_TSTSH_126 2525
#define USTRING_TSTSH_127 2526
#define USTRING_TSTSH_128 2527
#define USTRING_TSTSH_129 2528
#define USTRING_TSTSH_130 2529
#define USTRING_TSTSH_131 2530
#define USTRING_TSTSH_132 2531
#define USTRING_TSTSH_133 2532
#define USTRING_TSTSH_134 2533
#define USTRING_TSTSH_135 2534
#define USTRING_TSTSH_136 2535
#define USTRING_TSTSH_137 2536
#define USTRING_TSTSH_138 2537
#define USTRING_TSTSH_139 2538
#define USTRING_TSTSH_140 2539
#define USTRING_TSTSH_141 2540
#define USTRING_TSTSH_142 2541
/* #define USTRING_TSTSH_143 2542 - Obsolete */
#define USTRING_TSTSH_144 2543
#define USTRING_TSTSH_145 2544
#define USTRING_TSTSH_146 2545
#define USTRING_TSTSH_147 2546
#define USTRING_TSTSH_148 2547
#define USTRING_TSTSHHELP_01 2600
#define USTRING_TSTSHHELP_02 2601
#define USTRING_TSTSHHELP_03 2602
#define USTRING_TSTSHHELP_04 2603
#define USTRING_TSTSHHELP_05 2604
#define USTRING_TSTSHHELP_06 2605
#define USTRING_TSTSHHELP_07 2606
#define USTRING_TSTSHHELP_08 2607
#define USTRING_TSTSHHELP_09 2608
#define USTRING_TSTSHHELP_10 2609
#define USTRING_TSTSHHELP_11 2610
#define USTRING_TSTSHHELP_12 2611
#define USTRING_TSTSHHELP_13 2612
#define USTRING_TSTSHHELP_14 2613
#define USTRING_TSTSHHELP_15 2614
#define USTRING_TSTSHHELP_16 2615
#define USTRING_TSTSHHELP_17 2616
#define USTRING_TSTSHHELP_18 2617
#define USTRING_TSTSHHELP_19 2618
#define USTRING_TSTSHHELP_20 2619
#define USTRING_TSTSHHELP_21 2620
#define USTRING_TSTSHHELP_22 2621
#define USTRING_TSTSHHELP_23 2622
#define USTRING_TSTSHHELP_24 2623
#define USTRING_TSTSHHELP_25 2624
#define USTRING_TSTSHHELP_26 2625
#define USTRING_TSTSHHELP_27 2626
#define USTRING_TSTSHHELP_28 2627
#define USTRING_TSTSHHELP_29 2628
#define USTRING_TSTSHHELP_30 2629
#define USTRING_TSTSHHELP_31 2630
#define USTRING_TSTSHHELP_32 2631
#define USTRING_TSTSHHELP_33 2632
#define USTRING_TSTSHHELP_34 2633
#define USTRING_TSTSHHELP_35 2634
#define USTRING_TSTSHHELP_36 2635
#define USTRING_TSTSHHELP_37 2636
#define USTRING_TSTSHHELP_38 2637
#define USTRING_TSTSHHELP_39 2638
#define USTRING_TSTSHHELP_40 2639
#define USTRING_TSTSHHELP_41 2640
#define USTRING_TSTSHHELP_42 2641
#define USTRING_TSTSHHELP_43 2642
#define USTRING_TSTSHHELP_44 2643
#define USTRING_TSTSHHELP_45 2644
#define USTRING_TSTSHHELP_46 2645
#define USTRING_TSTSHCMD_01 2800
#define USTRING_TSTSHCMD_02 2801
#define USTRING_TSTSHCMD_03 2802
#define USTRING_TSTSHCMD_04 2803
#define USTRING_TSTSHCMD_05 2804
#define USTRING_TSTSHCMD_06 2805
#define USTRING_TSTSHCMD_07 2806
#define USTRING_TSTSHCMD_08 2807
#define USTRING_TSTSHCMD_09 2808
#define USTRING_TSTSHCMD_10 2809
#define USTRING_TSTSHCMD_11 2810
#define USTRING_TSTSHCMD_12 2811
#define USTRING_TSTSHCMD_13 2812
#define USTRING_TSTSHCMD_14 2813
#define USTRING_TSTSHCMD_15 2814
#define USTRING_TSTSHCMD_16 2815
#define USTRING_TSTSHCMD_17 2816
#define USTRING_TSTSHCMD_18 2817
#define USTRING_TSTSHCMD_19 2818
#define USTRING_TSTSHCMD_20 2819
#define USTRING_TSTSHCMD_21 2820
#define USTRING_TSTSHCMD_22 2821
#define USTRING_TSTSHCMD_23 2822
#define USTRING_TSTSHCMD_24 2823
#define USTRING_TSTSHCMD_25 2824
#define USTRING_TSTSHCMD_26 2825
#define USTRING_TSTSHCMD_27 2826
#define USTRING_TSTSHCMD_28 2827
#define USTRING_TSTSHCMD_29 2828
#define USTRING_TSTSHCMD_30 2829
#define USTRING_TSTSHCMD_31 2830
#define USTRING_TSTSHCMD_32 2831
#define USTRING_TSTSHCMD_33 2832
#define USTRING_TSTSHCMD_34 2833
#define USTRING_TSTSHCMD_35 2834
#define USTRING_TSTSHCMD_36 2835
#define USTRING_TSTSHCMD_37 2836
#define USTRING_TSTSHCMD_38 2837
#define USTRING_TSTSHCMD_39 2838
#define USTRING_TSTSHCMD_40 2839
#define USTRING_TSTSHCMD_41 2840
#define USTRING_TSTSHCMD_42 2841
#define USTRING_TSTSHCMD_43 2842
#define USTRING_TSTSHCMD_44 2843
#define USTRING_TSTSHCMD_45 2844
#define USTRING_TSTSHCMD_46 2845
#define UPROMPT_CRITERR 1
#define UPROMPT_REGRESS 2
#define UPROMPT_TSTSH1 5
#define UPROMPT_TSTSH2 6
#define UPROMPT_TSTSH3 7
#define UPROMPT_TSTSH4 8
#define UPROMPT_TSTSH5 9
#define UPROMPT_TSTSH6 10
#define UPROMPT_TSTSH7 11
#define UPROMPT_TSTSH8 12
#define UPROMPT_TSTSH9 13
#define UPROMPT_TSTSH10 14
#define UPROMPT_TSTSH11 15
#define UPROMPT_TSTSH12 16
#define UPROMPT_TSTSH13 17
#define UPROMPT_TSTSH14 18
#define UPROMPT_TSTSH15 19
#define UPROMPT_TSTSH16 20
#define UPROMPT_TSTSH17 21
#define UPROMPT_TSTSH18 22
#define UPROMPT_WINSPLSH 23

View File

@ -0,0 +1,40 @@
/*---------------------------------------------------------------------------*
Project: CTR - for RTFS
File: drfile.h
2006 Nintendo.
*---------------------------------------------------------------------------*/
#ifndef __DR_FILE_H__
#define __DR_FILE_H__
#include <twl.h>
#include <rtfs.h>
/*---------------------------------------------------------------------------*
使
*---------------------------------------------------------------------------*/
/*RTFS用 FATパラメータ*/
typedef struct {
u32 capacity; //data areaのサイズ(512Byte単位)
u32 adjusted_capacity; //memory_capacityをシリンダ(heads*secptrack)の倍数に調整したサイズ(cylinders*heads*secptrackになる)
u16 heads;
u16 secptrack;
u16 cylinders;
} FileSpec;
/*---------------------------------------------------------------------------*
API
*---------------------------------------------------------------------------*/
BOOL fileRtfsAttach( PCFD fileDesc, int driveno);
#endif /*__DR_FILE_H__*/

View File

@ -0,0 +1,50 @@
/*****************************************************************************
*Filename: PORTCONF.H - RTFS porting layer tuning constants
*
*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc, 1993-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
* Description:
* This file contains porting layer tuning constants for configuring RTFS.
* It is included by rtfsconf.h.
*
****************************************************************************/
#ifndef __PORTCONF__
#define __PORTCONF__ 1
/* CPU Configuration section */
#define KS_LITTLE_ENDIAN 1 /* See porting reference guide for explanation */
#define KS_LITTLE_ODD_PTR_OK 0 /* See porting reference guide for explanation */
#define KS_CONSTANT const /* See porting reference guide for explanation */
#define KS_FAR /* See porting reference guide for explanation */
/* Compile time constants to control device inclusion
See the reference guide for an explanation
*/
#define INCLUDE_SD 0
#define INCLUDE_IDE 0 /* - Include the IDE driver */
#define INCLUDE_PCMCIA 0 /* - Include the pcmcia driver */
#define INCLUDE_PCMCIA_SRAM 0 /* - Include the pcmcia static ram card driver */
#define INCLUDE_COMPACT_FLASH 0 /* - Support compact flash (requires IDE and PCMCIA) */
#define INCLUDE_FLASH_FTL 0 /* - Include the linear flash driver */
#define INCLUDE_ROMDISK 0 /* - Include the rom disk driver */
#define INCLUDE_RAMDISK 0 /* - Include the rom disk driver */
#define INCLUDE_MMCCARD 0 /* - Include the multi media flash card driver */
#define INCLUDE_SMARTMEDIA 0 /* - Include the smart media flash card driver */
#define INCLUDE_FLOPPY 0 /* - Include the floppy disk driver */
#define INCLUDE_HOSTDISK 0 /* - Include the host disk disk simulator */
#define INCLUDE_UDMA 0 /* - Include ultra dma support for the ide driver */
#define INCLUDE_82365_PCMCTRL 0 /* - Include the 82365 pcmcia controller driver */
#endif /* __PORTCONF__ */

View File

@ -0,0 +1,190 @@
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
* This file is automatically included in rtfs.h if INCLUDE_FAILSAFE_CODE is enabled
* this file is note intended for inclusion by user code.
*/
/* PRFS.H - ERTFS-PRO Directory FailSafe routines */
/*
CFG_VALIDATE_JOURNAL - Set this to one to force a a low level read of the
whole journal file before it is accessed. If any of the reads call Failsafe
tries to recover by re-writing the whole file with zeros, for some media
types this will correct a read error. When the overwrite is completed
the file is read again, if that succeeds we continue, otherwise the journal
file open fails. A disk mount that encounters this error will fail and
errno will be set to PEIOERRORREADJOURNAL */
#define CFG_VALIDATE_JOURNAL 0
/*
CFG_VALIDATE_BUFFER_SIZE - This is the size, in blocks of the special
buffer dedicated to performing the tasks described in CFG_VALIDATE_JOURNAL.
The largest usable value for CFG_VALIDATE_BUFFER_SIZE is 128. Larger
values will not be utilized but memory will be wasted.
The whole journal file is scanned during startup in disk reads of up to
CFG_VALIDATE_BUFFER_SIZE blocks. Larger values will require fewer reads
and improve perfromance over smaller values.
The buffer is declared as:
static byte validate_buffer[CFG_VALIDATE_BUFFER_SIZE*512];
in prfsnvio.c.
If CFG_VALIDATE_JOURNAL is zero the value of CFG_VALIDATE_BUFFER_SIZE
is irrelevant because the buffer is not declared.
*/
#define CFG_VALIDATE_BUFFER_SIZE 64
/*
CFG_NUM_JOURNAL_BLOCKS - This is the default number of 512 byte blocks
to assign to the failsafe for journalling directory blocks. If
the user does not provide a non-zero value in the journal_size argument
to pro_failsafe_init() then the journal file will sized to be large
enough to hold the whole file allocation table plus CFG_NUM_JOURNAL_BLOCKS.
The default value is 128. This represents a very small percentage of all
but the smallest disks but it should be adequate for almost any imaginable
usage. It may be reduced to as little as 1 and FailSafe will still work
fine under most conditions.
*/
#define CFG_NUM_JOURNAL_BLOCKS 128
/*
CFG_NUM_INDEX_BUFFERS - This compile time constant determines number of
512 byte buffers to reserve for buffering FailSafe index pages. It
effects the size of the failsafe context structure. It must be at
least one and unless ram resources are very precious it should be
set to at least two if possible. The default value is 4 which should
be large enough for almost any application.
*/
#define CFG_NUM_INDEX_BUFFERS 4
/* Fail configuration and context structure */
typedef struct failsafecontext {
/* Configuration values to be set before calling pro_failsafe_init
and not modified thereafter */
#define FS_MODE_AUTORESTORE 0x01
#define FS_MODE_AUTORECOVER 0x02
#define FS_MODE_AUTOCOMMIT 0x04
/* Internal flags set by failsafe. Not user assignable */
#define FS_MODE_JOURNALING 0x08
int configuration_flags;
/* configuration_flags values
FS_MODE_AUTORESTORE- If removable media is reinserted and the
journal file indicates that restore is needed, automatically restore
and continue. If this flag is not set when this condition occurs
the mount of the volume fails and the errno is set to PEFSRESTORENEEDED,
the application must then handle this errno setting and call the
pro_failsafe_restore routine
FS_MODE_AUTORECOVER- If autorestore is required but the restore process
failed due to a bad journal file or IO error abort the restore but don't
report an error. Try to reinitialize the journal file and continue.
If a restore error did occur and FS_MODE_AUTORECOVER is not set the
mount will fail and errno will be set to PEFSRESTOREERROR
FS_MODE_AUTOCOMMIT- If AUTOCOMMIT is enabled the FailSafe commit operation
will be performed automatically be ERTFS at the completion of each API
call. With AUTOCOMMIT enabled the FailSafe operation is transparent to the
user and it is not necessary to call pro_failsafe_commit().
*/
dword user_journal_size; /* In blocks */
/* Internal elements, not intended to be accessed from user code */
DDRIVE *pdrive;
dword journal_file_size; /* In blocks */
dword num_index_blocks; /* Blocks reserved remap index */
dword num_remap_blocks; /* Blocks reserved for block remaps */
dword total_blocks_mapped; /* number of valid index entries */
dword journal_checksum; /* Checksum of all index entries */
dword known_free_clusters; /* number of valid index entries */
dword nv_buffer_handle;
int blockmap_size;
struct fsblockmap *blockmap_freelist;
struct fsblockmap *sorted_blockmap;
#define FAILSAFE_HASHTABLE_SIZE 16
#define FAILSAFE_HASHMASK 0xf
struct fsblockmap *blockmap_hash_tbl[FAILSAFE_HASHTABLE_SIZE];
int next_index_buffer;
int index_offset[CFG_NUM_INDEX_BUFFERS];
BOOLEAN index_dirty[CFG_NUM_INDEX_BUFFERS];
dword index_buffer[CFG_NUM_INDEX_BUFFERS][128];
byte scratch_block[512];
/* Internal variable used to differentiate between IO
errors and other errors during journal file re-opens */
int open_status;
} FAILSAFECONTEXT;
typedef struct fsblockmap {
struct fsblockmap *pnext;
struct fsblockmap *pnext_by_block;
dword blockno;
dword replacement_block;
} FSBLOCKMAP;
/* Return codes for pro_failsafe_restore() */
#define FS_STATUS_OK 0
#define FS_STATUS_NO_JOURNAL 1
#define FS_STATUS_BAD_JOURNAL 2
#define FS_STATUS_IO_ERROR 3
#define FS_STATUS_BAD_CHECKSUM 4
#define FS_STATUS_RESTORED 5
#define FS_STATUS_MUST_RESTORE 6
#define FS_STATUS_OUT_OF_DATE 7
#define FS_STATUS_NO_INIT 8
/* Failsafe api prototypes see prfsapi.c */
BOOLEAN pro_failsafe_init(byte *drivename, FAILSAFECONTEXT *pfscntxt);
BOOLEAN pro_failsafe_commit(byte *path);
int pro_failsafe_restore(byte *drive_name, FAILSAFECONTEXT *fscntxt, BOOLEAN dorestore,BOOLEAN doclear);
BOOLEAN pro_failsafe_auto_init(DDRIVE *pdrive);
BOOLEAN pro_failsafe_shutdown(byte *drive_name, BOOLEAN abort);
/* Routines called internally by ertfs. see prfscore.c */
BOOLEAN pro_failsafe_dskopen(DDRIVE *pdrive);
BOOLEAN pro_failsafe_autorestore(DDRIVE *pdrive);
void fs_rewind_failsafe(FAILSAFECONTEXT *pfscntxt);
/* The rest of this header file contains information that is internal to
failsafe */
#define FS_JOURNAL_SIGNATURE_1 0x4641494C /* 'F''A''I''L' */
#define FS_JOURNAL_SIGNATURE_2 0x53414645 /* 'S''A''F''E' */
/* April-2004 version 2. - substantial rework */
#define FS_JOURNAL_VERSION 0x00000002
#define FS_STATUS_PROCESSING 0x01010101
#define FS_STATUS_COMPLETE 0x11111111
/* Internal field offsets in failsafe header */
#define INDEX_OFFSET_SIGNATURE_1 0
#define INDEX_OFFSET_SIGNATURE_2 1
#define INDEX_OFFSET_VERSION 2
#define INDEX_OFFSET_INDEX_STATUS 3
#define INDEX_OFFSET_TOTAL_BLOCKS_MAPPED 4
#define INDEX_OFFSET_INDEX_CHECKSUM 5
#define INDEX_OFFSET_FREE_CLUSTERS 6
#define INDEX_OFFSET_NUMB_INDEX_BLOCKS 7
#define INDEX_OFFSET_NUMB_REMAP_BLOCKS 8
#define JOURNAL_HEADER_SIZE 9 /* First 9 dwords are status */
#define JOURNAL_ENTRIES_P_BLOCK 128
#define JOURNAL_ENTRIES_ZERO (JOURNAL_ENTRIES_P_BLOCK-JOURNAL_HEADER_SIZE)
/* Prototypes of internal function implemented in prfscore.c */
BOOLEAN pro_failsafe_init_internal(DDRIVE *pdrive, FAILSAFECONTEXT *pfscntxt);
int pro_failsafe_commit_internal(FAILSAFECONTEXT *pfscntxt);
int failsafe_restore_internal(FAILSAFECONTEXT *pfscntxt, BOOLEAN dorestore, BOOLEAN doclear);
BOOLEAN pro_failsafe_dskopen(DDRIVE *pdrive);
BOOLEAN pro_failsafe_autorestore(DDRIVE *pdrive);
BOOLEAN pro_failsafe_autocommit(DDRIVE *pdrive);
BOOLEAN pro_failsafe_journal_full(DDRIVE *pdrive);
/* Prototypes of internal function implemented in prfsnvio.c */
BOOLEAN failsafe_reopen_nv_buffer(FAILSAFECONTEXT *pfscntxt);
BOOLEAN failsafe_create_nv_buffer(FAILSAFECONTEXT *pfscntxt);
BOOLEAN failsafe_write_nv_buffer(FAILSAFECONTEXT *pfscntxt, dword block_no, byte *pblock);
BOOLEAN failsafe_read_nv_buffer(FAILSAFECONTEXT *pfscntxt, dword block_no, byte *pblock);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
#ifndef __RTFS_NAMING_CONVENTION__
#define __RTFS_NAMING_CONVENTION__
/*#define original-name centrair-name*/
#define pc_ertfs_init rtfs_pc_ertfs_init
#define pc_ertfs_config rtfs_pc_ertfs_config
#define pc_free_user rtfs_pc_free_user
#define pc_set_cwd rtfs_pc_set_cwd
#define pc_set_default_drive rtfs_pc_set_default_drive
#define pc_pwd rtfs_pc_pwd
#define pc_gfirst rtfs_pc_gfirst
#define pc_gnext rtfs_pc_gnext
#define pc_gdone rtfs_pc_gdone
#define pc_enumerate rtfs_pc_enumerate
#define get_errno rtfs_get_errno
#define rtfs_set_driver_errno rtfs_rtfs_set_driver_errno
#define rtfs_get_driver_errno rtfs_rtfs_get_driver_errno
#define pc_free rtfs_pc_free
#define pc_get_attributes rtfs_pc_get_attributes
#define pc_isdir rtfs_pc_isdir
#define pc_isvol rtfs_pc_isvol
#define pc_stat rtfs_pc_stat
#define pc_fstat rtfs_pc_fstat
#define pc_check_disk rtfs_pc_check_disk
#define pc_mkdir rtfs_pc_mkdir
#define pc_mv rtfs_pc_mv
#define pc_rmdir rtfs_pc_rmdir
#define pc_deltree rtfs_pc_deltree
#define pc_set_attributes rtfs_pc_set_attributes
#define pc_unlink rtfs_pc_unlink
#define pc_diskflush rtfs_pc_diskflush
#define po_open rtfs_po_open
#define po_close rtfs_po_close
#define po_flush rtfs_po_flush
#define po_read rtfs_po_read
#define po_write rtfs_po_write
#define po_lseek rtfs_po_lseek
#define po_useek rtfs_po_useek
#define po_chsize rtfs_po_chsize
#define po_truncate rtfs_po_truncate
#define pc_get_media_parms rtfs_pc_get_media_parms
#define pc_partition_media rtfs_pc_partition_media
#define pc_format_media rtfs_pc_format_media
#define pc_format_volume rtfs_pc_format_volume
#define pc_cluster_size rtfs_pc_cluster_size
#define pc_get_file_extents rtfs_pc_get_file_extents
#define pc_get_free_list rtfs_pc_get_free_list
#define pc_raw_read rtfs_pc_raw_read
#define pc_raw_write rtfs_pc_raw_write
#define po_extend_file rtfs_po_extend_file
#define pc_regression_test rtfs_pc_regression_test
#define tst_shell rtfs_tst_shell
#endif /*__RTFS_NAMING_CONVENTION__*/

View File

@ -0,0 +1,74 @@
#ifndef __RTFS_TARGET_OS_H__
#define __RTFS_TARGET_OS_H__
/***********************************************************************
OS指定
***********************************************************************/
#define TARGET_OS_NITRO (1)
#define TARGET_OS_CTR (TARGET_OS_NITRO ^ 1)
/***********************************************************************
NITRO OSのとき
***********************************************************************/
#if (TARGET_OS_NITRO == 1)
/* #if( DEBUG_PRINT_ON == 1)
#define PRINTDEBUG OS_TPrintf
#else
#define PRINTDEBUG( ...) ((void)0)
#endif
*/
#define OSAPI_CPUFILL8 MI_CpuFill8
#define OSAPI_CPUCOPY8 MI_CpuCopy8
#define OSAPI_MALLOC OS_Alloc
#define OSAPI_FREE OS_Free
#define OSAPI_STRLEN STD_GetStringLength
#define OSAPI_STRNCMP STD_CompareNString
#define OSAPI_STRCMP STD_CompareString
#define OSAPI_FLUSHCACHEALL DC_FlushAll
#define OSAPI_WAITCACHEBUF DC_WaitWriteBufferEmpty
#define OSAPI_ENABLEINTR OS_EnableInterrupts
#define OSAPI_DISABLEINTR OS_DisableInterrupts
#define OSAPI_RESTOREINTR OS_RestoreInterrupts
#define OSAPI_RTCINIT RTC_Init
/***********************************************************************
CTR OSのとき
***********************************************************************/
#else
#if (DEBUG_PRINT_ON == 1)
#if (CTR_DEF_ENVIRONMENT_DSEMU == 1)
#define PRINTDEBUG osTPrintf
#else
#include <ctr/vlink.h>
#define PRINTDEBUG vlink_dos_printf
#endif
#else
#define PRINTDEBUG( ...) ((void)0)
#endif
#define OSAPI_CPUFILL8 miCpuFill8
#define OSAPI_CPUCOPY8 miCpuCopy8
#define OSAPI_MALLOC i_elAlloc
#define OSAPI_FREE i_elFree
#define OSAPI_STRLEN strlen
#define OSAPI_STRNCMP strncmp
#define OSAPI_STRCMP strcmp
#define OSAPI_FLUSHCACHEALL osFlushDCacheAll
#define OSAPI_WAITCACHEBUF osWaitWriteBufferEmpty
#define OSAPI_ENABLEINTR osEnableInterrupts
#define OSAPI_DISABLEINTR osDisableInterrupts
#define OSAPI_RESTOREINTR osRestoreInterrupts
#define OSAPI_RTCINIT rtcInit
#endif
#endif /*__RTFS_TARGET_OS_H__*/

View File

@ -0,0 +1,25 @@
/*****************************************************************************
*Filename: RTFSAPI.H - Public declarations for the rtfs API set
*
*
* EBS - RTFSAPI (Real Time File Manager)
*
* Copyright Peter Van Oudenaren , 1993
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
*
*
* Description:
*
*
*
*
****************************************************************************/
#ifndef __RTFSAPI__
#define __RTFSAPI__ 1
#include <rtfs.h>
#endif

View File

@ -0,0 +1,153 @@
/*****************************************************************************
*Filename: RTFSCONF.H - RTFS tuning constants
*
*
* EBS - RTFS (Real Time File Manager)
*
* Copyright Peter Van Oudenaren, 1993
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
* Description:
* This file contains tuning constants for configuring RTFS.
* It is included by rtfs.h
*
****************************************************************************/
#ifndef __RTFSCONF__
#define __RTFSCONF__ 1
/* Include CPU and peripheral configuration */
#include <portconf.h>
/* Character set support */
#define INCLUDE_CS_JIS 0 /* Set to 1 to support JIS (kanji) */
#define INCLUDE_CS_ASCII 1 /* Set to 1 to support ASCII only */
#define INCLUDE_CS_UNICODE 0 /* Set to 1 to support unicode characters requires VFAT */
/* Note: After we implemented VFAT we learned that Microsoft patented
the Win95 VFS implementation. US PATENT # 5,758,352.
Leaving VFAT set to zero will exclude potential patent infringment
problems.
3-19-99
*/
/* Set to 1 to support long filenames */
#define VFAT 1
/* Set to 1 to support 32 bit FATs */
#define FAT32 1
/* Set to 0 to disable file share modes saves ~0.5 K */
#define RTFS_SHARE 0
/* Set to 0 to disable subdirs. Feature not implemented must be 1*/
#define RTFS_SUBDIRS 1
/* Set to 0 to disable write support. Feature not implemented must be 1*/
#define RTFS_WRITE 1
/* Set to 1 to include failsafe support */
#define INCLUDE_FAILSAFE_CODE 1
/* Set to 1 to include support for extended DOS partitions */
/* ERTFS contains code to interpret extended DOS partitions but since this
feature is rarely used it is provided as a compile time option */
#define SUPPORT_EXTENDED_PARTITIONS 0
/* STORE_DEVICE_NAMES_IN_DRIVE_STRUCT - If this value is set to one then
we save device names for future viewing by diagnostics */
#define STORE_DEVICE_NAMES_IN_DRIVE_STRUCT 1
/* Set to the maximum file size ERTFS may create. If po_chsize or po_extend_file()
are called with a size request larger than this they fail and set errno
to PETOOLARGE. When po_write() is asked to expend the file beyond this maximum
the behavior is determined by the value of RTFS_TRUNCATE_WRITE_TO_MAX */
#define RTFS_MAX_FILE_SIZE 0xffffffff
/* #define RTFS_MAX_FILE_SIZE 0x80000000 */
/* Set to 1 to force RTFS to truncate po_write() requests to fit within
RTFS_MAX_FILE_SIZE. If RTFS_TRUNCATE_WRITE_TO_MAX is set to 0, po_write
requests that attempt to extend the file beyond RTFS_TRUNCATE_WRITE_TO_MAX
Fail and set errno to PETOOLARGE. If RTFS_TRUNCATE_WRITE_TO_MAX is set to
1, po_write requests that attempt to extend the file beyond
RTFS_MAX_FILE_SIZE are truncated to fill the file until its
size reaches RTFS_MAX_FILE_SIZE bytes. */
#define RTFS_TRUNCATE_WRITE_TO_MAX 1
#if (VFAT)
#define FILENAMESIZE_CHARS 255
#else
#if (INCLUDE_CS_UNICODE)
#error - Unicode requires VFAT
#endif
#define FILENAMESIZE_CHARS 8
#endif
#if (VFAT)
#define EMAXPATH_CHARS 260 /* Maximum path length. Change if you like */
#else
#define EMAXPATH_CHARS 148 /* Maximum path length. Change if you like */
#endif
/* Declare buffer sizes, leave room for terminating NULLs, allign to
four bytes for good form. */
#if (VFAT)
#if (INCLUDE_CS_UNICODE || INCLUDE_CS_JIS)
#define EMAXPATH_BYTES 524
#define FILENAMESIZE_BYTES 512
#else
#define EMAXPATH_BYTES 264
#define FILENAMESIZE_BYTES 256
#endif
#else /* Not VFAT */
#if (INCLUDE_CS_UNICODE || INCLUDE_CS_JIS)
#define EMAXPATH_BYTES 300
#define FILENAMESIZE_BYTES 20
#else
#define EMAXPATH_BYTES 152
#define FILENAMESIZE_BYTES 12
#endif
#endif
/* When scanning a directory cluster chain fail if more than this many
clusters are in the chain. (Indicates endless loop)
*/
#define MAX_CLUSTERS_PER_DIR 4096
/* Make sure a character set is enabled */
#if (INCLUDE_CS_JIS)
#if (INCLUDE_CS_UNICODE||INCLUDE_CS_ASCII)
#error Only one character set may be selected
#endif
#elif (INCLUDE_CS_UNICODE)
#if (INCLUDE_CS_JIS||INCLUDE_CS_ASCII)
#error Only one character set may be selected
#endif
#elif (INCLUDE_CS_ASCII)
#if (INCLUDE_CS_UNICODE||INCLUDE_CS_JIS)
#error Only one character set may be selected
#endif
#else
#error At least one character set must be selected
#endif
/*--- ctr modified ---*/
#define RTFS_DEBUG_PRINT_ON (0)
/*--- ctr modified end ---*/
/********************************************************************
TYPES
********************************************************************/
#define TRUE 1 /* Don't change */
#define FALSE 0 /* Don't change */
typedef unsigned char byte; /* Don't change */
typedef unsigned short word; /* Don't change */
typedef unsigned long dword; /* Don't change */
/* typedef int BOOLEAN; Don't change */
#define BOOLEAN int
#endif /* __RTFSCONF__ */

View File

@ -0,0 +1,53 @@
/*****************************************************************************
*Filename: RTFSPRO.H - Defines & structures for RTFSPRO Enhancements
*
*
* EBS - RTFS (Real Time File Manager)
*
* Copyright Peter Van Oudenaren , 2004
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
*
*
* Description:
*
* This file is automatically included in rtfs.h if INCLUDE_RTFS_PRO is enabled
* this file is note intended for inclusion by user code.
*
*
****************************************************************************/
#ifndef __RTFSPRO__
#define __RTFSPRO__ 1
struct pro_buffer_stats {
/* Informational fields. These are filled in by a call to ?? */
int failsafe_mode;
dword failsafe_blocks_used;
dword failsafe_blocks_free;
dword total_block_buffers;
dword block_buffers_pending;
dword block_buffers_available;
dword block_buffers_fail;
dword block_buffers_low;
dword block_buffers_cache_hits;
dword block_buffers_cache_misses;
dword fat_buffers_pending;
dword fat_buffers_free;
dword fat_buffers_available;
dword fat_buffer_primary_cache_hits;
dword fat_buffer_secondary_cache_hits;
dword fat_buffer_cache_loads;
dword fat_buffer_cache_swaps;
dword total_fat_buffers;
};
BOOLEAN pro_buffer_status(byte *drive_name, struct pro_buffer_stats *fsstat);
BOOLEAN pro_assign_buffers(byte *drivename, BLKBUFFCNTXT *block_buffer_context,
int block_hashtable_size, BLKBUFF **block_hash_table,
int block_buffer_pool_size, BLKBUFF *block_buffer_pool_data);
#endif