device_driver(3K) DG/UX R4.11MU05 device_driver(3K)
NAME
device_driver: dev_xxx_init, dev_xxx_configure, dev_xxx_deconfigure,
dev_xxx_device_to_name, dev_xxx_name_to_device, dev_xxx_open,
dev_xxx_close, dev_xxx_service_interrupt, dev_xxx_read_write,
dev_xxx_start_io, dev_xxx_select, dev_xxx_ioctl, dev_xxx_open_dump,
dev_xxx_write_dump, dev_xxx_read_dump, dev_xxx_close_dump,
dev_xxx_maddmap, dev_xxx_mmap, dev_xxx_munmap, dev_xxx_powerfail -
implement a device driver
SYNOPSIS
#include "/usr/src/uts/aviion/ii/i_io.h"
status_type dev_xxx_close (
io_device_handle_type device_handle, READ_ONLY
io_channel_flags_type channel_flags READ_ONLY )
status_type dev_xxx_close_dump (
io_device_handle_type device_handle READ_ONLY )
status_type dev_xxx_configure (
char_ptr_type device_name_ptr, READ_ONLY
io_major_device_number_type major_number READ_ONLY )
status_type dev_xxx_deconfigure (
char_ptr_type device_name_ptr READ_ONLY )
status_type dev_xxx_device_to_name (
io_device_number_type device_number, READ_ONLY
char_ptr_type name_ptr, WRITE_ONLY
uint32_type size READ_ONLY )
void dev_xxx_init ()
status_type dev_xxx_ioctl (
io_device_handle_type device_handle, READ_ONLY
bit32e_type command, READ_ONLY
bit32e_type parameter, READ_WRITE
int32e_ptr_type return_value_ptr WRITE_ONLY )
void dev_xxx_maddmap (
io_device_handle_type device_handle, READ_ONLY
opaque_ptr_type file_id, READ_ONLY
int32_type mmap_count_delta READ_ONLY )
status_type dev_xxx_mmap (
io_device_handle_type device_handle, READ_ONLY
opaque_ptr_type file_id, READ_ONLY
io_mmap_request_ptr_type request_ptr, READ_ONLY
io_channel_flags_type io_flags, READ_ONLY
byte_address_ptr_type start_address_ptr WRITE_ONLY )
status_type dev_xxx_munmap (
io_device_handle_type device_handle, READ_ONLY
opaque_ptr_type file_id, READ_ONLY
io_mmap_request_ptr_type request_ptr, READ_ONLY
byte_address_type start_phys_addr READ_ONLY )
status_type dev_xxx_name_to_device (
char_ptr_type device_name_ptr, READ_ONLY
io_device_number_ptr_type number_ptr WRITE_ONLY )
status_type dev_xxx_open (
io_device_number_type device_number, READ_ONLY
io_channel_flags_type channel_flags, READ_ONLY
io_device_handle_ptr_type device_handle_ptr WRITE_ONLY )
status_type dev_xxx_open_dump (
char_ptr_type device_name, READ_ONLY
io_device_handle_ptr_type device_handle_ptr READ_ONLY )
status_type dev_xxx_powerfail ()
status_type dev_xxx_read_dump (
io_dump_request_info_ptr_type dump_rb_ptr READ_ONLY )
status_type dev_xxx_read_write (
io_request_info_ptr_type request_info_ptr READ_ONLY )
void dev_xxx_select (
io_device_handle_type device_handle, READ_ONLY
boolean_type select_mode, READ_ONLY
vp_ec_ptr_type ec_ptr, READ_ONLY
io_select_intent_ptr_type intent_ptr READ_WRITE )
void dev_xxx_service_interrupt (
dev_xxx_device_info_ptr_type device_info_ptr READ_ONLY )
status_type dev_xxx_start_io (
io_operation_record_ptr_type op_record_ptr READ_ONLY )
status_type dev_xxx_write_dump (
io_dump_request_info_ptr_type dump_rb_ptr READ_ONLY )
void kernel_complete_io (
io_operation_record_ptr_type op_record_ptr, READ_ONLY
status_type status READ_ONLY )
where:
channel_flags Flags indicating how the device was or will be
opened (read, write, or read/write) and whether the
open is for block or character special operation.
These flags are listed below under Constants and
Data Structures, io_channel_flags_type. (See also
i_io.h for a listing of the channel flags.) The
driver does not need to validate this argument.
command A command to the device. The driver must validate
the command because commands are driver-specific.
device_handle The device handle that was returned by the driver's
dev_xxx_open routine. The driver does not need to
validate this argument.
device_handle_ptr A pointer to the location where the device handle
is to be returned. If the routine does not return
an OK status, this value is undefined. The driver
does not need to validate this pointer.
device_info_ptr A pointer to the device information structure for
the interrupting device. A pointer to the
dev_xxx_service_interrupt routine is the first
field in this structure. The driver does not need
to validate this pointer.
device_name A pointer to the null-terminated string identifying
the device to be opened as a dump device.
device_name_ptr A pointer to a null-terminated string specifying
the name of the device to be configured,
deconfigured, or translated.
device_number The major and minor device numbers of a particular
device.
dump_rb_ptr A pointer to the dump request information
structure. This structure contains the
io_buffer_vector, the device_handle, the
device_offset, and the device_offset_extender
fields. The device_handle field is returned from
the dev_xxx_open_dump routine.
ec_ptr A pointer to the eventcounter to be advanced by the
driver when the particular type of select is
satisfied. The driver does not need to validate
this pointer.
file_id A file identifier associated with the character
special file that was initially opened to gain
access to the device.
intent_ptr A pointer to an intent variable consisting of a set
of intent flags. The kernel calls the driver with
the intent flags showing whether the device is
being selected for read, write, or exceptional
conditions or any combination of these. When the
driver returns, it sets the intent flags to show
which input conditions are currently TRUE. The
driver does not need to validate this argument.
The possible intent flags are described under
Constants and Data Structures below.
io_flags The channel flags for the descriptor passed to
mmap(2).
major_number The major number of the device to be configured.
mmap_count_delta The amount to increment or decrement the mmap use
count for the device.
name_ptr A pointer to the location where the device name is
to be written as a null-terminated string.
number_ptr A pointer to where the corresponding device number
is to be written. The device number consists of a
major and minor device number.
op_record_ptr A pointer to the operation record for an
asynchronous request. The operation record
contains the following fields:
· The device handle that is the target of the
operation.
· The operation to be performed; for example,
read, write, or both.
· The offset indicating where the read/write
operation should begin. The offset is a file
pointer maintained by the kernel. For example,
on a disk the offset might indicate where to
start reading after the start of the sector.
The interpretation of the offset is driver-
dependent.
· The address of the kernel's I/O completion
routine that is to be called by the driver's
complete_io routine when the operation
completes. The Kernel I/O completion routine
follows the interface shown under
kernel_complete_io below. Note that you pass
the op_record and a completion status back as
parameters to the kernel_complete_io routine.
· An io_buffer_vector structure that holds the
transfer size and the address of the memory
buffers.
parameter An argument to the command. The interpretation of
the parameter is specific to the driver and the
command. The parameter is often used to transfer
information between the caller and the device, in
both direction. For example one might use it to
send a pointer to a buffer supplied by the caller.
request_info_ptr A pointer to a request information structure.
request_ptr Information indicating which memory is to be memory
mapped (and in what mode) or unmapped. The members
of this structure correspond directly to mmap(2)
arguments as follows:
Member name mmap Argument
start_address addr
file_offset_extender set to 0 by mmap()
file_offset off
byte_count len
protection_flags prot
control_flags flags
request_ptr Additional information indicating which memory is
requested to be unmapped.
return_value_ptr A pointer to a value that the routine defines and
returns. This additional return value increases
the flexibility of your ioctl operation by
providing variations on the generic return value
specified in the "Return Value" subsection.
select_mode If select_mode is TRUE, this is the start of a
select operation. If select_mode is FALSE, this is
the end of a select operation.
size The maximum number of bytes, including the
terminating null, that is to be written to
name_ptr.
start_address_ptr Location used to return the start address in the
user address space of the newly mapped region.
start_phys_addr The physical memory address of the beginning of the
region to be unmapped.
status The completion status of the request.
DESCRIPTION
This man page gives the detailed interface specifications for the
following device driver routines:
dev_xxx_init Perform pre-configuration initialization
dev_xxx_configure Configure a device
dev_xxx_deconfigure Deconfigure a device
dev_xxx_device_to_name Return name associated with device number
dev_xxx_name_to_device Return device number for device name
dev_xxx_open Open a device
dev_xxx_close Close a device
dev_xxx_service_interrupt Handle device interrupts
dev_xxx_read_write Synchronously read from or write to device
dev_xxx_start_io Start asynchronous I/O operation
kernel_complete_io Clean up after asynchronous I/O operation
dev_xxx_select Check whether device ready for I/O
dev_xxx_ioctl Performs control operation on device
dev_xxx_open_dump Open a dump device
dev_xxx_write_dump Write system dump data to dump destination
dev_xxx_read_dump Read a system dump device
dev_xxx_close_dump Close a dump device
dev_xxx_maddmap Modify device memory map reference count
dev_xxx_mmap Implement the mmap system call
dev_xxx_munmap Determine whether to unmap memory
dev_xxx_powerfail* Restart devices after power failure
__________
*Not currently supported
Each routine specification includes a "Return Value" subsection that
lists specific return values that the kernel can process when the
routine returns. When no return value is specified, the routine must
not fail (the kernel will not process any returns or exceptions). If
the driver routine experiences an exception other than those
specified in the "Return Value" subsection, it can proceed in one of
the following three ways:
1. It can return an exception by returning a value other than one
of the specified values. The kernel will filter this value
back to the user as a standard errno. You can either define
your own values for this errno or use values already defined
by the system. Check /usr/include/sys/errno.h for a listing
of the existing errnos and their definitions.
2. It can use the error server to log an error.
3. It can halt the system. Some driver routines are not allowed
to halt. The "Return Value" subsection of the interface
description indicates whether or not a routine can halt.
The status_code_macros(3K) man page describes how to define an error
status and how to log an error to the error server. The sc_panic(3K)
man page describes how to use the routine that halts the system.
Constants and Data Structures
This subsection describes constants and data structures defined in
the include files cited in the SYNOPSIS section and used by the
routines documented in this man page.
Try to avoid dependencies on the specifics of these structures, such
as size or location of fields, because these specifics may change in
later releases of the software. You can verify exact variable
definitions in the appropriate include file. The best way to avoid
such dependencies is to use kernel-supplied routines to manipulate
these structures.
io_driver_routines_vector_type
typedef struct
{
uint16_type version;
bit16_type flags;
status_type (*open)();
void (*close)();
status_type (*read_write)();
void (*select)();
status_type (*ioctl)();
status_type (*start_io)();
void (*init)();
status_type (*configure)();
status_type (*deconfigure)();
status_type (*device_to_name)();
status_type (*name_to_device)();
status_type (*open_dump)();
status_type (*write_dump)();
status_type (*read_dump)();
status_type (*close_dump)();
status_type (*powerfail)();
status_type (*mmap)();
status_type (*munmap)();
status_type (*maddmap)();
} io_driver_routines_vector_type ;
The kernel must have a pointer to each of your routines that it
calls. You provide a vector of pointers to your driver's routines in
a routines vector of io_driver_routines_vector_type. You must
allocate a variable of this type for your driver in
dev_xxx_global_data.c.
The structure contains a version field that the kernel uses to
support compatibility with device drivers if the routines vector
changes between releases. This field is also used to flag the
difference between a device driver and an adapter driver. Adapter
drivers have two routines vectors, one of io_routines_vector_type
type and one of dev_scsi_adapter_routines_vector_type type. The
version field is used to signal the kernel that the driver is an
adapter driver and has another routines vector.
If the driver was written prior to release 5.4.2, you should set the
version field to one (1) for device drivers and to
IO_DRIVER_ROUTINES_VECTOR_SCSI_ADAPTER_VERSION for adapter drivers.
For drivers using the new wire/unwire memory calls for release 5.4.2
[see the io_buffer_vector(3K) and memory_allocation(3K) man pages],
the version field should be IO_DRIVER_ROUTINES_VECTOR_VERSION_2 for
device drivers and IO_DRIVER_ROUTINES_VECTOR_SCSI_ADAPTER_VERSION_2
for adapter drivers.
io_device_number_type
typedef struct
{
io_major_device_number_type major;
io_minor_device_number_type minor;
} io_device_number_type ;
A device number is a composite of the device's major and minor device
numbers. During configuration, the kernel calls your
dev_xxx_configure routine with the device's major number. Your
dev_xxx_configure routine gets the device's minor number and creates
the device number variable for the unit by calling the kernel's
io_allocate_device_number routine. dev_xxx_configure then uses the
device number to create the special file (node) for the specific
units. After dev_xxx_configure creates the device number, the kernel
uses it as an device identifier when calling your dev_xxx_open
routine. dev_xxx_open returns a file descriptor that the kernel uses
to identify the unit to the user and a device handle that the kernel
uses to identify the unit to other driver routines.
io_device_handle_type
typedef opaque32_type io_device_handle_type ;
A device handle identifies an open device to other calls to the
device driver. Your dev_xxx_open routine defines and returns the
device handle when the device is opened. The device handle becomes
invalid when the device is closed.
The kernel does not interpret the device handle. Thus, you are free
to define the device handle as you want. A common strategy is to use
a pointer to the unit-specific portion of the device information
structure as the device handle.
io_request_info_type
typedef struct
{
io_operation_type op;
io_channel_flags_type flags;
io_device_handle_type device_handle;
uint32_type device_offset_extender;
uint32_type device_offset;
io_buffer_vector_type buffer_vector;
df_self_id_type self_id;
} io_request_info_type;
The kernel uses a variable of this type to supply information to your
driver's routines about an I/O request made to your driver. The
request information package groups several related I/O request
parameters. The request information package fields are as follows:
op This field indicates the requested operation. See
io_operation_type for a list of the operation types. The op
request is modified by the flags field below.
flags This field holds an additional set of flags that modifies the
operation indicated by the op field. See
io_channel_flags_type described later in this subsection for a
list of the flags.
device_handle
This field holds the device handle of the device to which the
request is to be directed. It must be the device handle
returned by the driver's open routine.
device_offset_extender
This field exists for device offsets needing more than 32
bits. This field should be zero if the request does not use
large offsets (for example, nondisk devices). Disk drivers
should check this field. If your disk does not support
offsets needing the extender, you should reject requests where
this offset is non-zero.
device_offset
This field holds the offset in bytes on the device where the
transfer is to begin. The interpretation of this field is
defined by the driver to which the request is directed.
buffer_vector
This field holds a buffer vector describing the main memory
area that is to be used in the I/O operation. The addresses
may be logical or physical depending upon the operation
specified in the op field.
self_id
The home system identification against which read data is to
be checked if the IO_CHECK_SELF_ID flag is TRUE.
io_operation_type
typedef bit16_type io_operation_type ;
#define IO_OPERATION_READ
#define IO_OPERATION_WRITE
#define IO_OPERATION_CHECK_SELF_ID
#define IO_OPERATION_PHYSICAL_BUFFER
#define IO_OPERATION_USER_BUFFER
This type defines a bit field used to modify the I/O operation
specified in the op field of io_request_info_type. The READ or WRITE
bits are exclusive, only one can be on at a time. The
PHYSICAL_BUFFER flag indicates that the buffer address supplied with
the operation is a physical memory address not a logical memory
address. The USER_BUFFER flag indicates that the buffer address
supplied with the operation is a user memory address rather than a
kernel memory address. The PHYSICAL_BUFFER flag and the USER_BUFFER
flag may be present only on a READ or WRITE. The CHECK_SELF_ID flag
may be present only on a READ operation.
io_channel_flags_type
typedef bit32_type io_channel_flags_type ;
#define IO_CHANNEL_NO_FLAGS
#define IO_CHANNEL_READ_INTENT
#define IO_CHANNEL_WRITE_INTENT
#define IO_CHANNEL_EXCLUDE_WRITERS_INTENT
#define IO_CHANNEL_APPEND_INTENT
#define IO_CHANNEL_SYNC_IO
#define IO_CHANNEL_NO_WAIT
#define IO_CHANNEL_ASYNC_IO
#define IO_CHANNEL_NONBLOCK
#define IO_CHANNEL_NDELAY
#define IO_CHANNEL_BLOCK_SPECIAL
#define IO_CHANNEL_NO_RETRIES
#define IO_CHANNEL_NOTIFY_IF_MANDATORY
#define IO_CHANNEL_NOCTTY
This type defines a set of literals that modify the open operation.
The channel flags specify the open conditions that the user requested
and are passed in the flags field of the io_request_info_type. These
conditions are passed to the dev_xxx_open routine. See dev_xxx_open
for more information about the conditions. The open options are as
follows:
IO_CHANNEL_NO_FLAGS
This flag indicates that none of the conditions described
below applies.
IO_CHANNEL_READ_INTENT
This flag indicates that the channel is opened with read
intent. This flag corresponds to the O_RDONLY or O_RDWR
option on the open system call.
IO_CHANNEL_WRITE_INTENT
This flag indicates that the channel is opened with write
intent. This flag corresponds to the O_WRONLY or O_RDWR
option on the open system call.
IO_CHANNEL_EXCLUDE_WRITERS_INTENT
This flag indicates that the channel is opened only if there
are currently no writers, and future attempts to open with
write intent are disallowed. This flag is used internally by
the file system to prevent other processes from writing to a
disk it is managing.
IO_CHANNEL_APPEND_INTENT
This flag indicates that the channel is opened with append
intent. This flag corresponds to the O_APPEND option on the
open system call.
IO_CHANNEL_SYNC_IO
This flag indicates that the channel is opened with the
synchronous I/O option. This flag corresponds to the O_SYNC
option on the open system call.
IO_CHANNEL_NO_WAIT
This flag indicates that the channel is opened with the no-
wait I/O option. This flag corresponds to the O_NDELAY or to
the O_NONBLOCK option on the open system call.
IO_CHANNEL_ASYNC_IO
This flag indicates that the channel is opened with the
asynchronous I/O option. This flag corresponds to setting the
FASYNC option with the fcntl system call.
IO_CHANNEL_NONBLOCK
This flag indicates that the channel is opened with the
O_NONBLOCK option.
IO_CHANNEL_NDELAY
This flag indicates that the channel is opened with the
O_NDELAY option. The driver should not look at this flag.
IO_CHANNEL_BLOCK_SPECIAL
This flag indicates that the driver is being opened as a block
special device. This flag is used only internally.
IO_CHANNEL_NO_RETRIES
This flag indicates that the I/O performed via this channel
should not be retried if errors occur; all errors are treated
as hard errors. This flag may or may not be supported by a
given device driver.
IO_CHANNEL_NOTIFY_IF_MANDATORY
This flag indicates that the kernel uses this option
internally to avoid deadlock on mandatory locks. Drivers
should not use this option.
IO_CHANNEL_NOCTTY
This flag indicates that the driver is being opened with the
O_NOCTTY open flag set. The kernel uses this option to
prevent the controlling terminal from being set.
io_operation_record_type
typedef struct
{
misc_queue_links_type links;
io_request_info_type ri;
io_completion_routine_ptr_type completion_routine;
} io_operation_record_type;
You use the operation record when starting an asynchronous I/O
request using your driver's dev_xxx_start_io function. The structure
is basically an extension of the io_request_info_type that you use
for synchronous requests. This extension supplies extra information
needed to service the request in an asynchronous manner. The
operation record's fields are as follows:
links A pointer to a space that the driver can use to link this
operation record into a queue with other operation records.
The driver determines the actual use of this space.
ri The request information structure that specifies the request.
completion_routine
A pointer to the address of the function that should be called
when the operation denoted by this operation record is
complete. This function must conform to the I/O completion
routine interface described below under kernel_complete_io.
io_select_intent_type
typedef bit16_type io_select_intent_type ;
IO_SELECT_INTENT_READ
IO_SELECT_INTENT_WRITE
IO_SELECT_INTENT_EXCEPTION
IO_SELECT_INTENT_POLLIN
IO_SELECT_INTENT_POLLPRI
IO_SELECT_INTENT_POLLOUT
IO_SELECT_INTENT_POLLERR
IO_SELECT_INTENT_POLLHUP
IO_SELECT_INTENT_POLLNVAL
IO_SELECT_INTENT_NONE
IO_SELECT_INTENT_POLLWRBAND
IO_SELECT_INTENT_POLLRDBAND
IO_SELECT_INTENT_POLLRDNORM
This type describes the select options that may be specified to a
device driver's dev_xxx_select routine. The READ, WRITE, and
EXCEPTION options start a select for the corresponding operation.
Any combination of these three options may be sent in a single
dev_xxx_select call. IO_SELECT_INTENT_NONE is used as a return value
from io_select_cancel when no intent has been satisfied.
io_buffer_vector_type
typedef struct
{
union
{
io_buffer_vector_control_type many;
io_buffer_descriptor_type one;
} u;
uint16_type descriptor_count;
uint16_type current_descriptor;
uint32_type current_offset;
uint32_type total_remaining;
} io_buffer_vector_type ;
This structure defines a buffer vector, which is a collection of
individual buffer descriptors plus an associated state. A buffer
vector may be the source or destination of a single read or write
operation; the individual buffer descriptors define the locations
from which the data is being read or into which the data is being
written.
The current position indicates where the next byte of data will be
read from or written to. The current position is initialized to the
first byte of the first buffer descriptor. The current position
within the buffer vector is maintained by the associated state.
The fields in this structure are as follows:
many This field contains a pointer to the array of buffer
descriptors and the total of the sizes of all the elements of
the array. This field is used only when descriptor_count is
non-zero. See also io_buffer_vector_control_type later in
this subsection.
one This field contains the single buffer descriptor when the
buffer vector consists of a single descriptor. This field is
used only when descriptor_count is zero. See also
io_buffer_descriptor_type later in this subsection.
descriptor_count
This field indicates the number of entries in the many array
of the io_buffer_vector_control_type and is used to determine
the actual amount of memory allocated to the array. If this
field is zero, then there is no memory allocated to the array
and a single descriptor is stored in the one field. The
total_size field of io_buffer_vector_control_type controls the
number of entries that are actually used, which may be less
than the amount specified by descriptor_count.
current_descriptor
This field contains the index of the descriptor that contains
the current position.
current_offset
This field contains the offset of the current position in the
buffer descriptor indexed by current_descriptor.
total_remaining
This field indicates the total number of bytes remaining to be
moved to or from this buffer vector since it was initialized.
io_buffer_descriptor_type
typedef struct
{
pointer_to_any_type buffer_ptr;
uint32_type size;
} io_buffer_descriptor_type ;
This structure describes the buffer from which data is to be read or
to which data is to be written. The fields in this structure are as
follows:
buffer_ptr A pointer to the start of the buffer.
size The size of the buffer, in bytes.
io_buffer_vector_control_type
typedef struct
{
io_buffer_descriptor_ptr_type descriptors_ptr;
uint32_type total_size;
} io_buffer_vector_control_type;
This structure is used in the many field of io_buffer_vector_type.
The fields in this structure are as follows:
descriptors_ptr
A pointer to an array of buffer descriptors. The array may
contain as many as UINT16_MAX entries. (For the definition of
UINT16_MAX, see /usr/src/uts/aviion/ext/c_generics.h.)
total_size
The sum of the size fields in all the elements of the array
buffer descriptors.
DEVICE DRIVER ROUTINE DESCRIPTIONS
dev_xxx_close
This routine removes a specified device from the set of devices on
which this driver can perform I/O. You should invoke one
dev_xxx_close for each successful dev_xxx_open. dev_xxx_close should
always get the same intents supplied to the open and the same device
handle returned by the open. However, if a device is opened multiple
times, it will not necessarily be closed in the same or reverse order
of the opens.
Typically, dev_xxx_close performs any necessary exit operations such
as flushing any buffers that may be present and releasing previously
allocated storage. Some devices will also have special exit
requirements. For example, a tape close would probably rewind the
tape. Most drivers also use dev_xxx_close in coordination with
dev_xxx_open to manage the number of outstanding opens.
dev_xxx_close_dump
The routine closes the dump device previously opened by
dev_xxx_open_dump.
The dev_xxx_close_dump routine is called by the system dump code when
all of the data has been written to the dump destination.
dev_xxx_close_dump should perform all the standard exit operations
(for example, write End-of-file or rewind the tape). In particular,
it should close the completed volume and inform the operator that the
dump has completed.
dev_xxx_configure
This routine configures a single device of the type supported by this
driver.
The routine performs operations that make a physical device of the
driver's type supported accessible to the system. The
dev_xxx_configure routine can be called anytime. If your device has
system and master file entries, it will be called by system
initialization code during system boot. It is called once for each
system file entry in the system.
The dev_xxx_configure routine receives a device_name_ptr variable
that points to a device name. The name string is terminated by a
null character and has the following form:
device_mnemonic [@device_code]([parameters])
Because each dev_xxx_configure is called for all system file entries,
your dev_xxx_configure should verify that the name string for the
current call contains its device's name. If the name is not for one
of its devices, dev_xxx_configure should exit with a return value of
IO_ENXIO_DEVICE_NAME_NOT_RECOGNIZED.
dev_xxx_configure must initialize the device and must make the device
accessible to the kernel. Device initialization is unique to the
device and to the driver. The dev_xxx_configure routine should
perform the following functions:
· Allocate a device information structure. The driver uses the
device information structure to hold information relating to a
specific device (status, permissions, and so on). While the
driver can define most of this structure's internal specifics,
the structure must contain a pointer to the driver's interrupt
service routine (if it has one) in the first field. In
addition, if you want to use the kernel's routines for managing
a select list [see the io_select(3K) man page], you should
allocate a select list header in the device information
structure. The select list header type is defined in i_io.h.
You will also have to initialize this list by calling the
kernel's io_init_select routine.
· Register the device information structure. If the device
handles interrupts, you must register the device information
structure using the io_register_device_info routine.
Registering the device information links the device code and
device class of the driver with the interrupt service routine
given in the device information structure.
· Define a device handle and device number. You do this by
calling io_allocate_device_number. io_allocate_device_number
allocates a minor number for the device specified and links the
device number and device handle in the kernel's internal tables.
Later you can retrieve this information by using kernel routines
for accessing device information (see the device_interrupts(3K)
man page). The kernel will pass the device number to your
driver's dev_xxx_open routine, but thereafter it will identify a
device to all driver routines by passing the device handle. If
the device has a controller with accessible units, you should
establish a device number and device handle for all units that
users will access.
· Create device node special files. As with device numbers, you
should create device node special files for all the units that
users will access. We recommend that you create the special
files after registering your device information structure,
because it is possible for the register operation to fail. The
device_nodes(3K) man page describes kernel routines that create
device node special files.
If the device has a controller, the driver usually performs any
initialization needed to bring the controller on-line in
dev_xxx_configure. The driver can then initialize the controller's
units at open time.
If a failure occurs in any phase of the operation, dev_xxx_configure
must return the system to the state it was in before the
dev_xxx_configure routine was called. Data structures must be
deallocated and the device interrupt table slot freed.
You should write your dev_xxx_configure routine such that it can be
called any time during the life of the system.
dev_xxx_deconfigure
This routine deconfigures the specified device if it is of the device
type supported by this driver.
The dev_xxx_deconfigure routine does the opposite of the configure
routine (see dev_xxx_configure). It releases all system resources
obtained to configure the device. After dev_xxx_deconfigure has
completed, the system should be in the state it was in before the
device configure routine was executed. dev_xxx_deconfigure performs
the following functions:
· Deallocates a device information structure
· Frees the minor number
· Deregisters device information and removes the device from the
system dump list
· Releases all memory
· Releases Generic and I/O Server messages and timeout space, [see
io_unspecify_max_demon_messages(3K),
io_unspecify_max_generic_demon_messages(3K), and
vp_unspecify_max_timeouts(3K)].
· Removes /dev entries.
dev_xxx_deconfigure receives a pointer to a device specification of
the following form:
device_mnemonic [@device_code]([parameters])
The pointer is terminated by a null character.
dev_xxx_device_to_name
This routine returns the device name associated with the specified
device number. The name is returned as a null-terminated string.
The dev_xxx_device_to_name routine is called by various file system
utilities to translate a device number into a device name. It
returns the name in a string of the following form:
device_mnemonic [@device_code]([parameters])
If an earlier driver routine (for example, the configuration routine)
stored the device code and unit number in its unit tables, the
dev_xxx_device_to_name may call the kernel's io_map_device_number to
retrieve the device code and unit number for the given device number.
dev_xxx_init
This routine performs any pre-configuration initialization your
driver might need. It should not initialize the hardware device
itself, however.
The kernel calls the dev_xxx_init routine as part of system
initialization. dev_xxx_init gives the driver an opportunity to
perform any initialization needed before any of the driver's devices
are configured into the system. dev_xxx_init is invoked once in the
life of the system. No devices controlled by the driver will be
configured until after the dev_xxx_init routine completes.
The dev_xxx_init routine operates in a restricted environment. It
may not await or take a page fault.
dev_xxx_ioctl
This routine performs a control operation on the specified device.
The dev_xxx_ioctl routine performs an ioctl control operation on the
specified device based on the values of command and parameter. It is
invoked in response to a user or kernel ioctl call for one of the
driver's devices. However, not all user ioctl calls go to
dev_xxx_ioctl. Some ioctl calls are actually file descriptor
operations. These are intercepted and handled by the kernel. The
FIONCLEX operation, for example, would not reach dev_xxx_ioctl.
Multiple ioctl operations on the same or different minor devices may
be in progress simultaneously.
The kernel calls dev_xxx_ioctl with the command and parameter
arguments as specified by the ioctl system call. The kernel does not
interpret these arguments. Thus, you can define your driver's
command and parameter arguments as you wish.
Because ioctl operations are so specific to each driver, the kernel
validates only the device handle argument.
dev_xxx_maddmap
This routine modifies the reference count for memory-mapped sections
for the device. The reference count is called the "mmap use" count.
This routine maintains the mmap use count for the device. The count
indicates to the driver whether there are any outstanding memory
mappings of the device. If the count is positive, there are some
mappings. Otherwise, the count must be zero, indicating there are no
mappings.
This routine may assume that the device is either open or memory
mapped at the time it is called. That is, if the mmap count for the
device is zero when this routine is called, then the device's open
count and mmap_count_delta must both be positive. Typically, you can
maintain the mmap count and open count for a device as a single
unsigned integer (the use count), which must be at least 32 bits in
size and protected by the device's open lock. dev_xxx_maddmap
adjusts the device's use count by the (signed) amount specified by
mmap_count_delta. The use count must be positive prior to the call.
If the mmap count becomes zero and the open count is already zero as
a result of this call, then dev_xxx_maddmap should perform the
actions associated with the last system-wide close of the device (for
example, freeing resources). This means that the driver's close
routine must not perform the last close actions for a device unless
both the open count and mmap count are zero. If the use count
becomes zero, then dev_xxx_maddmap must perform the last close
actions for the device.
dev_xxx_mmap
This routine implements the mmap system call. It maps a physical
address region controlled by the xxx character special device into
the user address space.
This routine validates and translates the caller's mmap request based
on the mapping of device offsets to physical address regions defined
by device_handle, request_ptr, and io_flags. If the request is valid
and all required resources are available, then dev_xxx_mmap maps the
appropriate physical address region controlled by the device into
user memory at the address returned in start_address_ptr.
The required steps are as follows:
1. Verify that the device offset range corresponds to a range of
physical addresses controlled by the device and is safely
accessible by the caller. The device offset range is defined
by the file_offset_extender, file_offset, and byte_count
fields of request_ptr. If the range is not valid, return
IO_ENXIO_ILLEGAL_DEVICE_ADDRESS.
NOTE: file_offset_extender denotes the high 32 bits of the 64-bit
device offset. A driver that supports only 32-bit offsets
should return an error if file_offset_extender is non-zero.
2. Translate the beginning of the request's device offset range
to its corresponding physical address.
3. Compute the maximum access to the physical memory that the
mapping should allow. Generally, you should allow read and
execute access to the memory if the caller's channel flags
indicate that the device is open for reading. Similarly, you
should allow write access to the memory if the device is open
for writing.
4. Determine the appropriate memory cache control for the mapped
memory. Most memory mapped devices require caching to be
disabled.
After successfully completing these steps, dev_xxx_mmap calls
vm_mmap_physical_memory to complete the request and returns the
status from vm_mmap_physical_memory's to the caller. To prevent
deadlock, avoid holding any locks when calling
vm_mmap_physical_memory as vm_mmap_physical_memory calls the driver's
maddmap routine one or more times.
dev_xxx_munmap
This routine determines whether to allow an unmap of a previously
memory-mapped region of physical memory.
This routine has no side effects beyond returning a status.
Presently, all character special devices which support memory mapping
must also allow subsequent unmapping on arbitrary page boundaries.
Thus, this routine must return OK.
dev_xxx_name_to_device
This routine returns the device number for the specified device name.
This routine is called by various file system utilities to translate
a device name into the major and minor device numbers that are
required to access the device. The device name specified by
device_name_ptr is of the following form:
device_mnemonic [@device_code]([parameters])
To simplify its processing, dev_xxx_name_to_device can call the
kernel's io_get_device_info, which returns a pointer to the device
information structure that will contain the device's device number.
The driver should verify that the device mnemonic given in the name
matches its own mnemonic (xxx).
dev_xxx_open
This routine prepares a specified device for future I/O operations.
It also adds the device to the set of devices on which I/O can be
performed by this driver.
The kernel calls the routine whenever one of the driver's devices is
opened by a user or by the kernel. The kernel will not call
dev_xxx_open until both dev_xxx_init and dev_xxx_configure have
completed.
The DG/UX system allows multiple opens on a device, and dev_xxx_open
should manage this feature as appropriate to its device.
dev_xxx_open controls the number of outstanding opens. For example,
dev_xxx_open may impose restrictions such as requiring an exclusive
open of a particular minor device. To implement this, dev_xxx_open
might return an error status if the minor device has already been
opened but not closed. Multiple dev_xxx_open processes may be in
progress simultaneously on the same or different minor device
numbers.
The dev_xxx_open routine must also control the type of open
requested. The kernel passes dev_xxx_open a set of channel flags
that specify the intents given in the higher level open call (for
example, read, write or both). dev_xxx_open may reject the open
because of conflicts between the current open intent and open intents
that have already taken place or because of conflicts with the
device's capabilities. For example, a write intent on a read-only
device must fail.
dev_xxx_open typically performs other operations to prepare the
device and ensure that it is ready for I/O. For example, it may
allocate storage for and initialize databases to hold information
describing the I/O operation on the specific unit. If the device is
a real hardware device, dev_xxx_open may query the device to verify
that it is on-line and ready for the type of I/O specified in the
open intent. For example, it may check that there is a write ring in
the tape if write intent is specified.
dev_xxx_open must establish the device handle that the kernel will
use as a parameter in all future driver operations. It can retrieve
the handle that dev_xxx_configure stored by calling
io_map_device_number with the device number. If dev_xxx_open returns
an OK, it must return the device handle in device_handle_ptr. If it
returns a status other than OK, the kernel presumes that the open
failed and it will disregard the returned device_handle_ptr argument.
dev_xxx_open_dump
This routine prepares one of the driver's devices for use as the
destination of a system dump.
A master file entry specifies the default device for a system dump,
but during the dump procedure the user is allowed to specify an
alternative dump destination. If your device is selected as the dump
destination, the system will call your dev_xxx_open_dump routine if
the system halts.
The dev_xxx_open_dump routine initializes the device as a dump
destination. To do this, it must reinitialize the device's
controller (and/or units). Because the system is in an undefined
state as a result of the halt, the standard kernel facilities will
not be available for the initialization procedure. In particular,
this means that dev_xxx_open_dump must run in physical memory since
dynamically allocated memory cannot be accessed. dev_xxx_open_dump
should statically allocate its data structures in
dev_xxx_global_data.c.
The dev_xxx_open_dump routine should also use device polling when
interacting with the controller, because the standard interrupt
mechanism will not be available.
Because the dump procedure is a single-threaded process, you do not
need and should not use the kernel locking mechanisms.
The dev_xxx_open_dump routine receives a device name specified by
device_name. It should verify that the device specified is of the
driver's type. The device name is of the following form:
device_mnemonic [@device_code]([parameters])
Finally, as with any open routine, dev_xxx_open_dump should perform
any operations necessary to ensure that the device is on-line and
ready for a write operation. For example, if the device is a tape,
the tape should be on-line and write-enabled.
NOTE: This routine must not halt because it is invoked as part of
the halt sequence.
dev_xxx_powerfail
This routine restarts all devices managed by this driver when power
has been restored after a power failure.
The DG/UX system does not support this operation at this time. You
should use the appropriate io_nodevice stub for this routine.
dev_xxx_read_dump
This routine handles reading a system dump device.
This routine may be called during a halt to read one or more blocks
from the system dump device. Because it will be called during halt
processing, the normal kernel facilities may not be available. In
particular this routine should not use locks or interrupts. It
should implement the read operation by polling the device for the
read operation to complete.
dev_xxx_read_write
This routine performs a synchronous read or write of the specified
device.
You can assume the request information structure has a valid
operation code and device handle. The driver must validate the
device offset and transfer count as being appropriate for the device.
The driver must also be prepared to handle errors in referencing the
memory address as specified in the buffer vector.
The transfer count specifies the maximum number of bytes that should
be transferred. The driver determines how much data to actually
transfer before it returns. If there is an error, the amount may be
less than the transfer count. However, under no circumstances may
the amount of data transferred exceed the specified maximum.
The offset specified is a file pointer maintained by the kernel; it
indicates where the read/write operation should begin. For example,
on a disk, the offset might specify where, after the start of the
sector, the desired data is located. The driver may ignore this
parameter if it is not applicable to its device for example, if the
device is character special.
The request information structure can be accessed only when the
requesting process is running; it can not be accessed from the
interrupt level.
The dev_xxx_read_write routine performs a synchronous read or write
of the specified device, transferring data between the device and the
specified buffer. It is invoked whenever a user or kernel read or
write is performed on a device supported by this driver. This
routine is usually used for character special I/O, but it may also be
used for block special I/O.
Multiple reads/writes of the same or different minor devices may be
in progress simultaneously. Therefore the driver should take steps
to serialize requests as needed. This usually means using locks on
important data structures.
The dev_xxx_read_write routine should also handle any special
transfer constraints for its device. For example, a disk device
might allow only those transfer counts that are multiples of 512
bytes. dev_xxx_read_write should be prepared to handle a kernel-
requested self-identification check as indicated in the self-id field
in the request information structure. The flag indicates that the
driver should verify that this self-id matches the device's self-id
as stored in data blocks read from that device. You can use the
kernel's fs_check_self_id routine to retrieve the self-id stored in
the data (see the fs_check_self_id(3K) man page).
Because the dev_xxx_read_write routine is synchronous, any data that
is going to be transferred to or from the buffer must already be
transferred when it completes. Because it must wait for the I/O to
complete, dev_xxx_read_write will need to set up await mechanisms
such as a timeout, a signal, or an I/O completion event. The
event_counters(3K) man page describes kernel routines that the driver
can use to implement these await mechanisms.
The buffer can only be accessed only when the requesting process is
running. Be sure to check the buffer's access status before reading
or writing to it. You should check write access to the buffer for
read operations and read access to the buffer for write operations.
Many transfer operations must be done to wired buffers. The
specified buffer is wired unless the IO_OPERATION_USER_BUFFER
operation flag is set in the request block operation field. If the
buffer is unwired and the transfer requires a wired buffer, the
driver must explicitly wire the buffer and unwire it before
returning. The memory_allocation(3K) man page describes kernel
routines that the driver can use to wire and unwire memory.
After the read/write, the driver should update the buffer vector
pointers to reflect the actual data transferred (which may be less
than the transfer count in cases of error). You must use kernel
utilities for all references and updates to data contained in the
io_buffer_vector structure. The io_buffer_vector(3K) man page
describes the kernel routines used to manipulate buffer vectors.
dev_xxx_select
This routine supplies information about whether the specified device
is ready to perform an I/O operation.
The kernel calls the dev_xxx_select routine in response to user-level
select system calls. dev_xxx_select operates as follows:
· If the user is selecting a device (select_mode argument is
TRUE), and the device is ready for at least one of the
incoming intents, the driver should set the intent flags to
match the device's current state and return. It should set
the flags to FALSE for all intents that are not currently
ready. It should set the intent flag to TRUE if that flag was
TRUE on input and the intent is currently ready. If none of
the conditions the caller was interested in are TRUE, the
driver should add the eventcounter pointed to by ec_ptr to a
list of events maintained by the driver. Later, when one of
the specified intents becomes TRUE, the driver must advance
this eventcounter. Usually, drivers have the
dev_xxx_service_interrupt routine complete select processing
via a message to the Driver or Generic Server.
· If the user is unselecting the device (the select_mode
argument is FALSE), the driver should discard the previously
saved ec_ptr and report any intents that have become TRUE.
Multiple selects of the same or different minor devices may be in
progress simultaneously. The dev_xxx_select routine must be able to
store multiple eventcounter pointers for each of the read, write, and
exception selects and advance them all when the intent becomes TRUE.
Kernel routines for managing select lists (adding and removing
entries and satisfying selects) are described in the io_select(3K)
man page. The driver should have allocated and initialized the
select list structure before select operations begin, usually in the
dev_xxx_configure routine.
For many devices, such as disks and tapes, dev_xxx_select always
returns TRUE because the I/O operations are quick. dev_xxx_select is
more meaningful on character devices that depend upon external
intervention. For example, the kernel might send a select FALSE for
writing to a terminal when its output is being held with Ctrl-S.
Similarly, it would select FALSE for reading when the driver is
waiting for the user to type something.
dev_xxx_service_interrupt
This routine handles interrupts from devices under the control of
this driver. It is called by the system interrupt handler.
The dev_xxx_service_interrupt routine performs any steps needed to
service the device at interrupt level. It operates in a restricted
environment: interrupts are disabled; no page faults may be taken;
and the process must not wait. Because of these restrictions,
dev_xxx_service_interrupt should defer as much device service as
possible to a base-level process.
The dev_xxx_service_interrupt must avoid calling any routine that may
pend. Therefore, it must forgo virtually all the kernel-supplied
utilities. You should use the Driver or Generic Server to signal or
send information back to other processes. You send a message to the
appropriate server (daemon) by queuing a message with a completion
routine to the server's queue. [To queue messages, see
io_queue_message_to_driver_demon(3K) and
io_queue_message_to_generic_demon(3K).] The server will dequeue the
message and execute the completion routine in the server's context
rather than the interrupt service routine's limited context.
Typically, dev_xxx_service_interrupt might do any of the following:
read the device's status registers; advance an eventcounter for
synchronous events; send a message to the Driver or Generic Server
for an asynchronous event; or do a select satisfy for a select
operation. If the interrupt is not cleared automatically by reading
the status register, dev_xxx_service_interrupt must clear the
interrupt before exiting.
The pointer to the device information structure allows
dev_xxx_service_interrupt to access the device database associated
with the I/O request.
NOTE: If the device does not generate hardware interrupts, you do
not need to create this routine.
dev_xxx_start_io
This routine starts an asynchronous I/O operation on the specified
device.
When a user initiates a read or write operation on a block special
device, the kernel will invoke dev_xxx_start_io to process the
request asynchronously. The dev_xxx_start_io routine is used only on
block special devices. Multiple dev_xxx_start_io routines on the
same or different minor devices may be in progress simultaneously.
dev_xxx_start_io should start the operation and then exit, leaving
the completion to be handled by another routine. If dev_xxx_start_io
cannot initiate the operation (for example, if the device is busy),
it should queue the request to be handled later and exit. This
routine should not pend.
The operation record must reside in global kernel memory, so it may
be accessed by any process, not just the requester. The driver need
not validate most of the fields of the operation record. The
exceptions are the device offset and transfer size fields. The
driver may need to check these fields to ensure that they are
meaningful for the device.
The dev_xxx_start_io routine returns before the data transfer is
complete. The driver must therefore decide how to finish processing
once the operation does complete. The driver is relatively free to
handle completion as necessary for its own device.
The only thing the driver is required to do during completion is to
call the kernel completion routine supplied in the operation record.
The kernel waits until its I/O completion routine is called before
expecting new data in the buffer, modifying data in a buffer that was
written, or modifying the operation record that was passed in as an
argument. Until the driver calls the kernel's I/O completion
routine, the kernel does not consider the operation complete.
The driver decides when to call the kernel's I/O completion routine.
Typically, when the operation completes, the
dev_xxx_service_interrupt routine queues a message to the Driver or
Generic Server. The message contains a pointer to a routine which
the server will execute. This routine might be either the kernel's
I/O completion routine or a driver-supplied complete_io routine that
in turn calls the kernel's I/O completion routine. The
server_messages(3K) man page describes the kernel routines for
interacting with the Driver or Generic Server.
The information below under kernel_complete_io describes the
interface the kernel's I/O completion routine uses. You do not need
to the kernel-specified interface in your driver's complete_io
routine.
The following implementation notes are relevant regardless of how
completion is implemented:
· The driver must transfer the exact amount of data specified in
the request unless there is an I/O error (in which case less
data is acceptable). Under no circumstances may the amount of
data transferred exceed the amount specified.
· You must not call the kernel's I/O completion routine in the
same process from which the dev_xxx_start_io routine is called
lest the kernel's I/O completion routine be called before
dev_xxx_start_io finishes.
· The buffer to receive the data is wired in memory. The driver
may perform logical-to-physical address translations without
having to explicitly wire the buffer. Further, the buffer must
reside in global kernel memory, so any process may access the
buffer or perform the logical-to-physical translation.
dev_xxx_write_dump
This routine writes system dump data to the dump destination device
previously opened by dev_xxx_open_dump.
During a dump, the system's halt code path calls dev_xxx_write_dump
to write the data specified in the io_buffer_vector. The halt code
will call the dev_xxx_write_dump routine as many times as necessary
to transfer all of the dump data. You will not need to wire buffer
memory or verify parameters for this routine.
If the dump destination must use multiple volumes to hold the entire
system dump, the dev_xxx_write_dump routine should close the
completed volume, request that the operator mount a new volume, and
open the new volume.
NOTE: Because the normal kernel facilities are not available, this
routine should busy-wait for the write operations to complete.
The normal system interrupt handler is not available. Also,
this routine must not halt because it is invoked as part of
the halt sequence.
kernel_complete_io
This routine defines the kernel I/O completion routine interface.
The kernel supplies a routine that adheres to this interface to
perform work necessary when an asynchronous I/O operation completes.
The kernel's I/O completion routine performs the cleanup the kernel
must do to complete the asynchronous I/O. The driver calls it to
indicate that the operation is complete.
The status argument indicates the result of the asynchronous I/O
operation.
The kernel's I/O completion routine must always succeed. Therefore
it does not have a return value.
DIAGNOSTICS
Return Value
The dev_xxx_init routine does not return a status; any errors that it
encounters must result in a halt or in some method of flagging the
error to dev_xxx_configure for further processing.
For dev_xxx_configure:
OK The device was successfully configured.
IO_ENXIO_DEVICE_NAME_NOT_RECOGNIZED
device_name_ptr does not specify a device of the type
supported by this driver.
IO_ENXIO_DEVICE_NOT_SUPPORTED
device_name_ptr specifies a device of the type
supported by this driver, but the particular model is
not supported.
IO_EIO_PHYSICAL_UNIT_FAILURE
A request issued to the device controller failed with
an error status.
IO_EIO_DEVICE_TIMED_OUT
The controller did not respond to a request within a
reasonable length of time.
IO_ENXIO_DEVICE_IS_ALREADY_CONFIGURED
A device is already registered at the location
specified by device_name_ptr.
For dev_xxx_deconfigure:
OK The device was successfully deconfigured.
IO_ENXIO_DEVICE_NAME_NOT_RECOGNIZED
device_name_ptr does not specify a device of the type
supported by this driver. This error is returned when
the device mnemonic does not match the mnemonic
associated with the driver.
IO_EBUSY_DEVICE_HAS_OPEN_UNITS
The specified device currently has one or more units
that are open.
For dev_xxx_device_to_name:
OK The translation was performed successfully.
IO_ENXIO_DEVICE_IS_NOT_CONFIGURED
The specified device number is not configured.
For dev_xxx_name_to_device:
OK The device name was successfully translated.
IO_ENXIO_DEVICE_NAME_NOT_RECOGNIZED
The specified device is not supported by this driver.
This error is returned when the device mnemonic does
not match the mnemonic associated with the driver.
IO_ENXIO_DEVICE_IS_NOT_CONFIGURED
The specified device is supported by this driver but is
not currently configured in the system.
For dev_xxx_open:
OK The dev_xxx_open routine was successful in preparing
the device for further operations.
IO_ENXIO_UNIT_NOT_READY
The unit is not ready or on-line.
IO_ENXIO_DEVICE_IS_NOT_CONFIGURED
The specified device number cannot be mapped to a
configured device.
IO_ENXIO_OPEN_INTENT_CONFLICTS
The unit is already open and can only be opened
exclusively.
IO_ENXIO_NO_WRITE_RING
The tape was opened with write intent, but the tape did
not have a write ring (only applicable to tape
devices).
IO_ENXIO_TAPE_DENSITY_NOT_SUPPORTED
The requested density is not supported by the tape
controller (only applicable to tape devices).
IO_ENXIO_CANNOT_CHANGE_TAPE_DENSITY
The requested density is not compatible with the
current density setting of the unit, and the tape is
not at the beginning of the tape (BOT) (only applicable
to tape devices).
For dev_xxx_close:
OK The close was successful.
IO_STATUS_ERROR_ON_EARLIER_REQUEST
An error occurred on the last asynchronous request made
to the device. Since the last request was
asynchronous, this is the first opportunity to notify
the interested process.
The dev_xxx_read_write routine must return a status indicating the
success or failure of the transfer. The definition of success or
failure is determined by the driver and need not be related to the
number of bytes actually transferred.
OK The dev_xxx_read_write routine was successful.
IO_EINVAL_ILLEGAL_REQUEST_SIZE
The requested count is not valid for the device type.
IO_EINVAL_ILLEGAL_BUFFER_ADDRESS
The buffer was not aligned as required by the device.
IO_ENXIO_ILLEGAL_DEVICE_ADDRESS
The location specification for reading/writing is
invalid for the device.
IO_EIO_DEVICE_TIMED_OUT
The device controller did not respond to a request in a
reasonable length of time.
IO_EIO_HARD_IO_ERROR
An unrecoverable I/O error occurred, resulting from a
media failure.
IO_EIO_PHYSICAL_UNIT_FAILURE
An uncorrectable error occurred that presumably affects
I/O operations to the entire physical unit.
IO_EINTR_INTERRUPTED_BY_SIGNAL
A signal was received while waiting for the I/O to
complete.
IO_EINVAL_REQUEST_SIZE_TOO_LARGE
The requested count exceeds the limit of this device.
The dev_xxx_start_io routine must return a status indicating the
success or failure of the start of a transfer. All errors other than
IO_EINVAL_REQUEST_SIZE_TOO_LARGE are reported via the completion
routine.
OK The request was successfully started.
IO_EINVAL_REQUEST_SIZE_TOO_LARGE
The requested count exceeds the limit of this device.
The dev_xxx_ioctl routine should return a status indicating the
success or failure of the control operation. The definition of
success or failure is determined by the driver.
OK The dev_xxx_ioctl routine was successful. No errors
should be indicated to the caller.
IO_EINVAL_COMMAND_NOT_SUPPORTED_BY_DEVICE
The command was not supported by the driver.
For dev_xxx_open_dump:
OK The open completed successfully.
IO_STATUS_DUMP_NOT_SUPPORTED
The device identified by the device_name string is not
supported as a dump device by this driver. Either the
device mnemonic does not match the mnemonic associated
with your driver; the device name is in an
unrecognizable format; or the device specified by
device_name_ptr is supported by the driver but the
device type is not a valid dump destination device.
IO_EIO_HARD_IO_ERROR
A request to the dump destination device has resulted
in an error condition.
For dev_xxx_write_dump:
OK The write operation completed normally.
IO_STATUS_TAKE_CHECKPOINT
The write operation completed normally but was written
as the first record on a volume. The system dump code
should checkpoint its current state.
IO_EIO_HARD_IO_ERROR
An unrecoverable I/O error occurred. The system dump
code should restore its state from the last checkpoint
and begin writing again from there. This error does
not occur on the first record of the volume.
For dev_xxx_read_dump:
OK The volume was successfully read.
IO_EIO_HARD_IO_ERROR
An unrecoverable error occurred during the read
operation.
For dev_xxx_close_dump:
OK The volume was successfully closed.
IO_EIO_HARD_IO_ERROR
An unrecoverable error occurred in closing the volume.
The operator is prompted to mount another volume, and
the system dump utility should resume operation at its
last checkpoint.
For dev_xxx_mmap:
OK The call successfully created a mapping at the user
address returned in start_address_ptr.
IO_ENXIO_ILLEGAL_DEVICE_ADDRESS
The requested device offset range did not fall entirely
within a range of mappable device offsets.
other error status from vm_mmap_physical_memory
The mmap request failed due to a problem detected by
the vm_mmap_physical_memory routine.
vm_mmap_physical_memory will pass back the error
status.
For dev_xxx_munmap:
OK All munmaps of this device are allowed. dev_xxx_munmap
must return OK.
For dev_xxx_powerfail:
OK Return this value in all cases.
For the other routines: none.
SEE ALSO
adapter_driver(3K), adapter_manager(3K), device_interrupts(3K),
device_nodes(3K), event_counters(3K), fs_check_self_id(3K),
io_buffer_vector(3K), io_select(3K), memory_allocation(3K),
sc_panic(3K), server_messages(3K), status_code_macros(3K).
system_clock(3K).
Programming in the DG/UX Kernel Environment.
Licensed material--property of copyright holder(s)