/* * 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). * The latter list is kept in last-used order, and the two * lists are doubly linked to make it easy to remove * a buffer from one list when it was found by * looking through the other. * 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 */ #ifndef BUFMOD struct buf *b_forw; /* headed by devtab of b_dev */ struct buf *b_back; /* " */ #endif BUFMOD #ifdef BUFMOD char *b_forw; char *b_back; #endif BUFMOD struct buf *av_forw; /* position on free list, */ struct buf *av_back; /* if not BUSY*/ int b_dev; /* major+minor device name */ int b_wcount; /* transfer count (usu. words) */ char *b_addr; /* low order core address */ #ifdef BUFMOD char *b_paddr; /* physical address/64 of the buffer */ #endif BUFMOD char *b_xmem; /* high order core address */ char *b_blkno; /* block # on device */ char b_error; /* returned after I/O */ char *b_resid; /* words not transferred after error */ char *b_proc; /* process to be notified of i/o completion */ } buf[NBUF]; #ifdef BUFMOD /* control blocks of the NKS system buffers */ struct buf sbuf[NSBUF]; #endif BUFMOD /* * Each block device has a devtab, which contains private state stuff * and 2 list heads: the b_forw/b_back list, which is doubly linked * and has all the buffers currently associated with that major * device; and the d_actf/d_actl list, which is private to the * device but in fact is always used for the head and tail * of the I/O queue for the device. * Various routines in bio.c look at b_forw/b_back * (notice they are the same as in the buf structure) * but the rest is private to each device driver. */ struct devtab { char d_active; /* busy flag */ char d_errcnt; /* error count (for recovery) */ #ifdef BUFMOD char *b_forw; /* first buffer for this dev */ char *b_back; /* last buffer for this dev */ char *d_actf; /* head of I/O queue */ char *d_actl; /* tail of I/O queue */ #endif BUFMOD #ifndef BUFMOD struct buf *b_forw; /* first buffer for this dev */ struct buf *b_back; /* last buffer for this dev */ struct buf *d_actf; /* head of I/O queue */ struct buf *d_actl; /* tail of I/O queue */ #endif BUFMOD }; /* * This is the head of the queue of available * buffers-- all unused except for the 2 list heads. */ struct buf bfreelist; #ifdef BUFMOD /* this is the head of the queue of available system buffers in user space */ struct buf sbfreel; #endif BUFMOD /* * These flags are kept in b_flags. */ #define B_WRITE 0 /* non-read pseudo-flag */ #define B_READ 01 /* read when I/O occurs */ #define B_DONE 02 /* transaction finished */ #define B_ERROR 04 /* transaction aborted */ #define B_BUSY 010 /* not on av_forw/back list */ #define B_PHYS 020 /* Physical IO potentially using UNIBUS map */ #define B_MAP 040 /* This block has the UNIBUS map allocated */ #define B_WANTED 0100 /* issue wakeup when BUSY goes off */ #define B_AGE 0200 /* delayed write for correct aging */ #define B_ASYNC 0400 /* don't wait for I/O completion */ #define B_DELWRI 01000 /* don't write till block leaves available list */ #define B_SPEC 02000 /* special write from physio */ #ifdef PASYNC #define B_PASYNC 04000 /* non-sleeping physio flag jsq BBN 2-26-79 */ #endif #define BUFSIZE 20 /* number of bytes in buf for network interests */