/*	Convergent Technologies - System V - May 1983	*/
/*	"@(#)buf.h	1.5"	*/

#ifndef buf_h
#define buf_h

#include <sys/param.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/filsys.h>
#include <sys/ino.h>

/*
 *	This structure describes the current transfer,
 *	where it starts in memory, on the disk and how much will be done
 *	in this dma operation and how much remains to be done.
 */
struct xfrinfo {
	ushort	count;		/* total operation: physical sector count for
				   read/write, byte count for a format */
	ushort	thiscnt;	/* physical sector count for this portion */
	union {			/* 16 bit word adress used in transfer */
		int  b_addr;	/* to be loaded to the DMA */
		struct {
			ushort high;
			ushort low;
		} addr;
	} a_un;	
	ushort	cyl;		/* disk cylinder number for current part */
	ushort	sec;		/* physical sector within track for this part */
	ushort	trk;		/* disk head number for current part */
	char	mode;		/* current operation */
};

/*
 * Each buffer in the pool is usually doubly linked into 2 lists:
 * the device with which it is currently associated (always)
 * and also on a list of blocks available for allocation
 * for other use (usually).
 * A buffer is on the available list, and is liable
 * to be reassigned to another disk block, if and only
 * if it is not marked BUSY.  When a buffer is busy, the
 * available-list pointers can be used for other purposes.
 * Most drivers use the forward ptr as a link in their I/O active queue.
 * A buffer header contains all the information required to perform I/O.
 * Most of the routines which manipulate these things are in bio.c.
 */
struct buf
{
	int	b_flags;		/* see defines below */
	struct	buf *b_forw;		/* headed by d_tab of conf.c */
	struct	buf *b_back;		/*  "  */
	struct	buf *av_forw;		/* position on free list, */
	struct	buf *av_back;		/*     if not BUSY*/
#define	b_actf	av_forw			/* alternate names for driver queue */
#define	b_actl	av_back			/*    head - isn't history wonderful */
	dev_t	b_dev;			/* major+minor device name */
	unsigned b_bcount;		/* transfer count */
#define	b_active b_bcount		/* driver queue head: drive active */
	union {
	    caddr_t b_addr;		/* low order core address */
	    int	*b_words;		/* words for clearing */
	    struct filsys *b_filsys;	/* superblocks */
	    struct dinode *b_dino;	/* ilist */
	    daddr_t *b_daddr;		/* indirect block */
	} b_un;

#define	paddr(X)	(paddr_t)(X->b_un.b_addr)

	daddr_t	b_blkno;		/* block # on device */
	char	b_error;		/* returned after I/O */
	unsigned int b_resid;		/* words not transferred after error */
#define	b_errcnt b_resid		/* while i/o in progress: # retries */
#define	b_pfcent b_resid		/* garbage: don't ask */
	time_t	b_start;		/* request start time */
	struct  proc  *b_proc;		/* process doing physical or swap I/O */
	ushort b_paddr[2];		/* ONLY valid if B_UAREA is set -
					   contains page frame #s for upage */
	struct xfrinfo x;		/* information prepared by gdstrategy
					   to allow transfer to be split
					   into multiple parts if necessary */
	ino_t	b_inode;		/* inode of file using this buffer */
};

extern struct buf bfreelist;		/* head of available list */
extern struct buf pbuf[];		/* Physio header pool */
struct pfree {
	int	b_flags;
	struct	buf *av_forw;
};
extern struct pfree pfreelist;		/* head of physio pool */

extern struct	buf swbuf[];		/* swap I/O headers */
extern int	nswbuf;
extern struct	buf bswlist;		/* head of free swap header list */
extern struct	buf *bclnlist;		/* head of cleaned page list */


/*
 * These flags are kept in b_flags.
 */
#define	B_WRITE		0x0000		/* non-read pseudo-flag */
#define	B_READ		0x0001		/* read when I/O occurs */
#define	B_DONE		0x0002		/* transaction finished */
#define	B_ERROR		0x0004		/* transaction aborted */
#define	B_BUSY		0x0008		/* not on av_forw/back list */
#define	B_PHYS		0x0010		/* Phys IO potentially using mem map */
#define	B_WANTED 	0x0040		/* issue wakeup when BUSY goes off */
#define	B_AGE		0x0080		/* delayed write for correct aging */
#define	B_ASYNC		0x0100		/* don't wait for I/O completion */
#define	B_DELWRI 	0x0200		/* don't write till on available list */
#define	B_STALE 	0x0800		/* contents of buffer no longer current */

#define	B_PGOUT		0x002000	/* dirty page to be pushed out async */
#define	B_PGIN		0x004000	/* pagein op, so swap() can count it */
#define	B_UPAGES	0x200000	/* add u-area to a swap operation */
#define B_FORMAT	0x800000	/* perform a format operation with
					   the data associated with this hdr */
#define B_START		0x01000000	/* operation has been started */

/*
 * Fast access to buffers in cache by hashing.
 */

#define	bhash(d,b)	((struct buf *)&hbuf[(short)(((int)d+(int)b)&v.v_hmask)])

struct hbuf
{
	int	b_flags;
	struct	buf *b_forw;
	struct	buf *b_back;
};

extern struct hbuf hbuf[];
#endif
