/*
 * Selector channel scheduling routines
 */

#include "../h/local.h"
#ifdef  SCCS_ID
static char SCCS_ID [] = "%Z%%M%        %I%     %Y% %U% - %E% ";
#endif  SCCS_ID

#include "../h/param.h"
#include "../h/buf.h"
#include "../new/xselch.h"
#undef trace


extern char	devmap[];	/* map device address => minor device no */

/*
 * Queue of devices using each selch
 *	- top of queue is currently active device; others are waiting
 *
 * selchtab is indexed by the selch minor device number.
 * This should be generated by mkconf so it can have the
 * exact number of entries for the number of selches in the machine.
 * As it is, we assume that there will be no more than 8 selches.
 */
struct xselchtab {
	struct xselchq   *sc_actf;
	struct xselchq   *sc_actl;
} xselchtab[8];


/*
 * Request use of xselch with address n
 */
xselchreq(n, xselchq, unit)
struct xselchq *xselchq;
int     unit;
{
	register struct xselchq *s;
	register struct xselchtab *st;
	register free;
trace(2<<16, "xschrequest", xselchq);

	st = &xselchtab[devmap[n]];
	/* Make sure request not already on queue */
	for (s = st->sc_actf; s; s = s->sq_forw)
		if (s == xselchq)
			return;

	(s = xselchq)->sq_forw = 0;
	s->sq_unitno = unit;
	if (st->sc_actf) {
		st->sc_actl->sq_forw = s;
		free  = 0;
	} else {
		st->sc_actf = s;
		free = 1;
	}
	st->sc_actl = s;

	if (free){
		(*s->sq_sstart)(s->sq_unitno);
		return(0);
	} else {
		return(1);
	}
}

/*
 * Free xselch with address n for next device
 */
xselchfree(n)
{
	register struct xselchq *s;
	register struct xselchtab *st;

	st = &xselchtab[devmap[n]];
trace(2<<16, "xschfree", st->sc_actf);
	if ((s = st->sc_actf) == 0)
		return;
	st->sc_actf = s = s->sq_forw;

	if (s)
		(*s->sq_sstart)(s->sq_unitno);
}

/*
 * Selector channel interrupt -- handled by currently active device
 */
xselchintr(dev, stat)
{
	register struct xselchq *s;
	register struct xselchtab *st;
trace(4<<16, "xschint", dev);
trace(4<<16, "xstatus", stat);

	st = &xselchtab[dev];
	if (s = st->sc_actf)
		(*s->sq_sintr)(dev, stat, s->sq_unitno);
}
