host_ptn64.c 3.51 KB
/**************************************************************************
 *									  *
 *		 Copyright (C) 1997, Kyoto Micro Computer Co.,LTD.	  *
 *									  *
 **************************************************************************/

#include <os.h>

#ifndef _FINALROM

/*
 * For the interval timer used to wait for the partner status
 */
extern void memcpy(void *,void *,u32);

static volatile unsigned *ptwtmode= (unsigned *)0xbff08014;
static volatile unsigned *ptstat= (unsigned *)0xbff08004;
static volatile unsigned *ptport= (unsigned *)0xbff08000;
static volatile unsigned *n64piok= (unsigned *)0xa4600010;

static OSMesgQueue 	waitPtQueue;
static OSMesg		waitPtQueueBuf;

static u32		isWaitPtQueueCreated = 0;

/*
 * Now, we set 1 msec for the interval timer.
 */
#define	WAIT_CYCLES	OS_USEC_TO_CYCLES(1000)

/*
 * Create "waitPtQueue" which is used for the interval timer.
 * We only call this routine once (first time either osReadHost_pt()
 * or osWriteHost_pt() is called).
 */
static void createWaitPtQueue(void)
{
    osCreateMesgQueue(&waitPtQueue, &waitPtQueueBuf, 1);
    isWaitPtQueueCreated = 1;
}

/*
 * Wait for the partner status register's "bit" bit becomes 1.
 * We use an interval timer to wait instead of polling.
 */
static u32 getPT_wait(void)
{
    OSTimer waitTimer;
    u32 status;
  
    for(;;){
	while((*n64piok & 3)!=0) ;
	if((*ptstat & 2)!=0){
	    return *ptport;
	}
	__osPiRelAccess();
	osRecvMesg(&waitPtQueue, NULL, OS_MESG_NOBLOCK);
	osSetTimer(&waitTimer,WAIT_CYCLES,0, &waitPtQueue, NULL);
	osRecvMesg(&waitPtQueue, NULL, OS_MESG_BLOCK);
	__osPiGetAccess();
    }
}

static void putPT(u32 c)
{
    while((*n64piok & 3)!=0) ;
    while((*ptstat & 4)==0) ;
    *ptport=c;
}

static u32 getPT(void)
{
    while((*n64piok & 3)!=0) ;
    while((*ptstat & 2)==0) ;
    return *ptport;
}

void osReadHost_pt(void *dramAddr, u32 nbytes)
{
    u8  *tPtr;
    u32 buf[256],*bp,data;
    u32 ct,ct1,ct1_bak,shift;
    u32 cmd,size;

    if(nbytes==0) return;

    if(!isWaitPtQueueCreated){
	createWaitPtQueue();
    }

    __osPiGetAccess();
    putPT(0x82);
    cmd=getPT_wait();
    size=getPT();
    if(cmd!=2){
	nbytes=(u32)-1;
    }
    putPT(nbytes);
    if(size!=nbytes){
	goto osReadHost_ret;
    }

    tPtr=(u8*)dramAddr;
    ct=nbytes/4;
    while(ct){
	if(ct>sizeof(buf)/4){
	    ct1_bak=ct1=sizeof(buf)/sizeof(u32);
	    ct -= sizeof(buf)/sizeof(u32);
	}
	else{
	    ct1_bak=ct1=ct;
	    ct=0;
	}
	bp=buf;
	while(ct1){
	    *(bp++)=getPT();
	    --ct1;
	}
	memcpy(tPtr,buf,ct1_bak*sizeof(u32));
	tPtr+=ct1_bak*sizeof(u32);
    }
    nbytes &= 3;
    if(nbytes){
	data=getPT();
	shift=24;
	do{
	    *(tPtr++)=(u8)(data>>shift);
	    --nbytes;
	    shift -= 8;
	}while(nbytes) ;
    }

osReadHost_ret:
    __osPiRelAccess();
    return;
}

void osWriteHost_pt(void *dramAddr, u32 nbytes)
{
    u8  *tPtr;
    u32 buf[256],*bp;
    u32 ct,ct1,ct1_bak;
    u32 cmd,size;

    if(nbytes==0) return;

    if(!isWaitPtQueueCreated){
	createWaitPtQueue();
    }

    __osPiGetAccess();
    putPT(0x82);
    cmd=getPT_wait();
    size=getPT();
    if(cmd!=3){
	nbytes=(u32)-1;
    }
    putPT(nbytes);

    if(size!=nbytes){
	goto osWriteHost_ret;
    }
    tPtr=(u8*)dramAddr;
    ct=(nbytes+3)/4;
    while(ct){
	if(ct>sizeof(buf)/4){
	    ct1_bak=ct1=sizeof(buf)/sizeof(u32);
	    ct -= sizeof(buf)/sizeof(u32);
	}
	else{
	    ct1_bak=ct1=ct;
	    ct=0;
	}
	memcpy(bp=buf,tPtr,ct1_bak*sizeof(u32));
	while(ct1){
	    putPT(*(bp++));
	    --ct1;
	}
	tPtr+=ct1_bak*sizeof(u32);
    }
osWriteHost_ret:
    __osPiRelAccess();
    return;
}

#endif