/* $Id: hdblib.c,v 1.3 91/09/24 12:58:11 don Exp $ */
/* ex:set ts=4 sw=4: */
/****************************************************************/
/* hdblib.c - hps debugger memory read library					*/
/****************************************************************/
/*                 Confidential Information                     */
/*      Limited Distribution to Authorized Persons Only         */
/*     Created 1990 and Protected as an Unpublished Work        */
/*          Under the U.S. Copyright Act of 1976.               */
/*         Copyright (c) 1990, Systech Corporation              */
/*                  All Rights Reserved                         */
/*																*/
/*	THIS SOFTWARE IS LICENSED BY AND IS THE	CONFIDENTIAL AND 	*/
/*	PROPRIETARY PROPERTY OF SYSTECH COMPUTER CORPORATION AND 	*/
/*	MAY NOT, WITHOUT THE PRIOR WRITTEN CONSENT OF SYSTECH 		*/
/*	COMPUTER CORPORATION, BE REPRODUCED, USED OR DISCLOSED 		*/
/*	EXCEPT IN ACCORDANCE WITH A SYSTECH COMPUTER CORPORATION 	*/
/*	SOFTWARE LICENSE AGREEMENT.									*/
/****************************************************************/
/* This is a routine to read hps memory from either an actual	*/
/* board or a dumpfile.											*/
/****************************************************************/

/*
 *	INCLUDES
 */

#include <stdio.h>
#include <memory.h>
#include "hps.std.h"
#include "hps.iocb.h"
#include "hps.ioctl.h"
#include "hps.swap.h"
#include "st.dump.h"

#ifdef HPS_STREAMS
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/stropts.h>
#include "hps_svcintf.h"
#endif

/*
 *	IMPORTS
 */

extern long lseek();

extern long ram_start;
extern long ram_end;
extern long dumpfile;
extern char hps_intel;

/*
 *	LOCALS
 */

/*
 * Raw driver IOCB and data 
 */
static struct whole_thing
{
	LOADER_IOCB 	raw_iocb;
	char 		raw_buffer[512];
} iocb_buf;

/*
 *	FUNCTION hps_lread - read a block of memory from host adapter or dump file
 *
 *	DESCRIPTION
 *		This function reads a block of memory from either a Systech host 
 *		adapter or a Systech dumpfile.
 *
 *	PARAMETERS
 *		hpsfd	- file descriptor of open raw device or dump file
 *		dest	- buffer address to read into
 *		source	- source address on board or in file - this is an on board
 *					memory address
 *		count	- number of bytes to read (1..512)
 *
 *	GLOBAL VARIABLES USED
 *		ram_start	First valid address on source
 *		ram_end		Last valid address on source
 *		dumpfile	0 = board, non-zero = dumpfile
 *		hps_intel	used for byte-swapping
 *
 *	RETURN VALUES
 *		count		Successful return
 *		0			Invalid source address (outside range ram_start-ram_end)
 *		-1			Some file failure during read
 */
hps_lread(hpsfd, dest, source, count, pname)
int hpsfd;
char *dest;
bit32 source;
int count;
char *pname;
{
	bit32 ltmp;

#ifdef HPS_STREAMS
	struct strbuf	ctlbuf;
	struct strbuf	datbuf;
	long			ctlcmd;
	int				gflags;
#endif	

	if (source < ram_start || source >= ram_end)
	{
		fprintf(stderr, "%s: Requested address (0x%x) is outside the range 0x%x to 0x%x\n",
			pname, source, ram_start, ram_end);
		return(0);
	}

	if (dumpfile)
	{
		if (lseek(hpsfd, (source-ram_start)+DTOT_LEN, 0) < 0)
		{
			fprintf(stderr, "%s: Seek failed.\n", pname);
			perror(pname);
			return(-1);
		}
		if (read(hpsfd, dest, count) != count)
		{
			fprintf(stderr, "%s: Read failed.\n",pname);
			perror(pname);
			return(-1);
		}
	}
	else
	{
		memset(iocb_buf.raw_buffer, '\0', 512);

		iocb_buf.raw_iocb.header.len = sizeof(LOADER_IOCB);
		iocb_buf.raw_iocb.header.maj_dev = 1;
		iocb_buf.raw_iocb.header.min_dev = 0;
		iocb_buf.raw_iocb.header.int_enab = 1;
		iocb_buf.raw_iocb.header.data.hps_32 = (bit32)iocb_buf.raw_buffer;
		iocb_buf.raw_iocb.header.data_len = count;

		if (hps_intel)
		{
			iocb_buf.raw_iocb.command = (READ<<8)|(READ>>8);
			iocb_buf.raw_iocb.cmd_modifier = 0;
			SWAP_4BYTE(&ltmp, &source);
			iocb_buf.raw_iocb.hpsadr.hps_32 = ltmp;
			iocb_buf.raw_iocb.priority = 0;
			iocb_buf.raw_iocb.tid = 0;
			iocb_buf.raw_iocb.mode = 0x0100;
		}
		else
		{
			iocb_buf.raw_iocb.command = READ;
			iocb_buf.raw_iocb.cmd_modifier = 0;
			iocb_buf.raw_iocb.hpsadr.hps_32 = source;
			iocb_buf.raw_iocb.priority = 0;
			iocb_buf.raw_iocb.tid = 0;
			iocb_buf.raw_iocb.mode = 1;
		}

#	ifdef HPS_STREAMS 
		ctlbuf.maxlen = 0;
		ctlbuf.len    = sizeof(long);
		ctlbuf.buf    = (char *)&ctlcmd;
		ctlcmd        = HPS_DOIOCB;
		datbuf.maxlen = 0;
		datbuf.len    = sizeof(iocb_buf);
		datbuf.buf    = (char *)&iocb_buf;

		if (putmsg(hpsfd,&ctlbuf,&datbuf,0) < 0)
		{
			printf("hps_lread: putmsg failed\n");
			return(-1);
		}

		ctlbuf.len    = 0;
		ctlbuf.maxlen = sizeof(long);
		ctlbuf.buf    = (char *)&ctlcmd;
		datbuf.len    = 0;
		datbuf.maxlen = sizeof(iocb_buf);
		datbuf.buf    = (char *)&iocb_buf;
		gflags        = 0;
		ctlcmd        = 0;
		bzero((char *)&iocb_buf,sizeof(iocb_buf));

		if (getmsg(hpsfd,&ctlbuf,&datbuf,&gflags) != 0)
#	elif BSD
		if (read(hpsfd, &iocb_buf, sizeof(iocb_buf)) < 0)
#	else
		if (ioctl(hpsfd, DO_IOCB, &iocb_buf) < 0)
#	endif
		{
			fprintf(stderr, "%s: Read failed.\n", pname);
			perror(pname);
			return(-1);
		}

		memcpy(dest, iocb_buf.raw_buffer, count);
	}
	return(count);
}

/*
 * MODIFICATION HISTORY:
 *
 * $Log:	hdblib.c,v $
 * Revision 1.1.2.1  92/06/24  13:53:16  marker
 * Branch RISCOS_5_01_2_FIXES off of trunk.
 * 
 * Revision 1.3  91/09/24  12:58:11  don
 * Changed to use hps.std.h not hps.types.h.
 * Changed to use st.dump.h for DTOT_LEN rather than 1024.
 * Added standard file header information.
 * Used memset() and memcpy().
 * Other misc stuff.
 * INTERNAL
 * 
 * 
 */
