SCO OpenServer
physio(D3oddi)
physio, physck --
direct (raw) I/O for block drivers
Synopsis
#include <sys/buf.h>
int physck(daddr_t nblocks, int rwflags);
void physio(int (strategy) (struct buf ), struct buf bp,
dev_t dev, int rwflags);
Description
The physio function supports raw (direct) I/O
for block devices.
It validates the request,
locks the relevant pages of the process in core,
and examines the driver's attributes
to determine how to handle the I/O request.
It then builds an appropriate number of buffer headers
and passes these to the driver
with calls to the driver's
strategy(D2oddi)
routine.
physck ensures that a requested raw I/O request
can be serviced by the device being read from or written to.
Arguments
nblocks-
maximum number of 512-byte blocks on the device,
or in the disk partition.
The number of blocks is converted to bytes
to find the size limit
and then compared with
u.u_offset
.
strategy-
Address of the driver's
strategy(D2oddi)
routine.
bp-
Retained for backward compatibility;
should be set to NULL.
dev-
device number
(includes both major and minor device numbers).
rwflags-
defines the I/O operation.
Valid values are:
B_READ-
read operation
B_WRITE-
write operation
B_BDEV-
If set, device attributes are determined through the
getbattr( )
function;
if not set, these attributes are determined through the
getcattr( )
function.
B_NOSG-
no scatter/gather
Implicit arguments:
u.u_base
-
start address for transfer
u.u_count
-
count for transfer
u.u_offset
-
offset on device for transfer
(see
u.u_fmode
description)
u.u_segflg
-
0 indicates user data, 1 indicates system data
u.u_fmode
-
if FBMODE is set,
u.u_offset
is in units of 512-byte sectors;
otherwise, in units of bytes
u.u_error
-
checked to see if an error has been recorded
The u.u_base
, u.u_count
, and
u.u_offset
values must be set up prior to the
physio call, and must point to the appropriate user-data
area.
Return values
physck returns 0 (zero) on an error; 1 if successful:
Note the following side effects:
-
If
u.u_offset
is
greater than the size limit,
and rwflag is set to B_WRITE,
then u.u_error
is set to ENXIO
and 0 (zero) is returned.
-
If
u.u_offset
is greater than or equal to the limit,
and rwflag is B_READ,
then 0 (zero) is returned and no error is set.
-
If
u.u_offset
plus u.u_count
is greater than the limit,
then u.u_count
is reduced by the number of bytes
that it differs from the limit and the test is completed.
physio does not return a value.
Various globals are updated:
u.u_base
-
incremented by amount of data transferred
u.u_count
-
decremented by amount of data transferred
u.u_offset
-
incremented by amount of data transferred
u.u_error
-
set to an appropriate value if error occurred
c_sysinfo->phread
-
incremented if this was a read operation
c_sysinfo->phwrite
-
incremented if this was a write operation
Usage
The following example illustrates a typical call to physio:
physio(mystrategy, (struct buf *) NULL, dev, B_READ);
physio( )
handles various device characteristics as defined in the
mdevice(F)
file:
-
If the device allows scatter/gather operations
(option g in the mdevice file)
and the required data transfer
is most efficiently performed by scatter/gather,
physio( )
prepares the appropriate scatter/gather lists
for the driver.
-
If the device cannot handle physical addresses beyond 16MB
(option d is not set in the mdevice file),
then
physio( )
uses copy buffers below the 16MB limit as required.
-
physio( )
is aware of q and u options
in the mdevice file
and uses them to determine the block size
prior to checking if partial block accesses are required.
Unless the T option is set
(indicating that this is a tape drive),
physio( )
arranges that writes to any partial blocks
are dealt with by issuing a full block read,
updating the data as required,
and then writing it back.
Context and synchronization
User
context.
Hardware applicability
All
Version applicability
oddi:
1, 2, 2mp, 3, 3mp, 4, 4mp, 5, 5mp, 6, 6mp
Differences between versions
For ODDI releases prior to ODDI 3,
the bp argument was either a pointer to
a buffer header to be used for the I/O operation
or a NULL pointer.
The current implementation of physio
no longer makes any use of a supplied buffer header,
and using it slows the execution of the data transfer
because of processing required for backward compatibility.
In earlier releases, it was necessary to call
dma_breakup(D3oddi)
or
pio_breakup(D3oddi)
in conjunction with
physio( )
for devices that used DMA
or programmed I/O, respectively.
physio( )
now handles this functionality internally
so these calls are not required.
SVR5 DDI compatibility
For DDI drivers prior to version 8, the
physiock(D3)
function replaces both
physio( )
and
physck( ).
DDI 8 drivers use the
do_biostart(D3)
function instead.
References
strategy(D2oddi)
19 June 2005
© 2005 The SCO Group, Inc. All rights reserved.
OpenServer 5 HDK - June 2005