'\"macro stdmacro
.if n .pH ddi_dki.physiock @(#)physiock	40.7 of 11/16/89
.\" Copyright 1989 AT&T
.de IX
.ie '\\n(.z'' .tm .Index: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9	\\n%
.el \\!.IX \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
..
.nr X
.if \nX=0 .ds x} physiock D3D "3B2" "DDI" "\&"
.if \nX=1 .ds x} physiock D3D "3B2" "DDI"
.if \nX=2 .ds x} physiock D3D "" "\&"
.if \nX=3 .ds x} physiock "" "" "\&"
.TH \*(x}
.IX "\f4physiock\fP(D3DK)"
.SH NAME
\f4physiock\f1 \- validate and issue raw I/O request
.SH SYNOPSIS
.nf
.na
\f4#include<sys/types.h>
#include <sys/buf.h>
#include <sys/errno.h>
#include <sys/uio.h>
#include <sys/cred.h>
.sp 0.5
int physiock(int (*(\f2strategy\f4) (), struct buf *\f2buf, \f4dev_t\f2 dev,
	\f4int \f2rwflag, \f4daddr_t \f2nblocks, \f4uio_t *\f2uio_p\f4);\f1
.ad
.fi
.SH ARGUMENTS
.RS 0n 10
.IP "\f2strategy\f1" 10n
Address of the driver \f4strategy\f1 routine.
.IP "\f2buf\f1" 10n
Pointer to the \f4buf\f1 structure describing the I/O request.  If set to
\f4NULL\f1, then a buffer is allocated from the buffer pool and
returned to the free list after the transfer completes.
.IP "\f2dev\f1" 10n
Device number.
.IP "\f2rwflag\f1" 10n
Flag indicating whether the access is a read (\f4B_READ\f1) or 
a write (\f4B_WRITE\f1).
Note that \f4B_WRITE\f1 cannot be directly tested as it is \f40\f1
.IP "\f2nblocks\f1" 10n
Number of blocks that a logical device can support, for example, a disk
partition, or tape.
.IP "\f2uio_p\f1" 10n
Pointer to the \f4uio\f1 structure that defines the user space of the I/O
request.
.RE
.SH DESCRIPTION
\f4physiock\f1 is called by the character interface to
block driver \f4read\f1(D2DK) and
\f4write\f1(D2DK) routines to help perform unbuffered I/O while
maintaining the buffer header as the interface structure.
.P
\f4physiock\f1 performs the following functions:
.IP
verifies the requested transfer is valid by checking if the offset is at
or past the end of the device
.IP
sets up a buffer header describing the transfer
.IP
faults pages in and locks the pages impacted by the
I/O transfer so they can not be swapped out
.IP
calls the driver \f4strategy\f1(D2DK) routine passed to it
.IP
sleeps until the transfer is complete and is awakened by the
\f4biodone\f1(D3DK) function in the driver's interrupt routine
.IP
performs the necessary cleanup and updates, then returns to the driver routine
.P
A transfer using \f4physiock\f1 is considered valid if the specified data
location exists on the device, and the user has specified a storage area that
exists in user memory space.
.SH RETURN VALUE
\f4physiock\f1 returns 0 if the result is successful, the appropriate error
number upon failure.  \f4physiock\f1 returns the \f4ENXIO\f1 
error (see \f2Appendix A\f1
for more information) if an attempt is made to read beyond the end of the
device.  If a read is performed at the end of the device, 0 is returned.  \f4ENXIO\f1
is also returned if an attempt is made to write at the end of a device or
beyond the end of the device.  \f4EFAULT\f1 is returned if user memory is not
available.  \f4EAGAIN\f1 is returned if \f4physiock\f1 could not lock pages for \s-1DMA\s0.
.SH LEVEL
Base Only  (Do not call from an interrupt routine)
.SH SEE ALSO
.na
\f4dma_pageio\f1(D3D),
\f4strategy\f1(D2DK)
.ad
.SH EXAMPLE
.ne 4
.P
.nf
.ft 4
.ps 7
 1  struct  dsize     {
 2          daddr_t nblocks;  /* disk partition block number */
 3          int     cyloff;   /* starting cylinder # of partition   */
 4  } DISKsizes[16] = {
 5
 6          20448,  21,   /* partition 0 = cyl 21-305   */
 7          12888,  126,  /*     "     1 = cyl 126-305  */
 8          9360,   175,  /*     "     2 = cyl 175-305  */
 9          7200,   205,  /*     "     3 = cyl 205-305  */
10          3600,   255,  /*     "     4 = cyl 255-305  */
11          21816,  3,    /*     "     5 = cyl 2-305    */
12          21888,  1,    /*     "     6 = cyl 1-305    */
13          72,     1,    /*     "     7 = cyl 1        */
14  };
15
16  DISKread(dev, uio_p, cred_p)  /* direct read request from block device */
17          dev_t   dev;
18          uio_t   *uio_p;
19          cred_t  *cred_p;
20  {
21          register int nblks;
22
23           /* get number of blocks in the partition */
24          nblks = DISKsizes[minor(dev) & 0x7].nblocks;
25
26          /*
27           * Check limits of read request.  If request is in 
28           * the limits of the disk partition, schedule direct I/O.
29           */
30
31          physiock(DISKstrat, 0, dev, B_READ, nblks, uio_p); 
32     
33  } /* end DISKread */
34
35
36  DISKwrite(dev, uio_p, cred_p)  /* direct write request to block device */
36          dev_t   dev;
37          uio_t   *uio_p;
38          cred_t  *cred_p
39  {
40          register int nblks;
41
42          /* get number of blocks in the partition */
43          nblks = DISKsizes[minor(dev) & 0x7].nblocks;
44
45          /* 
46           * Check limits of write request.  If request is in 
47           * the limits of the disk partition, schedule direct I/O.
48           */
49
50          physiock(DISKstrat, 0, dev, B_WRITE, nblks, uio_p); 
51     
52  } /* end DISKwrite */
.ps
.ft 1
.fi
.P
.FG "physiock \- verify I/O request and schedule I/O"
