contramwrite.c 3.81 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"
#ifdef BBPLAYER
#include "bbint.h"
#endif

#ifndef BBPLAYER
extern	int	__osPfsLastChannel;
#endif

/*
 * This call issues a write memory card command to controllers to write
 * ram pad  from controllers.
 * A value of 0 is returned if the calls succeed, otherwise
 * error code is returned
 */
s32
__osContRamWrite(OSMesgQueue *mq, int channel, u16 address, u8 *buffer, 
	         int force)
{
	s32	ret = 0;
#ifndef BBPLAYER
	int	i;
	u8 	*ptr;
	int	retry = 2;
	u8	crc;
#endif

	if ((force != PFS_FORCE) && (address < PFS_LABEL_AREA) 
			&& (address != 0)){
		/* protect id area */
		return(0);
	}

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

#ifdef BBPLAYER
	if (__osBbPakAddress[channel]) {
	    if (address*BLOCKSIZE <= __osBbPakSize-BLOCKSIZE) {
                int i;
                for (i = 0; i < BLOCKSIZE; ++i) {
                    *((u8*)(__osBbPakAddress[channel]+address*BLOCKSIZE+i)) = buffer[i] ;
                }
            }
#ifndef _FINALROM
	    else if ((address != 0x400 || buffer[0] != 0)) /* bank select */
		osSyncPrintf("unexpected pfs write %x\n", address);
#endif

	} else
	    ret = PFS_ERR_NOPACK;
#else
	do { 	/* Retry if ADRS/DATA CRC error */
	  ptr = (u8 *)(&__osPfsPifRam);

	  if (__osContLastCmd != CONT_RAM_WRITE
	      || __osPfsLastChannel != channel) {
	    __osContLastCmd = CONT_RAM_WRITE;
	    __osPfsLastChannel = channel;

	    /* Set up request command format for all channels */
	    for (i = 0; i < channel; i++) *ptr++ = 0;

	    /* set format flag */
	    __osPfsPifRam.pifstatus = CONT_FORMAT;

	    /* Setup ram read format */
	    ((__OSContRamReadFormat *)ptr)->dummy = 0xff;
	    ((__OSContRamReadFormat *)ptr)->txsize = 35;
	    ((__OSContRamReadFormat *)ptr)->rxsize = 1;
	    ((__OSContRamReadFormat *)ptr)->cmd = CONT_RAM_WRITE;
	    ((__OSContRamReadFormat *)ptr)->datacrc = 0xff;

	    /* setup ram read format */
	    ptr[sizeof(__OSContRamReadFormat)] = FORMAT_END;
	  } else {
	    ptr += channel;
	  }
	  ((__OSContRamReadFormat *)ptr)->addrh =	(u8)(address >>3);
	  ((__OSContRamReadFormat *)ptr)->addrl =
	    (u8)( (address << 5) | __osContAddressCrc(address)) ;

	  bcopy(buffer, ((__OSContRamReadFormat *)ptr)->data, BLOCKSIZE);
	
	  ret = __osSiRawStartDma(OS_WRITE, &__osPfsPifRam);
	  crc = __osContDataCrc(buffer);
	  (void)osRecvMesg(mq, (OSMesg *)NULL, OS_MESG_BLOCK);

	  /* trigger pifmacro */
	  ret = __osSiRawStartDma(OS_READ, &__osPfsPifRam);
	  (void)osRecvMesg(mq, (OSMesg *)NULL, OS_MESG_BLOCK);

#ifndef _HW_VERSION_1
	  ret = (s32)((((__OSContRamReadFormat *)ptr)->rxsize & CON_ERR_MASK) >> 4);
#endif
	  if (ret == 0) {

	    /* check data CRC */
	    if (crc != ((__OSContRamReadFormat *)ptr)->datacrc){
	      /* reset status */
	      if ((ret = __osPfsGetStatus(mq, channel)) != 0){
		break;
	      } else {
		ret = PFS_ERR_CONTRFAIL;
	      }
	    }
	  } else {
	    ret = PFS_ERR_NOPACK;
	  }
	} while ((ret == PFS_ERR_CONTRFAIL) && (retry-- >= 0));
#endif
	__osSiRelAccess();
	return(ret);
}