/*	@(#)debugsys.h	13.1 (RC International) 91/02/02	*/

/*
 * Header for debugopen, debugcontrol calls
 */

#define	MAXBKPT		64
#define	MAXCOMMAND	32	/* MAXCOMLEN??? */

/* fd = debugopen(sbbid, processor, processid); */
enum	processor_type	{ UPU_PROC, RPU_PROC, CIP_PROC, IOP_PROC };
#define	DEBUG_WHOLE	-1	/* processid for whole processor */

/* result = debugcontrol(fd, request, inp, outp); */
/*
 * Each request has an input structure and an output structure (possibly).
 * Result indicates success (0) or failure (-1) as normal.
 */

/*
 * Input and output structures.
 */

/*
 * DC_ADDRESSING:
 * Mode is physical, kernel virtual, or user virtual.  If user virtual then
 * process number is given.  Subsequent reads and writes use this address space.
 * Normal is kernel virtual. For addresses in the u. region the process
 * number controls which area is viewed (procnum==DEBUG_WHOLE means current).
 * Foregoing applies only to upu-as-a-whole.  Input is new value,
 * output is old value.
 */
enum	dc_addr	{ DCA_KERNEL, DCA_USER, DCA_PHYSICAL };
struct	dc_addrmode
{
	enum dc_addr	mode;
	int		procnum;
};

/*
 * DC_GET_BREAK, DC_SET_BREAK:
 * Description of breakpoint is following:
 *  type of breakpoint (code, memory)
 *  address of breakpoint
 *  if debugging as-a-whole, description of which processes get it:
 *   (tagged union) name of processes; process numbers; everyone
 *  breakpoint count - if nonzero is to be executed past that many times
 *  breakpoint condition (TBD)
 *  if memory break, access class (read/write)
 */
enum	dc_breakty	{ DCB_CURRENT, DCB_NAME, DCB_NUMBERS, DCB_ALL };
enum	dc_holdty	{ DCH_PROCESS, DCH_THIS, DCH_BOTH, DCH_ALL };
struct	dc_break
{
	bool_t		membreak:1;	/* true for memory breaks */
	bool_t		mem_rw:1;	/* memory: read/write vs. readonly */
	enum dc_breakty	procty:3;	/* current proc, name, numberlist, all*/
	enum dc_holdty	holdty:3;	/* who gets stopped? */
	u_int		nproc:8;	/* for nl, all */
	u_int		count:16;	/* break repetition */
	caddr_t		address;
	union
	{
	    char	procname[MAXCOMMAND];	/* name */
	    short	procnum[MAXCOMMAND/sizeof(short)]; /* number */
	    /* single procnum in current case - filled in when set */
	    /* all: procnum is exception list */
	}		whichproc;
	/* struct ???	condition;	null for now */
};

/*
 * DC_GET_BREAK:
 */
struct	dc_breakd
{
	struct dc_break	b;
	int		uid;
	enum dc_addr	addrmode;
};

/*
 * DC_GET_BREAKSET, DC_SET_BREAKSET:
 * Array containing mask of breakpoints which apply to this process.
 */
struct	dc_brkmask
{
	char		brkmask[MAXBKPT/NBBY];
};

/*
 * DC_SET_BREAKSET:
 * Process number (-as-a-whole), array containing new mask for this process
 * (see DC_GET_BREAKSET). Output is old value of mask.
 */
struct	dc_brknewset
{
	int		procnum;
	char		brkmask[MAXBKPT/NBBY];
};

/*
 * DC_CLEAR_BREAK, DC_GET_BREAK, DC_SET_BREAK:
 * Breakpoint numbers are kept per-UPU where the system call is made.
 * -1 means all (suser for this) for clear.
 */
struct	dc_brkno
{
	int		brkno;
};

/*
 * DC_SET_BREAK:
 * Breakpoint numbers are kept per-UPU where the system call is made.
 */
struct	dc_brknoset
{
	int		brkno;
	bool_t		already;
};

/*
 * DC_GET_BREAKSET:
 * For -as-a-whole, the process number in question.
 */
struct	dc_brkset
{
	int		procnum;
};

/*
 * DC_GET_CPUREGS, DC_SET_CPUREGS:
 * Structure with fields for registers each stored as 32 bits.
 */
struct	dc_cpuregs
{
	int		sr;
	int		lo;
	int		hi;
	int		badVA;
	int		cause;
	int		epc;
	int		pc;
	int		fp;	/* used by DBX to hold the frame pointer */
};

/*
 * DC_CATCH_EXIT:
 * Catch is flag for yes (doit) or no (don't doit).  Sets state of UPU user
 * process so that before exiting (with state intact) it takes a breakpoint.
 * Input is new value, output is old value.
 */
struct	dc_exitstate
{
	bool_t		catch;
};

/*
 * DC_FILESTATUS:
 * Descriptor number of file. UPU user processes only.
 */
struct	dc_filenum
{
	int		filenum;
};

/*
 * DC_FILESTATUS:
 * Structure with file information, tbd (like stat) with file pointers too...
 * UPU user processes only.
 */
struct	dc_filestate
{
	struct stat	fstat;
	int		flag;		/* as from fcntl */
	off_t		offset;		/* current file offset */
	/* other stuff? */
};

/*
 * DC_GET_FPUREGS, DC_SET_FPUREGS:
 * Array of {f0 - f31, fcr} (as 32-bit quantities).
 * For setregs, output is old values.
 */
struct	dc_fpuregs
{
	int		fgr[32];
	int		fcr;
};

/*
 * DC_GET_GENREGS, DC_SET_GENREGS:
 * Array of the 4 paramregs and the 31 general registers r1 - r31:
 * { at, v0-v1, a0-a3, t0-t7, s0-s7, t8-t9, k0-k1, gp, sp, fp(s8), ra }.
 * They are addressed with the offsets from ../rc/reg.h
 * For setregs, output is old values.
 */
struct	dc_genregs
{
	int		rv[35];
};

/*
 * DC_HOLD:
 * For debug_whole indicates who to hold...
 */
struct	dc_hold
{
	enum dc_holdty	holdty;
};

/*
 * DC_GET_MMUREGS, DC_SET_MMUREGS:
 * Structure of all MMU registers.  Applies to kern only.
 * For setregs, output is old values.
 */
struct	dc_mmuregs
{
	int		entryhi;
	int		entrylo;
	int		index;
	int		random;
};

/*
 * DC_NEWCHILD:
 */
struct	dc_newchild
{
	int		pid;
	bool_t		isnew;	/* fork/vfork/run vs. exec */
};

/*
 * DC_OKRUN:
 * If set, ok to respond even if the object is running.
 * Return the old value.
 */
struct	dc_okrun
{
	bool_t		okrun;
};

/*
 * DC_CONTINUE, DC_STEP:
 * Signo is signal to continue with (0 for none).  Subsequent debugcontrol
 * calls hang until the process stops.  To kill the process do a continue
 * with SIGKILL.  Signals apply to UPU user processes only.  Count is the
 * number of times this will be done until control returns.
 * DC_STEP does this with the trace trap bit set.
 */
struct	dc_proceed
{
	int		signo;
	int		count;
};

/*
 * DC_PROCSTATUS:
 * Collection of random info about the process.
 * UPU user processes only; if want this for RPU processes use another command.
 */
struct	dc_procstate
{
	int		pri;
	int		pgrp;
	int		pid;
	int		uid;
	int		ruid;
	/* command; other stuff */
};

/*
 * DC_RPRCSTATUS:
 * Collection of random info about the rpu process.
 * RPU processes only.
 */
struct	dc_rprcstate
{
	char		name[MAXCOMMAND];
	short		priority;
	short		pid;
	struct queue	*q;
	int		*stackbase;
	int		*stacktop;
	int		alarmsec;
	char		state;		/* in <rte/process.h> */
	char		wait_flags;
	char		processor;
};

/*
 * DC_SERIAL_COMM:
 * Set to use serial line, clear to use ethernet.  Kernel debugging only.
 */
struct	dc_serial
{
	bool_t		use_serial;
};

/*
 * DC_GET_SIGNAL, DC_SET_SIGNAL:
 * Mask of signals; bits are set if the signal is to be handed directly to
 * the process as opposed to, to the debugger.  UPU user processes only.
 * The old value of the mask is returned for set.
 */
struct	dc_signal
{
	int		sigmsk;
};

/*
 * DC_SIGSTATUS:
 * Table of signal state for process (array of signal vectors plus everything
 * else from u.)  UPU user processes only.
 */
struct	dc_sigstate
{
	int		(*signal[NSIG])();
	int		sigmsk[NSIG];
	int		sigonstack;
	int		oldmask;
	int		code;
	struct sigstack	sigstack;
};

/*
 * DC_STATUS:
 * Structure with reason the process stopped.  For UPU user processes
 * this is a signal number.  For others this is the trap code, e.g. ABT, ...
 * Get numbers for these from some kernel header file.  The common reason
 * is BPT (breakpoint).  For processes which are not stopped but are blocked, 
 * that should be returned as well.  If stopped due to a breakpoint the
 * "breakpoint number" is in value.  Value for DCS_BLOCKED is ???.
 * Value for DCS_EXIT (see catch-exit) is exit code as returned to wait.
 * Procnum is for -as-a-whole, to identify which process was running.
 */
enum	dc_st_type 
{
	DCS_SIGNAL, DCS_BREAK, DCS_TRAP, DCS_BLOCKED,
	DCS_EXIT, DCS_RUNNING, DCS_HOLD
};
struct	dc_status
{
	enum dc_st_type	type;
	int		value;
	int		procnum;
};

enum	dc_request
{
				/* input		output */
	DC_ADDRESSING,		/* dc_addrmode		dc_addrmode */
	DC_CATCH_EXIT,		/* dc_exitstate		dc_exitstate */
	DC_CLEAR_BREAK,		/* dc_brkno */
	DC_CONTINUE,		/* dc_proceed */
	DC_FILESTATUS,		/* dc_filenum		dc_filestate */
	DC_GET_BREAK,		/* dc_brkno		dc_breakd */
	DC_GET_BREAKSET,	/* dc_brkset		dc_brkmask */
	DC_GET_CPUREGS,		/*			dc_cpuregs */
	DC_GET_FPUREGS,		/*			dc_fpuregs */
	DC_GET_GENREGS,		/* 			dc_genregs */
	DC_GET_MMUREGS,		/*			dc_mmuregs */
	DC_GET_SIGNAL,		/*			dc_signal */
	DC_HOLD,		/* dc_hold */
	DC_OKRUN,		/* dc_okrun		dc_okrun */
	DC_PROCSTATUS,		/*			dc_procstate */
	DC_RESOURCE,		/*			rusage */
	DC_RLIMIT,		/*			rlimit */
	DC_RPRCSTATUS,		/*			dc_rprcstate */
	DC_RTEINFO,		/*			rteinfo */
	DC_SERIAL_COMM,		/* dc_serial		dc_serial */
	DC_SET_BREAK,		/* dc_break		dc_brkno */
	DC_SET_BREAKSET,	/* dc_brknewset		dc_brkmask */
	DC_SET_CPUREGS,		/* dc_cpuregs		dc_cpuregs */
	DC_SET_FPUREGS,		/* dc_fpuregs		dc_fpuregs */
	DC_SET_GENREGS,		/* dc_genregs		dc_genregs */
	DC_SET_MMUREGS,		/* dc_mmuregs		dc_mmuregs */
	DC_SET_SIGNAL,		/* dc_signal		dc_signal */
	DC_SIGSTATUS,		/*			dc_sigstate */
	DC_STATUS,		/*			dc_status */
	DC_STEP,		/* dc_proceed */
	DC_NEWCHILD,		/* 			dc_newchild */
	DC_LAST		/* MUST BE LAST ONE */
};

/*
 * Random notes:
 * DC_RESOURCE and DC_RLIMIT apply only to UPU user processes.
 * DC_RTEINFO applies only to non-user processes (or whole).
 */
