Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ buf(D4DK) — Motorola System V 88k Release 4 Version 4.3

Media Vault

Software Library

Restoration Projects

Artifacts Sought

buf(D4DK)  —  

.IX \f4buf\fP(D4DK)

NAME

buf − block I/O data transfer structure

SYNOPSIS

#include <sys/types.h>
#include <sys/page.h>
#include <sys/proc.h>
#include <sys/buf.h>

DESCRIPTION

.IX \f4strategy\fP(D2DK)
.IX buffer header, \f4buf\fP(D4DK)
.IX block I/O, \f4buf\fP(D4DK)
The buf structure is the basic data structure for block I/O transfers.  Each block I/O transfer has an associated buffer header.  The header contains all the buffer control and status information.  For drivers, the buffer header pointer is the sole argument to a block driver strategy(D2DK) routine.  Do not depend on the size of the buf structure when writing a driver. 

It is important to note that a buffer header may be linked in multiple lists simultaneously.  Because of this, most of the members in the buffer header cannot be changed by the driver, even when the buffer header is in one of the drivers’ work lists. 

Buffer headers may be used by the system to describe a portion of the kernel data space for I/O for block drivers.  Buffer headers are also used by the system for physical I/O for block drivers.  In this case, the buffer describes a portion of user data space that is locked into memory [see physiock(D3DK)]. 

Block drivers often chain block requests so that overall throughput for the device is maximized.  The av_forw and the av_back members of the buf structure can serve as link pointers for chaining block requests. 

STRUCTURE MEMBERS

int b_flags; /∗ Buffer status ∗/
struct buf ∗b_forw; /∗ Kernel/driver list link ∗/
struct buf ∗b_back; /∗ Kernel/driver list link ∗/
struct buf ∗av_forw; /∗ Driver work list link ∗/
struct buf ∗av_back; /∗ Driver work list link ∗/
uint_t b_bcount; /∗ # of bytes to transfer ∗/
union {

       caddr_t b_addr; /∗ Buffer’s virtual address ∗/
} b_un;

daddr_t b_blkno; /∗ Block number on device ∗/
uint_t b_resid; /∗ # of bytes not transferred ∗/
clock_t b_start; /∗ Request start time ∗/
struct proc ∗b_proc; /∗ Process structure address ∗/
long b_bufsize; /∗ Size of allocated buffer ∗/
int (∗b_iodone)(); /∗ Function called by biodone ∗/
dev_t b_edev; /∗ Expanded dev field ∗/
void ∗b_private; /∗ For driver’s use ∗/

The members of the buffer header available to test or set by a driver are described below:

b_flags is a bitmask that stores the buffer status and tells the driver whether to read from or write to the device.  The driver must never clear the b_flags member.  If this is done, unpredictable results can occur. 

Valid flags are as follows:

B_PAGEIOThe buffer is being used in a paged I/O request.  If B_PAGEIO is set, the the buffer header will refer to a list of page structures sorted by block location on the device.  Also, the b_un.b_addr field of the buffer header will be the offset into the first page of the page list.  If B_PAGEIO is not set, the b_un.b_addr field of the buffer header will contain the starting virtual address of the I/O request (in user address space if B_PHYS is set or kernel address space otherwise).  The driver must not set or clear the B_PAGEIO flag. 

B_PHYSThe buffer header is being used for physical (direct) I/O to a user data area.  The b_un.b_addr member contains the starting virtual address of the user data area.  NOTE: B_PHYS and B_PAGEIO are never set simultaneously and must not be changed by the driver. 

B_READData are to be read from the peripheral device into main memory.  The driver should not change this flag unless the driver acquired the buffer with getrbuf(D3DK), geteblk(D3DK), or ngeteblk(D3DK). 

B_WRITEData are to be transferred from main memory to the peripheral device.  B_WRITE is a pseudo-flag that occupies the same bit location as B_READ.  B_WRITE cannot be directly tested; it is only detected as the absence of B_READ (!(bp->b_flags&B_READ).) 

B_ASYNCThe I/O request does not have a process immediately waiting for it to complete.  If the driver is capable of handling out of order I/O requests it may internally handle I/O requests marked B_ASYNC at a lower priority than I/O requests without B_ASYNC set. 

b_forw and b_back may only be used by the driver if the buffer was acquired by the driver with the getrbuf routine.  In that case, these members can be used to link the buffer into driver work lists. 

av_forw and av_back can be used by the driver to link the buffer into driver work lists. 

b_bcount specifies the number of bytes to be transferred in both a paged and a non-paged I/O request.  The driver may change this member. 

b_un.b_addr is either the virtual address of the I/O request, or an offset into the first page of a page list depending on whether B_PAGEIO is set.  If it is set, the buffer header will refer to a sorted list of page structures and b_un.b_addr will be the offset into the first page.  If B_PAGEIO is not set, b_un.b_addr is the virtual address from which data are read or to which data are written.  It represents a user virtual address if B_PHYS is set, or a kernel virtual address otherwise.  The driver may change this member if the driver allocated the buffer header via getrbuf. 

b_blkno identifies which logical block on the device is to be accessed.  The driver may have to convert this logical block number to a physical location such as a cylinder, track, and sector of a disk.  The driver may change this member if the driver allocated the buffer via geteblk, ngeteblk, or getrbuf. 

b_resid indicates the number of bytes not transferred because of an error.  The driver may change this member. 

b_start holds the time the I/O request was started.  It is provided for the driver’s use in calculating response time and is set by the driver.  Its type, clock_t, is an integral type upon which direct integer calculations can be performed.  It represents clock ticks. 

b_proc contains the process structure address for the process requesting an unbuffered (direct) data transfer to or from a user data area (this member is set to NULL when the transfer is buffered).  The process table entry is used to perform proper virtual to physical address translation of the b_un.b_addr member [see vtop(D3DK)].  The driver may not change this member. 

b_bufsize contains the size in bytes of the allocated buffer.  The driver may not change this member unless the driver acquired the buffer with getrbuf. 

(∗b_iodone) identifies a specific driver routine to be called by the system when the I/O is complete.  If one is specified, the biodone(D3DK) routine does not return the buffer to the system.  The driver may change this member. 

b_edev contains the external device number of the device. 

b_private is a private field for use by the driver.  The system does not interpret it.  The driver is free to use it in whatever manner it chooses.  For example, the driver could use it as part of a disk block sorting algorithm. 

NOTES

Buffers are a shared resource within the kernel.  Drivers should only read or write the members listed in this section in accordance with the rules given above.  Drivers that attempt to use undocumented members of the buf structure risk corrupting data in the kernel and on the device. 

DDI/DKI conforming drivers may only use buffer headers that have been allocated using geteblk, ngeteblk or getrbuf, or have been passed to the driver strategy routine. 

SEE ALSO

strategy(D2DK), biodone(D3DK), bioerror(D3DK), biowait(D3DK), brelse(D3DK), clrbuf(D3DK), freerbuf(D3DK), geteblk(D3DK), geterror(D3DK), getrbuf(D3DK), ngeteblk(D3DK), physiock(D3DK), iovec(D4DK), uio(D4DK)

DDI/DKI

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026