Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ dev_xxx_mmap(3K) — DG/UX 5.4R3.00

Media Vault

Software Library

Restoration Projects

Artifacts Sought



device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


NAME
       devicedriver: devxxxinit, devxxxconfigure, devxxxdeconfigure,
       devxxxdevicetoname, devxxxnametodevice, devxxxopen,
       devxxxclose, devxxxserviceinterrupt, devxxxreadwrite,
       devxxxstartio, devxxxselect, devxxxioctl, devxxxopendump,
       devxxxwritedump, devxxxreaddump, devxxxclosedump,
       devxxxmaddmap, devxxxmmap, devxxxmunmap, devxxxpowerfail -
       implement a device driver

SYNOPSIS
       #include "/usr/src/uts/aviion/ii/iio.h"

       statustype     devxxxclose (
       iodevicehandletype         devicehandle,    READONLY
       iochannelflagstype         channelflags     READONLY )

       statustype     devxxxclosedump (
       iodevicehandletype         devicehandle     READONLY )

       statustype     devxxxconfigure (
       charptrtype                 devicenameptr,  READONLY
       iomajordevicenumbertype   majornumber      READONLY )

       statustype     devxxxdeconfigure (
       charptrtype                 devicenameptr   READONLY )

       statustype     devxxxdevicetoname (
       iodevicenumbertype         devicenumber,    READONLY
       charptrtype                 nameptr,         WRITEONLY
       uint32type                   size              READONLY )

       void            devxxxinit ()

       statustype     devxxxioctl (
       iodevicehandletype         devicehandle,    READONLY
       bit32etype                   command,          READONLY
       bit32etype                   parameter,        READWRITE
       int32eptrtype               returnvalueptr  WRITEONLY )

       void            devxxxmaddmap (
       iodevicehandletype         devicehandle,    READONLY
       opaqueptrtype               fileid,          READONLY
       int32type                    mmapcountdelta  READONLY )

       statustype     devxxxmmap (
       iodevicehandletype         devicehandle,    READONLY
       opaqueptrtype               fileid,          READONLY
       iommaprequestptrtype      requestptr,      READONLY
       iochannelflagstype         ioflags,         READONLY
       byteaddressptrtype         startaddressptr WRITEONLY )







Licensed material--property of copyright holder(s)                         1




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       statustype     devxxxmunmap (
       iodevicehandletype         devicehandle,    READONLY
       opaqueptrtype               fileid,          READONLY
       iommaprequestptrtype      requestptr,      READONLY
       byteaddresstype             startphysaddr   READONLY )

       statustype     devxxxnametodevice (
       charptrtype                 devicenameptr,  READONLY
       iodevicenumberptrtype     numberptr        WRITEONLY )

       statustype     devxxxopen (
       iodevicenumbertype         devicenumber,    READONLY
       iochannelflagstype         channelflags,    READONLY
       iodevicehandleptrtype     devicehandleptr WRITEONLY )

       statustype     devxxxopendump (
       charptrtype                 devicename,      READONLY
       iodevicehandleptrtype     devicehandleptr READONLY )

       statustype     devxxxpowerfail ()

       statustype     devxxxreaddump (
       iodumprequestinfoptrtype dumprbptr       READONLY )

       statustype     devxxxreadwrite (
       iorequestinfoptrtype      requestinfoptr  READONLY )

       void            devxxxselect (
       iodevicehandletype         devicehandle,    READONLY
       booleantype                  selectmode,      READONLY
       vpecptrtype                ecptr,           READONLY
       ioselectintentptrtype     intentptr        READWRITE )

       void            devxxxserviceinterrupt (
       devxxxdeviceinfoptrtype  deviceinfoptr   READONLY )

       statustype     devxxxstartio (
       iooperationrecordptrtype  oprecordptr     READONLY )

       statustype     devxxxwritedump (
       iodumprequestinfoptrtype dumprbptr       READONLY )

       void        kernelcompleteio (
       iooperationrecordptrtype  oprecordptr,    READONLY
       statustype                   status            READONLY )

   where:
       channelflags     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, iochannelflagstype.  (See also
                         iio.h for a listing of the channel flags.)  The
                         driver does not need to validate this argument.



Licensed material--property of copyright holder(s)                         2




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       command           A command to the device.  The driver must validate
                         the command because commands are driver-specific.
       devicehandle     The device handle that was returned by the driver's
                         devxxxopen routine.  The driver does not need to
                         validate this argument.
       devicehandleptr 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.
       deviceinfoptr   A pointer to the device information structure for
                         the interrupting device.  A pointer to the
                         devxxxserviceinterrupt routine is the first
                         field in this structure.  The driver does not need
                         to validate this pointer.
       devicename       A pointer to the null-terminated string identifying
                         the device to be opened as a dump device.
       devicenameptr   A pointer to a null-terminated string specifying
                         the name of the device to be configured,
                         deconfigured, or translated.
       devicenumber     The major and minor device numbers of a particular
                         device.
       dumprbptr       A pointer to the dump request information
                         structure.  This structure contains the
                         iobuffervector, the devicehandle, the
                         deviceoffset, and the deviceoffsetextender
                         fields.  The devicehandle field is returned from
                         the devxxxopendump routine.
       ecptr            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.
       fileid           A file identifier associated with the character
                         special file that was initially opened to gain
                         access to the device.
       intentptr        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.
       ioflags          The channel flags for the descriptor passed to
                         mmap(2).
       majornumber      The major number of the device to be configured.
       mmapcountdelta  The amount to increment or decrement the mmap use
                         count for the device.
       nameptr          A pointer to the location where the device name is
                         to be written as a null-terminated string.
       numberptr        A pointer to where the corresponding device number
                         is to be written.  The device number consists of a
                         major and minor device number.



Licensed material--property of copyright holder(s)                         3




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       oprecordptr     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
                            kernelcompleteio below.  Note that you pass
                            the oprecord and a completion status back as
                            parameters to the kernelcompleteio routine.
                         ⊕  An iobuffervector 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.
       requestinfoptr  A pointer to a request information structure.
       requestptr       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
       requestptr       Additional information indicating which memory is
                         requested to be unmapped.
       returnvalueptr  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.
       selectmode       If selectmode is TRUE, this is the start of a
                         select operation.  If selectmode is FALSE, this is
                         the end of a select operation.
       size              The maximum number of bytes, including the



Licensed material--property of copyright holder(s)                         4




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


                         terminating null, that is to be written to
                         nameptr.
       startaddressptr Location used to return the start address in the
                         user address space of the newly mapped region.
       startphysaddr   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:
       devxxxinit              Perform pre-configuration initialization
       devxxxconfigure         Configure a device
       devxxxdeconfigure       Deconfigure a device
       devxxxdevicetoname    Return name associated with device number
       devxxxnametodevice    Return device number for device name
       devxxxopen              Open a device
       devxxxclose             Close a device
       devxxxserviceinterrupt Handle device interrupts
       devxxxreadwrite        Synchronously read from or write to device
       devxxxstartio          Start asynchronous I/O operation
       kernelcompleteio        Clean up after asynchronous I/O operation
       devxxxselect            Check whether device ready for I/O
       devxxxioctl             Performs control operation on device
       devxxxopendump         Open a dump device
       devxxxwritedump        Write system dump data to dump destination
       devxxxreaddump         Read a system dump device
       devxxxclosedump        Close a dump device
       devxxxmaddmap           Modify device memory map reference count
       devxxxmmap              Implement the mmap system call
       devxxxmunmap            Determine whether to unmap memory
       devxxxpowerfail*        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 panic the system.  Some driver routines are not allowed
              to panic.  The "Return Value" subsection of the interface



Licensed material--property of copyright holder(s)                         5




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


              description indicates whether or not a routine can panic.

       The statuscodemacros(3K) man page describes how to define an error
       status and how to log an error to the error server.  The scpanic(3K)
       man page describes how to use the routine that panics 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.

       iodriverroutinesvectortype
              typedef struct
                  {
                  uint16type         version;
                  bit16type          flags;
                  statustype         (*open)();
                  void                (*close)();
                  statustype         (*readwrite)();
                  void                (*select)();
                  statustype         (*ioctl)();
                  statustype         (*startio)();
                  void                (*init)();
                  statustype         (*configure)();
                  statustype         (*deconfigure)();
                  statustype         (*devicetoname)();
                  statustype         (*nametodevice)();
                  statustype         (*opendump)();
                  statustype         (*writedump)();
                  statustype         (*readdump)();
                  statustype         (*closedump)();
                  statustype         (*powerfail)();
                  statustype         (*mmap)();
                  statustype         (*munmap)();
                  statustype         (*maddmap)();
                  }  iodriverroutinesvectortype ;

       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 iodriverroutinesvectortype.  You must
       allocate a variable of this type for your driver in
       devxxxglobaldata.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



Licensed material--property of copyright holder(s)                         6




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       drivers have two routines vectors, one of ioroutinesvectortype
       type and one of devscsiadapterroutinesvectortype 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
       IODRIVERROUTINESVECTORSCSIADAPTERVERSION for adapter drivers.
       For drivers using the new wire/unwire memory calls for release 5.4.2
       [see the iobuffervector(3K) and memoryallocation(3K) man pages],
       the version field should be IODRIVERROUTINESVECTORVERSION2 for
       device drivers and IODRIVERROUTINESVECTORSCSIADAPTERVERSION2
       for adapter drivers.

       iodevicenumbertype
              typedef struct
                  {
                  iomajordevicenumbertype         major;
                  iominordevicenumbertype         minor;
                  }  iodevicenumbertype ;

       A device number is a composite of the device's major and minor device
       numbers.  During configuration, the kernel calls your
       devxxxconfigure routine with the device's major number.  Your
       devxxxconfigure routine gets the device's minor number and creates
       the device number variable for the unit by calling the kernel's
       ioallocatedevicenumber routine.  devxxxconfigure then uses the
       device number to create the special file (node) for the specific
       units.  After devxxxconfigure creates the device number, the kernel
       uses it as an device identifier when calling your devxxxopen
       routine.  devxxxopen 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.

       iodevicehandletype
              typedef opaque32type    iodevicehandletype ;

       A device handle identifies an open device to other calls to the
       device driver.  Your devxxxopen 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.

       iorequestinfotype
              typedef struct
                  {
                  iooperationtype                   op;
                  iochannelflagstype               flags;
                  iodevicehandletype               devicehandle;
                  uint32type                         deviceoffsetextender;



Licensed material--property of copyright holder(s)                         7




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


                  uint32type                         deviceoffset;
                  iobuffervectortype               buffervector;
                  dfselfidtype                     selfid;
                  }  iorequestinfotype;

       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
              iooperationtype 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
              iochannelflagstype described later in this subsection for a
              list of the flags.
       devicehandle
              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.
       deviceoffsetextender
              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.
       deviceoffset
              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.
       buffervector
              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.
       selfid
              The home system identification against which read data is to
              be checked if the IOCHECKSELFID flag is TRUE.

       iooperationtype
              typedef bit16type              iooperationtype ;
              #define IOOPERATIONREAD
              #define IOOPERATIONWRITE
              #define IOOPERATIONCHECKSELFID
              #define IOOPERATIONPHYSICALBUFFER
              #define IOOPERATIONUSERBUFFER

       This type defines a bit field used to modify the I/O operation
       specified in the op field of iorequestinfotype.  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



Licensed material--property of copyright holder(s)                         8




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       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.

       iochannelflagstype
              typedef bit32type      iochannelflagstype ;
              #define   IOCHANNELNOFLAGS
              #define   IOCHANNELREADINTENT
              #define   IOCHANNELWRITEINTENT
              #define   IOCHANNELEXCLUDEWRITERSINTENT
              #define   IOCHANNELAPPENDINTENT
              #define   IOCHANNELSYNCIO
              #define   IOCHANNELNOWAIT
              #define   IOCHANNELASYNCIO
              #define   IOCHANNELNONBLOCK
              #define   IOCHANNELNDELAY
              #define   IOCHANNELBLOCKSPECIAL
              #define   IOCHANNELNORETRIES
              #define   IOCHANNELNOTIFYIFMANDATORY
              #define   IOCHANNELNOCTTY

       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 iorequestinfotype.  These
       conditions are passed to the devxxxopen routine.  See devxxxopen
       for more information about the conditions.  The open options are as
       follows:

       IOCHANNELNOFLAGS
              This flag indicates that none of the conditions described
              below applies.

       IOCHANNELREADINTENT
              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.

       IOCHANNELWRITEINTENT
              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.

       IOCHANNELEXCLUDEWRITERSINTENT
              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.

       IOCHANNELAPPENDINTENT
              This flag indicates that the channel is opened with append
              intent.  This flag corresponds to the O_APPEND option on the
              open system call.



Licensed material--property of copyright holder(s)                         9




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       IOCHANNELSYNCIO
              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.

       IOCHANNELNOWAIT
              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.

       IOCHANNELASYNCIO
              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.

       IOCHANNELNONBLOCK
              This flag indicates that the channel is opened with the
              O_NONBLOCK option.

       IOCHANNELNDELAY
              This flag indicates that the channel is opened with the
              O_NDELAY option.  The driver should not look at this flag.

       IOCHANNELBLOCKSPECIAL
              This flag indicates that the driver is being opened as a block
              special device.  This flag is used only internally.

       IOCHANNELNORETRIES
              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.

       IOCHANNELNOTIFYIFMANDATORY
              This flag indicates that the kernel uses this option
              internally to avoid deadlock on mandatory locks.  Drivers
              should not use this option.

       IOCHANNELNOCTTY
              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.

       iooperationrecordtype
              typedef struct
                  {
                  miscqueuelinkstype               links;
                  iorequestinfotype                ri;
                  iocompletionroutineptrtype      completionroutine;
                  }  iooperationrecordtype;

       You use the operation record when starting an asynchronous I/O
       request using your driver's devxxxstartio function.  The structure
       is basically an extension of the iorequestinfotype that you use



Licensed material--property of copyright holder(s)                        10




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       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.

       completionroutine
              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 kernelcompleteio.

       ioselectintenttype
              typedef bit16type  ioselectintenttype ;
                  IOSELECTINTENTREAD
                  IOSELECTINTENTWRITE
                  IOSELECTINTENTEXCEPTION
                  IOSELECTINTENTPOLLIN
                  IOSELECTINTENTPOLLPRI
                  IOSELECTINTENTPOLLOUT
                  IOSELECTINTENTPOLLERR
                  IOSELECTINTENTPOLLHUP
                  IOSELECTINTENTPOLLNVAL
                  IOSELECTINTENTNONE
                  IOSELECTINTENTPOLLWRBAND
                  IOSELECTINTENTPOLLRDBAND
                  IOSELECTINTENTPOLLRDNORM

       This type describes the select options that may be specified to a
       device driver's devxxxselect 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
       devxxxselect call.  IO_SELECT_INTENT_NONE is used as a return value
       from ioselectcancel when no intent has been satisfied.

       iobuffervectortype
              typedef struct
                  {
                  union
                  {
                  iobuffervectorcontroltype    many;
                  iobufferdescriptortype        one;
                  } u;
                  uint16type                      descriptorcount;
                  uint16type                      currentdescriptor;
                  uint32type                      currentoffset;
                  uint32type                      totalremaining;
                  }  iobuffervectortype ;

       This structure defines a buffer vector, which is a collection of



Licensed material--property of copyright holder(s)                        11




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       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 descriptorcount is
              non-zero.  See also iobuffervectorcontroltype 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 descriptorcount is zero.  See also
              iobufferdescriptortype later in this subsection.

       descriptorcount
              This field indicates the number of entries in the many array
              of the iobuffervectorcontroltype 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
              totalsize field of iobuffervectorcontroltype controls the
              number of entries that are actually used, which may be less
              than the amount specified by descriptorcount.

       currentdescriptor
              This field contains the index of the descriptor that contains
              the current position.

       currentoffset
              This field contains the offset of the current position in the
              buffer descriptor indexed by currentdescriptor.

       totalremaining
              This field indicates the total number of bytes remaining to be
              moved to or from this buffer vector since it was initialized.

       iobufferdescriptortype
              typedef struct
                  {
                  pointertoanytype  bufferptr;
                  uint32type          size;
                  }  iobufferdescriptortype ;

       This structure describes the buffer from which data is to be read or



Licensed material--property of copyright holder(s)                        12




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       to which data is to be written.  The fields in this structure are as
       follows:

       bufferptr  A pointer to the start of the buffer.

       size        The size of the buffer, in bytes.

       iobuffervectorcontroltype
              typedef struct
                  {
                  iobufferdescriptorptrtype     descriptorsptr;
                  uint32type                       totalsize;
                  }  iobuffervectorcontroltype;

       This structure is used in the many field of iobuffervectortype.
       The fields in this structure are as follows:

       descriptorsptr
              A pointer to an array of buffer descriptors.  The array may
              contain as many as UINT16MAX entries.  (For the definition of
              UINT16MAX, see /usr/src/uts/aviion/ext/cgenerics.h.)

       totalsize
              The sum of the size fields in all the elements of the array
              buffer descriptors.

DEVICE DRIVER ROUTINE DESCRIPTIONS
   devxxxclose
       This routine removes a specified device from the set of devices on
       which this driver can perform I/O.  You should invoke one
       devxxxclose for each successful devxxxopen.  devxxxclose 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, devxxxclose 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 devxxxclose in coordination with
       devxxxopen to manage the number of outstanding opens.

   devxxxclosedump
       The routine closes the dump device previously opened by
       devxxxopendump.

       The devxxxclosedump routine is called by the system dump code when
       all of the data has been written to the dump destination.
       devxxxclosedump 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.




Licensed material--property of copyright holder(s)                        13




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


   devxxxconfigure
       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
       devxxxconfigure 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 devxxxconfigure routine receives a devicenameptr variable
       that points to a device name.  The name string is terminated by a
       null character and has the following form:
              devicemnemonic [@devicecode]([parameters])

       Because each devxxxconfigure is called for all system file entries,
       your devxxxconfigure 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, devxxxconfigure should exit with a return value of
       IOENXIODEVICENAMENOTRECOGNIZED.

       devxxxconfigure 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 devxxxconfigure 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 ioselect(3K) man page], you should
            allocate a select list header in the device information
            structure.  The select list header type is defined in iio.h.
            You will also have to initialize this list by calling the
            kernel's ioinitselect routine.

       ⊕    Register the device information structure.  If the device
            handles interrupts, you must register the device information
            structure using the ioregisterdeviceinfo 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 ioallocatedevicenumber.  ioallocatedevicenumber
            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
            systemconfiguration(3K) man page].  The kernel will pass the



Licensed material--property of copyright holder(s)                        14




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


            device number to your driver's devxxxopen 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 special files.  As with device numbers, you should
            create 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 systemconfiguration(3K)
            man page describes kernel routines that create device special
            files.

       If the device has a controller, the driver usually performs any
       initialization needed to bring the controller on-line in
       devxxxconfigure.  The driver can then initialize the controller's
       units at open time.

       If a failure occurs in any phase of the operation, devxxxconfigure
       must return the system to the state it was in before the
       devxxxconfigure routine was called.  Data structures must be
       deallocated and the device interrupt table slot freed.

       You should write your devxxxconfigure routine such that it can be
       called any time during the life of the system.

   devxxxdeconfigure
       This routine deconfigures the specified device if it is of the device
       type supported by this driver.

       The devxxxdeconfigure routine does the opposite of the configure
       routine (see devxxxconfigure).  It releases all system resources
       obtained to configure the device.  After devxxxdeconfigure has
       completed, the system should be in the state it was in before the
       device configure routine was executed.  devxxxdeconfigure 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
            iounspecifymaxdemonmessages(3K),
            iounspecifymaxgenericdemonmessages(3K), and
            vpunspecifymaxtimeouts(3K)].

       ⊕    Removes /dev entries.




Licensed material--property of copyright holder(s)                        15




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       devxxxdeconfigure receives a pointer to a device specification of
       the following form:
              devicemnemonic [@devicecode]([parameters])

       The pointer is terminated by a null character.

   devxxxdevicetoname
       This routine returns the device name associated with the specified
       device number.  The name is returned as a null-terminated string.

       The devxxxdevicetoname 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:
              devicemnemonic [@devicecode]([parameters])

       If an earlier driver routine (for example, the configuration routine)
       stored the device code and unit number in its unit tables, the
       devxxxdevicetoname may call the kernel's iomapdevicenumber to
       retrieve the device code and unit number for the given device number.

   devxxxinit
       This routine performs any pre-configuration initialization your
       driver might need.  It should not initialize the hardware device
       itself, however.

       The kernel calls the devxxxinit routine as part of system
       initialization.  devxxxinit gives the driver an opportunity to
       perform any initialization needed before any of the driver's devices
       are configured into the system.  devxxxinit is invoked once in the
       life of the system.  No devices controlled by the driver will be
       configured until after the devxxxinit routine completes.

       The devxxxinit routine operates in a restricted environment.  It
       may not await or take a page fault.

   devxxxioctl
       This routine performs a control operation on the specified device.

       The devxxxioctl 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
       devxxxioctl.  Some ioctl calls are actually file descriptor
       operations.  These are intercepted and handled by the kernel.  The
       FIONCLEX operation, for example, would not reach devxxxioctl.
       Multiple ioctl operations on the same or different minor devices may
       be in progress simultaneously.

       The kernel calls devxxxioctl 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



Licensed material--property of copyright holder(s)                        16




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       validates only the device handle argument.

   devxxxmaddmap
       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 mmapcountdelta 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.  devxxxmaddmap
       adjusts the device's use count by the (signed) amount specified by
       mmapcountdelta.  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 devxxxmaddmap 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 devxxxmaddmap must perform the last close
       actions for the device.

   devxxxmmap
       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 devicehandle, requestptr, and ioflags.  If the request is valid
       and all required resources are available, then devxxxmmap maps the
       appropriate physical address region controlled by the device into
       user memory at the address returned in startaddressptr.

       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 fileoffsetextender, fileoffset, and bytecount
              fields of requestptr.  If the range is not valid, return
              IOENXIOILLEGALDEVICEADDRESS.

       NOTE:  fileoffsetextender denotes the high 32 bits of the 64-bit
              device offset.  A driver that supports only 32-bit offsets



Licensed material--property of copyright holder(s)                        17




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


              should return an error if fileoffsetextender 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,  devxxxmmap calls
       vmmmapphysicalmemory to complete the request and returns the
       status from vmmmapphysicalmemory's to the caller.  To prevent
       deadlock, avoid holding any locks when calling
       vmmmapphysicalmemory as vmmmapphysicalmemory calls the driver's
       maddmap routine one or more times.

   devxxxmunmap
       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.

   devxxxnametodevice
       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
       devicenameptr is of the following form:
              devicemnemonic [@devicecode]([parameters])

       To simplify its processing, devxxxnametodevice can call the
       kernel's iogetdeviceinfo, 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).

   devxxxopen
       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



Licensed material--property of copyright holder(s)                        18




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       opened by a user or by the kernel.  The kernel will not call
       devxxxopen until both devxxxinit and devxxxconfigure have
       completed.

       The DG/UX system allows multiple opens on a device, and devxxxopen
       should manage this feature as appropriate to its device.
       devxxxopen controls the number of outstanding opens.  For example,
       devxxxopen may impose restrictions such as requiring an exclusive
       open of a particular minor device.  To implement this, devxxxopen
       might return an error status if the minor device has already been
       opened but not closed.  Multiple devxxxopen processes may be in
       progress simultaneously on the same or different minor device
       numbers.

       The devxxxopen routine must also control the type of open
       requested.  The kernel passes devxxxopen a set of channel flags
       that specify the intents given in the higher level open call (for
       example, read, write or both).  devxxxopen 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.

       devxxxopen 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, devxxxopen 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.

       devxxxopen must establish the device handle that the kernel will
       use as a parameter in all future driver operations.  It can retrieve
       the handle that devxxxconfigure stored by calling
       iomapdevicenumber with the device number.  If devxxxopen returns
       an OK, it must return the device handle in devicehandleptr.  If it
       returns a status other than OK, the kernel presumes that the open
       failed and it will disregard the returned devicehandleptr argument.

   devxxxopendump
       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 devxxxopendump routine if
       the system panics.

       The devxxxopendump 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 panic, the standard kernel facilities will



Licensed material--property of copyright holder(s)                        19




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       not be available for the initialization procedure.  In particular,
       this means that devxxxopendump must run in physical memory since
       dynamically allocated memory cannot be accessed.  devxxxopendump
       should statically allocate its data structures in
       devxxxglobaldata.c.

       The devxxxopendump 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 devxxxopendump routine receives a device name specified by
       devicename.  It should verify that the device specified is of the
       driver's type.  The device name is of the following form:
              devicemnemonic [@devicecode]([parameters])

       Finally, as with any open routine, devxxxopendump 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 panic because it is invoked as part of
              the panic sequence.

   devxxxpowerfail
       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 ionodevice stub for this routine.

   devxxxreaddump
       This routine handles reading a system dump device.

       This routine may be called during a panic to read one or more blocks
       from the system dump device.  Because it will be called during panic
       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.

   devxxxreadwrite
       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



Licensed material--property of copyright holder(s)                        20




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       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 devxxxreadwrite 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 devxxxreadwrite 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.  devxxxreadwrite 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 fscheckselfid routine to retrieve the self-id stored in
       the data (see the fscheckselfid(3K) man page).

       Because the devxxxreadwrite 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, devxxxreadwrite will need to set up await mechanisms
       such as a timeout, a signal, or an I/O completion event.  The
       eventcounters(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 IOOPERATIONUSERBUFFER



Licensed material--property of copyright holder(s)                        21




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       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 memoryallocation(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
       iobuffervector structure.  The iobuffervector(3K) man page
       describes the kernel routines used to manipulate buffer vectors.

   devxxxselect
       This routine supplies information about whether the specified device
       is ready to perform an I/O operation.

       The kernel calls the devxxxselect routine in response to user-level
       select system calls.  devxxxselect operates as follows:

       ⊕      If the user is selecting a device (selectmode 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 ecptr 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
              devxxxserviceinterrupt routine complete select processing
              via a message to the Driver or Generic Server.

       ⊕      If the user is unselecting the device (the selectmode
              argument is FALSE), the driver should discard the previously
              saved ecptr and report any intents that have become TRUE.

       Multiple selects of the same or different minor devices may be in
       progress simultaneously.  The devxxxselect 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 ioselect(3K)
       man page.  The driver should have allocated and initialized the
       select list structure before select operations begin, usually in the
       devxxxconfigure routine.

       For many devices, such as disks and tapes, devxxxselect always
       returns TRUE because the I/O operations are quick.  devxxxselect 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.



Licensed material--property of copyright holder(s)                        22




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       Similarly, it would select FALSE for reading when the driver is
       waiting for the user to type something.

   devxxxserviceinterrupt
       This routine handles interrupts from devices under the control of
       this driver.  It is called by the system interrupt handler.

       The devxxxserviceinterrupt 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,
       devxxxserviceinterrupt should defer as much device service as
       possible to a base-level process.

       The devxxxserviceinterrupt 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
       ioqueuemessagetodriverdemon(3K) and
       ioqueuemessagetogenericdemon(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, devxxxserviceinterrupt 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, devxxxserviceinterrupt must clear the
       interrupt before exiting.

       The pointer to the device information structure allows
       devxxxserviceinterrupt 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.

   devxxxstartio
       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 devxxxstartio to process the
       request asynchronously.  The devxxxstartio routine is used only on
       block special devices.  Multiple devxxxstartio routines on the
       same or different minor devices may be in progress simultaneously.

       devxxxstartio should start the operation and then exit, leaving
       the completion to be handled by another routine.  If devxxxstartio
       cannot initiate the operation (for example, if the device is busy),
       it should queue the request to be handled later and exit.  This



Licensed material--property of copyright holder(s)                        23




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       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 devxxxstartio 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
       devxxxserviceinterrupt 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 completeio routine that
       in turn calls the kernel's I/O completion routine.  The
       servermessages(3K) man page describes the kernel routines for
       interacting with the Driver or Generic Server.

       The information below under kernelcompleteio describes the
       interface the kernel's I/O completion routine uses.  You do not need
       to the kernel-specified interface in your driver's completeio
       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 devxxxstartio routine is called
            lest the kernel's I/O completion routine be called before
            devxxxstartio 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



Licensed material--property of copyright holder(s)                        24




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


            buffer or perform the logical-to-physical translation.

   devxxxwritedump
       This routine writes system dump data to the dump destination device
       previously opened by devxxxopendump.

       During a dump, the system's panic code path calls devxxxwritedump
       to write the data specified in the iobuffervector.  The panic code
       will call the devxxxwritedump 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 devxxxwritedump 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 panic because it is invoked as part of
              the panic sequence.

   kernelcompleteio
       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 devxxxinit routine does not return a status; any errors that it
       encounters must result in a panic or in some method of flagging the
       error to devxxxconfigure for further processing.

       For devxxxconfigure:
              OK     The device was successfully configured.
              IOENXIODEVICENAMENOTRECOGNIZED
                     devicenameptr does not specify a device of the type
                     supported by this driver.
              IOENXIODEVICENOTSUPPORTED
                     devicenameptr specifies a device of the type
                     supported by this driver, but the particular model is
                     not supported.




Licensed material--property of copyright holder(s)                        25




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


              IOEIOPHYSICALUNITFAILURE
                     A request issued to the device controller failed with
                     an error status.
              IOEIODEVICETIMEDOUT
                     The controller did not respond to a request within a
                     reasonable length of time.
              IOENXIODEVICEISALREADYCONFIGURED
                     A device is already registered at the location
                     specified by devicenameptr.

       For devxxxdeconfigure:
              OK     The device was successfully deconfigured.
              IOENXIODEVICENAMENOTRECOGNIZED
                     devicenameptr 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.
              IOEBUSYDEVICEHASOPENUNITS
                     The specified device currently has one or more units
                     that are open.

       For devxxxdevicetoname:
              OK     The translation was performed successfully.
              IOENXIODEVICEISNOTCONFIGURED
                     The specified device number is not configured.

       For devxxxnametodevice:
              OK     The device name was successfully translated.
              IOENXIODEVICENAMENOTRECOGNIZED
                     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.
              IOENXIODEVICEISNOTCONFIGURED
                     The specified device is supported by this driver but is
                     not currently configured in the system.

       For devxxxopen:
              OK     The devxxxopen routine was successful in preparing
                     the device for further operations.
              IOENXIOUNITNOTREADY
                     The unit is not ready or on-line.
              IOENXIODEVICEISNOTCONFIGURED
                     The specified device number cannot be mapped to a
                     configured device.
              IOENXIOOPENINTENTCONFLICTS
                     The unit is already open and can only be opened
                     exclusively.
              IOENXIONOWRITERING
                     The tape was opened with write intent, but the tape did
                     not have a write ring (only applicable to tape
                     devices).
              IOENXIOTAPEDENSITYNOTSUPPORTED
                     The requested density is not supported by the tape
                     controller (only applicable to tape devices).



Licensed material--property of copyright holder(s)                        26




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


              IOENXIOCANNOTCHANGETAPEDENSITY
                     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 devxxxclose:
              OK     The close was successful.
              IOSTATUSERRORONEARLIERREQUEST
                     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 devxxxreadwrite 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 devxxxreadwrite routine was successful.
              IOEINVALILLEGALREQUESTSIZE
                     The requested count is not valid for the device type.
              IOEINVALILLEGALBUFFERADDRESS
                     The buffer was not aligned as required by the device.
              IOENXIOILLEGALDEVICEADDRESS
                     The location specification for reading/writing is
                     invalid for the device.
              IOEIODEVICETIMEDOUT
                     The device controller did not respond to a request in a
                     reasonable length of time.
              IOEIOHARDIOERROR
                     An unrecoverable I/O error occurred, resulting from a
                     media failure.
              IOEIOPHYSICALUNITFAILURE
                     An uncorrectable error occurred that presumably affects
                     I/O operations to the entire physical unit.
              IOEINTRINTERRUPTEDBYSIGNAL
                     A signal was received while waiting for the I/O to
                     complete.

       For devxxxstartio:
              OK     This routine always returns OK.  Errors that occur on
                     the request are reported via the completion routine.

       The devxxxioctl 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 devxxxioctl routine was successful.  No errors
                     should be indicated to the caller.
              IOEINVALCOMMANDNOTSUPPORTEDBYDEVICE
                     The command was not supported by the driver.

       For devxxxopendump:
              OK     The open completed successfully.




Licensed material--property of copyright holder(s)                        27




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


              IOSTATUSDUMPNOTSUPPORTED
                     The device identified by the devicename 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
                     devicenameptr is supported by the driver but the
                     device type is not a valid dump destination device.
              IOEIOHARDIOERROR
                     A request to the dump destination device has resulted
                     in an error condition.

       For devxxxwritedump:
              OK     The write operation completed normally.
              IOSTATUSTAKECHECKPOINT
                     The write operation completed normally but was written
                     as the first record on a volume.  The system dump code
                     should checkpoint its current state.
              IOEIOHARDIOERROR
                     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 devxxxreaddump:
              OK     The volume was successfully read.
              IOEIOHARDIOERROR
                     An unrecoverable error occurred during the read
                     operation.

       For devxxxclosedump:
              OK     The volume was successfully closed.
              IOEIOHARDIOERROR
                     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 devxxxmmap:
              OK     The call successfully created a mapping at the user
                     address returned in startaddressptr.
              IOENXIOILLEGALDEVICEADDRESS
                     The requested device offset range did not fall entirely
                     within a range of mappable device offsets.
              other error status from vmmmapphysicalmemory
                     The mmap request failed due to a problem detected by
                     the vmmmapphysicalmemory routine.
                     vmmmapphysicalmemory will pass back the error
                     status.

       For devxxxmunmap:
              OK     All munmaps of this device are allowed.  devxxxmunmap
                     must return OK.




Licensed material--property of copyright holder(s)                        28




device_driver(3K)              DG/UX 5.4R3.00              device_driver(3K)


       For devxxxpowerfail:
              OK     Return this value in all cases.

       For the other routines: none.

SEE ALSO
       adapterdriver(3K), adaptermanager(3K), eventcounters(3K),
       fscheckselfid(3K), iobuffervector(3K), ioselect(3K),
       memoryallocation(3K), scpanic(3K), servermessages(3K),
       statuscodemacros(3K).  systemclock(3K), systemconfiguration(3K).
       Programming in the DG/UX Kernel Environment.














































Licensed material--property of copyright holder(s)                        29


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