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;
}