pfsreadwritefile.c 5.1 KB
/**************************************************************************
 *                                                                        *
 *               Copyright (C) 1995, Silicon Graphics, Inc.               *
 *                                                                        *
 *  These coded instructions, statements, and computer programs  contain  *
 *  unpublished  proprietary  information of Silicon Graphics, Inc., 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 Silicon Graphics, Inc.  *
 *                                                                        *
 **************************************************************************/

#include "osint.h"
#include "controller.h"

#define	CHECK_IPAGE(p,pfs)	(((p).ipage >= (pfs).inode_start_page) && \
                                 ((p).inode_t.bank < (pfs).banks) && \
                                 ((p).inode_t.page >= 0x01) && \
                                 ((p).inode_t.page < 0x80))

static	s32
__osPfsGetNextPage(OSPfs *pfs, u8 *bank, __OSInode *inode, __OSInodeUnit *page)
{
    s32  ret;

    /*  If given inode data is invalid -> load new inode */
    if (page->inode_t.bank != *bank) {
	*bank = page->inode_t.bank;
	if ((ret = __osPfsRWInode(pfs, inode, PFS_READ, *bank)) != 0) {
	    return(ret);
	}
    }
    *page = inode->inode_page[page->inode_t.page];
  
    if (!CHECK_IPAGE(*page, *pfs)) {
        if (page->ipage == PFS_EOF) {
            return(PFS_ERR_INVALID);
        }
        return(PFS_ERR_INCONSISTENT);
    }
    return 0;
}


s32
osPfsReadWriteFile(OSPfs *pfs, s32 file_no, u8 flag, int offset, 
		   int size_in_bytes, u8 *data_buffer)
{
    s32		  ret;
    __OSDir 	  dir;
    __OSInode 	  inode;
    __OSInodeUnit cur_page;
    int		  cur_block;
    int		  siz_block;
    u8 		  *buffer;
    u8  	  bank;
    u16		  blockno;

    if ((file_no >= (s32)pfs->dir_size) || (file_no < 0))
        return(PFS_ERR_INVALID);
    if ((size_in_bytes <= 0) || ((size_in_bytes % BLOCKSIZE) != 0))
        return(PFS_ERR_INVALID);
    if ((offset < 0) || ((offset % BLOCKSIZE) != 0))
        return(PFS_ERR_INVALID);
    if (!(pfs->status & PFS_INITIALIZED))
        return(PFS_ERR_INVALID);
  
    if (__osCheckId(pfs) == PFS_ERR_NEW_PACK) {
        return(PFS_ERR_NEW_PACK);
    }
  
    /* Get dir and inode structures */

#ifdef	_PFS_1M_EXTENSION
    if ((ret = __osPfsSelectIdBank(pfs)) != 0) return(ret);
#else
    if (pfs->activebank != 0) {
        if ((ret = __osPfsSelectBank(pfs, 0)) != 0)
            return(ret);
    }
#endif
    if ((ret = __osContRamRead(pfs->queue, pfs->channel,
			     (u16)(pfs->dir_table + (int)file_no),
			     (u8 *)&dir)) != 0)
        return(ret);	
	
    if ((dir.company_code == 0) || (dir.game_code == 0))
        return(PFS_ERR_INVALID);

    if (!CHECK_IPAGE(dir.start_page, *pfs)) {
        if (dir.start_page.ipage == PFS_EOF) {
            return(PFS_ERR_INVALID);
        }
        return(PFS_ERR_INCONSISTENT);
    }
  
    if ((flag == PFS_READ) && ((dir.status & PFS_WRITTEN) == 0))
        return(PFS_ERR_BAD_DATA);
  
    /* inode buffer is empty, so set "bank" to dummy value */
    bank = 255;
  
    /* get offset */
    cur_block = offset / BLOCKSIZE;
    cur_page  = dir.start_page;
  
    /* seek to the specified offset */
    while (cur_block >= 8) {
        if ((ret = __osPfsGetNextPage(pfs,&bank,&inode,&cur_page)) != 0) {
            return (ret);
        }
        cur_block -= 8;
    }
  
    /* read/write data from/to memory pack */
  
    siz_block = size_in_bytes / BLOCKSIZE;
    buffer = data_buffer;
  
    while (siz_block > 0) {
    
        /* check if end of block in current page */
        if (cur_block == 8) {
            if ((ret = __osPfsGetNextPage(pfs,&bank,&inode,&cur_page)) != 0) {
	        return (ret);
            }
            cur_block = 0;
        }  /* if */
    
        /* check active bank */
        if (pfs->activebank != cur_page.inode_t.bank) {
            if ((ret = __osPfsSelectBank(pfs, cur_page.inode_t.bank)) != 0) {
	        return(ret);
            }
        }  /* if */

        blockno = (u16)((u16)cur_page.inode_t.page * PFS_ONE_PAGE + cur_block);
        if (flag == PFS_READ) {
            ret = __osContRamRead(pfs->queue, pfs->channel, blockno, buffer);
        } else {	
            ret = __osContRamWrite(pfs->queue, pfs->channel,blockno,buffer,0);
        }
        if (ret != 0) return(ret);
    
        buffer += BLOCKSIZE;
        cur_block ++;
        siz_block --;
    }  /* while */

    if (flag == PFS_WRITE && !(dir.status & PFS_WRITTEN)) {
        dir.status |= PFS_WRITTEN;
#ifdef	_PFS_1M_EXTENSION
	if ((ret = __osPfsSelectIdBank(pfs)) != 0) return(ret);
#else
	if (pfs->activebank != 0)
	  if ((ret = __osPfsSelectBank(pfs, 0)) != 0) return(ret);
#endif
        if ((ret = __osContRamWrite(pfs->queue, pfs->channel,
				(u16)(pfs->dir_table + (int)file_no),
				(u8 *)&dir, 0)) != 0)
            return(ret);
    }  /* if */

    ret = __osPfsGetStatus(pfs->queue, pfs->channel);
    return(ret);
}