Coherent4.2.10/io.386/bufq.c

/* $Header: /ker/io.386/RCS/bufq.c,v 2.3 93/08/19 04:02:17 nigel Exp Locker: nigel $ */
/*
 *	Queueing routines for SCSI driver.
 *	Should be generalizable for other hard drives.
 *
 * $Log:	bufq.c,v $
 * Revision 2.3  93/08/19  04:02:17  nigel
 * Nigel's R83
 * 
 * Revision 2.2  93/07/26  15:28:01  nigel
 * Nigel's R80
 * 
 * Revision 1.1  93/04/14  10:10:07  root
 * r75
 * 
 * Revision 1.3  92/04/06  15:35:10  hal
 * *** empty log message ***
 * 
 * Revision 1.2  91/05/21  23:23:36  hal
 * Enhanced debug printout.
 * 
 * Revision 1.1  91/05/21  13:54:11  root
 * First running version.
 */

#include <sys/coherent.h>
#include <sys/buf.h>

typedef struct {
	BUF	* head;	/* point to first node */
	BUF	* tail;	/* point to last node */
	int	count;	/* number of nodes in the queue */
} bufq_type;

static int	num_q;		/* number of queues in use */
static bufq_type  * bufq_q;	/* pointer to allocated queue structs */


int bufq_init();
void bufq_rlse();
void bufq_wr_tail();
BUF * bufq_rd_head();
BUF * bufq_rm_head();

/*
 * Debug macros.
 */
#if (DEBUG >= 3)
#define QSIZE	printf("Q%d:%d ", s_id, bqp->count)
#else
#if (DEBUG >= 2)
#define QSIZE	{if (bqp->count>1)printf("Q%d:%d ", s_id, bqp->count);}
#else
#define QSIZE
#endif
#endif

/*
 * bufq_init()
 *
 * Set up the desired number of queues.
 *
 * Return 1 if ok, 0 if kalloc() failed.
 */
int bufq_init(qcount)
int qcount;
{
	int ret;

	if (qcount > 0 && (bufq_q = kalloc(qcount*sizeof(bufq_type)))) {
		ret = 1;
		kclear(bufq_q, qcount*sizeof(bufq_type));
		num_q = qcount;
#if (DEBUG >= 2)
printf("%d queues allocated\n", qcount);
#endif
	} else
		ret = 0;

	return ret;
}

/*
 * bufq_rlse()
 *
 * Deallocate buffer queue structs.
 */
void bufq_rlse()
{
	num_q = 0;
	if (bufq_q)
		kfree(bufq_q);
}

/*
 * bufq_wr_tail()
 *
 * Append a BUF object to the doubly-linked queue.
 * Object to be inserted has been allocated by the caller.
 */
void bufq_wr_tail(s_id, bp)
int s_id;
BUF * bp;
{
	int s;
	bufq_type * bqp;

	if (s_id < num_q) {
		bqp = bufq_q + s_id;
		s = sphi();
		if (bqp->count == 0) {
			bqp->head = bqp->tail = bp;
			bp->b_actf = bp->b_actl = NULL;
		} else {
			bqp->tail->b_actf = bp;
			bp->b_actf = NULL;
			bp->b_actl = bqp->tail;
			bqp->tail = bp;
		}
		bqp->count++;
QSIZE;
		spl(s);
	}
}

/*
 * bufq_rd_head()
 *
 * Nondestructively fetch the head entry in the queue - i.e., this routine
 * does not remove an entry from the queue (see ss_rm_head() for that).
 * Return NULL if queue is empty, else return pointer to head item.
 */
BUF * bufq_rd_head(s_id)
int s_id;
{
	bufq_type * bqp;

	if (s_id < num_q) {
		bqp = bufq_q + s_id;
		return bqp->head;
	} else
		return NULL;
}

/*
 * bufq_rm_head()
 *
 * Delete head item from the queue.  Return a pointer to the node deleted,
 * or NULL if the queue was already empty.
 *
 * This routine does NOT deallocate the node.  That must be done by the
 * calling function after this routine runs.
 */
BUF * bufq_rm_head(s_id)
int s_id;
{
	BUF * ret;
	int s;
	bufq_type * bqp;

	if (s_id < num_q) {
		bqp = bufq_q + s_id;
		s = sphi();
		if (bqp->count > 0) {
			ret = bqp->head;
			if (bqp->count == 1) {
				bqp->head = bqp->tail = NULL;
			} else {
				bqp->head = bqp->head->b_actf;
				bqp->head->b_actl = NULL;
			}
			bqp->count--;
QSIZE;
		} else
			ret = NULL;
		spl(s);
	} else
		ret = NULL;

	return ret;
}