static char rcsid[] = "$Header: mb.c,v 820.1 86/12/04 19:55:57 root Exp $";
static char sccsid[]="%W% %Y% %Q% %G%";

/************************************************************************
*									*
*				Copyright 1984				*
*			VALID LOGIC SYSTEMS INCORPORATED		*
*									*
*	This listing contains confidential proprietary information	*
*	which is not to be disclosed to unauthorized persons without	*
*	written consent of an officer of Valid Logic Systems 		*
*	Incorporated.							*
*									*
*	The copyright notice appearing above is included to provide	*
*	statutory protection in the event of unauthorized or 		*
*	unintentional public disclosure.				*
*									*
************************************************************************/

/*
 * Multibus handler
 *
 * Multibus interrupts from 1 to 5 are vectored to one of mbintr?(),
 * which in turn calls the device interrupt routines.  This way, we
 * can handle multiple devices on the same vector, although slowly.
 *
 * During autoconfig, when a device probe routine causes an interrupt,
 * mbint?() saves the vector number in cvec, and changes the return
 * psl to ipl7 to give the probe routine a chance to clear the interrupt.
 *
 * After configuration, the vectors with only a single device interrupt
 * are redirected to the mbintx?() routines, which is as fast as the
 * pre-autoconfig interrupt scheme.
 */

#include "../h/param.h"
#include "../s32/psl.h"
#include "../s32dev/mbvar.h"

#ifndef lint
extern int cold;
extern int cvec;

	/* stack passed to an interrupt routine via _mbint() */
struct stack {
	int	st_reg[4];		/* d0, d1, a0, a1 */
	u_short	st_psl;			/* return ps */
	caddr_t st_addr;		/* return address */
};

static char mberr[] = "mbint%d: spurious interrupt.\n";
#ifdef DEBUG
static char mbmsg[] = "mbint%d:\n";
#else
static char mbmsg[] = "";
#endif

#define A(a)	asm("a");
#define B(a, b)	asm("a,b");

A(MB_NDEV = 8)

/*
 * Front end to the Multibus interrupt routines
 */
#define _MBINT(f, a) \
int f(); \
	A(	.text) \
	A(	.globl	f) \
	A(f:) \
	B(	moveml	#0xc0c0,sp@-) \
	a \
	B(	moveml	sp@+,#0x0303) \
	B(	addql	#1,cnt+12)		/* ++cnt.v_intr */ \
	A(	jmp	chksoftclk) \
	A(	.data)				/* we need this */

/*
 * Multibus interrupt handler
 *
 * In cold start mode, we just set cvec to ipl - 1, turn off
 * interrupts, and return.
 * Otherwise, each of the interrupt routines at this ipl is called
 * in turn until one returns true.
 */
#define MBINT(ipl) \
_MBINT(mbint/**/ipl, \
	A(	jsr	_mbint/**/ipl)) \
_mbint/**/ipl(s) \
	struct stack s; \
{ \
	register struct mb_vec *p; \
	if (cold) { \
		printf(mbmsg, ipl); \
		s.st_psl |= PSL_INTPRI;		/* return to spl7 */ \
		cvec = ipl - 1; \
		return; \
	} \
	for (p = mb_vec[ipl - 1]; p->mv_func; p++) \
		if ((*p->mv_func)(p->mv_unit)) \
			return; \
	printf(mberr, ipl); \
}

/*
 * Simple Multibus interrupt handler
 *
 * This is used after cold start to handle vectors with only
 * a single interrupt routine.  Here, time is of the essence.
 * The goal is to handle tty input at 9600 baud.
 */
#define MBINTX(ipl) \
_MBINT(mbintx/**/ipl, \
	B(	movl	#[ipl-1]*8*[MB_NDEV+1]+mb_vec,a0) \
	B(	movl	a0@+,a1) \
	B(	movl	a0@,sp@-) \
	A(	jsr	a1@) \
	B(	addql	#4,sp) \
	A(	tstl	d0) \
	A(	bnes	.ipl.x0) \
	B(	movl	#mberr,sp@-) \
	B(	movl	#ipl,sp@-) \
	A(	jsr	printf) \
	B(	addql	#8,sp) \
	A(.ipl.x0:))

MBINT(1)
MBINT(2)
MBINT(3)
MBINT(4)
MBINT(5)
MBINT(6)
MBINT(7)
MBINTX(1)
MBINTX(2)
MBINTX(3)
MBINTX(4)
MBINTX(5)
MBINTX(6)
MBINTX(7)
#else
mbint1() {}
mbint2() {}
mbint3() {}
mbint4() {}
mbint5() {}
mbint6() {}
mbint7() {}
mbintx1() {}
mbintx2() {}
mbintx3() {}
mbintx4() {}
mbintx5() {}
mbintx6() {}
mbintx7() {}
#endif

int (*mbint[MB_NVEC])() =
	{ mbint1, mbint2, mbint3, mbint4, mbint5, mbint6, mbint7 };
int (*mbintx[MB_NVEC])() =
	{ mbintx1, mbintx2, mbintx3, mbintx4, mbintx5, mbintx6, mbintx7 };
