std_shmem.c 6.02 KB

/**************************************************************************
 *                                                                        *
 *               Copyright (C) 1994, 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.  *
 *                                                                        *
 *************************************************************************/

/*
 * File:	std_shmem.c
 * Creator:	hsa@sgi.com
 * Create Date:	Fri Mar 10 10:43:35 PST 1995
 *
 * This file implements a shared-memory interface to the RSP C 
 * simulator. With this, we can connect the simulator directly
 * to an R4300 simulator.
 *
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <signal.h>
#if 0
#include <errno.h>

extern int errno;
#endif

#include <sys/mman.h>
#include <fcntl.h>

#include <PR/rsp_ipc.h>

#include <PR/os.h>	/* for signal */
#include <PR/em.h>	/* for signal */
#include <errno.h>

#include "rsp.h"
#include "rspctl.h"
#include "memory.h"

/*
 * Define this for more verbose messages...
#define SP_VERBOSE	1
 */

#ifndef KSEG0_BASE
#   define KSEG0_BASE      (0x20000000)
#endif

static int		semid;
static rsp_shm_buf_t	*bufptr = (rsp_shm_buf_t *) -1;

/*
 * initialize the shared memory interface.
 */
void
rsp_ShmemInit(int mem_key, char *dramFile)
{
    int		sem_key, dramfd;
    
    sem_key = mem_key + 10;
    
#ifdef SP_VERBOSE
       fprintf(stderr,"rsp : mem_key = %d sem_key = %d\n",
	       mem_key, sem_key);
#endif
    
    /*
     * To simulate DRAM, create a shared mapped file that can be used
     * by the emulator and the rsp simulator.
     */
    if ((dramfd = open(dramFile, O_RDWR, 0600)) == -1) {
	fprintf(stderr, "rsp : cannot create temp file %s (%s)\n",
		dramFile, strerror(errno));
	exit(1);
    }
    
    if (mmap((void *)KSEG0_BASE, sizeof(rsp_shm_buf_t), PROT_READ|PROT_WRITE|PROT_EXEC,
#ifdef __linux__
	     MAP_FIXED|MAP_SHARED,
#else
	     MAP_FIXED|MAP_SHARED|MAP_AUTOGROW,
#endif
	     dramfd, 0) == (void *)-1) {
	fprintf(stderr,
		"rsp : mmap(0x%x, 0x%x) of temp file failed (%s)\n",
		KSEG0_BASE, sizeof(rsp_shm_buf_t),
		strerror(errno));
	exit(1);
    }

    bufptr = (rsp_shm_buf_t *) KSEG0_BASE;
    
    bufptr->cmd = CMD_NULL;

    /*
     * open a semaphore.
     */
    if ((semid = sem_open(sem_key)) < 0) {
	fprintf(stderr,"%s : can't open semaphore.\n", "rsp");
	exit(-1);
    }

    /*
     * re-direct DRAM:
     */
    rsp_mainMemory = (u8 *) &(bufptr->dram[0]);
}

/*
 * take over the RSP. Does not return (until the 'quit' command)
 */
void
rsp_ShmemRun()
{
    int		docont = 1;
    char	cmd[32], oldline[256], regsym[32];
    int		lastcmd = -1;

    /*
     * this loop becomes the clock loop, calling ProcessorStep()
     * when the RSP is running.
     *
     */
#ifdef SP_VERBOSE
    fprintf(stderr,"rsp command loop starting\n");
#endif
    while (docont) {

#ifdef SP_VERBOSE
	if (bufptr->cmd != lastcmd) {
	    fprintf(stderr,"rsp : cmd = %d\n",bufptr->cmd);
	    lastcmd = bufptr->cmd;
	}
#endif

	/* test (read) the command with out semaphores... */
	if (bufptr->cmd != CMD_NULL) {
	    /* new command, lock semaphore and process: */
	    sem_wait(semid);
	    if (bufptr->cmd == CMD_QUIT) {
		fprintf(stdout,"rsp server: received quit command...");
		docont = 0;
	    } else if (bufptr->cmd == CMD_CMD) {

		/* check for null command (repeat last command) */
		if (bufptr->string[0] != '\n') {
		    strcpy(oldline, bufptr->string);
		}

#ifdef SP_VERBOSE
		fprintf(stderr,"rsp : server command [%s]\n",oldline);
#endif

		/* pick off first thing typed: */
		sscanf(oldline,"%s",cmd);
		if ((strncmp(cmd, "step", strlen(cmd)) == 0) ||
		    (strncmp(cmd, "run", strlen(cmd)) == 0)) {
		    /* don't let 'run' or 'step' commands through */
		} else {
		    process_command(cmd, oldline, NULL);
		}
	    } else if (bufptr->cmd == CMD_DMA_READ) {
		/* read memory */
		/* copy 'length' bytes from 'addr' to 'buff' */
		rsp_MemToIPC(bufptr->addr, (u32) &(bufptr->buff[0]), 
			     bufptr->length);
	    } else if (bufptr->cmd == CMD_DMA_WRITE) {
		/* write memory */
		/* copy 'length' bytes from 'buff' to 'addr' */
		rsp_MemFromIPC((u32) &(bufptr->buff[0]), bufptr->addr, 
			       bufptr->length);
	    } else if (bufptr->cmd == CMD_READ_WORD) {
		bufptr->buff[0] = rsp_MemReadMap(bufptr->addr);
	    } else if (bufptr->cmd == CMD_WRITE_WORD) {
		rsp_MemWriteMap(bufptr->addr, bufptr->buff[0]);
	    } else {
		fprintf(stderr,"rsp : BOGUS COMMAND!\n");
	    } 
	    bufptr->cmd = CMD_NULL;
	    sem_signal(semid);
	}

	/*
	 * check for somebody that has initiated 'single-step'.
	 */
	if (!Flagged(rsp_controlReg, rsp_CtlHaltMask) && docont &&
	    Flagged(rsp_controlReg, SP_STATUS_SSTEP)) {
#ifdef SP_VERBOSE
		fprintf(stderr,"rsp : in single step mode\n");
#endif
	    rsp_ProcessorSStep();
	    rsp_controlReg = Flag(rsp_controlReg, SP_STATUS_HALT);
	    rsp_controlReg = Flag(rsp_controlReg, SP_STATUS_BROKE);
	}


	if (!Flagged(rsp_controlReg, rsp_CtlHaltMask) && docont) {
	    rsp_ProcessorStep();
#ifdef SP_VERBOSE
		fprintf(stderr,"rsp : step?\n");
#endif
	    /*
	     * Detect a break.
	     */
#ifdef SP_VERBOSE
		fprintf(stderr,"about to check break...\n");
#endif
	    if (!Flagged(rsp_controlReg, SP_STATUS_SSTEP) &&
		Flagged(rsp_controlReg, rsp_CtlHaltMask)) {
#ifdef SP_VERBOSE
		fprintf(stderr,"rsp : BREAK!!!!!!!!!!!!!!!!\n");
#endif
		fflush(stderr);
		kill(getppid(), SIGSP);
	    }
	}
    }

    /*
     * close the semaphore.
     */
    sem_close(semid);

    fprintf(stdout,"[rsp server] exiting.\n");
    fflush(stdout);

    /*
     * So the emulator exits first, avoiding SIGCHLD problems...
     */
    sleep(10);
}