/*
 * Selector channel scheduling routines
 */

#include "../h/local.h"

#ifdef  SCCS_ID
static char SCCS_ID [] = "@(#)selch.c        3.3      15:03:44 - 82/09/10 ";
#endif  SCCS_ID

#include "../h/param.h"
#include "../h/buf.h"
#include "../h/selch.h"


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 selchtab {
	struct selchq	*sc_actf;
	struct selchq	*sc_actl;
} selchtab[8];


/*
 * Request use of selch with address n
 */
selchreq(n, selchq, unit)
struct selchq *selchq;
register int     unit;
{
	register struct selchq *s;
	register struct selchtab *st;
	register free;

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

	(s = selchq)->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 selch with address n for next device
 */
selchfree(n)
{
	register struct selchq *s;
	register struct selchtab *st;

	st = &selchtab[devmap[n]];
	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
 */
selchintr(dev, stat)
{
	register struct selchq *s;
	register struct selchtab *st;

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