Interdata732/usr/sys/selch.c

#

/*
 * Selector channel scheduling routines
 */

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

#define	NSELCH	2	/* number of channels */

char	selchaddr[NSELCH] = {
	0xf0,
	0xf1
};

#define devmap(addr)	(addr&03)	/* map channel address=>channel no. */

/*
 * Queue of devices using selch
 *	- top of queue is currently active device; others are waiting
 */
struct {
	struct selchq	*sc_actf;
	struct selchq	*sc_actl;
} selchtab[NSELCH];

/*
 * Request use of selch #n
 */
selchreq(n, selchq)
struct selchq *selchq;
{
	register struct selchq *s;
	register struct selchtab *st;
	register free;
	trace(040<<16, "schrequest", selchq);

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

	(s = selchq)->sq_forw = 0;
	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)();
}

/*
 * Free selch #n for next device
 */
selchfree(n)
{
	register struct selchq *s;
	register struct selchtab *st;

	st = &selchtab[n];
	trace(040<<16, "schfree", st->sc_actf);
	if ((s = st->sc_actf) == 0)
		return;
	st->sc_actf = s = s->sq_forw;

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

/*
 * Selector channel interrupt -- handled by currently active device
 */
selchintr(dev, stat)
{
	register struct selchq *s;
	register struct selchtab *st;
	trace(040<<16, "interrupt", dev);
	trace(040<<16, "status", stat);

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