/* $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 */

#ident "$Header: dio.h 1.1 90/05/02 $"

/*
 * dio.h
 *	direct I/O commands and asynchronous I/O structure definitions
 */


#ifndef	_SYS_DIO_H_

/* $Log:	dio.h,v $
 */

/* Commands for the DIO syscall */
#define	DIO_WRITE	1	/* write command */
#define DIO_READ	2	/* read command */
#define	DIO_AINIT	3	/* initialize for asynchronous I/O */
#define	DIO_APOLL	4	/* poll for completion of async I/O */

/*
 * Structure used for generating an asynchronous I/O request with the
 * DIO_read and DIO_write calls.
 */
struct	AIO_req {
	int	aio_flags;	/* flags and version number, see below */
	int	aio_key;	/* key used to identify request */
	int	aio_sig;	/* signal to be generated on completion */
				/* 0 means no signal */
	pid_t	aio_pid;	/* process to receive signal */
				/* 0 means current process */
};


/* Values for aio_flags */

#define	AIO_VMASK	0xff	/* mask for version number */
#define	AIO_ASYNC	0x100	/* do asynchronous I/O */
#define	AIO_DELAY	0x200	/* wait for asynchronous I/O buffer */


/* Structure used by AIO_poll to return status of completed request */

struct	AIO_status {
	int	aio_error;	/* error number for this request */
	int	aio_size;	/* actual number of bytes transferred */
	int	aio_key;	/* key value for this request */
};

#ifdef	INKERNEL
/*
 * Structures used to track asynchronous I/O request internally in the
 * kernel
 */

struct AIO_buf {
	struct	buf ab_buf;	/* buffer structure for async I/O request */
	struct	AIO *ab_aio;	/* ptr to AIO structure for this request */
	struct	vnode *ab_vnp;	/* pointer to vnode for this request */
	proc_t	*ab_procp;	/* process to receive signal */
	int	ab_extra;	/* amount of request that extends past EOF */
	int	ab_key;		/* key value for request */
	int	ab_sig;		/* signal to be used for this request */
};

struct AIO_uio {
	struct	uio au_uio;	/* uio structure */
	int	au_key;		/* key used to identify this request */
	int	au_sig;		/* signal to be sent on completion */
	struct	vnode *au_vnp;	/* pointer to vnode for this request */
	proc_t	*au_procp; 	/* process to receive the signal */
};
	
struct AIO {
	lock_t	aio_lock;	/* lock for access to this structure */
	int	aio_refcnt;	/* reference count for this structure */
	int	aio_count;	/* count of outstanding request */
	sema_t	aio_sema;	/* I/O completion semaphore */
	dlink_t	aio_pend;	/* list of request to be completed */
	dlink_t	aio_done;	/* list of request that have completed */
};


/* Queue management macros */

/* AQ_INIT and AQ_EMPTY are copies of DL_INIT and DL_EMPTY */
#define AQ_INIT(dl)             { (dl)->dl_next = (dl)->dl_prev = (dl); }

#define AQ_EMPTY(dl)            ((dl)->dl_next == (dl))

/*
 * AQ_APPEND and AQ_DEQUEUE have a first argument of type dlink_t and
 * a second argument of type (struct buf *).
 */
#define AQ_APPEND(dl, bp) { \
	if ((dl)->dl_prev == (dl)) { \
		(dl)->dl_next = (dlink_t *) (bp); \
	} else { \
		((struct buf *) (dl)->dl_prev)->b_forw = (struct buf *) (bp); \
	} \
	((struct buf *) (bp))->b_back = (struct buf *) (dl)->dl_prev; \
	((struct buf *) (bp))->b_forw = (struct buf *) (dl); \
	(dl)->dl_prev = (dlink_t *) (bp); \
}

#define AQ_DEQUEUE(dl, bp) { \
	if (((struct buf *) (bp))->b_back == (struct buf *) (dl)) \
		(dl)->dl_next = (dlink_t *) ((struct buf *) (bp))->b_forw; \
	else \
		((struct buf *) (bp))->b_back->b_forw = \
				((struct buf *) (bp))->b_forw; \
	if (((struct buf *) (bp))->b_forw == (struct buf *) (dl)) \
		(dl)->dl_prev = (dlink_t *) ((struct buf *) (bp))->b_back; \
	else \
		((struct buf *) (bp))->b_forw->b_back = \
				((struct buf *) (bp))->b_back; \
}

extern struct AIO_buf *abuf;
extern int nabuf, maxaio;

#endif	/* INKERNEL */

#endif	/* _SYS_DIO_H_ */
