'\"macro stdmacro
.if n .pH ddi_dki.dma_pageio @(#)dma_pageio	40.8 of 12/19/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} dma_pageio D3D "3B2" "DDI" "\&"
.if \nX=1 .ds x} dma_pageio D3D "3B2" "DDI"
.if \nX=2 .ds x} dma_pageio D3D "" "\&"
.if \nX=3 .ds x} dma_pageio "" "" "\&"
.TH \*(x}
.IX "\f4dma_pageio\fP(D3D)"
.SH NAME
\f4dma_pageio\f1 \- break up an I/O request into manageable units
.SH SYNOPSIS
.nf
.na
\f4#include <sys/buf.h>
.sp 0.5
void dma_pageio(\f4void (*strat)() \f1\f2strat, \f4struct buf *\f2bp\f4);\f1
.ad
.fi
.SH ARGUMENTS
.RS 0n 10
.IP "\f2*strat\f1" 10n
Pointer to the \f4strategy\f1(D2DK) routine to call to complete the I/O
transfer.
.IP "\f2bp\f1" 10n
Pointer to the \f4buf\f1 structure.
.RE
.SH DESCRIPTION
\f4dma_pageio\f1 breaks up a data transfer request from \f4physiock\f1(D3DK)
into units of contiguous memory.  This function enhances the
capabilities of the direct memory access controller (\s-1DMAC\s+1).  The data is
broken into 512-byte sectors until the last data bytes are encountered.
\f4dma_pageio\f1 executes \f4spl0\f1 around its internal
\f4sleep\f1 calls on reads and writes after the \f4strategy\f1
routine is called.  This may alter previously set \f4spl\f1(D3D) calls.
.IX DMA (Direct Memory Access)
.IX "Direct Memory Access (DMA)"
.IX "\f4spl\fP(D3D), during DMA"
.P
The driver must modify \f4b_flags\f1 to indicate whether the transfer is a read or a 
write.
OR in \f4B_READ\f1 to indicate a read;
turn \f4B_READ\f1  off to indicate a write.
.SH RETURN VALUE
None.
However, conditions in \f4dma_pageio\f1 can cause the following
to be set:
.IP
If memory for a temporary buffer cannot be allocated,
\f4b_flags\f1 is \s-1OR\s0ed with \f4B_ERROR\f1 and \f4B_DONE\f1,
and \f4b_error\f1 is set to \f4EAGAIN\f1 (resource temporarily 
unavailable).  All allocated temporary buffers are deallocated when the
transfer completes.
.IP
If the I/O transfer is incomplete (\f4b_flags\f1 does not contain
\f4B_DONE\f1), then \f4b_flags\f1 is set to \f4B_WANTED\f1 and
\f4sleep\f1(D3DK) is called to wait  until a buffer can be allocated.  The
\f4sleep\f1 priority is set to \f4PRIBIO\f1.
.IP
The \f4sleep\f1 code section is surrounded by a \f4spl6\f1-\f4spl0\f1
function set which may alter a previously set \f4spl\f1 value.
.IP
If \f4B_ERROR\f1 is set after the \f4strategy\f1(D2DK) routine completes,
allocated memory is freed and \f4dma_pageio\f1 returns.
.IP
When the transfer completes, any allocated buffers are freed.
.SH LEVEL
Base Only
.SH SEE ALSO
\f2BCI Driver Development Guide\f1, Chapter 6, ``Input/Output Operations''
.ad
.SH EXAMPLE
.IX "\f4buf\fP(D4DK), example"
.IX "\f4dma_pageio\fP(D3D), example"
.IX "\f4getminor\fP(D3DK), example"
.IX "\f4physiock\fP(D3DK), example"
.IX "\f4read\fP(D2DK), example"
.IX "\f4strategy\fP(D2DK), example"
.IX "\f4write\fP(D2DK), example"
.P
The following example shows how \f4dma_pageio\f1 is used when reading
or writing disk data.
.ne 4
.P
.nf
.ft 4
.ps 7
 1  struct  dsize    {
 2          daddr_t nblocks;  /* number of blocks in disk partition    */
 3          int     cyloff;   /* starting cylinder # of partition      */
 4  } my_sizes[4] = {
 5
 6          20448, 21,        /* partition 0 = cyl 21-305              */
 7          21888, 1          /* partition 1 = cyl  1-305              */
 8  };
 9
10  /*    physical read    */
11  my_read(dev, uio_p, cred_p)
12          dev_t   dev;
13          uio_t   *uio_p;
14          cred_t  *cred_p;
15  {
16          register int nblks;
17          /* get number of blocks in the partition                   */
18          nblks = my_sizes[getminor(dev) & 0x7].nblocks;
19          
20          /* if request is within limits for the device, schedule I/O*/
21          physiock(my_breakup, 0, dev, B_READ, nblks, uio_p); 
22         
23  }
24  /*    physical write    */
25  my_write(dev, uio_p, cred_p)
26          dev_t   dev;
27          uio_t   *uio_p;
28          cred_t  *cred_p;
29  {
30          register int nblks;
31          /* get the number of blocks in the partition                */
32          nblks = my_sizes[getminor(dev) & 0x7].nblocks;
33
34          /* if request is within limits for the device, schedule I/O */
35           physiock(my_breakup, 0, dev, B_WRITE, nblks, uio_p);
36          }
37  }
38  /*
39   *    break up the request that came from physio into chunks of
40   *    contiguous memory.  Pass at least 512 bytes (one sector) at a
41   *    time (except for the last request).
42   */
43
44  static
45  my_breakup(bp)
46         register struct buf *bp;
47  {
48         dma_pageio(my_strategy, bp);
49  }
.ps
.ft 1
