  | 
		
OpenVMS Alpha Guide to Upgrading Privileged-Code
Applications
 
 
A.6 Direct I/O Buffer Map (DIOBM)
The Direct I/O Buffer Map (DIOBM) is a new structure that is used to
solve the "cross-process PTE problem" for buffers that have
been locked into memory for direct I/O.
 
There are two variants of the DIOBM structure. The first is the primary
DIOBM structure. The primary DIOBM structure can be used in the
following mutually exclusive ways:
 
  - To contain copies of the actual PTEs that map the buffer.
  
 - To point to a larger secondary DIOBM structure if the primary DIOBM
  structure has insufficient room for all the PTEs that map the user
  buffer.
  
 - To manage a PTE window in S0/S1 space onto the actual PTEs that map
  the buffer if the required PTE count exceeds the capacity of the
  largest allowable DIOBM structure.
  
Each of these methods yields a 32-bit system virtual address for the
PTEs that map the buffer. This address is valid regardless of process
or system context.
 
The fixed-size DIOBM structure contains room for exactly
DIOBM$K_PTECNT_FIX (9) PTEs and is 88 bytes long. Most primary DIOBM
structures are fixed-sized and embedded in other structures. For
example, the IRP, IRPE, VCRP, and DCBE structures all contain an
embedded fixed-sized primary DIOBM structure.
 
A secondary DIOBM structure can have room for up to
ioc$gl_diobm_ptecnt_max
 PTEs and is used only for PTE copies.
 
Although the offsets and types for both the primary and secondary DIOBM
structures are identical, for clarity, they are described in separate
tables (see Table A-6 and Table A-7).  
 
  Table A-6 Primary DIOBM Structure
  
    | Field  | 
    Type  | 
    Comments  | 
   
  
    | 
      diobm$ps_aux_diobm
     | 
    
      DIOBM *
     | 
    
       This is a pointer to a secondary DIOBM structure that is valid if and
       only if DIOBM$M_AUX_INUSE in
      
      diobm$l_flags
      
               is set. The secondary DIOBM structure contains copies of the PTE that
               map the buffer. When a secondary DIOBM is used, the only use for the
               primary DIOBM is to locate the secondary.
     | 
   
  
    | 
      diobm$l_pte_count
     | 
    
      unsigned int
     | 
    
       If DIOBM$M_PTE_WINDOW is clear in
      
      diobm$l_flags
      
              , this cell contains the count of PTEs that have been copied to the PTE
              vector
      
      diobm$q_pte_vector
      
               in this DIOBM structure.
        If DIOBM$M_PTE_WINDOW is set in
      
      diobm$l_flags
      
              , this cell contains the count of SPTEs that have been allocated for a
              PTE window in S0/S1 space to the actual PTEs that map the buffer.
      | 
   
  
    | 
      diobm$w_size
     | 
    
      unsigned short
     | 
    
      Size of the DIOBM packet in bytes.
     | 
   
  
    | 
      diobm$b_type
     | 
    
      unsigned char
     | 
    
      Nonpaged pool packet type code, DYN$C_MISC
     | 
   
  
    | 
      diobm$b_subtype
     | 
    
      unsigned char
     | 
    
      Nonpaged pool packet subtype code, new DYN$C_MISC subtype code
      DYN$C_DIOBM
     | 
   
  
    | 
      diobm$l_flags
     | 
    
      unsigned int
     | 
    
      Flag bits.
     | 
   
  
    | 
      diobm$v_rel_dealloc
     | 
    
      bit
     | 
    
       A bit equal to DIOBM$M_REL_DEALLOC in the
      
      diobm$l_flags
      
               cell. If set, routine IOC_STD$RELEASE_DIOBM deallocates this DIOBM
               structure. The routine IOC_STD$FILL_DIOBM sets this bit on any
               secondary DIOBM structure that it may allocate. The routine
               IOC_STD$CREATE_DIOBM sets this bit on the primary DIOBM structure that
               it allocates.
     | 
   
  
    | 
      diobm$v_pte_window
     | 
    
      bit
     | 
    
       A bit equal to DIOBM$M_PTE_WINDOW in the
      
      diobm$l_flags
      
               cell. This bit is set if the direct I/O buffer is too large for a DIOBM
               packet (the buffer requires more than ioc$gl_diobm_ptecnt_max PTEs) and
               a window in S0 to its PTEs has been allocated. When this bit is set,
      
      diobm$l_pte_count
      
               contains the count of SPTEs that have been allocated and the
      
      diobm$l_ptew_sva
      
               cell contains the system virtual address that is mapped by the first
               SPTE allocated for the PTE window. This bit must be clear if
      
      diobm$v_aux_inuse
      
               is set.
     | 
   
  
    | 
      diobm$v_aux_inuse
     | 
    
      bit
     | 
    
       A bit equal to DIOBM$M_AUX_INUSE in the
      
      diobm$l_flags
      
               cell. The
      
      diobm$ps_aux_diobm
      
               cell contains a pointer to a secondary DIOBM structure if and only if
               the
      
      diobm$v_aux_inuse
      
               bit is set. This bit must be clear if
      
      diobm$v_pte_window
      
               is set.
     | 
   
  
    | 
      diobm$v_inuse
     | 
    
      bit
     | 
    
       A bit equal to DIOBM$M_INUSE in the
      
      diobm$l_flags
      
               cell. This flag is an aid to detecting inproper use of DIOBM structures
               and is used only by the full-checking versions of the routines in the
               IO_ROUTINES_MON.EXE execlet. This flag is set by the IOC_STD$FILL_DIOBM
               and IOC_STD$CREATE_DIOBM routines and is cleared by the
               IOC_STD$RELEASE_DIOBM routine. Prior to setting the flag, the
               IOC_STD$FILL_DIOBM routine checks this flag if the
      
      diobm$b_type
      
               cell contains the DYN$C_MISC value and
      
      diobm$b_subtype
      
               contains DYN$C_DIOBM. If the
      
      diobm$v_inuse
      
               flag is set under these conditions, the IOC_STD$FILL_DIOBM routine
               declares a INCONSTATE bugcheck.
     | 
   
  
    | 
      diobm$v_s0pte_window
     | 
    
      bit
     | 
    
       A bit equal to DIOBM$M_S0PTE_WINDOW in the
      
      diobm$l_flags
      
               cell. This bit is set if the S0/S1 PTE window was used to derive a
               32-bit PTE address for this buffer. When this bit is set the
      
      diobm$v_pte_window
      
               and
      
      diobm$v_aux_inuse
      
               flags must be clear and the
      
      diobm$l_pte_count
      
               cell must contain 0.
     | 
   
  
    | 
      DIOBM$K_HDRLEN
     | 
    
      constant
     | 
    
       Size in bytes of the minimal DIOBM packet header excluding the PTE
       vector. This is equal to the byte offset of the
      
      diobm$q_pte_vector[0]
      
               cell (16).
     | 
   
  
    | 
      diobm$q_pte_vector
     | 
    
      PTE[diobm$l_pte_count]
     | 
    
       Vector of
      
      diobm$l_pte_count
      
               quadword PTEs that are copies of the PTEs that map the buffer that has
               been locked for direct I/O. This vector is valid only if both
               DIOBM$M_AUX_INUSE and DIOBM$M_PTE_WINDOW in
      
      diobm$l_flags
      
               are clear.
     | 
   
  
    | 
      DIOBM$K_PTECNT_FIX
     | 
    
      constant
     | 
    
       This constant specifies the number of PTE entries (9) that fit into the
       PTE vector in a fix-sized DIOBM structure.
     | 
   
  
    | 
      DIOBM$K_PTECNT_MAX_UNI
     | 
    
      constant
     | 
    
       This constant specifies the number of PTE entries (94) that fit into
       the PTE vector in the largest allowable DIOBM structure on an
       uniprocessor system.
     | 
   
  
    | 
      DIOBM$K_PTECNT_MAX_SMP
     | 
    
      constant
     | 
    
       This constant specifies the number of PTE entries (430) that fit into
       the PTE vector in the largest allowable DIOBM structure on an SMP
       system.
     | 
   
  
    | 
      diobm$ps_ptew_sva
     | 
    
      void *
     | 
    
       The lowest S0/S1 space virtual address that is mapped by the PTEs that
       have been allocated for the window onto the direct I/O buffer PTEs.
       This cell is used to deallocate the PTE window. This cell is overlaid
       on a portion of
      
      diobm$q_pte_vector
      
               since its use is mutually exclusive. This cell is valid if and only if
               DIOBM$M_PTE_WINDOW in
      
      diobm$l_flags
      
               is set.
     | 
   
  
    | 
      DIOBM$M_NORESWAIT
     | 
    
      constant
     | 
    
       This is an option bit mask for the flags parameter to the
       IOC_STD$FILL_DIOBM and IOC_STD$CREATE_DIOBM routines.
       When this option bit is set and there are insufficient resources for
      the needs of these routines an error status is returned to their
      callers instead of putting the process into a resource wait state.
      | 
   
 
 
 
  Table A-7 Secondary DIOBM Structure
  
    | Field  | 
    Type  | 
    Comments  | 
   
  
    | 
      diobm$ps_aux_diobm
     | 
    
      DIOBM *
     | 
    
       This cell must be zero in a secondary DIOBM structure.
     | 
   
  
    | 
      diobm$l_pte_count
     | 
    
      unsigned int
     | 
    
       Contains the number of PTEs that can fit into the
      
      diobm$q_pte_vector
      
               in this DIOBM structure.
     | 
   
  
    | 
      diobm$w_size
     | 
    
      unsigned short
     | 
    
      Size of the DIOBM packet in bytes.
     | 
   
  
    | 
      diobm$b_type
     | 
    
      unsigned char
     | 
    
      Nonpaged pool packet type code, DYN$C_MISC
     | 
   
  
    | 
      diobm$b_subtype
     | 
    
      unsigned char
     | 
    
      Nonpaged pool packet subtype code, new DYN$C_MISC subtype code
      DYN$C_DIOBM
     | 
   
  
    | 
      diobm$l_flags
     | 
    
      unsigned int
     | 
    
      Flag bits.
     | 
   
  
    | 
      diobm$v_rel_dealloc
     | 
    
      bit
     | 
    
       A bit equal to DIOBM$M_REL_DEALLOC in the
      
      diobm$l_flags
      
               cell. If set, routine IOC_STD$RELEASE_DIOBM deallocates this DIOBM
               structure.
     | 
   
  
    | 
      diobm$v_pte_window
     | 
    
      bit
     | 
    
       A bit equal to DIOBM$M_PTE_WINDOW in the
      
      diobm$l_flags
      
               cell. This bit must be clear in a secondary DIOBM structure.
     | 
   
  
    | 
      diobm$v_aux_inuse
     | 
    
      bit
     | 
    
       A bit equal to DIOBM$M_AUX_INUSE in the
      
      diobm$l_flags
      
               cell. This bit must be clear in a secondary DIOBM structure.
     | 
   
  
    | 
      diobm$v_s0pte_window
     | 
    
      bit
     | 
    
       A bit equal to DIOBM$M_S0PTE_WINDOW in the
      
      diobm$l_flags
      
               cell. This bit must be clear in a secondary DIOBM structure.
     | 
   
  
    | 
      diobm$q_pte_vector
     | 
    
      PTE[diobm$l_pte_count]
     | 
    
       Vector of
      
      diobm$l_pte_count
      
               quadword PTEs that are copies of the PTEs that map the buffer that has
               been locked for direct I/O.
     | 
   
 
A.7 Function Decision Table (FDT)
This section describes the additions to the driver Function Decision
Table (FDT) structure (see Table A-8).  
 
  Table A-8 FDT Structure Changes
  
    | Field  | 
    Type  | 
    Comments  | 
   
  
    | 
      fdt$q_ok64bit
     | 
    
      unsigned int64
     | 
    
       A 64-bit mask corresponding to the 64 possible I/O function codes. The
       corresponding bit is set if the function supports a 64-bit $QIO
      
      p1
      
               parameter value. This cell is initialized to zero by the MACRO-32 macro
               FDT_INI, the BLISS macro FDTAB, and in the prototype FDT, DRIVER$FDT,
               which is used by drivers written in C. This cell has been added to the
               end of the existing FDT structure.
     | 
   
 
A.8 I/O Request Packet (IRP)
This section describes the additions and changes to cells in the I/O
Request Packet (IRP) structure. The significant IRP changes are:
 
  - The IRP resembles a 64-bit capable ACB64 structure instead of the
  existing ACB structure.
  
 - A fixed-size primary DIOBM is embedded in the IRP for use in
  deriving a 32-bit system virtual address for the PTEs that map a buffer
  locked into memory for direct I/O.
  
 - The IRP cells that contain copies of the 64-bit $QIO parameter
  values and the caller's IOSB address have been expanded from 32-bits to
  64-bits.
  
 - Any cells overlaid on the
irp$l_ast
,
irp$l_astprm
, or
irp$l_iosb
 cells move to the low-order longword of their quadword replacements.
  
 - Alternative cell names have been defined for the
ast
,
astprm
, and
iosb
 cells that can be used for arbitrary parameters in internal IRPs.
  
The size of an IRP has increased by 160 bytes (43%), from 376 to 536
bytes (see Table A-9).  
 
  Table A-9 IRP Changes
  
    | Field  | 
    Type  | 
    Comments  | 
   
  
    | 
      irp$b_mode
     | 
    
      unsigned char
     | 
    
       This is an existing cell in the IRP that contains the caller's mode in
       the low-order 2 bits. The
      
      irp$l_acb_flags
      
               cell is considered valid by SCH$QAST if and only if ACB$M_FLAGS_VALID
               mask is set in this cell. The ACB$M_FLAGS_VALID mask is always set in
               this cell by EXE$QIO when the IRP is allocated.
     | 
   
  
    | 
      irp$l_acb64x_offset
     | 
    
      int
     | 
    
       Offset to the ACB64X structure embedded in this IRP. This cell is
       considered valid by SCH$QAST if and only if ACB$M_64BITS is set in the
      
      irp$l_acb_flags
      
               cell. This cell is initialized to the offset value of the
      
      irp$pq_acb64_ast
      
               field. This cell corresponds to the
      
      acb64$l_acb64x
      
               cell. Because this cell is at the same offset as the
      
      acb$l_ast
      
               cell, the
      
      irp$l_ast
      
               cell has been removed.
     | 
   
  
    | 
      irp$l_acb_flags
     | 
    
      unsigned int
     | 
    
       This cell has been initialized to the mask value ACB$M_64BITS to
       indicate that the
      
      irp$l_acb64x_offset
      
               field contains an offset to the ACB64X structure. Corresponds to the
      
      acb$l_flags
      
               cell.
     | 
   
  
    | 
      irp$l_thread_pid
     | 
    
      int
     | 
    
       Corresponds to the
      
      acb$l_thread_pid
      
               cell. Reserved for use by the Kernel Threads project.
     | 
   
  
    | 
      irp$pq_acb64_ast
     | 
    
      VOID_FUNC_PQ
     | 
    
       This cell corresponds to the
      
      acb64$pq_ast
      
               cell and replaces the
      
      irp$l_ast
      
               cell.
     | 
   
  
    | 
      irp$l_ast
     | 
    
      -
     | 
    
       This cell has been removed. It has been replaced by the
      
      irp$pq_acb64_ast
      
               cell.
     | 
   
  
    | 
      irp$l_shd_iofl
     | 
    
      IRP *
     | 
    
       This is an existing cell that contains the link to the cloned shadowing
       IRPs. This cell was overlaid on
      
      irp$l_ast
      
               and is now overlaid on the low-order longword of the
      
      irp$pq_acb64_ast
      
               cell.
     | 
   
  
    | 
      irp$l_iirp_p0
     | 
    
      int
     | 
    
       Generic parameter cell that is available in internal IRPs. This cell
       overlays the low-order longword of the
      
      irp$pq_acb64_ast
      
               cell and is intended for use by components that use the
      
      irp$l_ast
      
               cell for this purpose.
     | 
   
  
    | 
      irp$q_acb64_astprm
     | 
    
      int64
     | 
    
       This cell corresponds to the
      
      acb64$q_astprm
      
               cell and replaces the
      
      irp$l_astprm
      
               cell.
     | 
   
  
    | 
      irp$l_astprm
     | 
    
      -
     | 
    
       This cell has been removed. It is replaced by the
      
      irp$q_acb64_astprm
      
               cell.
     | 
   
  
    | 
      irp$l_shad
     | 
    
      SHAD *
     | 
    
       This is an existing cell in IRPs cloned by shadowing that points to the
       SHAD structure. This cell was overlaid on
      
      irp$l_astprm
      
               and is now overlaid on the low-order longword of the
      
      irp$q_acb64_astprm
      
               cell.
     | 
   
  
    | 
      irp$l_hrb
     | 
    
      HRB *
     | 
    
       This is an existing cell in MSCP server IRPs that points to a Host
       Request Block structure. This cell was overlaid on
      
      irp$l_astprm
      
               and is now overlaid on the low-order longword of the
      
      irp$q_acb64_astprm
      
               cell.
     | 
   
  
    | 
      irp$l_mv_tmo
     | 
    
      int
     | 
    
       This cell is used in internal mount verification IRPs to contain the
       timeout value. This cell overlays the low-order longword of the
      
      irp$q_acb64_astprm
      
               cell and is intended for use by components that currently use the
      
      irp$l_astprm
      
               cell for this purpose.
     | 
   
  
    | 
      irp$l_iirp_p1
     | 
    
      int
     | 
    
       Generic parameter cell that is available in internal IRPs. This cell
       overlays the low-order longword of the
      
      irp$q_acb64_astprm
      
               cell and is intended for use by components that use the
      
      irp$l_astprm
      
               cell for this purpose.
     | 
   
  
    | 
      irp$q_user_thread_id
     | 
    
      uint64
     | 
    
       Unique user thread identifier. Corresponds to the
      
      acb64$q_user_thread_id
      
               cell. Reserved for use by the Kernel Threads project.
     | 
   
  
    | 
      irp$pq_iosb
     | 
    
      VOID_PQ
     | 
    
      64-bit pointer to the caller's IOSB. This cell replaces
      
      irp$l_iosb
      
              .
     | 
   
  
    | 
      irp$l_iosb
     | 
    
      -
     | 
    
       This cell has been removed. It is replaced by the
      
      irp$pq_iosb
      
               cell.
     | 
   
  
    | 
      irp$l_cln_wle
     | 
    
      unsigned int
     | 
    
       This is an existing cell that contains the shadowing write log state.
       This cell was overlaid on
      
      irp$l_iosb
      
               and is now overlaid on the low-order longword of the
      
      irp$pq_iosb
      
               cell.
     | 
   
  
    | 
      irp$l_iirp_p2
     | 
    
      int
     | 
    
       Generic parameter cell that is available in internal IRPs. This cell
       overlays the low-order longword of the
      
      irp$pq_iosb
      
               cell and is intended for use by components that use the
      
      irp$l_iosb
      
               cell for this purpose.
     | 
   
  
    | 
      irp$pq_va_pte
     | 
    
      PTE_PQ
     | 
    
       A 64-bit pointer to the actual PTEs that map the user buffer. If the
       user buffer is not in shared system space, then this PTE virtual
       address is only valid in the caller's process context.
     | 
   
  
    | 
      irp$l_svapte
     | 
    
      PTE *
     | 
    
       A 32-bit pointer to PTE values that map the user buffer. The PTE values
       may be copies of the actual PTEs in Page Table Space that map the user
       buffer. If zero, then no PTEs have been locked for this request. Note
       that for compatibility with existing drivers, this cell remains
       overlaid on
      
      irp$ps_bufio_pkt
      
               and this use is valid only if IRP$M_BUFIO is clear in
      
      irp$l_sts
      
              . Note also that this cell contains a pointer into the CPT structure if
              IRP$M_CACHEIO is set in
      
      irp$l_sts2
      
              .
     | 
   
  
    | 
      irp$ps_bufio_pkt
     | 
    
      BUFIO *
     | 
    
       Pointer for the buffered I/O packet for this request. If zero, then no
       packet has been allocated for this request. Note that for compatibility
       with existing drivers, this cell remains overlaid on
      
      irp$l_svapte
      
               and this use is valid only if IRP$M_BUFIO is set in
      
      irp$l_sts
      
              .
     | 
   
  
    | 
      irp$r_diobm
     | 
    
      DIOBM
     | 
    
       Embedded fixed-size primary "direct I/O buffer map" structure. This
       embedded DIOBM structure is valid if and only if
      
      irp$l_svapte
      
               points to a set of PTEs whose pages have been locked down for direct
               I/O. Specifically, the DIOBM is in use when both IRP$M_BUFIO and
               IRP$M_CACHEIO in
      
      irp$l_sts
      
               are clear and the
      
      irp$l_svapte
      
               cell contains a non-zero value. See Section A.6 for a complete
               description of the DIOBM structure.
     | 
   
  
    | 
      irp$q_qio_p1
     | 
    
      int64
     | 
    
       Copy of device dependent $QIO parameter p1. The low order 32-bits of
       this cell remain accesible via
      
      irp$l_qio_p1
      
              .
     | 
   
  
    | 
      irp$q_qio_p2
     | 
    
      int64
     | 
    
       Copy of device dependent $QIO parameter p2. The low order 32-bits of
       this cell remain accesible via
      
      irp$l_qio_p2
      
              .
     | 
   
  
    | 
      irp$q_qio_p3
     | 
    
      int64
     | 
    
       Copy of device dependent $QIO parameter p3. The low order 32-bits of
       this cell remain accesible via
      
      irp$l_qio_p3
      
              .
     | 
   
  
    | 
      irp$q_qio_p4
     | 
    
      int64
     | 
    
       Copy of device dependent $QIO parameter p4. The low order 32-bits of
       this cell remain accesible via
      
      irp$l_qio_p4
      
              .
     | 
   
  
    | 
      irp$q_qio_p5
     | 
    
      int64
     | 
    
       Copy of device dependent $QIO parameter p5. The low order 32-bits of
       this cell remain accesible via
      
      irp$l_qio_p5
      
              .
     | 
   
  
    | 
      irp$q_qio_p6
     | 
    
      int64
     | 
    
       Copy of device dependent $QIO parameter p6. The low order 32-bits of
       this cell remain accesible via
      
      irp$l_qio_p6
      
              .
     | 
   
 
  
  
		 |