fs.c 10.1 KB
#include "ultra64.h"
#include <PR/bcp.h>
#include "os_bb.h"

#include "fs.h"


#define DMA_QUEUE_SIZE	200
#define PRINTF		osSyncPrintf
#define MSG_FAULT	0x10


/*
 * Thread and stack structures
 */
char   bootStack[STACKSIZE] __attribute__ ((aligned (8)));

static OSThread idleThread;
static char     idleThreadStack[STACKSIZE] __attribute__ ((aligned (8)));

static OSThread mainThread;
static char     mainThreadStack[STACKSIZE] __attribute__ ((aligned (8)));


/*
 * Message queues and message buffers used by this app 
 */
static OSMesg           PiMessages[DMA_QUEUE_SIZE];
static OSMesgQueue      PiMessageQ;

static OSMesg           SiMessages[DMA_QUEUE_SIZE];
static OSMesgQueue      SiMessageQ;

/*
 * Local variables and routines
 */

static void		idleproc(char *);
static void		mainproc(char *);

void
boot(void)
{
    osInitialize();
    osCreateThread(&idleThread, 1, (void(*)(void *))idleproc, (void *)0,
                   idleThreadStack+STACKSIZE, 8);
    osStartThread(&idleThread);
}


static void
idleproc(char *argv)		/* priority 8 */
{
    osCreateViManager(OS_PRIORITY_VIMGR);
    osViSetMode(&osViModeTable[OS_VI_NTSC_LPN1]);

    /*
     * Start PI Mgr for access to cartridge - start before the debugger
     */
    osCreatePiManager((OSPri) OS_PRIORITY_PIMGR, &PiMessageQ, PiMessages,
            DMA_QUEUE_SIZE);

    osCreateMesgQueue(&SiMessageQ, SiMessages, DMA_QUEUE_SIZE);
    osSetEventMesg(OS_EVENT_SI, &SiMessageQ, (OSMesg)DMA_QUEUE_SIZE);

    /*
     * The main thread's priority must be the same or lower than the original
     * idle's thread priority. This allows the idle thread to change its
     * priority to 0 before the main thread starts execution.
     */
    osCreateThread(&mainThread, 3, (void(*)(void *))mainproc, argv,
           mainThreadStack+STACKSIZE/8, (OSPri)7);
    osStartThread(&mainThread);

    osSetThreadPri(0, OS_PRIORITY_IDLE);
    for(;;);                                    /* idle thread */
}

static OSMesgQueue	retraceMessageQ;
static OSMesg		dummyMessage, retraceMessageBuf;
static u8 block[1024*16];
static OSBbFs fs;
#define NDIR 100
static OSBbDirEnt dir[NDIR];
static OSBbStatBuf sb;
static OSBbStatFs fsb;
static u16 blist[256];
static u8 blocks[16*BB_FL_BLOCK_SIZE];

static u32
dump_file(const char* name, int c) {
    int i, j, rv;
    u32 off;
    u16 sum = 0;
    if ((i = osBbFOpen(name, "r")) < 0) {
	PRINTF("osBbFOpen %s failed %d\n", name, i);
	return 0;
    }
    if ((rv = osBbFStat(i, &sb, NULL, 0)) < 0) {
	PRINTF("osBbFStat failed %d\n", rv);
	return 0;
    }
    PRINTF("type %d size %d\n", sb.type, sb.size);
    if ((rv = osBbFStat(i, &sb, blist, sizeof(blist)/sizeof(blist[0]))) < 0) {
	PRINTF("osBbFStat failed %d\n", rv);
	return 0;
    }
    PRINTF("blocks: ");
    for(j = 0; j < BB_FL_BYTE_TO_BLOCK(sb.size+BB_FL_BLOCK_SIZE-1); j++)
	PRINTF("%d ", blist[j]);
    PRINTF("\n");
    for(off = 0; off < sb.size;) {
	if ((rv = osBbFRead(i, off, block, sizeof block)) < 0)
	    PRINTF("osBbFRead failed %d\n", rv);
	off += BB_FL_BLOCK_SIZE;
	for(j = 0; j < BB_FL_BLOCK_SIZE; j++) {
	    sum += block[j];
	    if (c)
		PRINTF("%c", block[j]);
	}
    }
    if ((rv = osBbFClose(i)) < 0) {
	PRINTF("osBbFClose failed %d\n", rv);
	return 0;
    }
    return sum;
}

static void
dump_dir(int count) {
    int i;
    for(i = 0; i < count; i++)
	osSyncPrintf("%-12s %d %d\n", dir[i].name, dir[i].type, dir[i].size);
}

#if 0
IDE_WRITE(0x046fffe4, 1); /* backdoor module remove */
IDE_WRITE(0x046fffe4, 0); /* backdoor module insert */
#endif

struct {
    char* name;
    u16 sum;
} file[] = {
    { "zero"         , 0 },
    { "one."         , 0xe6b8 } ,
    { "two.x"        , 0x9f21 } ,
    { "three.xy"     , 0x5c1d } ,
    { "four.xyz"     , 0x1e4a } ,
    { "fivefive.xyz" , 0x9a86 } ,
    { "2Mfile.xyz"   , 0xaab0 } , 
    { 0, 0 }
};

static void 
mainproc(char *argv) {
    s32 count, i, j, rv;
    u32 sum, sum2;
    osCreateMesgQueue(&retraceMessageQ, &retraceMessageBuf, 1);
    osViSetEvent(&retraceMessageQ, dummyMessage, 1);

    PRINTF("\n=> mainproc...\n");
    PRINTF("init\n");
    if ((rv = osBbFInit(&fs)) < 0) {
	PRINTF("osBbFInit failed %d\n", rv);
	goto out;
    }
    if ((rv = osBbFStatFs(&fsb)) < 0) {
	PRINTF("osBbFStatFs failed %d\n", rv);
	goto out;
    }
    if (fsb.files != 7 || fsb.freeFiles != BB_INODE16_ENTRIES-fsb.files ||
	fsb.blocks != 143 || fsb.freeBlocks != 3873) {
	PRINTF("osBbFFStatFS files %d free files %d blocks %d free blocks %d\n", fsb.files, fsb.freeFiles, fsb.blocks, fsb.freeBlocks);
	goto out;
    }
    if ((count = osBbFReadDir(dir, NDIR)) < 0 || count != 7) {
	PRINTF("osBbFReadDir failed %d\n", count);
	goto out;
    }
    //dump_dir(count);

    for(i = 0; file[i].name; i++) {
	if ((rv = dump_file(file[i].name, 0)) != file[i].sum) {
	    PRINTF("bad sum %s expected %x computed %x\n", file[i].name, file[i].sum, rv);
	    goto out;
	}
    }
    if ((i = osBbFCreate("zero", 1, BB_FL_BLOCK_SIZE)) != BBFS_ERR_EXISTS) {
	PRINTF("osBbFCreate (exists) failed\n", i);
	goto out;
    }
    if ((i = osBbFCreate("big.c", 1, 1024*16*5000)) != BBFS_ERR_SPACE) {
	PRINTF("osBbFCreate too big file failed %d\n", i);
	goto out;
    }
    if ((i = osBbFCreate("junk.c", 1, BB_FL_BLOCK_SIZE)) < 0) {
	PRINTF("osBbFCreate failed %d\n", i);
	goto out;
    }
    bzero(block, sizeof block);
    strcpy(block, "foobar from hell\n");
    if ((rv = osBbFWrite(i, 0, block, sizeof block)) < 0) {
	PRINTF("osBbFWrite failed %d\n", rv);
	goto out;
    }
    if ((rv = osBbFWrite(i, 2, block, sizeof block/2)) != BBFS_ERR_INVALID) {
	PRINTF("osBbFWrite unaligned length failed %d\n", rv);
	goto out;
    }
    if ((rv = osBbFClose(i)) < 0) {
	PRINTF("osBbFClose failed %d\n", rv);
	goto out;
    }
    dump_file("junk.c", 0);
    if ((rv = osBbFDelete("junk.c")) < 0) {
	PRINTF("osBbFDelete failed %d\n", rv);
	goto out;
    }


    /* make a big file */
    sum = 0;
    for(i = 0; i < 16; i++) {
	for(j = 0; j < BB_FL_BLOCK_SIZE; j++) {
	    blocks[i*BB_FL_BLOCK_SIZE+j] = (j&1)?j : ((i<<4)|(j>>8));
	    sum += blocks[i*BB_FL_BLOCK_SIZE+j];
	}
    }
    if ((i = osBbFCreate("big.c", 1, sizeof blocks)) < 0) {
	PRINTF("osBbFCreate big.c failed %d\n", i);
	goto out;
    }
    if ((rv = osBbFWrite(i, 0, blocks, sizeof blocks)) < 0) {
	PRINTF("osBbFWrite big.c failed %d\n", rv);
	goto out;
    }
    bzero(blocks, sizeof blocks);
    if ((rv = osBbFRead(i, 0, blocks, sizeof blocks)) < 0 || rv != sizeof blocks) {
	PRINTF("osBbFRead big.c failed %d\n", rv);
	goto out;
    }
    sum2 = 0;
    for(j = 0; j < 16; j++) {
	int k;
	for(k = 0; k < BB_FL_BLOCK_SIZE; k++) {
	    sum2 += blocks[j*BB_FL_BLOCK_SIZE+k];
	}
    }
    if (sum != sum2) {
	PRINTF("osBbFRead big.c sum mismatch read %x expected %x\n", sum2, sum);
	goto out;
    }


    dump_file("big.c", 0);
    if ((rv = osBbFRepairBlock(i, 0, blocks, BB_FL_BLOCK_SIZE)) < 0 || rv != BB_FL_BLOCK_SIZE) {
	PRINTF("osBbFRepairBlock big.c failed %d\n", rv);
	goto out;
    }
    dump_file("big.c", 0);

    bzero(blocks, sizeof blocks);
    if ((rv = osBbFRead(i, 0, blocks, sizeof blocks)) < 0 || rv != sizeof blocks) {
	PRINTF("osBbFRead2 big.c failed %d\n", rv);
	goto out;
    }
    sum2 = 0;
    for(j = 0; j < 16; j++) {
	int k;
	for(k = 0; k < BB_FL_BLOCK_SIZE; k++) {
	    sum2 += blocks[j*BB_FL_BLOCK_SIZE+k];
	}
    }
    if (sum != sum2) {
	PRINTF("osBbFRead2 big.c sum mismatch read %x expected %x\n", sum2, sum);
	goto out;
    }
    
    if ((rv = osBbFClose(i)) < 0) {
	PRINTF("osBbFClose big.c failed %d\n", rv);
	goto out;
    }
    if ((rv = osBbFStatFs(&fsb)) < 0) {
	PRINTF("osBbFStat Fsfailed %d\n", rv);
	goto out;
    }
    PRINTF("files %d free %d blocks %d free %d\n", fsb.files, fsb.freeFiles, fsb.blocks, fsb.freeBlocks);
    if ((rv == osBbFRename("big.c", "notbig.c")) < 0) {
	PRINTF("osBbFRename failed %d\n", rv);
	goto out;
    }
    if ((rv = osBbFDelete("big.c")) != BBFS_ERR_ENTRY) {
	PRINTF("osBbFDelete big.c failed %d\n", rv);
	goto out;
    }
    if ((rv = osBbFDelete("notbig.c")) < 0) {
	PRINTF("osBbFDelete notbig.c failed %d\n", rv);
	goto out;
    }
    
    /* test bad parameters descriptors */
    if ((rv = osBbFClose(-1)) != BBFS_ERR_INVALID ||
	(rv = osBbFClose(1000)) != BBFS_ERR_INVALID ||
	(rv = osBbFClose(400)) != BBFS_ERR_INVALID ||
	(rv = osBbFRead(-1, 0, blocks, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFRead(1000, 0, blocks, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFRead(400, 0, blocks, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFRead(0, 0, blocks, 1)) != BBFS_ERR_INVALID ||
	(rv = osBbFRead(0, 0, blocks, BB_FL_BLOCK_SIZE*1000)) != BBFS_ERR_INVALID ||
	(rv = osBbFRead(0, BB_FL_BLOCK_SIZE*1000, blocks, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFRead(0, 1, blocks, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFWrite(1000, 0, blocks, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFWrite(400, 0, blocks, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFWrite(0, 0, blocks, 1)) != BBFS_ERR_INVALID ||
	(rv = osBbFWrite(0, 0, blocks, BB_FL_BLOCK_SIZE*1000)) != BBFS_ERR_INVALID ||
	(rv = osBbFWrite(0, BB_FL_BLOCK_SIZE*1000, blocks, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFWrite(0, 1, blocks, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFStat(-1, 0, 0, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFStat(1000, 0, 0, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFStat(400, 0, 0, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFOpen("", "r")) != BBFS_ERR_INVALID ||
	(rv = osBbFOpen(".", "r")) != BBFS_ERR_INVALID ||
	(rv = osBbFOpen("blahblah", "r")) != BBFS_ERR_ENTRY ||
	(rv = osBbFCreate("", 1, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFCreate(".", 1, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFDelete("")) != BBFS_ERR_INVALID ||
	(rv = osBbFDelete(".")) != BBFS_ERR_INVALID ||
	(rv = osBbFRename("", "foo")) != BBFS_ERR_INVALID ||
	(rv = osBbFRename(".", "foo")) != BBFS_ERR_INVALID ||
	(rv = osBbFRename("foo", "")) != BBFS_ERR_INVALID ||
	(rv = osBbFRename("foo", ".")) != BBFS_ERR_INVALID ||
	(rv = osBbFRepairBlock(-1, 0, blocks, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFRepairBlock(400, 0, blocks, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFRepairBlock(0, BB_FL_BLOCK_SIZE*1000, blocks, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFRepairBlock(0, 0, blocks+1, 0)) != BBFS_ERR_INVALID ||
	(rv = osBbFRepairBlock(-1, 0, blocks, BB_FL_BLOCK_SIZE*1000)) != BBFS_ERR_INVALID
	) {
	PRINTF("osBbFXXX invalid param failed %d\n", rv);
	goto out;
    }

out:
    IO_WRITE(PI_GPIO_REG, 0|(1 << PI_GPIO_ENABLE_SHIFT));
    for(;;) ;
}