conteepwrite.c 5.98 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
static void	__osPackEepWriteData(u8, u8 *);
#endif

/*
 * This call issues a write eeprom command to pif to write
 * 8 bytes to eeprom.
 * A value of 0 is returned if the calls succeed, otherwise
 * -1 is returned
 */
s32
osEepromWrite(OSMesgQueue *mq, u8 address, u8 *buffer)
{
	s32	ret = 0;
#ifndef BBPLAYER
	u16	type;
	u8 			*ptr = (u8 *)(&__osEepPifRam);
	__OSContEepromFormat 	eepromformat;
	OSContStatus 		sdata;
	u8	temp[8];
#endif
	

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

#ifdef BBPLAYER
	/* continue to use SI as resource token */
	ret = 0;
	if (__osBbEepromSize == 512) {
	    if(address >= EEPROM_MAXBLOCKS) ret = -1;
	} else if (__osBbEepromSize == 2048) {
	    if(address >= EEP16K_MAXBLOCKS) ret = -1;
	} else {
	    ret = CONT_NO_RESPONSE_ERROR;
	}
	if (ret != 0) {
	    __osSiRelAccess();
	    return ret;
	}
        {
            int i;
            for (i = 0; i < EEPROM_BLOCK_SIZE; ++i) {
                *(u8*)(__osBbEepromAddress+address*EEPROM_BLOCK_SIZE+i) = buffer[i];
            }
        }

#else
	/* Need to make sure EEPROM is not busy before write */

	ret = __osEepStatus(mq, &sdata);
	type = (u16)(sdata.type & (u16)(CONT_EEPROM | CONT_EEP16K));

	if (ret == 0) {
	  switch(type) {
	  case (u16)CONT_EEPROM :
	    if(address >= EEPROM_MAXBLOCKS) {
	      ret = -1;
	    }
	    break;
	  case (u16)(CONT_EEPROM | CONT_EEP16K) :
	    if(address >= EEP16K_MAXBLOCKS) {
	      ret = -1;
	    } else if (__osEepromRead16K != 0) {
	      /* dummy read for EEPROM-16K bug */
	      __osEepromRead16K = 0;
	      __osSiRelAccess();
	      osEepromRead(mq, (address^1), temp);
	      __osSiGetAccess();
	    }
	    break;
	  default:
	    ret = CONT_NO_RESPONSE_ERROR;
	  }
	}
	if (ret != 0)  {
	  __osSiRelAccess();
	  return(ret);
	}

	while (sdata.status & CONT_EEPROM_BUSY) {
		__osEepStatus(mq, &sdata);
	}
		
	/* Set up request command format for eeprom */

	__osPackEepWriteData(address, buffer);
	ret = __osSiRawStartDma(OS_WRITE, &__osEepPifRam);
	(void)osRecvMesg(mq, (OSMesg *)NULL, OS_MESG_BLOCK);

	/* trigger pifmacro */

	 ret = __osSiRawStartDma(OS_READ, &__osEepPifRam);
	__osContLastCmd = CONT_EEPROM_WRITE;

	(void)osRecvMesg(mq, (OSMesg *)NULL, OS_MESG_BLOCK);

	ptr += MAXCONTROLLERS;
	
	eepromformat = *((__OSContEepromFormat *)ptr);
#ifndef _HW_VERSION_1
	ret = (s32)((eepromformat.rxsize & CON_ERR_MASK) >> 4);
#endif
#endif
	__osSiRelAccess();
	return(ret);
}

#ifndef BBPLAYER
static void
__osPackEepWriteData(u8 address, u8* buffer)
{
	u8 			*ptr = (u8 *)(&__osEepPifRam);
	__OSContEepromFormat 	eepromformat;
	int 			i;

	/* clear pif ram */

#if	0
	for (i = 0; i < PIFRAMSIZE-1 ; i++)
		__osEepPifRam.ramarray[i] = 0xff;
#endif
#ifndef _HW_VERSION_1
	__osEepPifRam.pifstatus = CONT_FORMAT;
#else
	__osEepPifRam.pifstatus = 0;
#endif 

	/* Setup eeprom format */

        eepromformat.txsize = 10;
        eepromformat.rxsize = 1;
        eepromformat.cmd = CONT_EEPROM_WRITE;
        eepromformat.address = address;
        for (i = 0; i < EEPROM_BLOCK_SIZE ; i++)
                eepromformat.data[i] = *buffer++;


	for (i = 0; i < MAXCONTROLLERS; i++)
		*ptr++ = 0;

        *((__OSContEepromFormat *)ptr) = eepromformat;

#ifndef _HW_VERSION_1
	ptr += sizeof(eepromformat);
	*((u8 *)ptr) = FORMAT_END;
#endif
}

s32
__osEepStatus(OSMesgQueue *mq, OSContStatus *data)
{
	s32 			ret = 0;
	int i;
	u8 			*ptr = (u8 *)(&__osEepPifRam);
	__OSContRequesFormat 	requestformat;
	
	/* Set up request command format for channel 5 */

	for (i = 0; i < PIFRAMSIZE ; i++)
                __osEepPifRam.ramarray[i] = 0;
#ifndef _HW_VERSION_1
        __osEepPifRam.pifstatus = CONT_FORMAT;
#else
        __osEepPifRam.pifstatus = 0;
#endif
	ptr = (u8 *)(&__osEepPifRam);
	for (i = 0; i < MAXCONTROLLERS; i++) 
		*ptr++ = 0;

	requestformat.dummy = 0xff;
        requestformat.txsize = 1;
        requestformat.rxsize = 3;
        requestformat.cmd = CONT_REQUEST;
        requestformat.typeh = 0xff;
        requestformat.typel = 0xff;
        requestformat.status = 0xff;
        requestformat.dummy1 = 0xff;

	*((__OSContRequesFormat *)ptr) = requestformat;
	ptr += sizeof(requestformat);
#ifndef _HW_VERSION_1
        *((u8 *)ptr) = FORMAT_END;
#endif

	ret = __osSiRawStartDma(OS_WRITE, &__osEepPifRam);
	(void)osRecvMesg(mq, (OSMesg *)NULL, OS_MESG_BLOCK);
	__osContLastCmd = CONT_ETC; /* NOT CONT_REQUEST!! */
	
	/* trigger pifmacro */

	ret = __osSiRawStartDma(OS_READ, &__osEepPifRam);
	(void)osRecvMesg(mq, (OSMesg *)NULL, OS_MESG_BLOCK);
	if (ret)
		return(ret);
	
	/* Reformat the 64 bytes RAM data into RequestData format */

	ptr = (u8 *)(&__osEepPifRam);
	for (i = 0; i < MAXCONTROLLERS; i++) 
		*ptr++ = 0;

	requestformat = *((__OSContRequesFormat *)ptr);
#ifndef _HW_VERSION_1
                data->errno = (u8)((requestformat.rxsize & CON_ERR_MASK) >> 4);
#else
                data->errno = (u8)(((requestformat.txsize & CON_ERR_MASK) >> 4)
                | ((requestformat.rxsize & CON_ERR_MASK) >> 6));
#endif
	data->type =(u16)((requestformat.typel<<8)|requestformat.typeh);
	data->status = requestformat.status;
	if (data->errno)
		return((s32)(data->errno));
	return(0);
}
#endif