/*
 *	Micro RTX bindings for the gnu C compiler
 *
 *	  ++jrb		bammi@dsrgsun.ces.cwru.edu
 *
 *  preprocessor symbols:
 *	__NO_INLINE__	if #define'd do not generate inline traps. use
 *			functional form of bindings in grtxbind.c (32 bit)
 *			or srtxtraps.s (16 bit default ints).
 *			you'll need to #define this when using some
 *			debuggers, that otherwise get confused by
 *			inline traps.
 *
 *	__MSHORT__	automatically defined when compiling with 16
 *			bit integer defaults for `int'. automatically
 *			undefined when compiling for 32 bit ints.
 *
 */
#ifndef _RTXBIND_H
#define _RTXBIND_H

#include <basepage.h>
#include <osbind.h>

#if ((defined(__GNUC__)) && (!defined(__NO_INLINE__)))
/*
 * GNU C (pseudo inline) Statement Exprs for traps
 *	note: use of statement expr instead of inline routines
 *	due to brain damage in gcc 1.36.
 *
 *	to see the actual rtxbindings search for the string 'data struct'
 *	forward in this file
 */

#define _trap5_w(n)							\
({									\
	long retvalue;							\
	    								\
	__asm__ volatile						\
	("\
		movw    %1,sp@-; \
		trap    #5;	\
		addqw   #2,sp;	\
		movl    d0,%0"						\
	: "=g"(retvalue)			/* outputs */		\
	: "r"(n)				/* inputs  */		\
	: "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */	\
	);								\
	retvalue;							\
})

#define _trap5_wl(n, l1)						\
({									\
	long retvalue;							\
	    								\
	__asm__ volatile						\
	("\
 		movl	%2,sp@-; \
		movw    %1,sp@-; \
		trap    #5;	\
		addqw   #6,sp;	\
		movl    d0,%0"						\
	: "=g"(retvalue)			/* outputs */		\
	: "r"(n), "r"(l1)			/* inputs  */		\
	: "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */	\
	);								\
	retvalue;							\
})

#define _trap5_wlw(n, l1, w1)						\
({									\
	long retvalue;							\
	    								\
	__asm__ volatile						\
	("\
 		movw	%3,sp@-; \
 		movl	%2,sp@-; \
		movw    %1,sp@-; \
		trap    #5;	\
		addqw   #8,sp;	\
		movl    d0,%0"						\
	: "=g"(retvalue)			/* outputs */		\
	: "r"(n), "r"(l1), "r"(w1)		/* inputs  */		\
	: "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */	\
	);								\
	retvalue;							\
})

#define _trap5_wlwl(n, l1, w1, l2)					\
({									\
	long retvalue;							\
	    								\
	__asm__ volatile						\
	("\
 		movl	%4,sp@-; \
 		movw	%3,sp@-; \
 		movl	%2,sp@-; \
		movw    %1,sp@-; \
		trap    #5;	\
		lea     sp@(12),sp;	\
		movl    d0,%0"						\
	: "=g"(retvalue)			/* outputs */		\
	: "r"(n), "r"(l1), "r"(w1), "r"(l2)	/* inputs  */		\
	: "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */	\
	);								\
	retvalue;							\
})

#define _trap5_wll(n, l1, l2)						\
({									\
	long retvalue;							\
	    								\
	__asm__ volatile						\
	("\
 		movl	%3,sp@-; \
 		movl	%2,sp@-; \
		movw    %1,sp@-; \
		trap    #5;	\
		lea     sp@(10),sp;	\
		movl    d0,%0"						\
	: "=g"(retvalue)			/* outputs */		\
	: "r"(n), "r"(l1), "r"(l2)		/* inputs  */		\
	: "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */	\
	);								\
	retvalue;							\
})

#define _trap5_wlll(n, l1, l2, l3)					\
({									\
	long retvalue;							\
	    								\
	__asm__ volatile						\
	("\
 		movl	%4,sp@-; \
 		movl	%3,sp@-; \
 		movl	%2,sp@-; \
		movw    %1,sp@-; \
		trap    #5;	\
		lea     sp@(14),sp;	\
		movl    d0,%0"						\
	: "=g"(retvalue)			/* outputs */		\
	: "r"(n), "r"(l1), "r"(l2), "r"(l3)	/* inputs  */		\
	: "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */	\
	);								\
	retvalue;							\
})

#define _trap5_wwl(n, w1, l1)						\
({									\
	long retvalue;							\
	    								\
	__asm__ volatile						\
	("\
 		movl	%3,sp@-; \
 		movw	%2,sp@-; \
		movw    %1,sp@-; \
		trap    #5;	\
		addqw   #8,sp;	\
		movl    d0,%0"						\
	: "=g"(retvalue)			/* outputs */		\
	: "r"(n), "r"(w1), "r"(l1)		/* inputs  */		\
	: "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */	\
	);								\
	retvalue;							\
})

#define _trap5_wllwl(n, l1, l2, w1, l3)					\
({									\
	long retvalue;							\
	    								\
	__asm__ volatile						\
	("\
 		movl	%4,sp@-; \
 		movw	%3,sp@-; \
		movl    %2,sp@-; \
 		movl	%1,sp@-; \
		movw    %0,sp@-" \
	: 						/* outputs */	\
	: "r"(n), "r"(l1), "r"(l2), "r"(w1), "r"(l3)	/* inputs  */	\
	);								\
	__asm__ volatile						\
	("\
		trap    #5;	\
		lea     sp@(16),sp;	\
		movl    d0,%0"						\
	: "=g"(retvalue)			/* outputs */		\
	: 					/* inputs  */		\
	: "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */	\
	);								\
	retvalue;							\
})

#define _trap5_wlwwlwll(n, l1, w1, w2, l2, w3, l3, l4)			\
({									\
	long retvalue;							\
	    								\
	__asm__ volatile						\
	("\
 		movl	%4,sp@-; \
 		movl	%3,sp@-; \
		movw    %2,sp@-; \
 		movl	%1,sp@-; \
		movw    %0,sp@-" \
	: 						/* outputs */	\
	: "r"(w2), "r"(l2), "r"(w3), "r"(l3), "r"(l4)	/* inputs  */	\
	);								\
	__asm__ volatile						\
	("\
 		movw	%3,sp@-; \
 		movl	%2,sp@-; \
		movw    %1,sp@-; \
		trap    #5;	\
		lea     sp@(24),sp;	\
		movl    d0,%0"						\
	: "=g"(retvalue)			/* outputs */		\
	: "r"(n), "r"(l1), "r"(w1)		/* inputs  */		\
	: "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */	\
	);								\
	retvalue;							\
})

#define _trap5_wwllllll(n, w1, l1, l2, l3, l4, l5, l6)			\
({									\
	long retvalue;							\
	    								\
	__asm__ volatile						\
	("\
 		movl	%4,sp@-; \
 		movl	%3,sp@-; \
		movl    %2,sp@-; \
 		movl	%1,sp@-; \
		movl    %0,sp@-" \
	: 						/* outputs */	\
	: "r"(l2), "r"(l3), "r"(l4), "r"(l5), "r"(l6)	/* inputs  */	\
	);								\
	__asm__ volatile						\
	("\
 		movl	%3,sp@-; \
 		movw	%2,sp@-; \
		movw    %1,sp@-; \
		trap    #5;	\
		lea     sp@(28),sp;	\
		movl    d0,%0"						\
	: "=g"(retvalue)			/* outputs */		\
	: "r"(n), "r"(w1), "r"(l1)		/* inputs  */		\
	: "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */	\
	);								\
	retvalue;							\
})

/*
 * additional gemdos bindings (not in <osbind.h>)
 */
#define trap_1_wwwll(n, w1, w2, l1, l2)					\
({									\
	long retvalue;							\
									\
	__asm__ volatile						\
	("\
		movl    %4,sp@-; \
		movl    %3,sp@-; \
		movw    %2,sp@-; \
		movw    %1,sp@-; \
		movw    %0,sp@- "					\
	:					 /* outputs */		\
	: "r"(n), "r"(w1), "r"(w2), "r"(l1), "r"(l2) /* inputs  */	\
	);								\
  /* no more than 5 operand allowed in asm() -- therefore the split */  \
									\
	__asm__ volatile						\
	("\
		trap    #1;	\
		lea    sp@(14),sp;	\
		movl    d0,%0"						\
	: "=g"(retvalue)			/* outputs */		\
	:					/* inputs  */		\
	: "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */	\
	);								\
	retvalue;							\
})

#else /* __GNUC__ && !__NO_INLINE__ */

/* if inlines are not allowed, then declare things external */
/* if __MSHORT__ is defined (16 bit integers) then use the
   "traditional" rtxbind. Otherwise, pick up the
   necessary stuff from the library(grtxbind.c), relying on the fact that the
   default return type (int) is 32 bits, hence big enough to hold return
   values.
*/
#ifdef __MSHORT__
extern long gemdos(), rtxbind();
#define _trap5_w		rtxbind
#define _trap5_wl		rtxbind
#define _trap5_wlw		rtxbind
#define _trap5_wlwl		rtxbind
#define _trap5_wll		rtxbind
#define _trap5_wlll		rtxbind
#define _trap5_wwl		rtxbind
#define _trap5_wllwl		rtxbind
#define _trap5_wlwwlwll		rtxbind
#define _trap5_wwllllll		rtxbind
#define trap_1_wwwll		gemdos

#else

extern long
    	_trap5_w(), _trap5_wl(), _trap5_wlw(), _trap5_wlwl(), _trap5_wll(),
	_trap5_wlll(), _trap5_wwl(), _trap5_wllwl(), _trap5_wlwwlwll(),
	_trap5_wwllllll(), trap_1_wwwll();

#endif /* __MSHORT__ */
#endif /* !__NO_INLINE__ */

/*
 * data structs
 */
typedef struct {
    BASEPAGE *basepage;		/* gemdos basepage (extern BASEPAGE *_base) */
    short max_proc;		/* max processes        	            */
    short max_msgs;		/* max system message buffers  	            */
    short max_queues;		/* max message queue        	            */
    void (*create_call)();	/* process creation hook 	*/
    void (*delete_call)();	/* process delete hook		*/
    void (*switch_call)();	/* process (re)schedule hook	*/
} CONFIG;

typedef struct {		/* RTX process status */
    unsigned short	unused1:10;
    unsigned short	EWAIT:1;	/* blocked for event */
    unsigned short	QWAIT:1;	/* blocked for queue */
    unsigned short	PAUSED:1;	/* blocked for timer */
    unsigned short	RUNNING:1;	/* running	     */
    unsigned short	READY:1;	/* ready to run	     */
    unsigned short	unused2:1;
} PROCESS_STATE;

typedef struct {	/* RTX sgtty */
    unsigned short	unused1:7;
    unsigned short	FD_RAWIO:1;
    unsigned short	FD_NOECHO:1;
    unsigned short	FD_CLOSED:1;
    unsigned short	FD_PIPE:1;
    unsigned short	FD_STD:1;
    unsigned short	FD_WRITE:1;
    unsigned short	FD_READ:1;
    unsigned short	FD_FILE:1;
    unsigned short	FD_TTY:1;
} RTXTTY;


#define rtx_install(conf) \
    (char *)_trap5_wl((short)0x00, (CONFIG *)(conf))

#define p_create(name, priority, slice, load, arg_count, args, stack_size)  \
    (char *)_trap5_wlwwlwll((short)0x01, (char *)(name), (short)(priority), \
			    (short)(slice), (void(*)())(load),		    \
			    (short)(arg_count), (char *)(args),             \
			    (long)(stack_size))
#define 	p_delete(pid) \
    (short)_trap5_wl((short)0x02, (char *)(pid))

#define 	p_priority(pid, delta) \
    (short)_trap5_wlw((short)0x03, (char *)pid, (short)(delta))

#define		p_slice(pid, delta) \
    (short)_trap5_wlw((short)0x04, (char *)(pid), (short)(delta))

#define		q_create(name, mode) \
    (char *)_trap5_wlw((short)0x05, (char *)(name), (short)(mode))

#define 	q_delete(qid) \
    (short)_trap5_wl((short)0x06, (char *)(qid))

#define		q_send(qid, msg) \
    (short)_trap5_wll((short)0x07, (char *)(qid), (long *)(msg))

#define		q_req(qid, msg, nowait_option, timeout) \
    (short)_trap5_wllwl((short)0x08, (char *)(qid), (long *)(msg), \
                  	(short)(nowait_option), (long)(timeout))

#define		q_jam(qid, msg) \
    (short)_trap5_wll((short)0x09, (char *)(qid), (long *)(msg))

#define		e_signal(pid, event) \
    (short)_trap5_wlw((short)0x0a, (char *)(pid), (short)(event))

#define		e_wait(event, condition, timeout) \
    (short)_trap5_wlwl((short)0x0b, (short *)(event), (short)(condition), \
		       (long)(timeout))

#define		p_pause(msec) \
    (short)_trap5_wl((short)0x0c, (long)(msec))

#define		m_alloc(size) \
    (void *)_trap5_wl((short)0x0d, (unsigned long)(size))

#define		m_free(segment) \
    (short)_trap5_wl((short)0x0e, (void *)(segment))

#define 	m_assign(segment, pid) \
    (short)_trap5_wll((short)0x0f, (void *)(segment), (char *)(pid))

#define		 p_lookup(name) \
    (char *)_trap5_wl((short)0x010, (char *)(name))

#define		 q_lookup(name) \
    (char *)_trap5_wl((short)0x011, (char *)(name))


#define		p_info(pid, state) \
    (char *)_trap5_wll((short)0x012, (char *)(pid), (PROCESS_STATE *)(state))

#define 	p_vector(pid, vector) \
    (void *)_trap5_wll((short)0x013, (char *)(pid), (void *)(vector))

#define		p_suspend(pid)  /* ret type in manual does'nt jive */ \
    (short)_trap5_wl((short)0x014, (char *)(pid))

#define		p_resume(pid)   /* ret type in manual does'nt jive */ \
    (short)_trap5_wl((short)0x015, (char *)(pid))

#define		d_install(unit, name, constat, conin, conout, costat, cntrl) \
    (short)_trap5_wwllllll((short)0x016, (short)(unit), (char *)(name), \
			   (void(*)())(constat), (void(*)())(conin),    \
			   (void(*)())(conout),  (void(*)())(costat),   \
			   (void(*)())(cntrl))

#define		d_cntrl(unit, parm) \
    (short)_trap5_wwl((short)0x017, (short)(unit), (void *)(parm))

#define		q_info(qid, proc_q, msg_q) \
    (short)_trap5_wlll((short)0x018, (char *)(qid), (short *)(proc_q), \
		       (short *)(msg_q))

#define 	rtx_remove() \
    (short)_trap5_w((short)0x0ff)

#define		Popen(fd) \
    (short)trap_1_wl((short)0x100,(short *)(fd))

#define 	Ftype(handle) \
    (short)trap_1_ww((short)(0x101),(short)(handle))

#define		Flock(fd, flag, offset, length) \
    (short)trap_1_wwwll((short)(0x102), (short)(fd), (short)(flag), \
			(long)(offset), (long)(length))


#define		Fcntrl(fd, mode) \
    (RTXTTY)trap_1_www((short)(0x104), (short)(fd), (RTXTTY)(mode))
    
#define 	Psettpa(size) \
    (long)trap_1_wl((short)(0x103),(long)(size))

#define 	Mquota(a) \
    (long)trap_1_wl((short)(0x105), (long)(a))	/* is this correct?? */

#endif /* _RTXBIND_H */
