contramread.c 3.29 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"

extern OSPifRam		__osPfsPifRam;		/* RAM buffer */
int			__osPfsLastChannel = -1;

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

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

	do { 	/* Retry if ADRS/DATA CRC error */
	  ptr = (u8 *)(&__osPfsPifRam);

	  if (__osContLastCmd != CONT_RAM_READ
	      || __osPfsLastChannel != channel) {
	    __osContLastCmd = CONT_RAM_READ;
	    __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 = 3;
	    ((__OSContRamReadFormat *)ptr)->rxsize = 33;
	    ((__OSContRamReadFormat *)ptr)->cmd = CONT_RAM_READ;
	    ((__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)) ;

	  ret = __osSiRawStartDma(OS_WRITE, &__osPfsPifRam);
	  (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 (__osContDataCrc(((__OSContRamReadFormat *)ptr)->data)
		!= ((__OSContRamReadFormat *)ptr)->datacrc) {
	      /* reset status */
	      if ((ret = __osPfsGetStatus(mq, channel)) != 0){
		break;
	      } else {
		ret = PFS_ERR_CONTRFAIL;
	      }
	    } else {
	      bcopy(((__OSContRamReadFormat *)ptr)->data, buffer, BLOCKSIZE);
#if 0
	      if (((__OSContRamReadFormat *)ptr)->datacrc == 0xff) {
		ret = __osPfsGetStatus(mq, channel);
	      }
#endif
	    }
	  } else {
	    ret = PFS_ERR_NOPACK;
	  }
	} while ((ret == PFS_ERR_CONTRFAIL) && (retry-- >= 0));
	__osSiRelAccess();
	return(ret);
}