pfsinitpak.c 4.86 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"
#include "siint.h"

static s32 __osPfsCheckRamArea(OSPfs *);

s32
osPfsInitPak(OSMesgQueue *queue, OSPfs *pfs, int channel)
{
#ifdef _PFS_1M_EXTENSION
        int	k;
#endif
	s32 ret = 0;
	u16 sum, isum;
	u8 temp[BLOCKSIZE];
	__OSPackId *id;
	__OSPackId newid;

	/* Block to get resource token */
        __osSiGetAccess();

	ret = __osPfsGetStatus(queue, channel);
	
	__osSiRelAccess();

	if (ret != 0) {
	  return(ret);
	}
	
	pfs->queue = queue;
	pfs->channel = channel;
	pfs->status = 0;

	/* Check Ram Area */

	if ((ret = __osPfsCheckRamArea(pfs)) != 0) {
	  return(ret);
	}

	/* Check vaild id */

#ifdef _PFS_1M_EXTENSION
	k = PFS_ID_BANK_256K;
	while (1) {
	  if ((ret = __osPfsSelectBank(pfs, (u8)k)) != 0) return(ret);

	  if ((ret = __osContRamRead(pfs->queue, pfs->channel, 
				     PFS_ID_0AREA, temp)) != 0)
	    return(ret);
	  __osIdCheckSum((u16 *)temp, &sum, &isum);
	  id = (__OSPackId *)temp;
	  if ((id->checksum != sum) || (id->inverted_checksum != isum)) {
	    if (k == PFS_ID_BANK_256K) {
	      k = PFS_ID_BANK_1M;
	    } else {
	      k = -1;
	      break;
	    }
	  } else {
	    break;
	  }
	}
	if (k < 0) {
	  if ((ret = __osCheckPackId(pfs, id)) != 0) {
	    pfs->status |= PFS_ID_BROKEN;
	    return(ret);	  /* PackId has been trashed */
	  }
	}
#else
	if ((ret = __osPfsSelectBank(pfs, 0)) != 0)
	  return(ret);

	if ((ret = __osContRamRead(pfs->queue, pfs->channel, 
					PFS_ID_0AREA, temp)) != 0)
		return(ret);
	__osIdCheckSum((u16 *)temp, &sum, &isum);
	id = (__OSPackId *)temp;
	if ((id->checksum != sum) || (id->inverted_checksum != isum)) {

	  /* PackId has been trashed */
	  
	  if ((ret = __osCheckPackId(pfs, id)) != 0) {
	    pfs->status |= PFS_ID_BROKEN;
	    return(ret);
	  }
	}
#endif

	/* make sure the device is memory pack */

	if ((id->deviceid & 0x01) == 0) {
	  ret = __osRepairPackId(pfs, id, &newid);
	  if (ret)  {
	    if (ret == PFS_ERR_ID_FATAL) pfs->status |= PFS_ID_BROKEN;
	    return(ret);
	  }
	  id = &newid;
	  if ((id->deviceid & 0x01) == 0) {
	    return(PFS_ERR_DEVICE);
	  }
	}

	bcopy(id, pfs->id, BLOCKSIZE);
	
	pfs->version = (int)id->version;

	/* 
	 * we only allow to have 16 files for this release.
	 * 1 page for System ID, 2 pages for Dir, and 1 page for each bank.
	 */

	pfs->banks = id->banks;
#ifdef	_PFS_1M_EXTENSION
	if (pfs->banks > 1) {
	  k = pfs->banks - PFS_ID_BANK_1M;
	} else {
	  k = pfs->banks;
	}
	pfs->inode_start_page = 1 + DEF_DIR_PAGES + (2 * k); 
#else
	pfs->inode_start_page = 1 + DEF_DIR_PAGES + (2 * pfs->banks); 
#endif
	pfs->dir_size =   DEF_DIR_PAGES * PFS_ONE_PAGE;

	/* inode table state from page 1 to page n, 1 page per bank */

	pfs->inode_table = 1 * PFS_ONE_PAGE;	
#ifdef	_PFS_1M_EXTENSION
	pfs->minode_table = (1 + k) * PFS_ONE_PAGE;
	pfs->dir_table = pfs->minode_table + (k * PFS_ONE_PAGE);
#else
	pfs->minode_table = (1 + pfs->banks) * PFS_ONE_PAGE;
	pfs->dir_table = pfs->minode_table + (pfs->banks * PFS_ONE_PAGE);
#endif
		
	if ((ret = __osContRamRead(pfs->queue, pfs->channel,
				   PFS_LABEL_AREA,(u8 *)pfs->label)) != 0)
	  return(ret);


	/* Check integrity of file system -- call osPfsChecker() */

	ret = osPfsChecker(pfs);

	pfs->status |= PFS_INITIALIZED;
	return(ret);
}

static s32
__osPfsCheckRamArea(OSPfs *pfs)			/* Check Ram Area */
{
  s32	i, ret = 0;
  u8	temp1[BLOCKSIZE], temp2[BLOCKSIZE], save[BLOCKSIZE];
  
#ifdef _PFS_1M_EXTENSION
  if ((ret = __osPfsSelectBank(pfs, PFS_ID_BANK_1M)) != 0) {
    return(ret);
  }
#else
  if ((ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K)) != 0) {
    return(ret);
  }
#endif

  /* Save data temporarily */
  if ((ret = __osContRamRead(pfs->queue, pfs->channel, 0, save)) != 0) {
    return(ret);
  }
  for (i = 0 ; i < BLOCKSIZE ; i ++ ) {
    temp1[i] = (u8)i;
  }
  if ((ret = __osContRamWrite(pfs->queue, pfs->channel, 0, temp1, 0)) != 0) {
    return(ret);
  }
  if ((ret = __osContRamRead(pfs->queue, pfs->channel, 0, temp2)) != 0) {
    return(ret);
  }
  if (bcmp(temp1, temp2, BLOCKSIZE) != 0) {
    return(PFS_ERR_DEVICE);
  }
  ret = __osContRamWrite(pfs->queue, pfs->channel, 0, save, 0);

  return(ret);
}