$! $! DS-QIO_DRIVERS.SDML $! Design Specification for QIO and device driver support of 64-bit addresses. $! This is Chapter 20 of the OpenVMS Alpha 64-bit Design Document. $! $! Author: Glenn C. Everhart $! $! Revision history: $! $! The revision history for this chapter is contained in last section of $! this file and is included in the generated output. $! $! $! Execute this file as a DCL procedure to generate the postscript output $! for Chapter 20 as a standalone document. $! $! $ SET NOON $ WRITE SYS$OUTPUT "You may disregard the preceding DCL warning." $ WRITE SYS$OUTPUT "" $ SET VERIFY $ DOCUMENT/NOPRINT/CONDITION=JUST_QIO 'F$ENVIRONMENT("PROCEDURE")' REPORT PS $! 'F$VERIFY("NO")' $ EXIT $! (just_qio) (confidential) (OpenVMS Multipath Failover Working Design Spec) (ps_chapter\Chapter 2) (equations_chapter\Chapter 4) (system_space_chapter\Chapter 6) (PFN_database_chapter\Chapter 7) (va_api_chapter\Chapter 14) (ast_chapter\Chapter 16) (internal_api_chapter\Chapter 30) (20) (Multiple Paths and Device Drivers\driver_chapter) (Introduction)

This chapter describes the issues involved in supporting failover where multiple paths exist to OpenVMS devices. These multiple paths can exist due to SCSI controllers which permit a device to be connected to a VMScluster system by more than one path, in general across more than one SCSI bus. Closely related issues exist where devices might be connected by multiple paths to a cluster where some parts of the path between a device and a system are served. To provide more reliable service, OpenVMS needs to have a facility to allow access to these devices to fail over from one path to another in the event one path fails, without manual intervention in the failover.

The chapter will also discuss some elements of the OpenVMS I/O system calling routines which must be modified to support a uniform handling of multiple path failover. While drivers may need to be modified to provide the most complete benfits of this failover support, partial support for path failover can be offered even for unmodified drivers.

This chapter outlines the internal changes to the OpenVMS Alpha I/O support routines, I/O data structures, and device drivers, that will be made to provide this support for multipath failover. (Overall Software Layout)

The path failover subsystem consists of some I/O switching code structured as an intercept driver, some modifications to IO_ROUTINES in the OpenVMS exec to permit control over all IRPs by an intercept, and a server (one of which would in principle reside in each cluster node) which will coordinate global naming choices and ensure consistency in names used from early in the bootstrap process on. (Summary of Impact on Device Drivers\infrastruct_summary)

Because it was deemed infeasible to insert switching code into every driver, this design inserts a layer of switching processing ahead of existing drivers. This layer intercepts driver entry points (by creating and using an edited copy of the Driver Dispatch Table) for one path into the device, and uses this path to provide the name and identity for the underlying storage. Other paths are hidden from the system, but are known to the switching code, and are used as needed by the switching code. The code is designed so that one path is used at a time, to avoid synchronization problems, and the path is switched when mount verify is found to be active for a time. (The switch does not occur when Mount Verify starts, because in SCSI drivers it is possible to enter Mount Verify when a bus reset occurs and the path is still good. Therefore switching is done after mount verify has been active a short time. This also guarantees that old operations are quiesced before new ones begin.)

In order to control all I/O even in the presence of drivers like DKDRIVER which pull IRPs off their input queue at points other than their main entry points, it is necessary for the switching code to control not only the start-IO entry, but the pending IO entry, I/O cancel entries, and mount verify start/end entries. Modifications to SYSQIOREQ and to IOSUBNPAG are needed further to ensure that all I/O sent to a driver be enqueued via the pending-io entry of the driver DDTAB (which by default points to EXE_STD$INSERT_IRP) so that IRPs will be seen at the pending_io entry or the start_io entry of a driver (or both) and can be redirected when seen. By the use of an existing hook in postprocessing, I/O completion can be seen by code in the switching layer prior to actual final postprocessing, permitting the switching code to monitor I/O status results for conditions indicating the currently used path may have gone bad and that mount verify should be initiated.

Thus the switching code acts merely as a switch inserted ahead of one of the driver units for devices, assuming its identity but in fact maintaining its own common input queue and directing I/O to one of its subordinate "path" devices at a time. The underlying device drivers and UCBs all exist (but are hidden), and I/O request packets are modified and forwarded to the appropriate underlying drivers, and switching is done when the paths go into mount verify.

It is seen here that switching of unmodified drivers can be handled at least after a fashion provided only that a driver follow the OpenVMS Step 2 interface standards. However, certain modifications are possible in a driver which can facilitate operation.

There are two areas where a driver may cooperate with the multipath switcher to facilitate operation. These are: (numbered) Drivers may determine when they should permit their names to be used by servers. Drivers may notify the switching code when they detect conditions which should result in changes to path availability.

These changes can be changes such as the HSZ controllers contemplate where failure of one of a pair of controllers causes notice to be sent to users of the remaining controller that the other controller has failed. ----------oldstuff---------- The design of the OpenVMS Alpha 64-bit Project includes a number of significant changes to OpenVMS Alpha privileged interfaces and data structures. These changes are part of the "infrastructure" work that is necessary to enable processes to grow their virtual address space beyond the existing 1 Gb limit of P0 space and the 1 Gb limit of P1 space.

It is a goal of the OpenVMS Alpha 64-bit Project to minimize the number and complexity of the source changes in privileged layered products that result from these infrastructure changes. However, this goal must be balanced against the other project goals, especially performance and maintainability. Thus, these infrastructure changes may impact any device driver and may require source changes to that driver regardless of whether it will be implementing support for 64-bit addresses or not.

This section lists the infrastructure changes that may impact device drivers and privileged components of layered products that access the internal VMS I/O database structures and support routines. Additional details about these changes can be found in other sections of this chapter as well as in other chapters of this design specification. (numbered) All device drivers will need to be recompiled and relinked in order to function on the Theta release.

Recompilation is necessary due to changes in the IRP and FDT structures. Device drivers that have not been recompiled and relinked against the Theta version of the system libraries will be prevented from being loaded on a Theta system. All components of privileged layered products that access fields in the following VMS kernel data structures will need to be recompiled and relinked: BOD, CDRP, CXB, DCBE, FDT, IRP, IRPE, and VCRP. All components of privileged layered products that use the VMS Communication Interface (VCI) to the LAN device drivers will need to be recompiled and relinked. There are significant changes to the addressability of Page Table Entries PTE.

This can impact device drivers in three ways: (alphabetic) Device drivers access PTEs to perform direct I/O.

This chapter includes an extensive discussion of changes to system-supplied I/O support routines that will allow almost all device drivers to access PTEs that have been locked for direct I/O without requiring source changes to the drivers. The only exceptions are those device drivers that directly call routines MMG_STD$IOLOCK, MMG$IOLOCK, MMG_STD$UNLOCK, MMG$UNLOCK, use the IRPE structure to manage additional buffers that are locked into memory, clear (irp$l_svapte) to keep a buffer locked after I/O completion, or pass a P0/P1 buffer address to the MMG_STD$SVAPTECHK or MMG$SVAPTECHK routines.

All the components on the OpenVMS Alpha masterpack that are exceptional in this fashion are discussed in detail in (impact_iolock), (impact_irpe), (impact_clr_svapte), and (impact_svaptechk) respectively. Device drivers can allocate and access System PTEs to double map the caller's buffer into S0/S1 space.

This code will continue to function unchanged due to the "SPT window(1\The presence of the SPT window obviates the need for a set of non-trival changes that would have been necessary in 47 of the 65 device drivers on the OpenVMS Alpha masterpack. This also reduces the impact on device drivers in layered products. For example, the Pathworks device drivers benefit from the presence of the SPT window.)" which is discussed in (system_space_chapter). Device drivers sometimes compute the PTE address for a virtual address in system space and use it in place of the PTE address of the caller's buffer. For example, this technique is used by some drivers if some attribute of the caller's buffer prevents it from being used for a DMA transfer to a particular I/O device on a particular adapter.

This code will continue to function unchanged due to the "SPT window(2)" which is discussed in (system_space_chapter). Some assumptions about data structure field adjacencies may be broken.

A number of changes need to be made "in the middle" of various I/O related data structures including the IRP, CDRP, IRPE, CXB, VCRP, and DCBE. These changes in structure layout may break some dependencies on field adjacencies in device driver code. Fixing these is expected to require isolated and simple source changes. It is expected that most of these on the OpenVMS Alpha masterpack will be detected by searches over the result disk.

All the data structure changes are described in (data_struct). There are changes to the use of the PFN database entry cells containing the page reference count and back link pointer.

The required, but simple, source changes are described in (PFN_database_chapter). The (SYS$\PDDRIVER) and the DECwindows (SYS$\INDRIVER) drivers are the only drivers on the OpenVMS Alpha masterpack that are impacted by the PFN database changes. There is an alternative ACB64 structure that maintains a 64-bit AST procedure value and a 64-bit AST parameter value.

However, unless a device driver wishes to provide 64-bit capabilities on attention ASTs or other similar driver-specific AST functions, it can continue to use the existing 32-bit ACB structure and the SCH$QAST routine. If a driver searches for or otherwise depends on knowledge of what an ACB looks like even when the ACB is built by some other independent driver or system service, the ACB handling code in that driver will need to be enhanced to deal with both standard ACBs and the new ACB64 format. In particular, the standard IRP structure that is built by the $QIO system service will use the ACB64 format.

The 64-bit AST support and ACB64 structure are described in (ast_chapter). All source code references to the (irp$l_ast), (irp$l_astprm), and (irp$l_iosb) cells will need to be changed.

As described in (qio_iosb) and (qio_ast), these IRP cells will be removed and replaced by new cells. A total of 30 source modules on the OpenVMS Alpha masterpack reference one of these cells. In some cases the intended reference is to the value of the $QIO (iosb), (astadr), or (astprm) parameters. Such references will need to be altered to match the 64-bit nature of these parameters. However, in the majority of cases these are simply references to arbitrary 32-bit parameters that were opportunistically placed in the (irp$l_ast), (irp$l_astprm), or (irp$l_iosb) cells of an internally allocated IRP. These references will need to be changed to use new names that will be defined specifically for this purpose.

In either case, the required source changes are localized and simple. These source changes are described in (impact_irp). Buffer objects can be mapped into S2 space or S0/S1 space.

If a driver handles buffer objects (described by a BOD data structure) that are created by some other independent driver or system service, the buffer object handling code in that driver will need to be enhanced to deal with buffer objects in S2 space.

Buffer objects in S2 space are discussed in (direct_io) and (bod_struct).

($QIO System Service Support for 64-bits)

The interfaces for the existing $QIO and $QIOW system services will be extended to support 64-bit addresses.

The current format of the $QIO and $QIOW system service calls is: status = sys$qio (efn,chan,func,iosb,astadr,astprm,p1,p2,p3,p4,p5,p6)

The 64-bit API guidelines stipulate that a 64-bit capable routine must accept 64-bit addresses on all its address parameters. With that in mind, (qio_arg) summarizes the changes to the data types of the $QIO and $QIOW system service parameters. ($QIO[W] Parameter Changes\qio_arg) (4\5\11\10) (Argument\Prior Type\New Type\Description) (efn\Unsigned longword\-\Event flag number. Unchanged.) (chan\Unsigned word\-\Channel number. Unchanged.) (func\Unsigned longword\-\I/O function code. Unchanged.) (iosb\32-bit pointer\64-bit pointer\ Pointer to a quadword I/O status block IOSB. The IOSB format is unchanged.) (astadr\32-bit pointer\64-bit pointer\ Procedure value of the caller's AST routine. On Alpha the procedure value is a pointer to the procedure descriptor.) (astprm\Unsigned longword\Quadword\ Parameter value for the AST routine.) (p1\Longword\Quadword\Device dependent parameter. Often p1 is a buffer address.) (p2\Longword\Quadword\Device dependent parameter. Only the low order 32-bits will be used by system-supplied FDT routines that use p2 as the buffer size.) (p3\Longword\Quadword\Device dependent parameter.) (p4\Longword\Quadword\Device dependent parameter.) (p5\Longword\Quadword\Device dependent parameter.) (p6\Longword\Quadword\Device dependent parameter. Sometimes p6 is used to contain the address of a diagnostic buffer.)

Since the OpenVMS Alpha 32-bit calling standard already requires 64-bit argument values these changes are upwardly compatible. Although the SYS$QIO[W] routine interfaces can be changed, the $QIO[W] macros for MACRO-32 and BLISS cannot be changed to access 64-bit values for any of their parameters. Such changes would break existing callers that are expecting longword accesses of the specified actual parameters.

The $QIOW system service is implemented as a caller's mode service that calls the $QIO system service followed by EXE$SYNCH_LOOP. To facilitate the passing of 64-bit parameter values, $QIOW will be recoded in C and will move from the SYSQIOREQ.MAR module to the new SYSQIOREQ2.C module. (IOSB Address\qio_iosb)

The $QIO system service will support a 64-bit (iosb) address. To avoid extra conditional branches, the $QIO support code will use the full 64-bits of the (iosb) address regardless of the number of significant bits in the caller's actual parameter value. This will require simple source changes to the SYSQIOREQ.MAR, IOCIOPOST.MAR, SYSCANCEL.MAR, SYSUPDSEC.MAR, and VCC_CACHE.MAR modules in the [SYS] facility. The (irp$l_iosb) cell, which contains the address of the caller's IOSB, will be replaced by the new (irp$pq_iosb) cell. The (irp$l_iosb) cell name will be removed to assure that any reference to the $QIO (iosb) via a 32-bit address is detected at compile-time or link-time.

The (irp$l_iosb) cell is also referenced by any device driver selective cancel routine. The driver selective cancel routine is an optional device driver routine that is used by the $CANCEL_SELECTIVE system service. This system service was added specifically to facilitate the implementation of POSIX features for OpenVMS.

The $CANCEL_SELECTIVE system-service allows the caller to cancel selected pending I/O requests on a channel. The caller identifies the I/O requests by specifying the (iosb) address that was used for the $QIO request. This service accepts a vector of 32-bit (iosb) addresses, copies this vector into nonpaged pool, and calls the device driver's selective cancel routine with the nonpaged pool version of the vector.

Although the $CANCEL_SELECTIVE system-service is restricted to 32-bit (iosb) addresses, and a $CANCEL_SELECTIVE_64 system-service is not planned for the Theta release, the format of the (iosb) vector in nonpaged pool will be changed to 64-bit entries that will be sign-extended from the caller's 32-bit entries. Because the comparisons of the vector entries to the (irp$l_iosb) cell need to be altered anyway, this additional change has very little impact if done now. No additional driver changes will be needed when the $CANCEL_SELECTIVE_64 is eventually added.

The Mailbox MBDRIVER and Terminal Class Driver SYS$TTDRIVER are the only device drivers on the OpenVMS Alpha masterpack that implement a selective cancel routine. Therefore, the impact of this change is very limited.

A number of device drivers and privileged components place arbitrary 32-bit parameters in the (irp$l_iosb) cell of an internally allocated IRP. These components take advantage of the fact that their internally allocated IRPs do not have a caller's (iosb) address and are not handled by the normal I/O postprocessing code. Because the (irp$l_iosb) cell is being removed, these references will need to be changed. The new (irp$l_iirp_p2) cell name will be added for this use and is described in (irp_struct). All the source modules on the OpenVMS Alpha masterpack that are affected by this are listed in (impact_irp). (AST Address and AST Parameter\qio_ast)

The $QIO system service will support a 64-bit AST routine address (astadr) and a 64-bit AST routine parameter value (astprm). The $QIO support code will rely on the 64-bit AST support and the new ACB64 structure that are described in (ast_chapter). The IRP structure will contain the necessary cells to allow it to be reused as an ACB64 by I/O postprocessing. To avoid extra conditional branches, the $QIO system service will set up the IRP as an ACB64 regardless of the number of significant bits in the caller's actual (astadr) and (astprm) parameter values. This will require simple source changes to the SYSQIOREQ.MAR, IOCIOPOST.MAR, SYSCANCEL.MAR, SYSUPDSEC.MAR, and VCC_CACHE.MAR modules in the [SYS] facility. The (irp$l_ast) and (irp$l_astprm) cells will be replaced by the new (irp$pq_acb64_ast) and (irp$q_acb64_astprm) cells. The (irp$l_ast) and (irp$l_astprm) cell names will be removed to assure that any reference to the $QIO (astadr) via a 32-bit address and (astprm) as a 32-bit value are detected at compile-time or link-time. All these changes to the IRP structure are described in detail in (irp_struct).

Unlike the (irp$l_iosb) cell, the (irp$l_ast) and (irp$l_astprm) cells are not part of any formal interface between the $QIO system service and device drivers. However, a number of device drivers and privileged components place arbitrary 32-bit parameters in the (irp$l_ast) or (irp$l_astprm) cells of an internally allocated IRP. These components take advantage of the fact that their internally allocated IRPs do not have a caller's (astadr) routine address or (astprm) parameter value, and are not handled by the normal I/O postprocessing code. Because the (irp$l_ast) and (irp$l_astprm) cells are being removed, these references will need to be changed. The new (irp$l_iirp_p0) and (irp$l_iirp_p1) cell names will be added for this use and are described in (irp_struct). All the source modules on the OpenVMS Alpha masterpack that are affected by this are listed in (impact_irp). (Device Dependent Parameters)

The full 64-bits of each of the device dependent parameters, (p1) through (p6), will be provided to device drivers via the IRP. The (irp$l_qio_p1) through (irp$l_qio_p6) cells will be promoted to quadwords (irp$q_qio_p1), etc. but the existing member names will also be provided as unions for the low order 32-bits of each of the parameter values. The existing names are being maintained to allow existing 32-bit drivers and system FDT support routines to continue to function without requiring source changes.

Since OpenVMS Alpha will support drivers that support 32-bit addresses and 64-bit addresses, there is a need for the $QIO system service to help assure that a request that requires 64-bit support is not sent to a driver that can not handle it. For example, if a 64-bit address were to be passed to a driver that only supported 32-bit addresses, the upper 32-bits of the address might be ignored by all references. In this case, the result of the I/O request might not be what the caller asked for and the eventual application fault might be difficult to trace back to this inappropriate use of a 64-bit address. The other possibility is that driver and system support routines sometimes used the full 64-bit address and sometimes used only the lower 32-bits of the address during the handling of the request. This could leave the system open to system crashers if, for example, the probe of the data and the transfer of the data ended up using different addresses.

Device drivers will declare their support for 64-bit addresses by individual I/O function. The FDT data structure will be expanded to include a 64-bit wide bit mask (fdt$q_ok64bit) (one bit for each of the 64 possible I/O function codes) where the bit will be set only if the driver supports a 64-bit address on that function. The default for this bit mask is zero. The method for setting up this mask is detailed in (fdt_64).

Usually the $QIO (p1) parameter specifies a buffer address. All the system-supplied upper-level FDT routines that support the read and write functions use this convention. Therefore, the (p1) parameter will be used as the key to determining if the caller of the $QIO service requires 64-bit support. The $QIO system service will reject an I/O request and return the following fatal system error status:

(3\2\14) (\SS$_NOT64DEVFUNC\64-bit address not supported by device for this function)

when both of the following conditions are true: (numbered) If the 64-bit value of the (p1) parameter does not equal the 32-bit value of the (p1) parameter sign extended into 64-bits, and, If the device driver has not declared 64-bit support for the requested I/O function code, i.e. the bit corresponding to the function code in the (fdt$q_ok64bit) mask is clear. The $QIO system service will usually perform this sign extension check only on the (p1) parameter. However, as described in (diag_buf), a similar sign extension check will be performed on the (p6) parameter when it specifies the address of a diagnostic buffer. Although the $QIO system service will not perform a sign extension check on the other device dependent parameters, a device driver that wishes to perform a similar check on other device dependent address parameters may do so in its driver-specific FDT routine.

The system-supplied upper-level FDT routines that support read and write functions ACP_STD$READBLK, EXE_STD$READ, EXE_STD$READLOCK, etc. will continue to only use the low-order 32-bits of the (p2) parameter for the buffer size and the low-order 32-bits of the (p3) parameter for the media address. Adding support for $QIO buffer sizes larger than 32-bits is beyond the scope of the 64-bit addressing project. The goals of this project are described in (ps_chapter). (Declaring Support for 64-bits in Drivers\fdt_64)

Device drivers declare that they can support a 64-bit address by individual function. The details vary depending on the language used to code the initialization of the driver's Function Decision Table. (Drivers Written in C)

Drivers written in C use the (ini_fdt_act) macro to initialize an FDT entry for an I/O function. This macro uses the DRIVER$INI_FDT_ACT routine. Both the macro and the routine will be enhanced.

The current format of the macro is: ini_fdt_act (fdt, func, action, bufflag)

where the (bufflag) parameter must be one of the following:

(3\2\12) (\BUFFERED\The specified function is buffered.) (\NOT_BUFFERED\The specified function is direct. This is a synonym for DIRECT.) (\DIRECT\The specified function is direct. This is a synonym for NOT_BUFFERED.)

The use of the (bufflag) parameter will be enhanced to include the declaration of 64-bit support by allowing 3 additional values:

(3\2\12) (\BUFFERED_64\The specified function is buffered and supports a 64-bit address in the p1 parameter.) (\NOT_BUFFERED_64\The specified function is direct and supports a 64-bit address in the p1 parameter.) (\DIRECT_64\The specified function is direct and supports a 64-bit address in the p1 parameter.)

If a driver does not support a 64-bit address on any of its functions, there is no need to change its use of the (ini_fdt_act) macro.

For example, the following C code segment declares that the IO$_READVBLK and IO$_READLBLK functions support 64-bit addresses. ini_fdt_act (&driver$fdt, IO$_SENSEMODE, my_sensemode_fdt, BUFFERED); ini_fdt_act (&driver$fdt, IO$_SETMODE, my_setmode_fdt, BUFFERED); ini_fdt_act (&driver$fdt, IO$_READVBLK, acp_std$readblk, DIRECT_64); ini_fdt_act (&driver$fdt, IO$_READLBLK, acp_std$readblk, DIRECT_64);

The interpretatation of the (bufflag) parameter to the DRIVER$INI_FDT_ACT routine will be enhanced to support the new values and the setting of the 64-bit support mask in the FDT data structure. (Drivers Written in MACRO-32)

Drivers written in MACRO-32 will use a new FDT_64 macro to declare the set of I/O functions for which the driver supports 64-bit addresses. The use of the FDT_64 macro is similar to the use of the existing FDT_BUF macro. If a driver does not support a 64-bit address on any of its functions, there is no need to use the new FDT_64 macro.

For example, the following MACRO-32 code segment declares that the IO$_READVBLK and IO$_READLBLK functions support 64-bit addresses. FDT_INI MY_FDT FDT_BUF FDT_64 FDT_ACT ACP_STD$READBLK, (Drivers Written in BLISS)

Drivers written in BLISS-32 and BLISS-64 will use a new optional keyword parameter, FDT_64, to the existing FDTAB macro to declare the set of I/O functions that support 64-bit addresses. The use of the new FDT_64 parameter is similar to the use of the existing FDT_BUF parameter. If a driver does not support a 64-bit address on any of its functions, there is no need to use the new FDT_64 parameter.

For example, the following BLISS code segment declares that the IO$_READVBLK and IO$_READLBLK functions support 64-bit addresses. FDTAB ( FDT_NAME = MY_FDT, FDT_BUF = (SENSEMODE,SETMODE), FDT_64 = (READVBLK,READLBLK), FDT_ACT = (ACP_STD$READBLK, (READVBLK,READLBLK) ) );

(Buffered I/O Functions)

OpenVMS device drivers that perform data transfers using "buffered" I/O functions do so by using a buffer "packet" in nonpaged pool for the actual I/O device transfer. For a write to the I/O device, the data from the caller's buffer is copied into the nonpaged pool buffer packet while still in process context, that is, in a driver FDT routine. The rest of the driver uses the data in the buffer packet to perform the write to the device. For a read from the I/O device, the driver FDT routine allocates a nonpaged pool buffer packet of sufficient size to contain the requested data. The caller's buffer address is saved in the buffer packet as well. The rest of the driver fills in the buffer packet with data obtained from the I/O device. When the driver completes the transfer from the I/O device, it sends the associated IRP on to I/O postprocessing. Finally, when the request arrives at the I/O postprocessing routine that executes in the requester's process context, the data read from the device is copied from the buffer packet to the caller's buffer using the address that was saved in the buffer packet.

OpenVMS supports three different buffer packet formats. The following sections discuss the three formats separately, because their adaptability for 64-bit support differs. (Simple Buffered I/O Packets\simple_bufio)

A simple buffered I/O packet BUFIO is used when a single buffer in nonpaged pool contains data that is destined for or from a single buffer in the caller's address space. It has a minimal header format that is 12 bytes long. The first longword contains a pointer into the buffer packet where the data begins often initialized by a (MOVAB 12(R2),(R2)) instruction; the second longword contains the virtual address of the caller's buffer; and the third longword contains the usual nonpaged pool structure size and type cells.

Although the format is simple, changing the packet header to include a 64-bit caller's buffer address is not so simple for the following reasons: (unnumbered) There are no symbolic offsets for the simple buffered I/O packet header. Existing code in drivers and IOCIOPOST.MAR uses numeric constants as offsets. It would be difficult to find all the places on the OpenVMS Alpha masterpack where there is a dependence on the existing values of these offsets. A dependency on the layout of the buffered I/O packet can occur anywhere in a device driver. For example, at fork level a device driver may resize and copy the packet or alter the saved buffer address within the packet. Device drivers allocate and build the simple buffered I/O packets themselves. There is no system-supplied utility routine or macro that sets up a simple buffered I/O packet header. In fact, some device drivers don't fully initialize the packet header if they know that their use doesn't require it.

Therefore, the following approach will be taken to provide 64-bit address support with simple buffered I/O packets: (numbered) The existing 32-bit simple buffered I/O packet format will remain supported. Any buffered I/O function that is restricted to a 32-bit caller's buffer address can continue to use the existing format. An alternative 64-bit simple buffered I/O packet format will be supported as well. This new format will be used for buffered I/O functions that support a 64-bit caller's buffer address. The simple buffered I/O packets are "self identifying." That is, it is possible to distinguish a 32-bit from a 64-bit format BUFIO packet from the 32-bit user buffer address cell. A -1 value symbolic constant BUFIO$K_64 in this cell will indicate that this is a 64-bit buffered I/O packet and that the user buffer address is in the new (bufio$pq_uva64) cell. This is very similar to the method used to identify a 64-bit descriptor. The details of the new BUFIO packet are described in (bufio_struct). Two new system-supplied routines will be provided. The routine EXE_STD$ALLOC_BUFIO_32 will allocate and initialize the header of a 32-bit simple buffered I/O packet. The routine EXE_STD$ALLOC_BUFIO_64 will allocate and initialize the header of a 64-bit simple buffered I/O packet. The details of these routines are described in (exe_alloc_bufio). (Complex Buffered I/O Packets\complex_bufio)

A complex buffered I/O packet IRP$M_COMPLX set in (irp$l_sts) is used when a single buffer packet in nonpaged pool contains data that is destined for or from multiple buffers in the caller's address space. On the OpenVMS Alpha masterpack, the complex buffered I/O packet format is used exclusively by the system-supplied upper-level FDT routines for the control functions to file structured devices ACP_STD$ACCESS, ACP_STD$MODIFY, etc.. These FDT routines build a complex buffered I/O packet that is then forwarded to the XQP or the appropriate ACP.

Each complex buffered I/O packet has an ACP I/O Buffer AIB header followed by a variable number of ACP Buffer Descriptors ABD each of which contains a 32-bit caller's buffer address and an offset within the packet to the data. These ABDs are built on the basis of the various data structures specified by the $QIO (p1) through (p6) parameters that are supported on the XQP and ACP function codes. These parameters specify the address of the File Information Block FIB, the address of a file name descriptor, the address of a word to receive the resultant file name length, the address of a descriptor for the resultant file name string, and the address of a list of file attribute descriptors.

As discussed in (driver_func_64), the XQP and ACP control functions will not be supporting 64-bit addresses in the Theta release. Therefore, support for a 64-bit capable AIB and ABDs will not be included in the Theta release.

It is highly unlikely that layered product device drivers would use the complex buffered I/O packet format unless they used the system-supplied ACP FDT routines or implemented a driver-specific file ACP. For the same reasons that apply to the XQP functions, these functions will be restricted to 32-bit addresses for the Theta release. (Complex Chained Buffered I/O Packets\chained_bufio)

Complex chained buffered I/O packets IRP$M_COMPLX and IRP$M_CHAINED set in (irp$l_sts) are used when multiple buffer packets in nonpaged pool contain data that is destined for or from a single buffer in the caller's address space. Each of the buffer packets in the chain is known as a CXB and contains some portion of the data for or from the caller's buffer.

On the OpenVMS Alpha masterpack, the complex chained buffered I/O packet format is used by the DECnet drivers for the $QIO read and write functions, by the LAN drivers for their $QIO read and write functions, and for the LAN driver "altstart" interface. As discussed in (driver_func_64), because these are data transfer operations, it is desirable to provide support for 64-bit addresses on these functions. However, DECnet's use of CXBs makes it prohibitively risky and difficult to provide this support for the DECnet read and write $QIO functions. On the other hand, the use of CXBs by the LAN drivers is much more orderly and is amenable to providing support for a 64-bit caller's buffer address. Since the LAN drivers must handle CXBs that are built by DECnet as well as their own CXBs, both the LAN drivers and I/O postprocessing must retain the ability to handle both CXBs with a 32-bit caller's buffer address as well as CXBs that contain a 64-bit caller's buffer address.

The use of CXBs shares some attributes with the use of the simple BUFIO packets. In the case of a transmit to the device, the OpenVMS I/O support code does not require that there is a valid caller's buffer address in the packet. This is because the movement of data from the caller's buffer to the packet takes place entirely within the driver-specific FDT routine. In the case of a receive from the device, I/O postprocessing requires that the first longword of each CXB points to the data within the CXB that's destined for the caller's buffer, and that the second longword of the first CXB in the chain points to the caller's buffer.

However, unlike the BUFIO packet, the CXB header contains a number of cells for which there are symbolic offsets and there is no hard-coded dependency on a specific numeric CXB packet header size.(1\The first two longwords in the CXB are named cxb$l_fl and cxb$l_bl. Unfortunately, the numeric offsets 0 and 4 are used when these cells are reused for the data pointer and caller's buffer address.) Also, unlike the BUFIO packet, while a CXB is in use by the driver, the first two longwords are sometimes used to contain queue forward and backward links. Thus, for a receive CXB, the packet data pointer and caller's buffer address in the CXB are filled in just before the associated IRP is sent to I/O postprocessing. In particular, the caller's buffer address is obtained from the (irp$l_iost2) cell in the IRP a.k.a. the (irp$l_ni_datbuf) cell by the LAN drivers. This IRP cell is set up by both the LAN drivers and the DECnet drivers.

Therefore, the following approach will be taken to provide 64-bit address support for CXBs: (numbered) The symbolic offsets (cxb$ps_pktdata) and (cxb$ps_uva32) will be defined for the first two longwords. The standard CXB header the portion of the CXB that is CXB$K_LENGTH bytes long will be expanded to include a new quadword aligned 64-bit (cxb$pq_uva64) cell as the last cell in the header. Since symbolic offsets are used by the code that deals with CXBs, the change in the CXB header length should not require any source changes. A -1 value symbolic constant BUFIO$K_64 in the (cxb$ps_uva32) cell will indicate that this is a 64-bit CXB and that the user buffer address is in the new (cxb$pq_uva64) cell. The (irp$l_ni_datbuf) cell will be renamed to (irp$l_ni_datbuf32). The DECnet drivers will continue to place the caller's buffer address in the (irp$l_ni_datbuf32) cell via the (irp$l_iost2) name. The routine LAN$RECEIVE_FDT will write the value BUFIO$K_64 into the (irp$l_ni_datbuf32) cell. This value indicates that the 64-bit caller's buffer address is in the (irp$q_qio_p1) cell. The routine ILAN$RECEIVE_FDT, is used to send either an IRP with a BUFIO packet (produced by LAN $QIO) or an IRP with a CXB to (produced by LAN "altstart") to I/O postprocessing. When handling a CXB, this routine will copy the (irp$l_ni_datbuf32) value to (cxb$ps_uva32) and the (irp$q_qio_p1) value to (cxb$pq_uva64) cell. When handling a BUFIO, this routine will copy the (irp$l_ni_datbuf32) value to (bufio$ps_uva32) and the (irp$q_qio_p1) value to (bufio$pq_uva64) cell.

As a result, no source changes are anticipated or required to any other drivers that create and manipulate CXBs. Such drivers will, however, be restricted to a 32-bit caller's buffer address.

Device drivers that wish to support a 64-bit buffer address with CXBs need to write the BUFIO$K_64 value into the (cxb$ps_uva32) cell and place the 64-bit buffer address in the (cxb$pq_uva64) cell. (Direct I/O Functions\direct_io)

OpenVMS device drivers that perform data transfers using "direct" I/O functions do so by locking the buffer into memory while still in process context, that is, in a driver FDT routine. The PTE address of the first page that maps the buffer is obtained and the byte offset within the page to the start of the buffer is computed. These values are saved in the IRP (irp$l_svapte) and (irp$l_boff). The rest of the driver then uses values in the (irp$l_svapte) and (irp$l_boff) cells and the byte count in (irp$l_bcnt) in order to perform the transfer. Eventually when the transfer has completed and the request returns to process context for I/O postprocessing, the buffer is unlocked using the (irp$l_svapte) value and not the original process buffer address.

Thus, to support 64-bit addresses on a direct I/O function, one only needs to ensure the proper handling of the buffer address within the FDT routine.

Almost all device drivers that perform data transfers via a direct I/O function use OpenVMS-supplied FDT support routines to lock the buffer into memory. Because these routines obtain the buffer address either indirectly from the IRP or directly from a parameter that is passed by value, the interfaces for these routines can easily be enhanced to support 64-bit wide addresses.

However, various OpenVMS Alpha memory management infrastructure changes that will be made to support 64-bit addressing have a potentially major impact on the current use of the 32-bit (irp$l_svapte) cell by device drivers. In general, there are two problems: (numbered) It will take a full 64-bits to address a process PTE in page table space, and, The 64-bit page table space address for a process PTE is only valid when in the context of that process. This is also known as the "cross-process PTE problem."

In most cases, both of these PTE access problems will be solved by copying the PTEs that map the buffer into nonpaged pool and setting (irp$l_svapte) to point to the copies. This copy will be done immediately after the buffer has been successfully locked. A copy of the PTE values is acceptable since device drivers only read the PTE values and are not allowed to modify them. These PTE copies will be held in a new nonpaged pool data structure, the Direct I/O Buffer Map DIOBM structure. A standard DIOBM structure also known as a fixed-size primary DIOBM will contain enough room for a vector of 9 DIOBM$K_PTECNT_FIX PTE values. This is sufficient for a buffer size up to 64K bytes on a system with 8 Kb pages.(1\Eight PTEs are sufficient only if the buffer begins exactly on a page boundary, otherwise a 9th is required.) It is expected that most I/O requests will be handled by this mechanism and that the overhead to copy a small number of PTEs is acceptable especially given that these PTEs have been recently accessed to lock the pages.

The standard IRP will contain an embedded fixed-size DIOBM structure. The (irp$l_svapte) cell will be set to point to the start of the PTE copy vector within the embedded DIOBM structure in that IRP when the PTEs that map a buffer fit into the embedded DIOBM.

If the buffer requires more than 9 PTEs, then a separate "secondary" DIOBM structure that is variably-sized will be allocated to hold the PTE copies. If such a secondary DIOBM structure is needed, it will be pointed to by the original, or "primary" DIOBM structure. The secondary DIOBM structure will be deallocated during I/O postprocessing when the buffer pages are unlocked. In this case, the (irp$l_svapte) cell will be set to point into the PTE vector in the secondary DIOBM structure. The secondary DIOBM will require only 8 bytes of nonpaged pool for each page in the buffer. The allocation of the secondary DIOBM structure will not be charged against the process BYTLM quota but will be controlled by the process direct I/O limit DIOLM. This is the same approach that is used for other internal data structures that are required to support the I/O, including the Kernel Process Block, Kernel Process stack, and the IRP itself.

However, as the size of the buffer increases, the run-time overhead to copy the PTEs into the DIOBM becomes noticeable. At some point it becomes less expensive to create a temporary window in S0/S1 space to the process PTEs that map the buffer. The PTE window method has a fixed cost, but the cost is relatively high because it requires PTE allocation and TB invalidates. This is why the PTE window method is not used for moderately sized buffers.

The transition point from the PTE copy method with a secondary DIOBM to the PTE window method was determined by performance tests on a prototype of the implementation. This testing demonstrated the performance benefit of the secondary DIOBM, especially on an SMP system where the cost of the TB invalidates is significantly higher. As a result, a new system data cell, (ioc$gl_diobm_ptecnt_max), will contain the maximum desirable PTE count for a secondary DIOBM. The PTE window method will be used if the buffer is mapped by more than (ioc$gl_diobm_ptecnt_max) PTEs.

During system initialization the (ioc$gl_diobm_ptecnt_max) cell will be set as shown in (diobm_ptecnt_max).

(Value for ioc$gl_diobm_ptecnt_max\diobm_ptecnt_max) (5\4\4\20\10) (DAG\The 3456 byte maximum size for a secondary DIOBM falls below the largest nonpaged pool lookaside list packet size of 5120 bytes which was the upper bound for this value.) (SMP\Value\Symbol\Max user buffer\Max nonpaged pool) (No \(##94)\DIOBM$K_PTECNT_MAX_UNI\ (#770#Kb)\(###768#bytes)) (Yes\(#430)\DIOBM$K_PTECNT_MAX_SMP\ (#3.5#Mb)\(##3456#bytes)(dag))

When a PTE window is used, (irp$l_svapte) will be set to the S0/S1 virtual address in the allocated PTE window that points to the first PTE that maps the buffer. This S0/S1 address is computed by taking the S0/S1 address that is mapped by the first PTE allocated for the window and adding the byte offset within page of the first buffer PTE address in page table space. A PTE window that is created in this fashion will be removed during I/O postprocessing.

The PTE window method will also be used if the attempt to allocate the required secondary DIOBM structure fails due to insufficient contiguous nonpaged pool. With an 8 Kb page size, the PTE window will require a set of contiguous system page table entries equal to the number of 8 Mb regions in the buffer plus 1. A failure to create a PTE window due to insufficient SPTEs is expected to be rare. However, in the unlikely event of such a failure, if the process has not disabled resource wait mode, the $QIO request will be backed out and the requesting process will be put into a resource wait state for nonpaged pool RSN$_NPDYNMEM. When the process is resumed, the I/O request will be retried. If the process has disabled resource wait mode, a failure to allocate the PTE window will result in the failure of the I/O request.(1\It would be possible to partition the locked buffer into smaller mapped buffer segments that could be mapped by the embedded DIOBM for the virtual read and write functions to disk devices. However, this approach will not be taken since this failure case is expected to be rare and this type of segmentation would have required the added complexity of a return back to process context between buffer segments. )

When the PTE window method is used, the level-3 process page table pages that contain the PTEs that map the user buffer are locked into memory as well. However, these level-3 page table pages are not locked when the PTEs are copied into nonpaged pool or when the SPT window is used.

The setting of (irp$l_svapte) by one of the previously described 3 methods will be done using the new IOC_STD$FILL_DIOBM routine. The OpenVMS-supplied FDT support routines (EXE_STD$\MODIFYLOCK), (EXE_STD$\READLOCK), and (EXE_STD$\WRITELOCK) will use the IOC_STD$FILL_DIOBM routine in the following way: (numbered) The buffer will be locked into memory by calling the new MMG_STD$IOLOCK_BUF routine. This routine will return a 64-bit pointer to the PTEs and will replace the obsolete MMG_STD$IOLOCK routine. status = mmg_std$iolock_buf (buf_ptr, bufsiz, is_read, pcb, &irp->irp$pq_va_pte, &irp->irp$ps_fdt_context->fdt_context$q_qio_r1_value);

This routine is fully described in (mmg_iolock). A value for the 32-bit (irp$l_svapte) cell will be derived by calling the new IOC_STD$FILL_DIOBM routine with a pointer to the embedded DIOBM in the IRP, the 64-bit pointer to the PTEs that was returned by MMG_STD$IOLOCK_BUF, and the address of the (irp$l_svapte) cell.(1\For performance reasons, the common case that can be handled by the PTE vector in the embedded DIOBM may be duplicated in line to avoid the routine call. ) status = ioc_std$fill_diobm (&irp->irp$r_diobm, irp->irp$pq_va_pte, pte_count, DIOBM$M_NORESWAIT, &irp->irp$l_svapte);

The DIOBM structure is fully described in (diobm_struct) and this routine is described in (fill_diobm).

Device drivers that call (MMG_STD$\IOLOCK) directly will need to examine their use of the returned values and may need to call the routine IOC_STD$FILL_DIOBM as well. This is discussed in greater detail in (mmg_iolock).

Two additional cases warrant special consideration when setting (irp$l_svapte) for direct I/O. The first is the case of a buffer located in S0/S1 space. Addresses in S0/S1 space are mapped by PTEs in shared 64-bit page table space and are also mapped using a "permanent" SPT window in 32-bit S0/S1 space onto the PTEs that map S0/S1 space. This window is "permanent" in the sense that it is created during system initialization and does not need to be dynamically created and deleted for each I/O request or other use. The IOC_STD$FILL_DIOBM routine will return a 32-bit system virtual address in the SPT window for buffers in S0/S1 space.

The second special case is the support of I/O to buffer objects by routines (ACP_STD$\READBLK) and (ACP_STD$\WRITE). A "buffer object" is a region of process virtual address space that is locked into memory and is also mapped into system space.

Currently, OpenVMS maps buffer objects into S0/S1 space. For these buffer objects, the S0/S1 address of the PTE that maps the S0/S1 mapping of the first page of the buffer object is currently stored in (bod$ps_svapte). The (bod$ps_svapte) value is used to calculate a value for (irp$l_svapte) based on the offset of the start of the buffer within the buffer object. This use will continue to be valid and will be unchanged.

The 64-bit Project will add support for buffer objects mapped by S2 space to enable the creation of very large buffer objects. In the case of a buffer object mapped by S2 space, the PTE address will require a full 64-bit address in shared system page table space which will be contained in the (bod$pq_va_pte) cell.(2\(bod_struct) contains a description of the changes to the BOD structure. (va_api_chapter) contains a complete description of the changes to the buffer object system services.) Since the memory for the buffer object is already locked, the routines (ACP_STD$\READBLK) and (ACP_STD$\WRITE) will call IOC_STD$FILL_DIOBM directly, passing in a value computed from (bod$pq_va_pte).

(svapte_table) summarizes the methods that the system-supplied direct I/O FDT routines will use to set the (irp$l_svapte) cell and the order in which each of these methods is considered.

(Methods Used to Set irp$l_svapte\svapte_table) (4\15\2\15) (Routines\Order\Condition\Method) (ACP_STD$READBLK\\\) (ACP_STD$WRITEBLK\ (#1.)\ Buffer object in S0/S1\ Calculation based on (bod$ps_svapte)) (\ (#2.)\ Buffer object in S2\ Call IOC_STD$FILL_DIOBM with PTE_PQ derived from (bod$pq_va_pte).

If error returned by IOC_STD$FILL_DIOBM, call (EXE_STD$\IORSNWAIT) to retry.) (\ (#3.)\ All other buffers\ Call EXE_STD$READLOCK or

EXE_STD$WRITELOCK) (Routines\Order\Condition\Method) (EXE_STD$MODIFYLOCK\\\) (EXE_STD$READLOCK\\\) (EXE_STD$WRITELOCK\ (#1.)\ Buffer mapped by 9 or less PTEs\ Call MMG_STD$IOLOCK_BUF and copy PTEs into PTE vector in primary DIOBM. This is an optimization to avoid a procedure call in the common case.) (\ (#2.)\ All other buffers\ Call MMG_STD$IOLOCK_BUF followed by

IOC_STD$FILL_DIOBM.

If error returned by (IOC_STD$\FILL_DIOBM), call (MMG_STD$\UNLOCK_BUF) followed by EXE_STD$IORSNWAIT to retry.) (Routine\Order\Condition\Method) (IOC_STD$FILL_DIOBM\ (#1.)\ Buffer in S0/S1\ Use SPT window.) (\ (#2.)\ Buffer mapped by 9 or less PTEs\ Copy PTEs into PTE vector in primary DIOBM.) (\ (#3.)\ Buffer mapped by more than 9 but less than or equal to ioc$gl_diobm_ptecnt_max

PTEs\ Allocate a secondary DIOBM and copy the PTEs into the secondary DIOBM.) (\ (#4.)\ Buffer mapped by more than ioc$gl_diobm_ptecnt_max

PTEs, or failure to allocate the required secondary

DIOBM structure.\ Create a temporary PTE window to the process PTEs and lock the level-3 page table pages that contain them. Either an error status is returned on failure to allocate the required number of system PTEs or the process is put into a temporary wait state. )

Because the methods used by the new routine IOC_STD$FILL_DIOBM may allocate additional nonpaged pool or SPTEs this will impose a new requirement to release these resources at the appropriate time. The new routine IOC_STD$RELEASE_DIOBM, which is described in detail in (release_diobm), will perform this function. This routine must be called for a given DIOBM before the data structure containing that DIOBM is about to be deallocated or reused for some other purpose. In almost all cases this is immediately after the buffer pages are unlocked.

(rel_diobm_table) summarizes the places on the OpenVMS Alpha masterpack that will be modified to release a DIOBM.

(Calls to IOC_STD$RELEASE_DIOBM\rel_diobm_table) (3\20\10) (Called by routine\Released DIOBM\Context) (IOC$IOPOST\irp$r_diobm\ Direct I/O completion at IPL 4 immediately after unlocking pages.) (UNLOCK_IRPES in IOCIOPOST\irpe$r_diobm\ Direct I/O completion at IPL 4 immediately after unlocking pages locked by an IRPE.) (IOC$IOPOST\irp$r_diobm\ Direct I/O completion at IPL 4 of a buffer object in S2 space.) (PAGIO in IOCIOPOST\irp$r_diobm\ Page read completion at IPL 4 just before IRP is deallocated. See also (exe_buildpkt).) (PAGIO in IOCIOPOST\irp$r_diobm\ Page write completion at IPL 4 just before special kernel AST to MMG$UPDSECAST is queued. See also (exe_buildpkt).) (EXE$FASTIO_FINISH\irp$r_diobm\ Direct Fast I/O completion at IPL 8.) (EXE_STD$LOCK_ERR_CLEANUP\irp$r_diobm

irpe$r_diobm\ Error path on failure to lock down pages with possible other page ranges already successfully locked. See also (exe_lock_err_cleanup) and (impact_irpe).) (SCATP$UNLOCK_BUFFER\vcrp$r_diobm\ IPC block transfer completion immediately after unlocking pages. See also (impact_iolock).)

(LAN VCI\lan_vci)

VMS Communications Interface VCI provides a privileged IPL 8 interface to the OpenVMS LAN drivers. This interface is more tailored and optimized for network transfers than the unprivileged $QIO system service interface to these drivers.

A collection of code that uses the VCI is also known as a "VMS Communication Module" or VCM. An upper-level VCM uses the VCI to obtain services from a lower-level VCM. The OpenVMS LAT driver, the OpenVMS Infoserver drivers, and OpenVMS DECnet Phase V are examples of upper-level VCMs to the OpenVMS LAN drivers.

The VCRP and the DCBE are two of the interface data structures that are used by upper- and lower-level VCMs. The VCRP structure is the VMS Communications Request Packet that is used to transfer data between an upper- and lower-level VCM. The DCBE structure is the Data Chain Block that can be used to specify the data that is to be transmitted with a VCRP. A chain of DCBEs is used when the data is contained in more than one discontiguous buffer in virtual memory.

There are two ways that a DCBE can identify a memory buffer. In both cases the buffer specified by a DCBE must be memory-resident before the DCBE is passed to a lower-level VCM. The first, and most frequently used, way is through the (dcbe$l_svapte), (dcbe$l_boff), and (dcbe$l_bcnt) values. When this method is used, the DCBE is subject to the same PTE access problems that were discussed in (direct_io) with respect to direct I/O. Furthermore, these PTE access problems must be resolved by the upper-level VCM. Because the VCRP can also be used as a DCBE, it is subject to these problems as well.

Therefore, the DCBE and the VCRP will be expanded to each include an embedded fixed-size primary DIOBM structure. This DIOBM can be used by an upper-level VCM to provide a 32-bit system virtual address for the PTEs that map the buffer. The lower-level VCM will not alter this embedded DIOBM nor make any assumptions about it.

If the buffer was locked prior to entry into the VCM, no changes are necessary to the VCM code that creates a DCBE. For example, if the buffer was previously locked using EXE_STD$WRITELOCK and an IRP, the (dcbe$l_svapte) cell can continue to be loaded using the value in the (irp$l_svapte) cell. However, if the upper-level VCM locks the buffer and does not have an IRP, it can use the embedded DIOBM and the IOC_STD$FILL_DIOBM routine to derive a value for the (dcbe$l_svapte) cell. The SYS$IPC_SERVICES image is an example of an upper-level VCM that will use the embedded DIOBM in this fashion.

An upper-level VCM can support either a 32-bit or 64-bit caller's buffer address with the (dcbe$l_svapte) and (dcbe$l_boff) cells. Because the upper-level VCM is responsible for locking the buffer into memory and providing the 32-bit PTE address, it is also responsible for making any necessary API and support code changes in order to support a 64-bit caller's buffer address. For example, no API changes to the $IPC services are being planned for the Theta release. Therefore, the $IPC services will be restricted to supporting a 32-bit caller's buffer address in the Theta release.

The second, and less frequently used, way for a DCBE to identify the buffer is through a 32-bit system virtual address in the (dcbe$l_buffer_address) cell. This method will remain restricted to a 32-bit system space address and will not support buffers in S2 space.(1\A third method involving a new (dcbe$pq_buffer_addr64\bold) cell, which could contain a 64-bit system virtual address, was considered. Support for this cell would have required a number of changes to each of the LAN.MAR, TMS380.C, PDQ.MAR, FXDRIVER.MAR, and HCDRIVER.C modules in the [LAN] facility, additional VCRP, VCRPLANDEF, and DCBE structure changes, and changes to the $VIRPHY and $VIRNXT macros in the LANIMAC.MAR module. The potential risks of these changes, the estimated implementation effort, and the required verification effort out weigh the potential benefits of having direct S2 buffer address support. ) Buffers in S2 space can be handled by the (dcbe$l_svapte) and (dcbe$l_boff) cells in conjunction with the embedded DIOBM structure in the DCBE. (Diagnostic Buffers\diag_buf)

The $QIO system service support code allows device drivers to implement a user-visible feature called "diagnostic buffers." These diagnostic buffers are a mechanism that callers of the $QIO system service can use to obtain additional driver-specific information for specific function codes. The $QIO system service will be enhanced to support a 64-bit diagnostic buffer address to met the requirements of the 64-bit API guidelines. The rest of this section provides a brief overview of the current support for diagnostic buffers and describes the changes to support a 64-bit address for the caller's diagnostic buffer.

The $QIO system service creates a diagnostic buffer packet for the IRP when all of the following conditions are met: (unnumbered) The I/O function is a physical I/O function The $QIO system service (p6) parameter is non-zero The device driver's (ddt$w_diagbuf) cell contains a non-zero value The requesting process has the DIAGNOSE privilege.

The format of a diagnostic buffer packet is very similar to the simple buffered I/O packet format that is discussed in (simple_bufio) and (bufio_struct). A device driver can put data into the diagnostic buffer packet at any point during its processing of the I/O function. A driver writes into the diagnostic buffer packet either indirectly, through its register dump routine which is called by the IOC_STD$DIAGBUFILL routine, or directly by obtaining a pointer to the packet from the (irp$l_diagbuf) cell. When the IRP is handled by the I/O postprocessing routine that executes in the requester's process context, the data in the diagnostic buffer packet is copied to the caller's diagnostic buffer and the diagnostic buffer packet is deallocated.

The $QIO system service and I/O postprocessing will be enhanced to support a diagnostic buffer packet format that includes room for a 64-bit caller's diagnostic buffer address. The header of the 64-bit diagnostic buffer packet will be exactly the same as the header of the 64-bit BUFIO packet that is described in (bufio_struct). This new support will be in addition to the support for the existing diagnostic buffer packet format that contains room for only a 32-bit caller's diagnostic buffer address.

Some drivers, particularly those that write directly to the diagnostic buffer packet, do not use the packet data pointer but instead depend on the current fixed 12 byte format of the diagnostic packet header. For example, a device driver must specify a diagnostic buffer size in its DDT that includes the 12 byte packet header. In addition, drivers tend to support diagnostic buffers with common routines that are shared by different I/O functions. It would add a great deal of complexity to such common routines if they had to deal with a varying diagnostic buffer packet format based on whether the particular I/O function supports a 64-bit buffer address or if the user specified an address that required more than 32-bits.

Therefore, support for a caller's 64-bit diagnostic buffer address will be a driver-wide option that is not directly linked to each I/O function's ability to support a 64-bit buffer address. Once the $QIO system service has determined that a diagnostic buffer packet is required, it will use the highest-order bit in the 16-bit (ddt$w_diagbuf) cell specified by the new mask constant DDT$M_DIAGBUF64 to determine the type of diagnostic buffer packet to create: (numbered) If DDT$M_DIAGBUF64 is clear in the (ddt$w_diagbuf) cell, a 32-bit diagnostic buffer packet will be constructed. However, if the 64-bit value of the (p6) parameter is not equal to the 32-bit value of the (p6) parameter sign extended into 64-bits, the SS$_NOT64DEVFUNC fatal error will be returned.

For this case, the size of the allocated 32-bit diagnostic buffer packet (ddt->ddt$w_diagbuf) and the expected size of the caller's diagnostic buffer (ddt->ddt$w_diagbuf-12) will remain exactly as they currently are. If DDT$M_DIAGBUF64 is set in the (ddt$w_diagbuf) cell, a 64-bit diagnostic buffer packet will be constructed and the low order 15-bits of the (ddt$w_diagbuf) cell will specify the size of the 64-bit diagnostic buffer packet.

Note that since the header of a 64-bit diagnostic buffer packet will be 12 bytes larger BUFIO$K_HDRLEN64-BUFIO$K_HDRLEN32, this size difference must reflected in the driver-supplied value for the (ddt$w_diagbuf) cell. Similarly, in this case, the expected size of the caller's diagnostic buffer will be the size of the diagnostic buffer packet minus the BUFIO$K_HDRLEN64 24 byte packet header size. Since the diagnostic buffer packets are self-identifying, the I/O postprocessing code will be enhanced to handle either type of packet.

Drivers can select the diagnostic buffer packet format that the $QIO system service will build using exactly the same means that they currently use to declare their support for diagnostic buffers.(1\Alternative methods of declaring support for a 64-bit diagnostic buffer address were considered. There is a separate flags longword in the DPT, but the DPT is generally used for driver load-time values, while the DDT is used for run-time values. The addition of a DDT flags longword could have led to confusion. A likely driver-writer error would have been the use of a DPT flag mask on the DDT flags cell. Such errors would not have been detected at compile-time. ) For example, a driver written in C will declare support for 64-bit diagnostic buffer addresses in the following way: ini_ddt_diagbf (&driver$ddt, USER_DIAGBUF_LEN+BUFIO$K_HDRLEN64+DDT$M_DIAGBUF64);

Some drivers allocate diagnostic buffer packets entirely on their own. These drivers can continue to do so without any source changes. Or, at their own discretion, they can convert to the 64-bit diagnostic buffer packet format. For example, the LAN drivers use the $QIO (p5) parameter on some functions to specify a caller's buffer address. The LAN drivers allocate and build a diagnostic buffer packet which contains this caller's address and rely on the I/O postprocessing support to transfer data to the caller's buffer.

(vmsdriver_diagbuf) summarizes the use of diagnostic buffers by drivers on the OpenVMS Alpha masterpack and the planned changes.

(Drivers Supporting Diagnostic Buffers\vmsdriver_diagbuf) (multipage\wide) (4\12\8\8) (Driver\Allocation\64-bit support\Changes required) (SYS$DUDRIVER\$QIO\yes\Declaration only) (\\\) (SYS$TUDRIVER\$QIO\yes\Declaration only) ( \Driver\yes\Simple change to driver source at allocation.) (\\\) (LAN drivers \$QIO\no\Potentially complex or risky changes would have been required. Structures are overlaid on the diagnostic buffer packet.) ( \Driver\no\The driver allocated diagnostic buffers are used by the same routines as the ones allocated by $QIO.) (VMScluster I/O Cache)

The VMScluster I/O Cache VIOC is a virtual block cache for file data transfers. It provides a virtual block data cache for I/O operations that are initiated via the $QIO system service and for page fault read operations. These two paths into VIOC are best considered separately.

Let's first consider the case of VIOC and the $QIO system service. Transfers to and from the VIOC for a $QIO system service call are initiated from the ACP_STD$READBLK and ACP_STD$WRITEBLK FDT routines that support direct I/O to file oriented devices. The VIOC copies data from the caller's buffer into VIOC cache buffers in S0/S1 space. Depending on whether the operation is a read or a write and if the requested data is already in some VIOC cache buffers these memory copies via MOVC3 take place either in FDT context or during I/O postprocessing in the IOC$DIRPOST special kernel AST in the originating process context. The VIOC alters various IRP cells (irp$l_svapte), (irp$l_boff), (irp$l_bcnt), (irp$l_segvbn) such that the actual data transfer takes place between the VIOC cache buffers in S0/S1 space and the I/O device. The caller's buffers are not locked into memory since they are only accessed by the memory copies that are performed at IPL 2.

The VIOC saves the caller's buffer virtual address in the (cpt$l_iova) cell. This cell will be increased to a quadword and renamed to (cpt$q_iova). A few minor modifications to the code in routines CACHE$QIO, READ_ACTION, READMISS_ACTION, and VWRITE in the [SYS]VCC_CACHE.MAR module will be necessary to assure that the full 64-bit buffer address is used and correctly updated. There are no required interface changes to these VIOC routines since the buffer address is either passed indirectly via the CPT structure or via a register parameter to a JSB-interface routine.

Now let's consider the case of VIOC and page fault read operations. Transfers from the VIOC for a page fault are initiated by a call to CACHE$PAGEIO from routine EXE$BUILDPKTR. These transfers are somewhat similar to the ordinary cache transfers initiated by $QIO in that if the request cannot be satisfied immediately from cache then the actual data transfer takes place between the VIOC cache buffers in S0/S1 space and the I/O device. Then the VIOC routines copy the data from the VIOC cache buffers into the faulted page via a memory copy. However, in contrast to a $QIO transfer, there is no user virtual address. Instead, the VIOC routines depend on the value in (irp$l_svapte) to double map the faulted page into S0/S1 space in order to perform the memory copy. Since the page fault handler must continue to provide a usable 32-bit value in (irp$l_svapte) the approach used by VIOC for page faults will continue to work.

Since there is no user virtual address, the routine CACHE$PAGEIO saves the original (irp$l_svapte) value in (cpt$l_iova) while it alters (irp$l_svapte) to point into a CPT structure. The original (irp$l_svapte) value is restored by routine CACHE$IOPOST. These two routines will be changed to use a new cell, (cpt$l_sva), which is named to reflect its actual use and will be overlaid on the (cpt$q_iova) cell. (Driver Changes to Support 64-bit Addresses\driver_func_64)

The principal requirement on device drivers is to support a 64-bit address for data transfers to and from the disk and tape devices. This specifically means that these device drivers must support 64-bit addresses on the virtual, logical, and physical read and write functions. This imposes a secondary requirement that all the port and class driver layers that can be called by the disk and tape drivers must also be able to support these 64-bit transfers.

Most of the read and write functions in the disk and tape drivers are implemented as direct I/O functions that use a small set of system-supplied FDT routines. Thus, as described in (direct_io) most of the impact is confined to the system-supplied I/O support routines and the driver-specific changes are relatively simple and small. The details of the changes to the system-supplied I/O support routines will be described in (io_support_rout).

When port and class drivers are involved, it is important to know when the boundary between the port and class drivers is crossed. For example, for a given SCSI disk device the SCSI disk class driver SYS$DKDRIVER invokes one of a set of platform and interface specific SCSI port drivers SYS$PKxDRIVER. Both the class driver and the port driver are involved in the transfer of raw data I/O via the direct I/O read and write functions. However, the class/port interface boundary is crossed in the start I/O environment of SYS$DKDRIVER after all of the FDT processing has been completed solely by SYS$DKDRIVER. Since these functions are implemented as direct I/O, the impact of 64-bit addresses is confined to FDT processing. Since the FDT processing is confined to SYS$DKDRIVER, the SCSI port drivers will transparently support data transfers to 64-bit buffers for disk I/O without requiring any changes to the port drivers. Note that the SCSI port drivers support the IO$_READLBLK function and contain FDT routines to do so. However, the port drivers use this function to support autoconfiguration and the port driver's FDT routine is not invoked when SYS$DKDRIVER handles an IO$_READLBLK function.

The same situation applies when considering the DSA/MSCP disk and tape drivers. For example, to access a disk served disk over Ethernet in a VMScluster the drivers (SYS$\DUDRIVER), (SYS$\PEDRIVER), and a LAN driver, are involved. But we only need to be concerned with the FDT routines used by the upper most layer, (SYS$\DUDRIVER), where the FDT processing take place. Similarly, if that disk were to be shadowed then (SYS$\SHDRIVER) is inserted as the top layer in the set of involved drivers and we need be concerned only with its FDT routines.

In addition to the above requirement for disk and tape support, a set of guidelines were developed to select which other driver functions should or could support 64-bits. This was done by putting all of the device driver I/O functions into one of 6 categories: (numbered) Direct I/O, raw data transfer

Functions in this category are implemented as direct I/O operations and transfer raw data from the caller's buffer to the device without significant alteration or interpretation of the data.

Usually these functions will support 64-bit addresses. The only area impacted in the driver are the corresponding FDT routines. Direct I/O, control data transfer

Functions in this category are implemented as direct I/O operations and transfer control information from the caller's buffer to the device driver. The device driver usually interprets the data or uses it to control the operation of the device. For example, the IO$_SENSEMODE function on some device drivers, and the IO$_CRESHAD function on SYS$DKDRIVER fall into this category.

Usually these functions will not support 64-bit addresses. In contrast to the raw data transfers, control data transfers tend to be smaller and are invoked less frequently. Thus, there is less need to be able to store such data in a 64-bit addressable region. The only area impacted in the driver are the corresponding FDT routines. However, control data often introduces the problem of embedded 32-bit pointers. Buffered I/O, raw data transfer

Functions in this category are implemented as buffered I/O operations by the device driver but are otherwise the same type of raw data transfer from the caller's buffer as the first category.

Most often these functions will not support 64-bit addresses. However, because these are raw data transfers there are some notable exceptions were 64-bit support will be provided, for example by the mailbox driver. Since these are buffered I/O functions the entire path through the driver is impacted. Thus, a key factor in choosing to provide 64-bit support was the complexity of the required changes. Buffered I/O, control data transfer

Functions in this category are implemented as buffered I/O operations by the device driver but are otherwise the same type of control data transfer from the caller's buffer as the second category.

Usually these functions will not support 64-bit addresses both because they are control operations, for the reasons discussed above, and because they are buffered and, thus, complex as well. The various XQP file control operations like opening a file IO$_ACCESS, deleting a file IO$_DELETE, placing an ACL on a file IO$_MODIFY, are all examples of such functions which will not support 64-bit addresses. In particular there are no required changes to the XQP or any ACP to implement the 64-bit functionality described in this chapter. Control operation, no data transfer, with parameters

Functions in this category control the device and do not transfer any data between a caller's buffer and the device. Since there is no caller's buffer it doesn't matter whether the function is designated as a buffered or direct I/O function. The control operation has parameters that are specified in (p1) through (p6) however these parameters do not point to a buffer. The IO$_SKIPFILE function on the tape drivers is an example of such a function.

Usually these functions will not support 64-bits. Because there are parameters these functions cannot be said to support 64-bits unless they accessed and used the full 64-bits of each of their parameters. Often it would not be difficult to do this, but there is usually little reason do so. Control operation, no data transfer, with no parameters

Functions in this category control the device and do not transfer any data between a caller's buffer and the device. Since there is no caller's buffer it doesn't matter whether the function is designated as a buffered or direct I/O function. In addition, there are no parameters for these functions. The IO$_REWIND function on the tape drivers is an example of such a function.

Since there is no buffer and no parameters it's really moot if this function is declared to support 64-bits. In any event, there are no changes required to code in the driver. The approach used here was that if the driver FDT declaration section was being altered to declare support for 64-bits on some other functions then 64-bit support was also declared on functions in this category.

(func_guidelines) summarizes the above categories of I/O functions.

(Guidelines for 64-bit support by I/O function\func_guidelines) (multipage\wide) (3\27\8) (Function group\64-bit support\Area of impact) (1. Direct I/O, raw data transfer\yes\FDT routines only) (2. Direct I/O, control data transfer\no\FDT routines only) (3. Buffered I/O, raw data transfer\no/yes\Entire path through driver) (4. Buffered I/O, control data transfer\no\Entire path through driver) (5. Control, no data transfer, parameters\no\Entire path but usually simple) (6. Control, no data transfer, no parameters\yes\None)

(driver_64) lists all the drivers on the OpenVMS Alpha masterpack that will contain support for 64-bit addresses.

(Drivers Supporting 64-bit Addresses\driver_64) (multipage\wide) (3\12\13) (Driver\Facility\Description) (SYS$DADDRIVER\[LAD]\Local area client disk) (SYS$DKDRIVER\[SCSI]\SCSI disk class driver) (SYS$DQDRIVER\[SIMCODE]\Mannequin simulator disk) (SYS$DRDRIVER\[DRIVER]\MYLEX DAC960, Astro and Pluto disk) (SYS$DUDRIVER\[DRIVER]\DSA disk class driver) (SYS$DVDRIVER\[DRIVER]\Intel 83077AA Floppy disk) (SYS$ECDRIVER\[LAN]\LANCE PMAD LAN, TC) (SYS$ERDRIVER\[LAN]\DE422 LAN, EISA) (SYS$ESDRIVER\[LAN]\LANCE LAN) (SYS$EWDRIVER\[LAN]\TULIP LAN, PCI) (SYS$EXDRIVER\[LAN]\DEMNA LAN, XMI) (SYS$EZDRIVER\[LAN]\SGEC/INEC/TGEC LAN) (SYS$FADRIVER\[LAN]\FDDI for Futurebus) (SYS$FCDRIVER\[LAN]\DEFZA, DEFTA LAN, TC) (SYS$FRDRIVER\[LAN]\DEFEA LAN, EISA) (SYS$FWDRIVER\[LAN]\DEFPA LAN, PCI) (SYS$FXDRIVER\[LAN]\DEMFA LAN, XMI) (SYS$GKDRIVER\[SCSI]\SCSI generic class driver) (SYS$HCDRIVER\[LAN]\OTTO class ATM) (SYS$ICDRIVER\[LAN]\TMS380 LAN, TC) (SYS$IRDRIVER\[LAN]\TMS380 EISA Token Ring) (SYS$LADDRIVER\[LAD]\Local Area Disk) (SYS$LASTDRIVER\[LAD]\Local Area System Trans) (SYS$LRDRIVER\[DRIVER]\VL82C106 parallel printer driver) (SYS$MADDRIVER\[LAD]\Local area client tape) (MBDRIVER\[SYS]\Mailbox driver) (SYS$MKDRIVER\[SCSI]\SCSI tape class driver) (NLDRIVER\[SYS]\Null device driver) (SYS$PADRIVER\[DRIVER]\SHAC CI and DSSI port driver) (SYS$PDDRIVER\[DRIVER]\RAM disk) (SYS$PEDRIVER\[DRIVER]\NI SCS port driver) (SYS$PIDRIVER\[DRIVER]\NCR 53C710 DSSI port) (SYS$PKCDRIVER\[SCSI]\SCSI NCR 53C94 Port) (SYS$PKEDRIVER\[SCSI]\NCR 53C810 SCSI port) (SYS$PKJDRIVER\[SCSI]\ADAPTEC 1742A SCSI port) (SYS$PKQDRIVER\[SCSI]\QLogic ISP1020 SCSI port) (SYS$PKSDRIVER\[SCSI]\SIMport TC-SCSI port) (SYS$PKTDRIVER\[SCSI]\NCR 53C710 SCSI port) (SYS$PKZDRIVER\[SCSI]\XZA SCSI Port) (SYS$PNDRIVER\[DRIVER]\NPORT SCS port) (SYS$PUDRIVER\[DRIVER]\Laser KDM DSA/SCS port) (SYS$RADRIVER\[SDA]\Remote SDA host) (SYS$SHDRIVER\[SHADOW]\Volume shadowing) (SYS$TUDRIVER\[DRIVER]\MSCP/DSA tape class) (SYS$WPDRIVER\[WATCHPOINT]\Watchpoint driver)

(driver_no64) lists all the drivers on the OpenVMS Alpha masterpack that will not contain any support for 64-bit addresses in the Theta release.

(Drivers Restricted to 32-bit Addresses\driver_no64) (multipage\wide) (3\12\13) (Driver\Facility\Description) (SYS$CTDRIVER\[RTPAD]\CTERM driver) (SYS$FBDRIVER\[TFF]\Terminal fallback driver) (SYS$FTDRIVER\[PTD]\Psuedo terminal driver) (SYS$FYDRIVER\[DUP]\DUP DSA protocol class driver) (SYS$GQADRIVER\[R5_DRIVER]\QVISION driver) (SYS$GTADRIVER\[R5_DRIVER]\DECwindows TX driver for Flamingo) (SYS$GXADRIVER\[R5_DRIVER]\Flamingo CXTurbo aka SFB, aka HX driver) (SYS$GYADRIVER\[R5_DRIVER]\SFB+ aka HX+, aka FFB driver) (SYS$GYBDRIVER\[R5_DRIVER]\Driver for TGA graphics on the PCI bus) (SYS$IEDRIVER\[R5_DRIVER]\DECwindows extension) (SYS$IKBDRIVER\[R5_DRIVER]\DECwindows PCXAL keyboard) (SYS$IKDRIVER\[R5_DRIVER]\DECwindows LKxxx keyboard) (SYS$IMBDRIVER\[R5_DRIVER]\DECwindows PCXAS PS2 mouse) (SYS$IMDRIVER\[R5_DRIVER]\DECwindows VSxxx mouse) (SYS$INDRIVER\[R5_DRIVER]\DECwindows input driver) (SYS$LTDRIVER\[LAT]\LAT terminal driver) (SYS$MSBDRIVER\[DRIVER]\Microsoft Sound Board driver) (NDDRIVER\[NETACP]\DECnet Phase IV DLE MOP support) (NETDRIVER\[NETACP]\DECnet Phase IV) (SYS$OPDRIVER\[OPDRIVER]\Console terminal port driver) (SYS$RTTDRIVER\[DRIVER]\Remote DECnet terminal driver) (SYS$SODRIVER\[DRIVER]\AMD79C30A Audio/ISDN driver) (SYS$THAI_DRIVER\[TTDRVR]\Thai version of SYS$TTDRIVER) (SYS$TTDRIVER\[TTDRVR]\Terminal class driver) (DECW$XTDRIVER\[DECW$XTERMINAL]\X Terminal class driver) (SYS$YRDRIVER\[TTDRVR]\Z85C30 SCC terminal port driver) (SYS$YSDRIVER\[TTDRVR]\PC87312 terminal port driver)

The following are some notable points about the drivers that will be restricted to 32-bit buffer addresses: (unnumbered) The terminal drivers will not support 64-bit addresses. There is little immediate need to support terminal I/O to buffers in a 64-bit address space. In addition, the terminal drivers are complex, perform buffered I/O, and thus 64-bit support would require significant effort. The drivers that are used by the DECwindows MOTIF software will not support 64-bit addresses. The DECnet Phase IV drivers will not support 64-bit addresses. NETDRIVER uses chained CXBs to perform buffered I/O. The code in NETDRIVER is complex and depends significantly on the 32-bit addressability of data via CXBs. The DECnet team believes that its resources would be better used to provide 64-bit support for DECnet Phase V DECnet/OSI rather than Phase IV. The DECnet team will investigate providing support for 64-bit addresses in DECnet/OSI. One possibility is that DECnet/OSI will support 64-bit addresses for applications that use the VCI interface but not for applications that continue to use the Phase IV compatible $QIO interface.

The remaining subsections in this section detail the support for 64-bit addresses by I/O function in each device driver that will contain 64-bit support. These device drivers are listed in alphabetical order.

When an I/O function is listed as supporting 64-bits in the tables in the remaining subsections, the "change" column identifies whether the required source changes are one of the following:

(3\2\8) (\sys\The required changes are confined to system-supplied FDT routines. These changes are described in (io_support_rout).) (\driver\Changes are required to driver routines.) (\none\No source changes are required. Support for 64-bit addresses is transparent.)

All device-dependent parameters that will support 64-bit addresses are marked with a footnote. All functions that must provide support for 64-bit addresses in order to meet the requirement for disk and tape data transfers are also marked with a footnote. Support for 64-bits on all other functions is less critical and somewhat discretionary. (SYS$DADDRIVER)

Because SYS$DADDRIVER is a disk driver, it must provide support for 64-bit addresses on its read and write functions. Since all these functions are direct and are initiated using system-supplied upper-level FDT routines, the only changes necessary to SYS$DADDRIVER are to declare the functions that support 64-bit addresses.

(SYS$DADDRIVER Local area client disk driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (2\Indicates function that is required to support 64-bit addresses.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (acpcontrol \p1,p2,p3,p4,p5\no\buffered\ACPCONTROL_FDT

ACP_STD$MODIFY\) (available \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (create \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (deaccess \p1,p2,p3,p4,p5\no\buffered\ACP_STD$DEACCESS\) (delete \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (modify \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (mount \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MOUNT\) (nop \-\yes\buffered\EXE_STD$ZEROPARM\none) (packack \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (readlblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readpblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readvblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (sensechar \-\yes\buffered\EXE_STD$SENSEMODE\none) (sensemode \-\yes\buffered\EXE_STD$SENSEMODE\none) (setchar \p1(1)\yes\buffered\EXE_STD$SETMODE\sys) (setmode \p1(1)\yes\buffered\EXE_STD$SETMODE\sys) (unload \-\yes\buffered\DAD$UNLOAD_FDT

EXE_STD$LCLDSKVALID\none

none) (writelblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writevblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys)

(SYS$DKDRIVER)

Because SYS$DKDRIVER is a disk driver, it must provide support for 64-bit addresses on its read and write functions. Excluding the IO$_DIAGNOSE function, all the remaining functions that must support 64-bit addresses are direct and are initiated using system-supplied upper-level FDT routines. The only changes necessary to SYS$DKDRIVER for those functions are to declare them as supporting 64-bit addresses.

The upper-level FDT routine for the IO$_DIAGNOSE function, DK_DIAGNOSE, uses support routines that are shared with SYS$GKDRIVER and SYS$MKDRIVER. All the required changes are confined to those common support routines and are described in (gkdriver). No changes are required to the driver-specific DK_DIAGNOSE routine.

Although the IO$_AUDIO function will be restricted to 32-bit addresses, the driver-specific FDT routines in SYS$DKDRIVER that support this function are impacted by the IRPE and MMG_STD$UNLOCK changes. This code uses an IRPE to manage two additional buffers that are locked down. This code will be changed to use a chain of two IRPEs instead of a single IRPE and will use the new EXE_STD$LOCK_ERR_CLEANUP routine. This change is described in detail in (impact_irpe).

The audio support code uses the (irp$l_ast) and (irp$l_astprm) offsets applied to an IRPE for references to driver-specific data. As described in (impact_irp), these references will be changed to use the new IRPE cells defined for this purpose.

(SYS$DKDRIVER SCSI disk class driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (2\Indicates function that is required to support 64-bit addresses.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (acpcontrol \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (audio \p1,p2\no\direct\DK_AUDIO\) (available \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (create \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (creshad \p1,p2,p3,p4\no\direct\DK_CRESHAD\) (deaccess \p1,p2,p3,p4,p5\no\buffered\ACP_STD$DEACCESS\) (delete \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (diagnose \p1(1),p2\yes\direct\DK_DIAGNOSE\driver) (dse \p2,p3\no\buffered\DK_DSE\) (format \p1\no\direct\EXE_STD$ONEPARM\) (modify \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (mount \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MOUNT\) (nop \-\yes\buffered\EXE_STD$ZEROPARM\none) (packack \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (readlblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readpblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readvblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (remshad \-\no\direct\DK_REMSHAD\) (sensechar \-\yes\buffered\EXE_STD$SENSEMODE\none) (sensemode \-\yes\buffered\EXE_STD$SENSEMODE\none) (setchar \p1(1)\yes\direct\EXE_STD$SETMODE\sys) (setmode \p1(1)\yes\direct\EXE_STD$SETMODE\sys) (unload \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (writecheck \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writelblk \p1(1),p2,p3\yes(2)\direct\DK_SHAD_WRITE

ACP_STD$WRITEBLK\none

sys) (writepblk \p1(1),p2,p3\yes(2)\direct\DK_SHAD_WRITE

ACP_STD$WRITEBLK\none

sys) (writevblk \p1(1),p2,p3\yes(2)\direct\DK_SHAD_WRITE

ACP_STD$WRITEBLK\none

sys)

(SYS$DQDDRIVER)

SYS$DQDRIVER is a disk driver that does not ship but is still useful internally. Since all the functions that need to support 64-bit addresses are direct and are initiated using system-supplied upper-level FDT routines, the only changes necessary to SYS$DQDRIVER are to declare the functions that support 64-bit addresses.

(SYS$DQDRIVER Mannequin simulator disk driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (2\Indicates function that is required to support 64-bit addresses.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (acpcontrol \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (available \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (create \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (deaccess \p1,p2,p3,p4,p5\no\buffered\ACP_STD$DEACCESS\) (delete \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (format \p1\no\buffered\EXE_STD$ONEPARM\) (modify \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (mount \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MOUNT\) (nop \-\yes\buffered\EXE_STD$ZEROPARM\none) (packack \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (readlblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readpblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readvblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (sensechar \-\yes\buffered\EXE_STD$SENSEMODE\none) (sensemode \-\yes\buffered\EXE_STD$SENSEMODE\none) (unload \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (writelblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writepblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writevblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys)

(SYS$DRDRIVER)

Because SYS$DRDRIVER is a disk driver, it must provide support for 64-bit addresses on its read and write functions. Since all these functions are direct and are initiated using system-supplied upper-level FDT routines, the only changes necessary to SYS$DRDRIVER are to declare the functions that support 64-bit addresses.

(SYS$DRDRIVER Mylex DAC960 Astro and Pluto disk driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (2\Indicates function that is required to support 64-bit addresses.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (acpcontrol \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (available \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (create \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (creshad \p1,p2,p3,p4\no\direct\DR_FDT_SHAD\) (deaccess \p1,p2,p3,p4,p5\no\buffered\ACP_STD$DEACCESS\) (delete \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (diagnose \p1,p2\no\direct\DR_FDT_DIAGNOSE\) (dse \p2,p3\no\direct\DR_FDT_DSE\) (modify \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (mount \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MOUNT\) (nop \-\yes\direct\EXE_STD$ZEROPARM\none) (packack \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (readlblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readpblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readvblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (remshad \-\no\direct\DR_FDT_SHAD\) (sensechar \-\yes\buffered\EXE_STD$SENSEMODE\none) (sensemode \-\yes\buffered\EXE_STD$SENSEMODE\none) (unload \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (writecheck \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writelblk \p1(1),p2,p3\yes(2)\direct\DR_FDT_WRITEBLK

ACP_STD$WRITEBLK\none

sys) (writepblk \p1(1),p2,p3\yes(2)\direct\DR_FDT_WRITEBLK

ACP_STD$WRITEBLK\none

sys) (writevblk \p1(1),p2,p3\yes(2)\direct\DR_FDT_WRITEBLK

ACP_STD$WRITEBLK\none

sys)

(SYS$DUDRIVER)

Because SYS$DUDRIVER is a disk driver, it must provide support for 64-bit addresses on its read and write functions. Since all these functions are direct and are initiated using system-supplied upper-level FDT routines, these functions can be simply declared to support 64-bit addresses.

As described in (impact_irp), there are 2 source modules in SYS$DUDRIVER that contain ASSUME statements to enforce the commonalty between the IRP and CDRP structures. The ASSUME statements will need to be altered to reflect the changes to these structures.

These are the only source changes that are necessary to SYS$DUDRIVER.

(SYS$DUDRIVER DSA disk class driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (2\Indicates function that is required to support 64-bit addresses.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (acpcontrol \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (available \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (create \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (creshad \p1,p2,p3,p4\no\direct\DU$CRESHAD_FDT\) (deaccess \p1,p2,p3,p4,p5\no\buffered\ACP_STD$DEACCESS\) (delete \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (dse \p2,p3\no\buffered\DU$DSE_FDT\) (format \p1\no\buffered\EXE_STD$ONEPARM\) (modify \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (mount \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MOUNT\) (nop \-\yes\buffered\EXE_STD$ZEROPARM\none) (packack \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (readlblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readpblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readvblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (remshad \-\yes\buffered\DU$REMSHAD_FDT\none) (sensechar \-\yes\buffered\EXE_STD$SENSEMODE\none) (sensemode \-\yes\buffered\EXE_STD$SENSEMODE\none) (setchar \p1(1)\yes\buffered\EXE_STD$SETMODE\sys) (setmode \p1(1)\yes\buffered\EXE_STD$SETMODE\sys) (setprfpath \p1\no\direct\DU$SETPATH\) (unload \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (writecheck \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writelblk \p1(1),p2,p3\yes(2)\direct\DU$SHAD_WCHECK_FDT

ACP_STD$WRITEBLK\none

sys) (writevblk \p1(1),p2,p3\yes(2)\direct\DU$SHAD_WCHECK_FDT

ACP_STD$WRITEBLK\none

sys)

(SYS$DVDRIVER)

Because SYS$DVDRIVER is a disk driver, it must provide support for 64-bit addresses on its read and write functions. Since all these functions are direct and are initiated using system provided upper-level FDT routines, the only changes necessary to SYS$DVDRIVER are to declare the functions that support 64-bit addresses.

(SYS$DVDRIVER Intel 83077AA Floppy disk) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (2\Indicates function that is required to support 64-bit addresses.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (acpcontrol \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (available \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (create \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (deaccess \p1,p2,p3,p4,p5\no\buffered\ACP_STD$DEACCESS\) (delete \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (drvclr \-\yes\buffered\EXE_STD$ZEROPARM\none) (format \p1\no\direct\EXE_STD$ONEPARM\) (modify \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (mount \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MOUNT\) (nop \-\yes\buffered\EXE_STD$ZEROPARM\none) (packack \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (readhead \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readlblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readpblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readtrackd \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readvblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (release \-\yes\buffered\EXE_STD$ZEROPARM\none) (seek \p1\no\buffered\EXE_STD$ONEPARM\) (sensechar \-\yes\buffered\EXE_STD$SENSEMODE\none) (sensemode \-\yes\buffered\EXE_STD$SENSEMODE\none) (setchar \p1(1)\yes\buffered\EXE_STD$SETMODE\sys) (setmode \p1(1)\yes\buffered\EXE_STD$SETMODE\sys) (unload \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (writecheck \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writelblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writepblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writevblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys)

(SYS$ExDRIVER, SYS$FxDRIVER, SYS$HCDRIVER, SYS$IxDRIVER LAN drivers)

The OpenVMS Alpha LAN device drivers provide a direct user-mode application interface for raw data transfers via the $QIO system service. Because these transfers are raw data transfers that are implemented as buffered I/O operations it is desirable that these data transfers support a 64-bit caller's buffer address.

All the existing LAN drivers share the same $QIO FDT support routines: LAN$RECEIVE_FDT and LAN$TRANSMIT_FDT. These routines use the complex chained buffer packets which are described in (chained_bufio). In addition to the changes described in (chained_bufio), these FDT support routines will be modified to use the full 64-bits of the (irp$q_qio_p1) cell when probing the caller's buffer. The LAN$TRANSMIT_FDT routine will build a 64-bit format CXB and will use the full 64-bit caller's buffer address when transferring data from the user buffer into the transmit CXB.

The second interface provided by the LAN drivers is the "altstart" interface. This interface is utilized by the DECnet Phase IV drivers and by the LAN driver's own FDT routines. As discussed in (chained_bufio), the "altstart" interface will be capable of supporting either a 64-bit or 32-bit caller's buffer address on the CXBs that it handles. The LAN driver will exploit the 64-bit capabilities of this interface, but the DECnet Phase IV drivers will continue to rely on the support for the 32-bit CXBs.

The third interface provided by the LAN drivers is the privileged VCI which is discussed in (lan_vci). Because this interface is used by SYS$PEDRIVER for NI VMScluster disk and tape raw data transfers, it must provide support for 64-bit addresses on these data transfers. However, because this interface is a (svapte)-based interface that is callable in system context at IPL 8, this support is transparent to the VCI support code in the LAN drivers.

As described in (impact_irp), the references to the (irp$l_ast) cell in the LAN.MAR module will need to be changed to use (irp$l_iirp_p0) instead.

(SYS$ExDRIVER, SYS$FxDRIVER, SYS$HCDRIVER, SYS$IxDRIVER LAN drivers) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1,p2,p3,p4\no\buffered\LAN$ACCESS\) (readlblk \p1(1),p2,p5\yes\buffered\LAN$RECEIVE_FDT\driver) (readpblk \p1(1),p2,p5\yes\buffered\LAN$RECEIVE_FDT\driver) (readvblk \p1(1),p2,p5\yes\buffered\LAN$RECEIVE_FDT\driver) (writelblk \p1(1),p2,p4,p5(1)\yes\buffered\LAN$TRANSMIT_FDT\driver) (writepblk \p1(1),p2,p4,p5(1)\yes\buffered\LAN$TRANSMIT_FDT\driver) (writevblk \p1(1),p2,p4,p5(1)\yes\buffered\LAN$TRANSMIT_FDT\driver) (sensechar \p1,p2\no\buffered\LAN$SENSEMODE_FDT\) (sensemode \p1,p2\no\buffered\LAN$SENSEMODE_FDT\) (setchar \p1,p2,p3\no\buffered\LAN$SETMODE_FDT\) (setmode \p1,p2,p3\no\buffered\LAN$SETMODE_FDT\)

(SYS$GKDRIVER\gkdriver)

The SYS$GKDRIVER is the generic SCSI class driver. It provides a mechanism by which an application program can control a SCSI device that can not otherwise be controlled by the standard OpenVMS SCSI disk and tape class drivers. This mechanism uses a control structure, the SCSI-2 Diagnose Buffer S2DGB, which is pointed to by the (p1) parameter on the $QIO IO$_DIAGNOSE function.

Although the S2DGB is a control structure, it contains pointers to three data buffers. One of these is used for raw data transfers via direct I/O. Therefore the FDT routines used by SYS$GKDRIVER will be enhanced to support a new 64-bit capable version of the S2DGB structure as well as the existing 32-bit version of this structure. The 64-bit variant of the S2DGB structure will support 64-bit addresses for the SCSI command, data, and sense buffers. In addition, the full 64-bits of the (p1) parameter will be used as a pointer to the caller's S2DGB structure regardless of the type of S2DGB structure being passed.

Simple source code changes are required to the (DKMK$\DIAGNOSE_FDT), (DKMK$\DIAG\NOSE_INIT), and (DKMK$\DIAGNOSE_SIO) routines in the [SCSI]DKMK.C module. The changes to the S2DGB structure are described in (s2dgb_struct). These routines and this data structure are also used to support the IO$_DIAGNOSE function in SYS$DKDRIVER and SYS$MKDRIVER. Thus, those drivers will inherit support for 64-bit addresses on their IO$_DIAGNOSE functions.

These routines in the [SCSI]DKMK.C module use an IRPE and the EXE_STD$READLOCK routine to lock down the sense buffer. A number of simple changes are required to these routines due to the changes to the IRPE structure that are described in (irpe_struct).

No changes are required to the GK_DIAGNOSE upper-level FDT routine. The only changes necessary to driver-specific code in SYS$GKDRIVER is to declare that the IO$_DIAGNOSE function supports 64-bit addresses.

(SYS$GKDRIVER SCSI generic class driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (Function\Arguments\64-bits\Type\FDT routine\Change) (diagnose \p1(1),p2\yes\direct\GK_DIAGNOSE\driver)

(SYS$LADDRIVER)

Because SYS$LADDRIVER is one of the driver layers that is used for local area disk and tape raw data transfers, it must provide support for 64-bit addresses on these data transfers. However, since the disk and tape raw data transfers are direct I/O functions and since this driver layer is invoked in its start I/O or fork environments for those transfers, this capability is transparent to SYS$LADDRIVER and does not require any additional source changes.

All the $QIO functions that are directly issued to this driver are control functions and will not be providing support for 64-bit addresses in the Theta release.

As described in (impact_irp), the references to the (irp$l_ast) and (irp$l_astprm) cells in this driver will need to be changed to use (irp$l_iirp_p0) and (irp$l_iirp_p1) instead. This is the only source change necessary to SYS$LADDRIVER.

(SYS$LADDRIVER Local Area disk server driver) (multipage\wide) (6\8\10\4\6\18) (Function\Arguments\64-bits\Type\FDT routine\Change) (initialize \p1,p2,p3,p4,p6\no\buffered\LAD$INITIALIZE_FDT\) (packack \p1,p2,p3,p6\no\buffered\LAD$LOAD_SERVICE_FDT\) (sensemode \p1,p2,p6\no\buffered\LAD$SENSEMODE_FDT\) (setmode \p1,p2,p6\no\buffered\LAD$SETMODE_FDT\) (unload \p1,p2,p3,p6\no\buffered\LAD$UNLOAD_SERVICE_FDT\)

(SYS$LASTDRIVER)

Because SYS$LASTDRIVER is one of the driver layers that is used for local area disk and tape raw data transfers, it must provide support for 64-bit addresses on these data transfers. However, since the disk and tape raw data transfers are direct I/O functions and since this driver layer is invoked in its start I/O or fork environments for those transfers, there are no required changes to this driver.

All the $QIO functions that are directly issued to this driver are control functions and will not be providing support for 64-bit addresses in the Theta release.

(SYS$LASTDRIVER Local Area System Transport driver) (multipage\wide) (6\8\10\4\6\18) (Function\Arguments\64-bits\Type\FDT routine\Change) (acpcontrol \p1,p2\no\buffered\LAST$ACPCONTROL\) (setmode \p1\no\buffered\LAST$SENSEMODE\) (sensemode \p1,p2,p3\no\buffered\LAST$SETMODE\)

(SYS$LRDRIVER)

SYS$LRDRIVER is the driver for the parallel printer port and the example device driver. For the Theta release, the V6.1 example device driver LRDRIVER.C will be enhanced by another project such that it will have all the features necessary to replace LRDRIVER.MAR.

Because this is the example device driver, LRDRIVER.C will be modified to support 64-bit buffer addresses on all functions. The driver will use the EXE_STD$ALLOC_BUFIO_64 routine to allocate 64-bit BUFIO packets. Additionally, a number of internally used pointers will need to be declared to be 64-bits wide.

(SYS$LRDRIVER parallel printer device driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (Function\Arguments\64-bits\Type\FDT routine\Change) (writelblk \p1(1),p2,p4\yes\buffered\LR$WRITE\driver) (writepblk \p1(1),p2,p4\yes\buffered\LR$WRITE\driver) (writevblk \p1(1),p2,p4\yes\buffered\LR$WRITE\driver) (sensechar \-\yes\buffered\EXE_STD$SENSEMODE\none) (sensemode \-\yes\buffered\EXE_STD$SENSEMODE\none) (setchar \p1(1)\yes\buffered\LR$SETMODE\driver) (setmode \p1(1)\yes\buffered\LR$SETMODE\driver)

(SYS$MADDRIVER)

Because SYS$MADDRIVER is a tape driver, it must provide support for 64-bit addresses on its read and write functions. Since all these functions are direct and are initiated using system-supplied upper-level FDT routines, the only changes necessary to SYS$MADDRIVER are to declare the functions that support 64-bit addresses.

(SYS$MADDRIVER Local area client tape driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (2\Indicates function that is required to support 64-bit addresses.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (acpcontrol \p1,p2,p3,p4,p5\no\buffered\MAD$ACPCONTROL_FDT

ACP_STD$MODIFY\) (available \-\yes\buffered\EXE_STD$ZEROPARM\none) (create \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (deaccess \p1,p2,p3,p4,p5\no\buffered\ACP_STD$DEACCESS\) (delete \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (drvclr \-\yes\buffered\EXE_STD$ZEROPARM\none) (dse \-\yes\buffered\MT_STD$CHECK_ACCESS\none) (erasetape \-\yes\buffered\MT_STD$CHECK_ACCESS\none) (modify \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (mount \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MOUNT\) (nop \-\yes\buffered\EXE_STD$ZEROPARM\none) (packack \-\yes\buffered\EXE_STD$ZEROPARM\none) (readlblk \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (readpblk \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (readpreset \-\yes\buffered\EXE_STD$ZEROPARM\none) (readvblk \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (recal \-\yes\buffered\EXE_STD$ZEROPARM\none) (rereadn \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (rereadp \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (rewind \-\yes\buffered\EXE_STD$ZEROPARM\none) (rewindoff \-\yes\buffered\EXE_STD$ZEROPARM\none) (sensechar \-\yes\buffered\EXE_STD$SENSEMODE\none) (sensemode \-\yes\buffered\EXE_STD$SENSEMODE\none) (setchar \p1(1)\yes\buffered\EXE_STD$SETMODE\sys) (setmode \p1(1)\yes\buffered\EXE_STD$SETMODE\sys) (skipfile \p1\no\buffered\EXE_STD$ONEPARM\) (skiprecord \p1\no\buffered\EXE_STD$ONEPARM\) (spacefile \p1\no\buffered\EXE_STD$ONEPARM\) (spacerecord \p1\no\buffered\EXE_STD$ONEPARM\) (unload \-\yes\buffered\EXE_STD$ZEROPARM\none) (writecheck \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writelblk \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writemark \-\yes\buffered\MT_STD$CHECK_ACCESS\none) (writeof \-\yes\buffered\MT_STD$CHECK_ACCESS\none) (writepblk \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writeret \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writevblk \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys)

(MBDRIVER)

The Mailbox Driver provides an inter-process message passing facility for processes on the same node. Co-operating processes can create or access an existing virtual mailbox device and then transfer data via the $QIO system service. Because these transfers are raw data transfers that are implemented as buffered I/O operations it is desirable that these data transfers support a 64-bit caller's buffer address.

The following changes will be made to the Mailbox Driver to provide support for 64-bit buffer addresses: (numbered) The driver source file, MBDRIVER.B32, will be converted for compilation with BLISS-64 instead of BLISS-32. The BLISS field sets used to define the layout of the mailbox read buffer packet and the mailbox message packet will converted to resemble the 64-bit BUFIO packet format. Currently, these two structures sufficiently resemble the 32-bit BUFIO format such that they can be passed to the buffered I/O postprocessing code. However, because of the differences, MBDRIVER.B64 will not be able to use the new EXE_STD$ALLOC_BUFIO_64 routine. The driver's FDT routines MB$FDT_READ and MB$FDT_WRITE will use the (irp$q_qio_p1) cell instead of (irp$l_qio_p1). Also, the driver will use the (irp$q_qio_p1) cell directly instead of keeping another copy of the caller's buffer address in the (irp$l_media) cell. Currently, MBDRIVER saves the caller's buffer address in the IRP because the OpenVMS VAX IRP does not otherwise contain a copy of the $QIO (p1) parameter. The new (irp$ps_bufio_pkt) name will be used instead of (irp$l_svapte) when a message or read buffer packet are attached to the IRP. The driver's selective cancel routine will reference the full 64-bit (iosb) addresses as described in (qio_iosb) and (impact_irp). The appropriate functions will be declared to support 64-bit addresses.

(MBDRIVER Mailbox driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (Function\Arguments\64-bits\Type\FDT routine\Change) (readlblk \p1(1),p2\yes\buffered\MB$FDT_READ\driver) (readpblk \p1(1),p2\yes\buffered\MB$FDT_READ\driver) (readvblk \p1(1),p2\yes\buffered\MB$FDT_READ\driver) (setmode \p1,p2,p3\no\direct\MB$FDT_SETMODE\) (sensemode \-\yes\direct\MB$FDT_SENSEMODE\none) (writelblk \p1(1),p2\yes\buffered\MB$FDT_WRITE\driver) (writeof \-\yes\buffered\MB$FDT_WRITE\driver) (writepblk \p1(1),p2\yes\buffered\MB$FDT_WRITE\driver) (writevblk \p1(1),p2\yes\buffered\MB$FDT_WRITE\driver)

(SYS$MKDRIVER)

Because SYS$MKDRIVER is a tape driver, it must provide support for 64-bit addresses on its read and write functions. Excluding the IO$_DIAGNOSE function, all the remaining functions that must support 64-bit addresses are direct and are initiated using system-supplied upper-level FDT routines. The upper-level FDT routine for the IO$_DIAGNOSE function, MK_DIAGNOSE, uses support routines that are shared with SYS$DKDRIVER and SYS$GKDRIVER. All the required changes are confined to those common support routines and are described in (gkdriver). No changes are required to the driver-specific MK_DIAGNOSE routine.

Therefore, the only changes necessary to SYS$MKDRIVER are to declare the functions that support 64-bit addresses.

(SYS$MKDRIVER SCSI tape class driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (2\Indicates function that is required to support 64-bit addresses.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (acpcontrol \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (available \-\yes\buffered\EXE_STD$ZEROPARM\none) (create \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (deaccess \p1,p2,p3,p4,p5\no\buffered\ACP_STD$DEACCESS\) (delete \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (diagnose \p1,p2\yes\direct\MK_DIAGNOSE\driver) (drvclr \-\yes\buffered\EXE_STD$ZEROPARM\none) (dse \-\yes\buffered\MT_STD$CHECK_ACCESS\none) (erasetape \-\yes\buffered\MT_STD$CHECK_ACCESS\none) (modify \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (mount \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MOUNT\) (nop \-\yes\buffered\EXE_STD$ZEROPARM\none) (packack \-\yes\buffered\EXE_STD$ZEROPARM\none) (readlblk \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (readpblk \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (readpreset \-\yes\buffered\EXE_STD$ZEROPARM\none) (readvblk \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (recal \-\yes\buffered\EXE_STD$ZEROPARM\none) (rereadn \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (rereadp \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (rewind \-\yes\buffered\EXE_STD$ZEROPARM\none) (rewindoff \-\yes\buffered\EXE_STD$ZEROPARM\none) (sensechar \p1,p2\no\buffered\MK_SENSEMODE\) (sensemode \p1,p2\no\buffered\MK_SENSEMODE\) (setchar \p1(1)\yes\buffered\EXE_STD$SETMODE\sys) (setmode \p1(1)\yes\buffered\EXE_STD$SETMODE\sys) (skipfile \p1\no\buffered\EXE_STD$ONEPARM\) (skiprecord \p1\no\buffered\EXE_STD$ONEPARM\) (spacefile \p1\no\buffered\EXE_STD$ONEPARM\) (spacerecord \p1\no\buffered\EXE_STD$ONEPARM\) (unload \-\yes\buffered\EXE_STD$ZEROPARM\none) (writecheck \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writelblk \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writemark \-\yes\buffered\MT_STD$CHECK_ACCESS\none) (writeof \-\yes\buffered\MT_STD$CHECK_ACCESS\none) (writepblk \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writeret \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writevblk \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys)

(NLDRIVER)

NLDRIVER is the driver for the null device. This driver does not touch the caller's buffer address on any of its functions. Thus, all the NLDRIVER functions can be declared as supporting 64-bit addresses without requiring any other source changes.

(NLDRIVER null device driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (Function\Arguments\64-bits\Type\FDT routine\Change) (readlblk \p1(1),p2\yes\direct\READ\none) (readvblk \p1(1),p2\yes\direct\READ\none) (writelblk \p1(1),p2\yes\direct\WRITE\none) (writeof \-\yes\direct\WRITE\none) (writevblk \p1(1),p2\yes\direct\WRITE\none)

(SYS$PKxDRIVER)

Because the SYS$PKxDRIVER drivers are the port drivers that are used for SCSI disk and tape raw data transfers, they must provide support for 64-bit addresses on these data transfers. However, since the disk and tape raw data transfers are direct I/O functions and since this driver layer is invoked in its start I/O or fork environments for those transfers, there are no required changes to this driver.

The $QIO read functions that are supported directly by this driver are actually control functions used to provide autoconfiguration support for SCSI devices and are not involved in the raw data transfers. However, since these functions utilize the system-supplied EXE_STD$READ upper-level FDT routine they will be inheriting support for 64-bit addresses. Therefore these SYS$PKxDRIVER functions will be declared as supporting 64-bit addresses.

(SYS$PKxDRIVER SCSI port drivers) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (Function\Arguments\64-bits\Type\FDT routine\Change) (nop \-\yes\buffered\EXE_STD$ZEROPARM\none) (readlblk \p1(1),p2,p3,p4\yes\direct\SA$AUTO_FDT

EXE_STD$READ\none

sys) (readpblk \p1(1),p2,p3,p4\yes\direct\SA$AUTO_FDT

EXE_STD$READ\none

sys) (readvblk \p1(1),p2,p3,p4\yes\direct\SA$AUTO_FDT

EXE_STD$READ\none

sys)

(SYS$PEDRIVER)

Because SYS$PEDRIVER is one of the driver layers that is used for NI VMScluster disk and tape raw data transfers, it must provide support for 64-bit addresses on these data transfers. However, since the disk and tape raw data transfers are direct I/O functions and since this driver layer is invoked in its start I/O or fork environments for those transfers, there are no required changes to this driver.

All the $QIO functions that are directly issued to this driver are control functions and will not be providing support for 64-bit addresses in the Theta release.

(SYS$PEDRIVER NI SCS port driver) (multipage\wide) (6\8\10\4\6\18) (Function\Arguments\64-bits\Type\FDT routine\Change) (def_comp \p1,p2,P3\no\buffered\PEM$ANA_COMP_DEF_FDT\) (def_comp_list \p1,p2\no\buffered\PEM$ANA_COMP_LIST_FDT\) (def_comp_list \p1,p2\no\buffered\PEM$ANA_COMP_LIST_FDT\) (start_analysis\-\yes\buffered\PEM$ANA_ENABLE_A...\none) (stop_analysis \-\yes\buffered\PEM$ANA_SHUTDOWN_A...\none) (start_bus \p1\no\buffered\PEM$START_BUS\) (stop_bus \p1\no\buffered\PEM$STOP_BUS\)

(SYS$PADRIVER)

Because SYS$PADRIVER is one of the driver layers that is used for VMScluster disk and tape raw data transfers, it must provide support for 64-bit addresses on these data transfers. However, since the disk and tape raw data transfers are direct I/O functions and since this driver layer is invoked in its start I/O or fork environments for those transfers, there are no required changes to this driver.

All the $QIO functions that are directly issued to this driver are unrelated to the disk and tape raw data transfers and will not be providing support for 64-bit addresses in the Theta release.

(SYS$PADRIVER SHAC CI and DSSI port driver) (multipage\wide) (6\8\10\4\6\18) (Function\Arguments\64-bits\Type\FDT routine\Change) (readpblk \p1,p2\no\buffered\SCSCI$READFDT\) (writepblk \p1,p2\no\buffered\SCSCI$WRITEFDT\)

(SYS$PDDRIVER)

Because SYS$PDDRIVER is a disk driver, it must provide support for 64-bit addresses on its read and write functions. Since all these functions are direct and are initiated using system-supplied upper-level FDT routines, these functions can be simply declared to support 64-bit addresses.

As described in (impact_pfn), some source references in SYS$PDDRIVER to PFN database entry cells will need to be changed to use macros that will be defined specifically for this purpose.

These are the only source changes that are necessary to SYS$PDDRIVER.

(SYS$PDDRIVER RAM disk driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (2\Indicates function that is required to support 64-bit addresses.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (acpcontrol \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (available \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (create \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (deaccess \p1,p2,p3,p4,p5\no\buffered\ACP_STD$DEACCESS\) (delete \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (format \p1\no\buffered\EXE_STD$ONEPARM\) (modify \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (mount \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MOUNT\) (nop \-\yes\buffered\EXE_STD$ZEROPARM\none) (packack \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (readlblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readpblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readvblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (sensechar \-\yes\buffered\EXE_STD$SENSEMODE\none) (sensemode \-\yes\buffered\EXE_STD$SENSEMODE\none) (unload \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (writelblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writepblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writevblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys)

(SYS$PIDRIVER)

Because SYS$PIDRIVER is one of the driver layers that is used for VMScluster disk and tape raw data transfers, it must provide support for 64-bit addresses on these data transfers. However, since the disk and tape raw data transfers are direct I/O functions and since this driver layer is invoked in its start I/O or fork environments for those transfers, there are no required changes to this driver.

All the $QIO functions that are directly issued to this driver are unrelated to the disk and tape raw data transfers and will not be providing support for 64-bit addresses in the Theta release.

(SYS$PIDRIVER NCR 53C710 DSSI port driver) (multipage\wide) (6\8\10\4\6\18) (Function\Arguments\64-bits\Type\FDT routine\Change) (readpblk \p1,p2\no\buffered\SCSCI$READFDT\) (writepblk \p1,p2\no\buffered\SCSCI$WRITEFDT\)

(SYS$PUDRIVER)

Because SYS$PUDRIVER is the port driver that is used for KDM disk and tape raw data transfers, it must provide support for 64-bit addresses on these data transfers. However, since the disk and tape raw data transfers are direct I/O functions and since this driver layer is invoked in its start I/O or fork environments for those transfers, there are no required changes to this driver.

All the $QIO functions that are directly issued to this driver are control functions that do not transfer any data and do not have any parameters. Therefore, these functions can be simply declared as supporting 64-bit addresses.

(SYS$PUDRIVER Laser KDM/SCS port driver) (multipage\wide) (6\8\10\4\6\18) (DAG\Indicates function that is required to support 64-bit addresses.) (Function\Arguments\64-bits\Type\FDT routine\Change) (initialize \-\yes\buffered\EXE_STD$ZEROPARM\none) (setchar \-\yes\buffered\EXE_STD$ZEROPARM\none) (stop \-\yes\buffered\EXE_STD$ZEROPARM\none)

(SYS$PNDRIVER)

Because SYS$PNDRIVER is one of the driver layers that is used for VMScluster disk and tape raw data transfers, it must provide support for 64-bit addresses on these data transfers. However, since the disk and tape raw data transfers are direct I/O functions and since this driver layer is invoked in its start I/O or fork environments for those transfers, there are no required changes to this driver.

All the $QIO functions that are directly issued to this driver are unrelated to the disk and tape raw data transfers and will not be providing support for 64-bit addresses in the Theta release.

(SYS$PNDRIVER NPORT SCS driver) (multipage\wide) (6\8\10\4\6\18) (Function\Arguments\64-bits\Type\FDT routine\Change) (readpblk \p1,p2\no\buffered\SCSNP$READFDT\) (writepblk \p1,p2\no\buffered\SCSNP$WRITEFDT\)

(SYS$RADRIVER)

The SYS$RADRIVER is the driver used by Remote SDA on the analysis host system. Although this driver does not ship with the OpenVMS kit, the Remote SDA capability is an important diagnostic tool internally.

The Remote SDA capability is implemented by code in [DRIVER]RADRIVER.MAR, [CLUSTER]REMOTE_SDA.MAR, and [SDA]QAST.MAR. These modules function together in this way. (unnumbered) The SDA utility runs on the analysis host system. Code in the [SDA]QAST.MAR module requests the contents of a range of virtual addresses for a specific process on the remote system by issuing a $QIO request to SYS$RADRIVER on the analysis host system. SYS$RADRIVER sends an SCS message to the Remote SDA SYSAP on the remote system. The Remote SDA SYSAP is implemented by the [CLUSTER]REMOTE_SDA.MAR module within the SYS$SCS execlet. This module obtains the contents of the desired virtual addresses within the address space of the specified process and sends the data back to SYS$RADRIVER on the analysis host system. SYS$RADRIVER returns the data to SDA and completes the $QIO request.

In particular, the code in [CLUSTER]REMOTE_SDA.MAR is affected by the privitazation of the process page tables. Therefore, source changes are necessary to maintain the existing functionality that supports 32-bit virtual addresses. A large portion of this capability will be implemented in the new MMG_STD$GET_PTE_FOR_VA routine.

In addition, the modules supporting the Remote SDA capability will be enhanced to support 64-bit virtual addresses. This will require a change in the Remote SDA-specific message formats between the analysis host and remote systems and a change in the Remote SDA protocol level number. As a result, a Theta analysis host will be required to remotely analyze a Theta system. Moreover, a Theta analysis host will not be able to analyze a pre-Theta system.

Finally, because it is extremely simple to do so, the functions implemented by SYS$RADRIVER will support 64-bit addresses for the local buffer on the analysis host system.

(SYS$RADRIVER Remote SDA driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (2\The p3 parameter specifies a 64-bit address on the remote system.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1(1),p2\yes\direct\RA_ACCESS_FDT\driver) (readpblk \p1(1),p2,p3(2),p4\yes\direct\RA_READ_FDT\driver)

(SYS$SHDRIVER)

Because SYS$SHDRIVER is a disk driver used to implement disk shadowing, it must provide support for 64-bit addresses on its read and write functions. Since all these functions are direct and are initiated using system-supplied upper-level FDT routines, these functions can be simply declared to support 64-bit addresses.

The shadowing driver makes copies of the write IRPs that are delivered to its start I/O routine. These cloned IRPs are then queued to the appropriate drivers for the member units in the shadow set. These cloned IRPs all use the same (irp$l_svapte) value as the master IRP. For example, the (irp$l_svapte) in each of the cloned IRPs may point to the (irp$q_pte_vector) in the master IRP, or point into a DIOBM structure that was allocated for the master IRP. The IRPs that are cloned by the shadowing driver bypass the normal buffer unlock that is performed during I/O postprocessing of direct I/O requests. The buffer is unlocked only when the master IRP is sent on to I/O postprocessing after all the cloned requests have been completed. Thus, the potential shared use of a DIOBM structure or a temporary PTE window by multiple shadowing IRPs does not require any changes to the existing code in SYS$SHDRIVER or I/O postprocessing.

As described in (impact_irp), the references to the (irp$l_ast), (irp$l_astprm), and (irp$l_iosb) cells in 4 source modules in SYS$SHDRIVER will need to be changed. The (irp$l_mv_tmo), (irp$l_iirp_p1), and (irp$l_cln_wle) cells will be used instead as indicated.

These are the only source changes that are necessary to SYS$SHDRIVER.

(SYS$SHDRIVER volume shadowing disk driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that will support a 64-bit address.) (2\Indicates function that is required to support 64-bit addresses.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (acpcontrol \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (addshad \p2,p3,p4\no\buffered\SH$ADDSHAD_FDT\) (available \-\yes\buffered\SH$AVAIL_FDT

EXE_STD$LCLDSKVALID\none

none) (copyshad \p2,p3,p4\no\direct\SH$COPYSHAD_FDT\) (create \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (creshad \p1,p2,p3,p4\no\buffered\SH$CRESHAD_FDT\) (deaccess \p1,p2,p3,p4,p5\no\buffered\ACP_STD$DEACCESS\) (delete \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (dse \p2,p3\no\buffered\SH$DSE_FDT\) (modify \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (mount \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MOUNT\) (nop \-\yes\buffered\EXE_STD$ZEROPARM\none) (packack \-\yes\buffered\EXE_STD$LCLDSKVALID\none) (readlblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readpblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (readvblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$READBLK\sys) (remshad \-\yes\buffered\SH$REMSHAD_FDT\none) (sensechar \-\yes\buffered\SH$SENSECHAR_FDT

EXE_STD$SENSEMODE\none

none) (sensemode \-\yes\buffered\EXE_STD$SENSEMODE\none) (setchar \p1(1)\yes\buffered\EXE_STD$SETMODE\sys) (setmode \p1(1)\yes\buffered\EXE_STD$SETMODE\sys) (shadmv \-\yes\buffered\SH$SHADMV_FDT\none) (unload \-\yes\buffered\SH$AVAIL_FDT

EXE_STD$LCLDSKVALID\none

none) (upshad \p1\no\buffered\SH$UPSHAD_FDT\) (writecheck \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writelblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writevblk \p1(1),p2,p3\yes(2)\direct\ACP_STD$WRITEBLK\sys)

(SYS$TUDRIVER)

Because SYS$TUDRIVER is a tape driver, it must provide support for 64-bit addresses on its read and write functions. All these functions are direct and, with the exception of the IO$_READLCHUNK and IO$_WRITELCHUNK functions, rely solely on system-supplied upper-level FDT routines. The FDT routines for the these two functions, TU$READLCHUNK and TU$WRITELCHUNK simply retrieve the buffer address in (irp$l_qio_p1) and call EXE_STD$READLOCK or EXE_STD$WRITELOCK. Thus, a simple source change is necessary to the driver-specific FDT routines TU$READLCHUNK and TU$WRITELCHUNK to retrieve the full 64-bit buffer address from (irp$q_qio_p1). Once this change is made, these functions can be simply declared to support 64-bit addresses.

As described in (impact_irp), there are 2 source modules in SYS$TUDRIVER that contain ASSUME statements to enforce the commonalty between the IRP and CDRP structures. The ASSUME statements will need to be altered to reflect the changes to these structures. In one of these modules, the references to the (cdrp$l_astprm) cell will need to be changed to use the (cdrp$l_hrb) cell name.

These are the only source changes that are necessary to SYS$TUDRIVER.

(SYS$TUDRIVER MSCP/DSA tape class driver) (multipage\wide) (6\8\10\4\6\18) (1\Device-dependent parameter that supports a 64-bit address.) (2\Indicates function that is required to support 64-bit addresses.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (acpcontrol \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (available \-\yes\buffered\EXE_STD$ZEROPARM\none) (create \p1,p2,p3,p4,p5\no\buffered\ACP_STD$ACCESS\) (deaccess \p1,p2,p3,p4,p5\no\buffered\ACP_STD$DEACCESS\) (delete \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (display \p1,p3,p4\no\buffered\DUTU$DISPLAY\) (dse \-\yes\buffered\MT_STD$CHECK_ACCESS\none) (erasetape \-\yes\buffered\MT_STD$CHECK_ACCESS\none) (flush \-\yes\buffered\EXE_STD$ZEROPARM\none) (freecap \-\yes\buffered\EXE_STD$ZEROPARM\none) (modify \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MODIFY\) (mount \p1,p2,p3,p4,p5\no\buffered\ACP_STD$MOUNT\) (nop \-\yes\buffered\EXE_STD$ZEROPARM\none) (packack \-\yes\buffered\EXE_STD$ZEROPARM\none) (readlblk \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (readlchunk \p1(1),p2,p5,p6\yes(2)\direct\TU$READLCHUNK

EXE_STD$READLOCK\driver

sys) (readpblk \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (readvblk \p1(1),p2\yes(2)\direct\ACP_STD$READBLK\sys) (recal \-\yes\buffered\EXE_STD$ZEROPARM\none) (rewind \-\yes\buffered\EXE_STD$ZEROPARM\none) (rewindoff \-\yes\buffered\EXE_STD$ZEROPARM\none) (sensechar \p1,p2\no\buffered\TU$SENSEMODE\) (sensemode \p1,p2\no\buffered\TU$SENSEMODE\) (setchar \p1,p2\no\buffered\TU$SETMODE\) (setmode \p1,p2\no\buffered\TU$SETMODE\) (skipfile \p1\no\buffered\EXE_STD$ONEPARM\) (skiprecord \p1\no\buffered\EXE_STD$ONEPARM\) (spacefile \p1\no\buffered\EXE_STD$ONEPARM\) (spacerecord \p1\no\buffered\EXE_STD$ONEPARM\) (unload \-\yes\buffered\EXE_STD$ZEROPARM\none) (writecheck \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writelblk \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writelchunk \p1(1),p2,p5,p6\yes(2)\direct\TU$WRITELCHUNK

EXE_STD$WRITELOCK\driver

sys) (writemark \-\yes\buffered\MT_STD$CHECK_ACCESS\none) (writeof \-\yes\buffered\MT_STD$CHECK_ACCESS\none) (writepblk \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys) (writevblk \p1(1),p2\yes(2)\direct\ACP_STD$WRITEBLK\sys) (SYS$WPDRIVER)

The SYS$WPDRIVER is the watchpoint driver. Because the ability to set watchpoints in S2 space is likely to be an important tool used to debug privileged code that makes first use of S2 space, it is desirable that this driver and its associated WP utility provide support of 64-bit addresses in S2 space. These changes are briefly summarized here.

First, the watchpoint user interface utility, WP, will need to be changed to accept and handle a 64-bit address. This utility is written mostly in C.

The watchpoint address is passed in the $QIO (p3) parameter. The driver-specific FDT routines will be modified to use the full 64-bits of the (p3) parameter directly and will no longer copy it to the (irp$l_media) cell.

Various watchpoint data structures will need to be changed to contain 64-bit addresses, including the 8 (wpcb$l_fld_adrN) cells and the (wptte$l_field) cell. References to these cells, and to the values derived from them, will need to be made 64-bit safe in 14 driver-specific routines.

The Watchpoint Control Block WPCB and the Watchpoint Trace Table Entry WPTTE structures are passed back to the WP utility via the IO$_RDSTATS function. As a result, various references to these structures made by code in the utility will also need to be made 64-bit safe.

The watchpoint driver includes a routine that replaces the system's standard access violation exception handler that is pointed to via the SCB. A number of changes will be necessary to this routine, including 64-bit safe handling of the virtual address, tests for system space addresses, and the calculation of a PTE address from a virtual address.

Although the watchpoint driver needs to be capable of supporting a 64-bit watchpoint address, there is no immediate need for allowing a 64-bit buffer addresses on the $QIO (p1) parameter with the IO$_RDSTATS function.

(SYS$WPDRIVER watchpoint driver) (multipage\wide) (6\8\10\4\6\18) (1\The p3 parameter specifies a 64-bit watchpoint address.) (Function\Arguments\64-bits\Type\FDT routine\Change) (access \p2,p3(1)\yes\buffered\WP$CREATE_DELETE_WP_FDT\driver) (deaccess \p2,p3(1)\yes\buffered\WP$CREATE_DELETE_WP_FDT\driver) (rdstats \p1,p2,p3(1)\no\buffered\WP$RDSTATS_WP_FDT\driver)

(XQP File System)

The Extended QIO Processor (XQP) implements the ODS-2 compliant file system on OpenVMS. The XQP is responsible for servicing file control requests, like file access, creation, deletion, etc. As discussed in (complex_bufio) and (driver_func_64), these XQP control functions will remain restricted to 32-bit buffer addresses for the Theta release.

The XQP is also involved in the handling of virtual read and write requests for data within files. However, in almost all cases, the XQP does not deal with the caller's data buffer. Usually, the XQP only assures that the relevant extents of the file are mapped and allows the I/O request to be dispatched to the relevant device driver. The only exception is the handling of a read beyond the high-water mark in a file. In this case the XQP zeroes the portion of the caller's buffer that goes beyond the file high-water mark point. Therefore, the only change that is necessary to the XQP is to enable it to zero buffers in a 64-bit address space.

Specifically, the XQP will be changed in the following ways: (numbered) The ZERO_USER_BUFFER routine is the relevant XQP routine. It is the only routine in the ZEROBUF.B32 module. In order to handle a 64-bit buffer address this module will need to be adapted for compilation by Bliss-64 and renamed ZEROBUF.B64. Because this module is very simple the work required for this is minimal. The ZERO_USER_BUFFER routine is called from the RWVB.B32 module. The setup for this call contains the only reference to the (irp->irp$l_qio_p1) cell within the XQP. Because the RWVB.B32 module is significantly larger and has dependencies on many require files it would require a significant effort to adapt for Bliss-64. Therefore, the interface to the ZERO_USER_BUFFER routine will be changed such that the reference to the (irp->irp$q_qio_p1) cell can be moved from the RWVB.B32 module to the ZEROBUF.B64 module. The RWVB.B32 module will remain in Bliss-32.

The existing interface: ZERO_USER_BUFFER ( .IRP, .BUFFER, .BYTE_COUNT)

will change to: ZERO_USER_BUFFER ( .IRP, .BYTE_OFFSET, .BYTE_COUNT)

The new version of the ZERO_USER_BUFFER routine will obtain the buffer start address from (irp$q_qio_p1) and will add the value of the BYTE_OFFSET parameter to compute the starting location of the region that needs to be cleared. Since the interface to the ZERO_USER_BUFFER routine is already architecture-dependent this change is easily done. (Spiralog Dollar File System)

The Spiralog File System, formerly known as the Dollar File System, for OpenVMS Alpha is currently under development and will be shipping its first version based on the Theta release.

The Spiralog File System will include emulation of the XQP $QIO interface via the driver SYS$FSDRIVER. Because this is a disk driver, it will need to support 64-bit addresses on its read and write functions. Since the internal interfaces were designed with 64-bit addresses in mind, this is not expected to be difficult. The 64-bit Project engineering team will work with the Spiralog engineering team to ensure that SYS$FSDRIVER includes the necessary 64-bit support for the Theta release.

Secondly, a future version of the Spiralog File System expects to take advantage of the 64-bit address space support by placing the Spiralog cache in S2 space. The 64-bit Project engineering team will work with the Spiralog engineering team to ensure that the necessary internal I/O interfaces are provided to facilitate the use of S2 space by Spiralog. (Fast I/O Services for TP)

A set of new I/O services $IO_PERFORM, etc. are currently under development for the Theta release. Because these services are tailored for the needs of transaction processing and are not as general purpose as the $QIO service, they will consume significantly less CPU time.

These new services will support 64-bit addresses as well. Some of this support will be inherited directly from the changes described in this chapter since the new services will use IRPs and some of the existing I/O support routines.

Additional information about these new services can be found in their functional and design specification: STAR::DOCD$:[EVMS.PROJECT_DOCUMENTS]FS-FASTIO.PS (Data Structure Changes\data_struct)

This section contains a detailed description of the I/O data structure changes that are required to implement $QIO and device driver support for I/O into 64-bit addressable regions.

The data structures are listed in alphabetical order. However, the individual structure members are listed in the order in which they are defined within each data structure. Note however, that the following sections only describe new or changed structure members. Existing unchanged members are not described. In addition, unused or "fill" structure members which might be added to obtain natural alignment are not listed. Thus you can not use the following descriptions to calculate the precise memory layout of the structures. However, you can assume that any new or changed structure members will be naturally aligned within the structure. (Pointer Size Conventions)

Any unqualified use of the term (pointer\italic) implies a 32-bit pointer. All 64-bit pointers will be explicitly identified as either a 64-bit or quadword pointer.(1\This chapter includes a short discussion of the pointer size conventions because understanding the data structure and routine changes in (data_struct) and (io_support_rout) depends on it. A broader discussion of the 64-bit internal programming conventions is contained in (internal_api_chapter).)

A new C compiler pragma will control the pointer size. To facilitate the use of 64-bit pointers, a new header file, (far_pointers.h) in SYS$STARLET_C.TLB, will define types for 64-bit pointers to the intrinsic C data types. The following example illustrates how the (far_pointers.h) header file will define these types: #pragma required_pointer_size save /* Save current pointer size */ #pragma required_pointer_size long /* Pointers are 64-bits */ typedef int * INT_PQ; /* 64-bit pointer to 32-bit int */ typedef void * VOID_PQ; /* 64-bit pointer to arbitrary data */ typedef void ** VOID_PPQ; /* 64-bit pointer to VOID_PQ */ typedef void (*VOID_FUNC_PQ)(); /* 64-bit ptr to function that returns void*/ #pragma required_pointer_size restore /* Return to previous pointer size */

By convention, various header files in SYS$LIB_C.TLB define types that correspond to the OpenVMS Alpha internal data structures. For example, (ptedef.h) defines the PTE type for the structure that reflects the contents of Page Table Entries. The definition of a 64-bit pointer type will be added for each OpenVMS Alpha internal data structure that is likely to be accessed using a 64-bit pointer. This definition will be included in the SDL-generated header file that defines the data structure type. For example, the definition of the PTE_PQ type, for a 64-bit wide pointer to a PTE, will be included in the (ptedef.h) header file: typedef struct _pte { ... } PTE; /* Current definition of PTE type */ #pragma required_pointer_size save /* Save current pointer size */ #pragma required_pointer_size long /* Pointers are 64-bits */ typedef PTE * PTE_PQ; /* 64-bit pointer to a PTE */ typedef PTE ** PTE_PPQ; /* 64-bit pointer to a PTE_PQ */ #pragma required_pointer_size restore /* Return to previous pointer size */

Thus, in the data structures and system routines sections that follow, (PTE *x) declares (x) to be a 32-bit wide pointer to a PTE and (PTE_PQ y) declares (y) to be a 64-bit wide pointer to a PTE. (BOD\bod_struct)

This section describes the additions and changes to cells in the Buffer Object Descriptor BOD structure.

(BOD Structure Changes) (3\14\10) (Field\Type\Comments) (bod$v_s2_window\bit\ A bit equal to BOD$M_S2_WINDOW in the (bod$l_flags) cell.

When this bit is clear, the buffer object is mapped into the S0/S1 portion of system space and the (bod$ps_svapte) and (bod$l_basesva) cells are valid.

When this bit is set, the buffer object is mapped into the S2 portion of system space and the (bod$pq_va_pte) and (bod$pq_basesva) cells are valid.) (bod$pq_basepva\VOID_PQ\ Process virtual address for the start of the buffer object. This cell replaces the (bod$l_basepva) cell.) (bod$l_basepva\-\ This cell will be removed. It will be replaced by the (bod$pq_basepva) cell.) (bod$pq_basesva\VOID_PQ\ System virtual address for the start of the buffer object. This cell is overlaid on the (bod$l_basesva) cell and this use is valid only if BOD$M_S2_WINDOW is set in (bod$l_flags).) (bod$pq_va_pte\PTE_PQ\ Virtual address for the first system PTE that maps the buffer object. This cell is overlaid on the (bod$ps_svapte) cell and this use is valid only if BOD$M_S2_WINDOW is set in (bod$l_flags).)

(BUFIO\bufio_struct)

The existing 32-bit Buffered I/O BUFIO packet format will continue to be supported. In addition, a new 64-bit BUFIO packet format will be supported. These BUFIO packets are "self identifying." That is, it is possible to distinguish a 32-bit from a 64-bit format BUFIO packet from information in the packet.

Although the structure type code DYN$C_BUFIO is defined and there is an expected layout for the header of buffered I/O packet there currently is no formal definition of a structure. Existing code in drivers and IOCIOPOST.MAR uses numeric constants as offsets.

The existing 32-bit BUFIO packet will be formally defined along with a new 64-bit BUFIO packet format. The 64-bit BUFIO structure format will also be used for 64-bit diagnostic buffer packets.

(BUFIO packet) (3\14\10) (Field\Type\Comments) (bufio$ps_pktdata\void *\ Pointer to the buffered data within the packet.) (bufio$ps_uva32\void *\ 32-bit pointer to user's address space. On a read function data is transfered from that user virtual address to the buffer packet during FDT processing. On a write function data is transfered to that user virtual address from the buffer packet during I/O Postprocessing. If this cell contains the value BUFIO$K_64 -1 then the pointer to the user buffer is in (bufio$pq_uva64).) (bufio$w_size\unsigned short\Size of the BUFIO packet in bytes.) (bufio$b_type\unsigned char\Nonpaged pool packet type code, DYN$C_BUFIO) (BUFIO$K_HDRLEN32\constant\ Size in bytes of the minimal buffered I/O packet header with a 32-bit user virtual address 12.) (bufio$pq_uva64\VOID_PQ\ 64-bit pointer to user's address space. On a read function data is transfered from that user virtual address to the buffer packet during FDT processing. On a write function data is transfered to that user virtual address from the buffer packet during I/O Postprocessing. This cell contains a valid address only if the (bufio$ps_uva32) cell contains the value BUFIO$K_64 -1.) (BUFIO$K_HDRLEN64\constant\ Size in bytes of the minimal buffered I/O packet header with a 64-bit user virtual address 24.)

(CDRP)

The Class Driver Request Packet CDRP structure contains an embedded IRP that is accessed with negative offsets from the origin of the CDRP at the (cdrp$l_fqfl) cell. Therefore, all the changes to the IRP structure that are described in (irp_struct) will be reflected in the CDRP as well.

(Additional CDRP Changes) (3\14\10) (Field\Type\Comments) (cdrp$l_hrb\HRB *\ This cell corresponds to the existing (irp$l_hrb) cell. To match its IRP counterpart, this cell will be overlaid on the low-order longword of the (cdrp$q_acb64_astprm) cell. The definition of this cell will be added to the CDRP to obviate the need for local definitions in various modules. )

(CPT)

This section describes changes to cells in the Cache I/O Page Table CPT structure that is used by the VMScluster I/O Cache facility.

(CPT Structure Changes) (3\14\10) (Field\Type\Comments) (cpt$q_iova\VOID_PQ\ Virtual address of caller's buffer for an I/O request using the VBN cache. This cell will replace (cpt$l_iova). Other cells in the CPT will be moved around in order to naturally align the (cpt$q_iova) cell and to utilize existing fill space in the CPT structure.) (cpt$l_iova\-\ This cell will be removed. It will be replaced by the (cpt$q_iova) cell.) (cpt$l_sva\PTE *\ Saved value from (irp$l_svapte) when doing a page I/O read from cache. Currently, the (cpt$l_iova) cell is used for this purpose. Since use of this cell is mutually exclusive with (cpt$q_iova), these cells will be in a union.)

(CXB\cxb_struct)

The CXB structure defines the format of entries that are linked together to build a complex chained buffered I/O packet. The use of complex chained buffered I/O packets is described in (chained_bufio).

The CXB structure will be enhanced such that it can be used by existing code with no source changes to support a 32-bit caller's buffer address. However, the same enhanced CXB structure can be used to support a 64-bit caller's buffer address as well.

(CXB Structure Changes) (3\14\10) (Field\Type\Comments) (cxb$ps_pktdata\void *\ Pointer to the buffered data within the packet. This cell will be overlaid on the existing (cxb$l_fl) cell to reflect its current alternate use.) (cxb$ps_uva32\void *\ 32-bit pointer to user's address space. If this cell contains the value BUFIO$K_64 -1 then the pointer to the user buffer is in (cxb$pq_uva64). This cell will be overlaid on the existing (cxb$l_bl) cell to reflect its current alternate use.) (cxb$pq_uva64\VOID_PQ\ 64-bit pointer to user's address space. This cell contains a valid address only if the (cxb$ps_uva32) cell contains the value BUFIO$K_64 -1. This cell will be inserted as the last aligned quadword just before the end of the standard CXB header which is CXB$K_LENGTH bytes long.)

(DCBE\dcbe_struct)

The DCBE structure is the Data Chain Block that is used by the OpenVMS LAN driver VMS Communications Interface VCI. A DCBE is used to connect to a VCRP all or part of the data to be transmitted. A chain of DCBEs is used when the data is contained in more than one discontiguous buffer in virtual memory.(1\The DCBE should not be confused with the similarly named DCB structure. The DCB is used internally by the DECnet Phase IV NETDRIVER. As described in (impact_svaptechk), the dcb$l_svapte cell value will be derived from the irp$l_svapte cell in the associated IRP and will rely on the DIOBM that's embedded in the IRP. For this reason there is no need for an embedded DIOBM in the DCB structure.)

There are two mutually exclusive methods that a DCBE can use to identify the start of the buffer: (numbered) When the (dcbe$l_buffer_address) cell contains a zero, the buffer address is specified by the (dcbe$l_svapte) and (dcbe$l_boff) cells. A fixed-size primary DIOBM structure will be added to the DCBE. This embedded DIOBM structure is available for use by an upper-level VCM if it needs to derive a 32-bit SVAPTE from a 64-bit VA_PTE for the PTEs that map the buffer. The lower-level VCM will not alter this embedded DIOBM nor make any assumptions about it. When the (dcbe$l_buffer_address) cell contains the a non-zero value, this value is the system virtual address of the buffer. This method will remain unchanged.

Because a VCRP can also be used as a DCBE, the named DCBE cells must be at the same offsets as their VCRP counterparts. Therefore, DCBE changes are reflected in the VCRP and changes to the common portion of the VCRP are reflected in the DCBE.

In addition, SYS$PEDRIVER overlays a DCBE with the (vcrp$t_internal_stack) area within the VCRP. Therefore, an increase in the size of the DCBE must be reflected by a corresponding increase in the size of the internal stack area within the VCRP.

(DCBE Structure Changes) (3\14\10) (Field\Type\Comments) (dcbe$l_reserved\int32[13]\This existing vector of 6 filler longwords will be increased to 13 fill longwords to reflect the increased size of the common portion of the VCRP. The common portion of the VCRP will be increased to accommodate either an ACB64 or ACB structure. ) (dcbe$pq_buffer_addr64\VOID_PQ\ 64-bit buffer address. This cell is available for use by upper-level VCMs only. Note that this cell does not replace the (dcbe$l_buffer_address) cell which will continue to be used by lower-level VCMs. The (dcbe$pq_buffer_addr64) cell will be added after the (dcbe$l_bcnt) cell. ) (dcbe$r_diobm\DIOBM\ Embedded fixed-size primary "direct I/O buffer map" structure. This DIOBM structure is available for use by upper-level VCMs that need to lock down a buffer and provide a value for the (dcbe$l_svapte) cell. This structure will be added just before the end of the DCBE header. )

(DDT)

This section describes the changes to the driver Driver Dispatch Table DDT structure.

(DDT Changes) (3\14\10) (Field\Type\Comments) (ddt$w_diagbuf\short\This is an existing cell in the DDT. However, the highest-order bit of this 16-bit cell will now be used as a flag to select the diagnostic buffer packet format that will be allocated by the $QIO system service.) (DDT$M_DIAGBUF64\constant\When this bit mask value is set in the (ddt$w_diagbuf) cell, the $QIO system service will build a 64-bit format diagnostic buffer packet for this driver.)

(DIOBM\diobm_struct)

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 will be 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: (numbered) 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 the above methods yield 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. It is expected that most primary DIOBM structures will be fixed-sized and embedded in other structures. For example, the IRP, IRPE, VCRP, and DCBE structures will 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.

(Primary DIOBM structure) (3\14\10) (Field\Type\Comments) (diobm$ps_aux_diobm\DIOBM *\ This 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 will deallocate this DIOBM structure. The routine IOC_STD$FILL_DIOBM will set this bit on any secondary DIOBM structure that it may allocate. The routine IOC_STD$CREATE_DIOBM will set 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$pq_ptew_va_spte) contains the 64-bit addresses of the first SPTE allocated for the window, (diobm$l_pte_count) contains the count of SPTEs that have been allocated, and the (diobm$ps_ptew_s0va) cell contains the S0 space 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 will only be used by the full-checking versions of the routines in the IO_ROUTINES_MON.EXE execlet. This flag will be set by the IOC_STD$FILL_DIOBM and IOC_STD$CREATE_DIOBM routines and will be cleared by the IOC_STD$RELEASE_DIOBM routine. Prior to setting the flag, the IOC_STD$FILL_DIOBM routine will check 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 will declare 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$pq_ptew_va_spte\PTE_PQ\ The 64-bit virtual address in page table space of the first SPTE allocated for the window onto the direct I/O buffer PTEs. This cell is used to deallocate the SPTEs when the PTE window is released. This cell is overlaid on a portion of (diobm$q_pte_vector) since their use is mutually exclusive. This cell is valid if and only if DIOBM$M_PTE_WINDOW in (diobm$l_flags) is set.) (diobm$ps_ptew_s0va\void *\ The S0/S1 space virtual address that is mapped by the PTE whose address is contained in (diobm$pq_ptew_va_spte). This cell is used to invalidate any translation buffer entries for this PTE window when it is released. This cell is overlaid on a portion of (diobm$q_pte_vector) since their 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.)

(Secondary DIOBM structure) (3\14\10) (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 will deallocate 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.)

(FDT)

This section describes the additions to the driver Function Decision Table FDT structure.

(FDT Structure Changes) (3\14\10) (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 will be 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 will be added to the end of the existing FDT structure.)

(FDT_CONTEXT)

This section describes the additions to the driver FDT_CONTEXT structure. This structure is used to contain the $QIO system service return value that results from FDT processing. During FDT processing the (irp$ps_fdt_context) cell points to the FDT_CONTEXT structure. Currently, this structure is a stack local structure in the EXE$QIO routine.

(FDT_CONTEXT Structure Changes) (3\14\10) (Field\Type\Comments) (fdt_context$q_qio_r1_value\int64\The value to be returned in register R1 when the $QIO system service returns control back to the system service dispatcher. When the $QIO system service returns the status SS$_QIO_CROCK in register R0, the returned R1 value contains the virtual address that must be faulted in the caller's mode. If necessary, this cell is set in the EXE_STD$MODIFYLOCK, EXE_STD$READLOCK, and EXE_STD$WRITELOCK routines based on the returned values from MMG_STD$IOLOCK_BUF. This cell replaces (fdt_context$l_qio_r1_value).) (fdt_context$l_qio_r1_value\-\ This cell will be removed. It will be replaced by the (fdt_context$q_qio_r1_value) cell.)

(IRP\irp_struct)

This section describes the additions and changes to cells in the I/O Request Packet IRP structure. The significant IRP changes are: (numbered) The IRP will resemble a 64-bit capable ACB64 structure instead of the existing ACB structure. The underlying AST support for 64-bit addresses and parameters and the new ACB64 structure are described in (ast_chapter). A fixed-size primary DIOBM will be 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 will be expanded from 32-bits to 64-bits. Any cells overlaid on the (irp$l_ast), (irp$l_astprm), or (irp$l_iosb) cells will move to the low-order longword of their quadword replacements. Alternative cell names will be defined for the (ast), (astprm), and (iosb) cells that can be used for arbitrary parameters in internal IRPs.

The size of an IRP will grow by 160 bytes 43%, from 376 to 536 bytes in size.

(IRP Changes) (3\14\10) (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 will always be 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 will be 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 will be removed. ) (irp$l_acb_flags\unsigned int\ This cell will be 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 will be removed. It will be 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 will be 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 will be removed. It will be 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 will be 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 will be 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 will be removed. It will be 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 will be 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 (diobm_struct) 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) )

(IRPE\irpe_struct)

This section describes the additions and changes to cells in the I/O Request Packet Extension IRPE structure. An IRPE structure can contain additional driver-specific information that needs to be associated with an IRP. It can also be used to manage additional buffers that are locked down for direct I/O.

If the IRP$M_EXTEND bit is set in (irp$l_sts) then the (irp$l_extend) cell contains a pointer to an associated IRPE structure. Similarly, if the IRPE$M_EXTEND bit is set in the (irpe$l_sts) cell, then the (irpe$l_extend) cell contains a pointer to another IRPE. In general, if there is an IRPE cell with the name (irpe$X) and an IRP cell with then name (irp$X), then the cells must be at the same offsets such that the IRP and the IRPE can be used interchangeably in contexts that depend only on these common cells.

Currently, a single IRPE structure can be used to keep track of two separate regions of locked down pages. The new IRPE structure will only be able to manage a single region of locked down pages and will contain a single fixed-size primary DIOBM structure for that purpose. Drivers that require two regions, for example, SYS$DKDRIVER, will need to allocate and link in two IRPE structures.

(IRPE Changes) (3\14\10) (Field\Type\Comments) (irpe$b_rmod\unsigned char\ Requestor's access mode. This corresponds to the (irp$b_rmod) cell. The space for this IRPE cell was reserved but the cell was not previously formally defined. The addition of this cell facilitates the usage of an IRPE with the EXE_STD$READLOCK routines because the (irpe$b_rmod) cell is one of the required implicit inputs. ) (irpe$l_oboff\unsigned int\ Original byte offset into first page for buffer locked into memory. This corresponds to the (irp$l_oboff) cell that was added to the IRP on OpenVMS Alpha but was not formally defined in the IRPE. This will correct that omission. ) (irpe$q_driver_p0\int64\ Available for use by driver. This cell is overlaid on what was previously filler space. ) (irpe$l_driver_p0\int\ Available for use by driver. This cell is overlaid on the low-order 32-bits of (irpe$q_driver_p0). ) (irpe$l_driver_p1\int\ Available for use by driver. This cell is overlaid on the high-order 32-bits of (irpe$q_driver_p0). ) (irpe$q_driver_p2\int64\ Available for use by driver. This cell is overlaid on what was previously filler space. ) (irpe$l_driver_p2\int\ Available for use by driver. This cell is overlaid on the low-order 32-bits of (irpe$q_driver_p2). ) (irpe$l_driver_p3\int\ Available for use by driver. This cell is overlaid on the high-order 32-bits of (irpe$q_driver_p2). ) (irpe$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. ) (irpe$l_svapte\PTE *\ A 32-bit pointer to a copy of the PTEs that map the user buffer. If zero, then no PTEs have been locked for this request. This cell replaces the (irpe$l_svapte1) cell. ) (irpe$l_svapte1\-\ This cell will be removed. It will be replaced by the (irpe$l_svapte) cell. ) (irpe$l_bcnt\unsigned int\ Byte count for buffer locked into memory. This cell replaces the (irpe$l_bcnt1) cell. ) (irpe$l_bcnt1\-\ This cell will be removed. It will be replaced by the (irpe$l_bcnt) cell. ) (irpe$l_boff\unsigned int\ Byte offset into first page for buffer locked into memory. This cell replaces the (irpe$l_boff1) cell. ) (irpe$l_boff1\-\ This cell will be removed. It will be replaced by the (irpe$l_boff) cell.) (irpe$r_diobm\DIOBM\ Embedded fixed-size primary "direct I/O buffer map" structure. This embedded DIOBM structure is valid if and only if the (irpe$l_svapte) cell contains a non-zero value. See (diobm_struct) for a complete description of the DIOBM structure. ) (irpe$l_svapte2\-\ This cell will be removed. It was used to contain a pointer to the first PTE for a second buffer that was locked into memory. If zero, then there was no second buffer. ) (irpe$l_bcnt2\-\ This cell will be removed. It was used for the byte count for the second buffer locked into memory. ) (irpe$l_boff2\-\ This cell will be removed. It was used for the byte offset for the second buffer locked into memory. )

(PHD\phd_struct)

This section describes the I/O-specific additions to cells in Process Header PHD structure.

(PHD Structure Changes) (3\14\10) (Field\Type\Comments) (phd$l_iorefc\uint32\ Number of reasons to keep the PHD resident due to groups of pages locked for direct I/O. This count is incremented by MMG_STD$IOLOCK_BUF and decremented by MMG_STD$IOUNLOCK_BUF. On the zero-to-one transition of this cell, the slot reference count for the process in the PHV$GL_REFCBAS_LW vector is incremented. On the one-to-zero transition of this cell, the slot reference count for the process in the PHV$GL_REFCBAS_LW vector is decremented. )

(S2DGB\s2dgb_struct)

The S2DGB is a STARLET structure that defines the layout of the SCSI-2 Diagnose Buffer. When the $QIO IO$_DIAGNOSE function is issued to the GK, DK, and MK devices the (p1) parameter points to a S2DGB structure. The existing S2DGB structure contains embedded 32-bit user virtual addresses of the SCSI command buffer, data buffer, and sense buffer.

Because the S2DGB is a STARLET structure, the existing format must be supported. However, the S2DGB is defined in a manner that is easily extendable for 64-bit buffer addresses while maintaining binary compatibility for its current users.

This 60 byte structure consists of the (s2dgb$l_opcode) and (s2dgb$l_flags) longword cells, 9 longword cells with names using the (s2dgb$l_32X) naming format, and 4 reserved longwords. An alternative set of (s2dgb$pq_64X) and (s2dgb$l_64X) cells will be overlaid via a union on the (s2dgb$l_32X) cells and reserved longwords. This alternative set will be valid if and only if the (s2dgb$l_opcode) cell contains the S2DGB$K_OP_XCD64 value. The current S2DGB$K_OP_XCDB32 value is the only other legal value for the (s2dgb$l_opcode) cell and it indicates that the (s2dgb$l_32X) cells are valid.

(S2DGB Changes) (3\14\10) (Field\Type\Comments) (S2DGB$K_OP_XCDB64\constant\ This constant value in the (s2dgb$l_opcode) cell indicates that this is the 64-bit variant version of this structure. The (s2dgb$pq_64X) and (s2dgb$l_64X) cells are valid if and only if the (s2dgb$l_opcode) cell contains the S2DGB$K_OP_XCDB64 value. ) (s2dgb$pq_64cdbaddr\VOID_PQ\ A 64-bit pointer to the caller's SCSI command buffer. This is the analogue to the (s2dgb$l_32cdbaddr) cell in the 32-bit version of this structure. ) (s2dgb$pq_64dataddr\VOID_PQ\ A 64-bit pointer to the caller's data buffer. This is the analogue to the (s2dgb$l_32dataddr) cell in the 32-bit version of this structure. ) (s2dgb$pq_64senseaddr\VOID_PQ\ A 64-bit pointer to the caller's sense buffer. This is the analogue to the (s2dgb$l_32senseaddr) cell in the 32-bit version of this structure. ) (s2dgb$l_64cdblen\int\ Byte length of the caller's SCSI command buffer. This is the analogue to the (s2dgb$l_32cdblen) cell in the 32-bit version of this structure. ) (s2dgb$l_64datlen\int\ Byte length of the caller's data buffer. This is the analogue to the (s2dgb$l_32datlen) cell in the 32-bit version of this structure. ) (s2dgb$l_64senselen\int\ Byte length of the caller's sense buffer. This is the analogue to the (s2dgb$l_32senselen) cell in the 32-bit version of this structure. ) (s2dgb$l_64padcnt\int\ Number of padding data bytes required. This is the analogue to the (s2dgb$l_32padcnt) cell in the 32-bit version of this structure. ) (s2dgb$l_64phstmo\int\ Phase transition timeout in seconds. This is the analogue to the (s2dgb$l_32phstmo) cell in the 32-bit version of this structure. ) (s2dgb$l_64dsctmo\int\ Disconnect reconnect timeout in seconds. This is the analogue to the (s2dgb$l_32dsctmo) cell in the 32-bit version of this structure. ) (S2DGB$K_XCDB64_

LENGTH\constant\ Size of the the 64-bit variant of the S2DGB structure. This constant has the same value as S2DGB$K_XCDB32_LENGTH 60. )

(UCB)

There are no UCB changes that are required to provide support for 64-bit buffer addresses. This is explicitly mentioned since UCB changes were previously thought to be necessary.

(VCRP\vcrp_struct)

The VCRP structure is the VMS Communications Request Packet that is used by the OpenVMS LAN driver VMS Communications Interface VCI. A VCRP is used to transfer data between an upper- and lower-level VCM.

The VCRP is designed so that it can be used as an ACB by an upper-level VCM. Therefore, the VCRP will be enhanced such that it can be used either as an ACB or ACB64 structure by an upper-level VCM. This will allow upper-level VCMs the flexibility of providing 64-bit AST support at some time in the future without requiring another VCRP change and the forced recompilation of all VCMs. The new ACB64 structure is described in (ast_chapter).

Because a VCRP can be used as a DCBE the changes described in (dcbe_struct) must also be reflected in the VCRP.

(VCRP Structure Changes) (3\14\10) (Field\Type\Comments) (vcrp$v_acb_flags_valid\bit\ This is a new bit in the (vcrp$b_rmod) cell that corresponds to the (acb$v_flags_valid) bit. This bit is available for the exclusive use of upper-level VCMs. ) (vcrp$l_acb64x_offset\int\ Offset to the ACB64X structure embedded in this VCRP. This cell corresponds to the (acb$l_acb64x) cell and will be overlaid on (vcrp$l_ast). This cell is available for the exclusive use of upper-level VCMs. ) (vcrp$l_acb_flags\unsigned int\ This cell corresponds to the (acb$l_flags) cell and will be overlaid on the first longword of the existing fork block filler space in the VCRP. This cell is available for the exclusive use of upper-level VCMs. ) (vcrp$l_thread_id\int\ This cell corresponds to the (acb$l_thread_pid) cell and will be overlaid on the second longword of the existing fork block filler space in the VCRP. Reserved for use by the Kernel Threads project. ) (vcrp$pq_acb64_ast\VOID_FUNC_PQ\ This cell corresponds to the (acb64$pq_ast) cell. This cell is available for the exclusive use of upper-level VCMs. ) (vcrp$q_acb64_astprm\int64\ This cell corresponds to the (acb64$q_astprm) cell. This cell is available for the exclusive use of upper-level VCMs. ) (vcrp$q_user_thread_id\uint64\ Unique user thread identifier. Corresponds to the (acb64$q_user_thread_id) cell. This cell is available for the exclusive use of upper-level VCMs. ) (vcrp$pq_buffer_addr64\VOID_PQ\ 64-bit buffer address. This cell is available for use by upper-level VCMs only. Note that this cell does not replace the (vcrp$l_buffer_address) cell which will continue to be used by lower-level VCMs. ) (vcrp$r_diobm\DIOBM\ Embedded fixed-size primary "direct I/O buffer map" structure. This DIOBM structure is available for use by upper-level VCMs that need to lock down a buffer and provide a value for the (vcrp$l_svapte) cell. ) (vcrp$t_internal_stack\char[220]\ This existing internal stack area of 92 bytes will be increased to 220 bytes to reflect the increased size of a DCBE. SYS$PEDRIVER requires that it can place a DCBE within this stack area. This space is available for the exclusive use of upper-level VCMs. )

(I/O Support Routines\io_support_rout)

This section contains a detailed description of changes to the interfaces and functional descriptions of existing I/O support routines and a detailed interface and functional description for new I/O support routines that are required to implement $QIO and device driver support for I/O into 64-bit addressable regions.

This section also includes a summary of the internal changes to these routines. This section describes internal changes in detail only if this description is not provided elsewhere in this chapter.

The routines are listed in alphabetical order. (ACP_STD$READBLK and ACP_STD$WRITEBLK)

The routines (ACP_STD$\READBLK) and (ACP_STD$\WRITEBLK) are upper-level FDT routines, so their interfaces will remain unchanged: int acp_std$readblk (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb) int acp_std$writeblk (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb)

The routine ACP_STD$WRITEBLK also uses the local routine SET_UP_ERASE. These three routines obtain the address of the caller's buffer from (irp->irp$l_qio_p1). These routines will be modified to obtain the full 64-bit buffer address from (irp->irp$q_qio_p1) and pass it to (EXE_STD$\READLOCK) or (EXE_STD$\WRITELOCK). Note, however, that the buffer size will remain a longword and will be obtained from (irp->irp$l_qio_p2) without checking the upper 32-bits.

Because the (ACP_STD$\READBLK) and (ACP_STD$\WRITEBLK) routines are used to perform direct I/O they will be faced with the "cross-process PTE problem" that is described in (direct_io). Most of the cross-process PTE access issues will be handled transparently by the 64-bit changes to the (EXE_STD$\READLOCK) and (EXE_STD$\WRITELOCK) routines. However, the (ACP_STD$\READBLK) and (ACP_STD$\WRITEBLK) routines will need to call the IOC_STD$FILL_DIOBM for buffer objects in S2 space. These internal changes are described in more detail in (direct_io) and (svapte_table).

These routines will remain in MACRO-32 in the SYSACPFDT.MAR module. (EXE_STD$ALLOC_BUFIO_32, EXE_STD$ALLOC_BUFIO_64\exe_alloc_bufio)

Routines EXE_STD$ALLOC_BUFIO_32 and EXE_STD$ALLOC_BUFIO_64 are new routines that device drivers can use to allocate and initialize simple buffered I/O BUFIO packets. The appropriate IRP and BUFIO header cells are initialized but it's up the the caller to copy any data into the packet.

The interfaces for these routines are: int exe_std$alloc_bufio_32 (IRP *irp, PCB *pcb, void *uva, int pktsiz) int exe_std$alloc_bufio_64 (IRP *irp, PCB *pcb, VOID_PQ uva, int pktsiz)

(alloc_bufio_arg) summarizes the use of the arguments.

(EXE_STD$ALLOC_BUFIO_32, EXE_STD$ALLOC_BUFIO_64 Arguments\alloc_bufio_arg) (4\7\10\6) (Argument\Type\Access\Description) (irp \IRP * \Input\Pointer to the current IRP.) (pcb \PCB * \Input\Pointer to the process PCB.) (uva \VOID_PQ \Input\User virtual address, EXE_STD$ALLOC_BUFIO_64) ( \void * \Input\User virtual address, EXE_STD$ALLOC_BUFIO_32) (pktsiz \int \Input\Required size of the packet including the packet header.)

These routines use the EXE_STD$DEBIT_BYTCNT_ALO routine to allocate the packet and charge the process for the required BYTCNT quota. Any failure status from this routine is returned to the caller.

(alloc_bufio_imp) lists all the implicit outputs that are valid on successful return from these routines.

(EXE_STD$ALLOC_BUFIO_32, EXE_STD$ALLOC_BUFIO_64 Implicit Outputs\alloc_bufio_imp) (2\15) (Field\Value on successful completion) (irp$ps_bufio_pkt\Pointer to the allocated BUFIO packet.) (irp$l_boff\Number of charged bytes and size of allocated packet.) (bufio$ps_pktdata\Pointer to the packet data region in the allocated BUFIO packet.) (bufio$ps_uva32\For EXE_STD$ALLOC_BUFIO_32, value of uva.

For EXE_STD$ALLOC_BUFIO_64, BUFIO$K_64.) (bufio$w_size\Size of allocated packet.) (bufio$b_type\DYN$C_BUFIO) (bufio$pq_uva64\For EXE_STD$ALLOC_BUFIO_64, value of uva.)

These routines are coded in C and are contained in the new SYSQIOFDT2.C module. (EXE_STD$ALLOC_DIAGBUF\exe_alloc_diagbuf)

Routine EXE_STD$ALLOC_DIAGBUF is a new routine that allocates either a 32-bit or 64-bit diagnostic buffer packet and initializes the diagnostic buffer packet header. Diagnostic buffer packets use the same layout as BUFIO packets. This routine initializes the appropriate IRP and BUFIO header cells in the diagnostic buffer packet header but it's up the the caller to copy any data into the packet.

The allocation of a 32-bit or 64-bit format diagnostic buffer packet is controlled by a flag bit in the packet size value that is passed to this routine. This allows callers to simply pass in the value of the (ddt$w_diagbuf) cell directly to this routine.

The interface for this routine is: int exe_std$alloc_diagbuf (IRP *irp, VOID_PQ *uva, int pktsiz)

(alloc_diagbuf_arg) summarizes the use of the arguments.

(EXE_STD$ALLOC_DIAGBUF Arguments\alloc_diagbuf_arg) (4\7\10\6) (Argument\Type\Access\Description) (irp \IRP * \Input\Pointer to the current IRP.) (uva \VOID_PQ \Input\User virtual address) (pktsiz \int \Input\The low-order 15-bits of this parameter specify the required size of the packet including the diagnostic packet header. If bit-16 DDT$M_DIAGBUF64 is set a 64-bit diagnostic buffer packet is allocated. Otherwise a 32-bit diagnostic buffer packet is allocated.)

This routine uses the EXE_STD$ALLOCBUF routine to allocate the packet. Any failure status from this routine is returned to the caller of EXE_STD$ALLOC_DIAGBUF. Note that the EXE_STD$ALLOCBUF routine may put the process in a resource wait state and there is no additional process quota charge for a diagnostic buffer packet.

(alloc_diagbuf_imp) lists all the implicit outputs that are valid on successful return from this routine.

(EXE_STD$ALLOC_DIAGBUF Implicit Outputs\alloc_diagbuf_imp) (2\15) (Field\Value on successful completion) (irp$l_diagbuf\Pointer to the allocated diagnostic buffer packet.) (irp$l_sts\Status flag IRP$M_DIAGBUF is set to indicate that the IRP has an associated diagnostic buffer packet.) (bufio$ps_pktdata\Pointer to the packet data region in the allocated diagnostic BUFIO packet.) (bufio$ps_uva32\If DDT$M_DIAGBUF64 clear, value of uva.

If DDT$M_DIAGBUF64 set, BUFIO$K_64.) (bufio$w_size\Size of allocated diagnostic buffer packet.) (bufio$b_type\DYN$C_BUFIO) (bufio$pq_uva64\If DDT$M_DIAGBUF64 set, value of uva.)

This routine is coded in C and is contained in the new SYSQIOFDT2.C module. (EXE$BUILDPKTx\exe_buildpkt)

Routines EXE$BUILDPKTR, EXE$BUILDPKTW, EXE$BLDPKTSWPR, (EXE$\BLDPKT\SWPW), and EXE$BLDPKTMPW are the I/O subsystem routines used by the memory management system to initiate I/O. These are all JSB-interface routines that are alternate entry-points into essentially a single routine in the SYSQIOREQ.MAR module.

(3\2\14\10) (\EXE$BUILDPKTR \Builds an I/O packet for a page read. Called from SYSUPDSEC.) (\EXE$BUILDPKTW \Builds an I/O packet for a page write. Called from PAGEFAULT.) (\EXE$BLDPKTSWPR\Builds an I/O packet for a swap read. Called from SWAPPER.) (\EXE$BLDPKTSWPW\Builds an I/O packet for a swap write. Called from SWAPPER.) (\EXE$BLDPKTMPW \Builds an I/O packet for a modified page write. Called from WRTMFYPAG.)

Registers R0 through R5 contain the input parameters for these entry points. For the purposes of this discussion the only interesting parameters are R3, which contains a 32-bit SVAPTE, and R5, which contains a pointer to a previously allocated and partially filled in IRP. The changes to the R3 input for these routines are summarized in (bldpkt_r3).

(Changes to EXE$BUILDPKTx SVAPTE Inputs in R3\bldpkt_r3) (3\12\20) (Routine\Prior R3 input value\New R3 input value) (EXE$BUILDPKTR\32-bit SVAPTE\64-bit VA_PTE) (EXE$BUILDPKTW\32-bit SVAPTE\64-bit VA_PTE) (EXE$BLDPKTSWPR\Points into the 32-bit addressable swapper map SWP$GL_MAP. \Unchanged, because the swapper map remains in S0/S1 space.) (EXE$BLDPKTSWPW\Points into the 32-bit addressable swapper map SWP$GL_MAP. \Unchanged, because the swapper map remains in S0/S1 space.) (EXE$BLDPKTMPW\Points to a 32-bit addressable psuedo page table MPWMAP within the IRP pointed to by R5. \Unchanged.)

The code path taken by the EXE$BUILDPKTR and EXE$BUILDPKTW entry points will be modified to convert the 64-bit process-private VA_PTE provided in R3 into a 32-bit SVAPTE. The EXE$BUILDPKTR and EXE$BUILDPKTW entry points are the only ones that set the IRP$M_PAGIO bit in the (irp$l_sts) cell. Therefore, if IRP$M_PAGIO is set the IOC_STD$FILL_DIOBM routine will be called to convert the VA_PTE in R3 to a SVAPTE using the embedded DIOBM in the IRP pointed to by R5. This DIOBM will be released in the IOCIOPOST.MAR module after the PAGIO_DEL_IRP label by calling the IOC_STD$RELEASE_DIOBM routine.

The R3 input value for the EXE$BLDPKTSWPR, EXE$BLDPKTSWPW, and (EXE$\BLDPKT\MPW) entry points can be copied directly into the (irp$l_svapte) cell and used by the rest of the I/O subsystem. This will remain unchanged because the R3 value will continue to be a 32-bit address within S0/S1 space.

The IRP pointed to by R5 contains implicit inputs which vary depending on the specific entry point. The changes to the implicit IRP inputs for these routines are summarized in (bldpkt_irp).

(Changes to EXE$BUILDPKTx Implicit Inputs in the IRP\bldpkt_irp) (4\10\12\12) ((4\LEFT)(EXE$BUILDPKTR\BOLD)) (\New field\Replaces\Description) (\irp$q_param_2\-\Used by kernel threads project.) (\irp$q_param_3\-\PT PFN if global non-CRF, zero otherwise.) ((4\LEFT)(EXE$BUILDPKTW\BOLD)) (\New field\Replaces\Use) (\irp$pq_acb64_ast\irp$l_ast\64-bit AST routine address.) (\irp$q_acb64_astprm\irp$l_astprm\64-bit AST parameter.) (\irp$pq_iosb\irp$l_iosb\64-bit address of I/O status block.) ((4\LEFT)(EXE$BLDPKTSWPR, EXE$BLDPKTSWPW, EXE$BLDPKTMPW\BOLD)) (\New field\Replaces\Use) (\irp$l_iirp_p1\irp$l_astprm\Address of special kernel AST routine.)

Some of these changes are the direct result of changes to the IRP structure and are also discussed in (irp_struct) and (impact_irp). (EXE_STD$LOCK_ERR_CLEANUP\exe_lock_err_cleanup)

Routine EXE_STD$LOCK_ERR_CLEANUP is a new routine. This routine unlocks any previously locked down buffers that are associated with the specified IRP or any IRPEs that are attached to it. Immediately after each buffer is unlocked the corresponding DIOBM is released. All the IRPEs attached to the IRP are deallocated.

This routine is designed to be called in a driver-supplied error callback routine that is called if any error is encountered in the EXE_STD$READLOCK, EXE_STD$WRITELOCK, or EXE_STD$MODIFY_LOCK routines.

The interface for this routine is: void exe_std$lock_err_cleanup (IRP *irp)

(lock_err_cleanup_arg) summarizes the use of the arguments.

(EXE_STD$LOCK_ERR_CLEANUP Arguments\lock_err_cleanup_arg) (4\7\10\6) (Argument\Type\Access\Description) (irp \IRP * \Input\Pointer to the current IRP.)

(lock_err_cleanup_imp) lists all the implicit inputs and outputs that are used by this routine.

(EXE_STD$LOCK_ERR_CLEANUP Implicit Inputs and Outputs\lock_err_cleanup_imp) (2\15) ((2\LEFT)(Implicit inputs from the IRP\BOLD)) (Field\Use) (irp$l_svapte \If non-zero, points to the first PTE for a set of pages that will be unlocked.) (irp$l_bcnt \Used only if irp$l_svapte is non-zero to calculate number of pages that will be unlocked.) (irp$l_boff \Used only if irp$l_svapte is non-zero to calculate number of pages that will be unlocked.) (irp$r_diobm \Used only if irp$l_svapte is non-zero as the address of the DIOBM to release.) (irp$v_extend \If set, the IRPE pointed to by irp$l_extend will be processed.) (irp$l_extend \Used only if irp$v_extend is set to find the first IRPE) ((2\LEFT)(Implicit inputs from each IRPE\BOLD)) (Field\Use) (irpe$l_svapte\If non-zero, points to the first PTE for a set of pages that will be unlocked.) (irpe$l_bcnt \Used only if irpe$l_svapte is non-zero to calculate number of pages that will be unlocked.) (irpe$l_boff \Used only if irpe$l_svapte is non-zero to calculate number of pages that will be unlocked.) (irpe$r_diobm \Used only if irpe$l_svapte is non-zero as the address of the DIOBM to release.) (irpe$v_extend\If set, the IRPE pointed to by irpe$l_extend will be processed.) (irpe$l_extend\Used only if irpe$v_extend is set to find the next IRPE) ((2\LEFT)(Implicit outputs in the IRP\BOLD)) (Field\Value written) (irp$l_svapte \Cleared to indicate no locked pages.) (irp$v_extend \Cleared to indicate no attached IPEs.)

This routine is coded in C and is contained in the new SYSQIOFDT2.C module. (EXE_STD$MODIFY, EXE_STD$READ, EXE_STD$WRITE)

The routines (EXE_STD$\MODIFY), (EXE_STD$\READ), and (EXE_STD$\WRITE) are upper-level FDT routines, so their interfaces will remain unchanged: int exe_std$modify (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb) int exe_std$read (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb) int exe_std$write (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb)

These three routines obtain the address of the caller's buffer from (irp->irp$l_qio_p1). These routines will be modified to obtain the full 64-bit buffer address from (irp->irp$q_qio_p1) and pass it to (EXE_STD$\READLOCK) or (EXE_STD$\WRITELOCK). Note, however, that the buffer size will remain a longword and will be obtained from (irp->irp$l_qio_p2) without checking the upper 32-bits.

These routines will remain in MACRO-32 in the SYSQIOFDT.MAR module.

These routines depend on the 64-bit changes to the (EXE_STD$\READLOCK) and (EXE_STD$\WRITELOCK) routines. (EXE_STD$MODIFYLOCK, EXE_STD$READLOCK, EXE_STD$WRITELOCK\exe_readlock)

The routines (EXE_STD$\MODIFYLOCK), (EXE_STD$\READLOCK), and (EXE_STD$\WRITE\LOCK) are FDT support routines that: (unnumbered) Probe the accessibility of a specified buffer by the mode contained in ((irp->irp$b_mode)) Lock the buffer into memory if the probe succeeds Return the address of the first PTE that maps the buffer in ((irp->irp$l_svapte)) If an error is encountered, an optional error callback routine is invoked and the I/O request is aborted. If the entire buffer is not resident then the I/O request is backed out and a special status is returned to request a pagefault of the needed page.

The existing interfaces for these routines are: int exe_std$modifylock (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb, void *buf, int bufsiz, void (*err_rout)(...)) int exe_std$readlock (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb, void *buf, int bufsiz, void (*err_rout)(...)) int exe_std$writelock (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb, void *buf, int bufsiz, void (*err_rout)(...))

The new interfaces for these routines will be: int exe_std$modifylock (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb, VOID_PQ buf, int bufsiz [, void (*err_rout)(...)] ) int exe_std$readlock (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb, VOID_PQ buf, int bufsiz [, void (*err_rout)(...)] ) int exe_std$writelock (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb, VOID_PQ buf, int bufsiz [, void (*err_rout)(...)] )

There are two differences in the new interfaces. First, these functions will use the full 64-bits of the buffer address (buf) that is passed by value. Currently, the buffer address is a 32-bit value that is sign-extended into a 64-bit parameter value. Secondly, it will be possible to omit the (err_rout) parameter. Currently, one can pass in 0 to specify that there is no error routine. The new interface will support either means of specifying that there is no error routine. Since many callers do not require an error routine this will allow them to call these routines more efficiently with 6 parameters.

Both of these are upwardly compatible changes to the interface.

Because these routines are used to perform direct I/O they will be faced with the "cross-process PTE problem" that is described in (direct_io). Additional internal changes to deal with this problem are described in more detail in (direct_io) and (svapte_table). These routines depend on the 64-bit changes to the (EXE_STD$\READCHK) and (EXE_STD$\WRITECHK) routines and the new routines MMG_STD$IOLOCK_BUF and IOC_STD$FILL_DIOBM.

These routines will remain in MACRO-32 in the SYSQIOFDT.MAR module. (CALL_xLOCK and CALL_xLOCK_ERR macros\call_readlock)

There are 6 MACRO-32 macros that facilitate the use of the routines described in (exe_readlock) by code that was originally written to use the JSB-interface counterparts for these routines. These macros have implicit register inputs and outputs that correspond to the register inputs and outputs of the JSB-interface routines.

The CALL_MODIFYLOCK, CALL_READLOCK, and CALL_WRITELOCK macros will be modified to pass the full 64-bits of R0 as the buffer address and to omit the optional error routine parameter instead of passing the value 0.

The CALL_MODIFYLOCK_ERR, CALL_READLOCK_ERR, and CALL_WRITELOCK_ERR macros will be modified to pass the full 64-bits of R0 as the buffer address.

This is an upwardly compatible change to the implementation of these macros. This change will be transparent to the existing users because R0 currently contains the 32-bit buffer address sign-extended to 64-bits.

These macros will be implemented using the new $SETUP_CALL64, $PUSH_ARG64, and $CALL64 macros. (EXE_STD$READCHK and EXE_STD$WRITECHK\exe_readchk)

The routines (EXE_STD$\READCHK) and (EXE_STD$\WRITECHK) probe the accessibility of a specified buffer by the mode contained in ((irp->irp$b_mode)).

The existing interfaces for these routines are: int exe_std$readchk (IRP *irp, PCB *pcb, UCB *ucb, void *buf, int bufsiz) int exe_std$writechk (IRP *irp, PCB *pcb, UCB *ucb, void *buf, int bufsiz)

The new interfaces for these routines will be: int exe_std$readchk (IRP *irp, PCB *pcb, UCB *ucb, VOID_PQ buf, int bufsiz) int exe_std$writechk (IRP *irp, PCB *pcb, UCB *ucb, VOID_PQ buf, int bufsiz)

The only difference in the new interface is that these functions will use the full 64-bits of the buffer address (buf) that is passed by value. Currently, the buffer address is a 32-bit value that is sign-extended into a 64-bit parameter value. Thus, this is an upward compatible change to the interface.

These routines will remain in MACRO-32 in the SYSQIOFDT.MAR module. (CALL_xCHK and CALL_xCHKR macros)

The CALL_READCHK, CALL_READCHKR, CALL_WRITECHK, and CALL_WRITECHKR MACRO-32 macros will be modified to pass the full 64-bits of the buffer address in a similar fashion as described in (call_readlock). (EXE_STD$SETCHAR and EXE_STD$SETMODE)

The routines (EXE_STD$\SETCHAR) and (EXE_STD$\SETMODE) are upper-level FDT routines, thus their interfaces will remain unchanged: int exe_std$setchar (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb) int exe_std$setmode (IRP *irp, PCB *pcb, UCB *ucb, CCB *ccb)

Both of these routines use the local routine CHECK_SET to obtain and validate a pointer to the caller's buffer from (irp->irp$l_qio_p1). The routine CHECK_SET will be modified to obtain the full 64-bit buffer address from (irp->irp$q_qio_p1). Routines (EXE_STD$\SETCHAR) and (EXE_STD$\SETMODE) will be modified to use the 64-bit pointer returned by CHECK_SET when loading the UCB characteristics from the caller's buffer.

These routines will remain in MACRO-32 in the SYSQIOFDT.MAR module. (IOC_STD$CREATE_DIOBM)

Routine IOC_STD$CREATE_DIOBM is a new routine that is used to derive a 32-bit system virtual address for a specific number of PTEs that are pointed to by a 64-bit process virtual address. This routine allocates a "primary" DIOBM structure of sufficient size for its needs and returns a pointer to it. When the derived 32-bit system virtual address is no longer required the DIOBM must be released by calling the IOC_STD$RELEASE_DIOBM routine.

The algorithm used by this routine is very similar to one used by IOC_STD$FILL_DIOBM as described in (fill_diobm). The significant difference is that IOC_STD$CREATE_DIOBM will allocate a sufficiently sized primary DIOBM structure for its needs and does not depend on a preallocated fixed-size DIOBM. This routine is designed for existing users of the MMG$IOLOCK routine that do not have an embedded DIOBM to work with, but can maintain a single pointer to the external DIOBM structure that is returned by IOC_STD$CREATE_DIOBM.

The interface for IOC_STD$CREATE_DIOBM is: int ioc_std$create_diobm (const PTE_PQ va_pte, const uint32 pte_count, const uint32 flags, PTE **svapte_p, DIOBM **diobm_p)

(create_diobm_arg) summarizes the use of the arguments.

(IOC_STD$CREATE_DIOBM Arguments\create_diobm_arg) (4\7\10\6) (Argument\Type\Access\Description) (va_pte \PTE_PQ \Input\A 64-bit pointer to the first PTE that maps the user buffer. This pointer must point to a PTE in page table space either directly or through the SPT window. It cannot be a pointer to a prior copy of the PTEs.) (pte_count\uint32 \Input\Number of PTEs that are required to map the entire buffer.) (flags\uint32 \Input\Option flags. The following bit mask values can be set:

DIOBM$M_NORESWAIT - Disable resource wait.

All other option bits must be zero.) (svapte_p \PTE ** \Output\Pointer to a 32-bit PTE address that is returned. The returned address is always a 32-bit system virtual address.) (diobm_p \DIOBM ** \Output\Pointer to DIOBM address that is returned.)

This routine requires system resources, nonpaged pool and possibly SPTEs. If there are insufficient resources this routine will, by default, place the process kernel thread in a kernel mode wait state for nonpaged pool and try again until it succeeds. In this case, the return value of this routine is always SS$_NORMAL because it will not return until it can do so successfully.

However, the caller can inhibit this resource wait by setting the DIOBM$M_NORESWAIT option in the flags parameter. When this is done an error status is returned to the caller if there are insufficient system resources. This capability is intended to be used in contexts where a resource wait in kernel mode is not acceptable or if the caller can readily put the process into a wait state in the requestor's mode.

This routine must be called in process context and assumes that it was called at IPL 2, or minimally that it can lower IPL to 2.

The use of the DIOBM structure by this routine is described in detail in (diobm_struct).

This routine is coded in C and is contained in the new DIOBM.C module. (IOC_STD$FILL_DIOBM\fill_diobm)

Routine IOC_STD$FILL_DIOBM is a new routine that is used to derive a 32-bit system virtual address for a specific number of PTEs that are pointed to by a 64-bit process virtual address. This routine employs a previously allocated or embedded "primary" DIOBM structure that must be supplied as one of its inputs. When the derived 32-bit system virtual address is no longer required the DIOBM must be released by calling the IOC_STD$RELEASE_DIOBM routine.

This routine derives a 32-bit system virtual address for the PTEs using one of the following methods: (numbered) If the PTEs are in the region of page table space that maps S0/S1 space, a 32-bit PTE address using the SPT window is returned. If less than or equal to DIOBM$K_PTECNT_FIX PTEs are required, the PTEs are copied into the PTE vector in the DIOBM and the 32-bit system virtual address of the PTE vector in the DIOBM is returned. If more than DIOBM$K_PTECNT_FIX and less than or equal to (ioc$gl_diobm_ptecnt_max) PTEs are required, a secondary DIOBM is allocated, the PTEs are copied into the PTE vector in the secondary DIOBM, and the 32-bit system virtual address of the PTE vector in the secondary DIOBM is returned. If more than (ioc$gl_diobm_ptecnt_max) PTEs are required, a temporary PTE window in S0/S1 space is created that maps the neccessary process level-3 page table pages. These level-3 page table pages are locked into memory and the 32-bit S0/S1 address of the PTEs through the PTE window is returned.

The algorithm used by this routine is described in additional detail in (direct_io).

The interface for IOC_STD$FILL_DIOBM is: int ioc_std$fill_diobm (DIOBM *const diobm, const PTE_PQ va_pte, const uint32 pte_count, const uint32 flags, PTE **svapte_p)

(fill_diobm_arg) summarizes the use of the arguments.

(IOC_STD$FILL_DIOBM Arguments\fill_diobm_arg) (4\7\10\6) (Argument\Type\Access\Description) (diobm \DIOBM * \Input\Pointer to a previously allocated but unused or uninitialized DIOBM structure.) (va_pte \PTE_PQ \Input\A 64-bit pointer to the first PTE that maps the user buffer. This pointer must point to a PTE in page table space either directly or through the SPT window. It cannot be a pointer to a prior copy of the PTEs.) (pte_count\uint32 \Input\Number of PTEs that are required to map the entire buffer.) (flags \uint32 \Input\Option flags. The following bit mask values can be set:

DIOBM$M_NORESWAIT - Disable resource wait.

All other option bits must be zero.) (svapte_p \PTE ** \Output\Pointer to a 32-bit PTE address that is returned. The returned address is always a 32-bit system virtual address.)

This routine may require system resources, either nonpaged pool or SPTEs, depending on the number of PTEs that are required to map the buffer. If there are insufficient resources this routine will, by default, place the process kernel thread in a kernel mode wait state for nonpaged pool and try again until it succeeds. In this case, the return value of this routine is always SS$_NORMAL because it will not return until it can do so successfully.

However, the caller can inhibit this resource wait by setting the DIOBM$M_NORESWAIT option in the flags parameter. When this is done an error status is returned to the caller if there are insufficient system resources. This capability is intended to be used in contexts where a resource wait in kernel mode is not acceptable or if the caller can readily put the process into a wait state in the requestor's mode.

This routine must be called in process context and assumes that it was called at IPL 2, or minimally that it can lower IPL to 2.

The use of the DIOBM structure by this routine is described in detail in (diobm_struct). The normal version of the IOC_STD$FILL_DIOBM routine makes no assumptions about the contents of the input DIOBM structure. In contrast, the full checking version of this routine in the IO_ROUTINES_MON.EXE execlet performs some initial validation and declares an INCONSTATE bugcheck should these check fail.

This routine is coded in C and is contained in the new DIOBM.C module. (IOC_STD$PTETOPFN)

The routine IOC_STD$PTETOPFN allows drivers or other components to obtain the PFN for a page that has been previously locked into memory but the valid bit in its PTE is currently clear. This routine handles transition PTEs and PTEs that have reverted into GPTX format.

The existing interface is: int ioc_std$ptetopfn (PTE *pte);

The new interface for this routine will be: int ioc_std$ptetopfn (PTE_PQ pte);

The first interface difference is that IOC_STD$PTETOPFN will use the full 64-bits of the caller's PTE address that is passed by value. The second interface difference is not apparent from the above function prototype. The IOC_STD$PTETOPFN routine will be enhanced to handle the case where the (pte$v_valid) bit is set in the PTE. Therefore, drivers will be able to use this routine without first checking the valid bit.

Both of these are upwardly compatible changes to the interface. (IOC_STD$RELEASE_DIOBM\release_diobm)

Routine IOC_STD$RELEASE_DIOBM is a new routine that is used to release the PTE mapping resources that were setup by a prior call to either the IOC_STD$CREATE_DIOBM or IOC_STD$FILL_DIOBM routines.

The interface for IOC_STD$RELEASE_DIOBM is: int ioc_std$release_diobm (DIOBM *const diobm)

(release_diobm_arg) summarizes the use of the arguments.

(IOC_STD$RELEASE_DIOBM Argument\release_diobm_arg) (4\7\10\6) (Argument\Type\Access\Description) (diobm \DIOBM * \Input\Pointer to an active primary DIOBM.) This routine deallocates any secondary DIOBM that is connected to the primary DIOBM. If this primary DIOBM has a PTE window the resources used for the window are deallocated. If the primary DIOBM was allocated by IOC_STD$CREATE_DIOBM, the primary DIOBM will be deallocated as well. The use of the DIOBM structure by this routine is described in detail in (diobm_struct).

The returned value of this routine is always SS$_NORMAL.

This routine does not depend on process context. However, the IPL and spinlocks of the caller must allow this routine to acquire and restore the MMG spinlock.

This routine is coded in C and is contained in the new DIOBM.C module. (IOC_STD$SIMREQCOM, IOC$SIMREQCOM\ioc_simreqcom)

The routine IOC_STD$SIMREQCOM allows drivers or other components to complete an I/O that does not have a normal IRP associated with it. Because this routine does not have an IRP, the necessary information to signal an I/O completion is passed directly in separate parameters. For example, the user's IOSB address, the event flag value, a pointer to an ACB, and the caller's access mode are among the parameters.

The existing interface is: int ioc_std$simreqcom (int32 iosb[2], int pri, int efn, int32 iost[2], ACB *acb, int acmode);

The new interface for this routine will be: int ioc_std$simreqcom (VOID_PQ iosb_p, int pri, int efn, int32 iost[2], ACB *acb, int acmode);

The first interface difference is that IOC_STD$SIMREQCOM will use the full 64-bits of the caller's IOSB address (iosb_p) that is passed by value. The second interface difference is not apparent from the above function prototype. The IOC_STD$SIMREQCOM routine will be enhanced to accept either a pointer to an ACB64 or ACB structure.

Both of these are upwardly compatible changes to the interface. (CALL_SIMREQCOM macro)

The CALL_SIMREQCOM MACRO-32 macro facilitates the use of the (IOC_STD$\SIM\REQ\COM) routine by code that was originally written to use the JSB-interface counterpart IOC$SIMREQCOM. The CALL_SIMREQCOM macro has implicit register inputs that correspond to the register inputs of the JSB-interface for the (IOC$\SIM\REQ\COM) routine.

Because this macro uses registers for its inputs, it can be altered to use the full 64-bit value of the caller's IOSB address which is passed in register R1. (IOC$SIMREQCOM)

The IOC$SIMREQCOM routine is simply a JSB-to-CALL jacket routine around IOC_STD$SIMREQCOM. Because it is implemented through the use of the CALL_SIMREQCOM macro, IOC$SIMREQCOM will transparently support a 64-bit caller's IOSB address in the R1 parameter. Similarly, this routine will allow R5 to point to either an ACB or ACB64 structure. (IOC_STD$SVAPTE_IN_BUF\svapte_in_buf)

Routine IOC_STD$SVAPTE_IN_BUF is a new routine that is used to calculate a 32-bit PTE address for a virtual address within a buffer that has been previously locked for this IRP and for which a 32-bit PTE address has been derived.

It is the caller's responsibility to assure that the virtual address is a legal address within a buffer that has been locked into memory prior to calling this routine and that a 32-bit PTE address has been derived for this buffer. The IOC_STD$SVAPTE_IN_BUF routine may declare a bugcheck if either of these conditions have not been met.

The interface for IOC_STD$SVAPTE_IN_BUF is: int ioc_std$svapte_in_buf (IRP *irp, VOID_PQ va, PTE **svapte_p)

(svapte_in_buf_arg) summarizes the use of the arguments.

(IOC_STD$SVAPTE_IN_BUF Arguments\svapte_in_buf_arg) (4\7\10\6) (Argument\Type\Access\Description) (irp \IRP * \Input\Pointer to the current IRP.) (va \VOID_PQ \Input\Virtual address within the buffer that was locked for this IRP.) (svapte_p \PTE ** \Output\Pointer to a 32-bit PTE address that is returned. The returned address is a 32-bit system virtual address that is derived based on the values in irp$l_svapte and irp$q_qio_p1.)

(svapte_in_buf_imp) lists all the implicit inputs that are used by this routine.

(IOC_STD$SVAPTE_IN_BUF Implicit Inputs\svapte_in_buf_imp) (2\15) (Field\Use) (irp$q_qio_p1 \Virtual address of the start of the buffer that has been previously locked into memory for this IRP.) (irp$l_svapte \32-bit PTE address for the PTEs that map the buffer.)

The returned value of this routine is always SS$_NORMAL.

This routine is coded in C and is contained in the new SVAPTE2.C module. (IOC_STD$VA_TO_PA\va_to_pa)

Routine IOC_STD$VA_TO_PA is a new routine that is used to derive a 64-bit physical memory address for a 64-bit virtual address. The virtual address is interpreted in the context of the current process and may be in either process-private or system space.

It is the caller's responsibility to assure that the virtual address is a legal address and that the memory page containing the specified virtual address is locked into memory prior to calling this routine. The IOC_STD$VA_TO_PA routine may declare a bugcheck if either of these conditions have not been met.

The interface for IOC_STD$VA_TO_PA will be: VOID_PQ ioc_std$va_to_pa (VOID_PQ va, VOID_PPQ pa_p)

The returned value of this routine is the 64-bit physical address. (va_to_pa_arg) summarizes the use of the arguments.

(IOC_STD$VA_TO_PA Arguments\va_to_pa_arg) (4\7\10\6) (Argument\Type\Access\Description) (va \VOID_PQ \Input\A 64-bit virtual address.) (pa_p \VOID_PPQ \Output\Pointer to a 64-bit physical address that is returned. This parameter is optional and may either be omitted entirely or specified as 0. The physical address is also returned as the value of the routine.)

Currently, the physical address for a process virtual address can be derived by calling MMG_STD$SVAPTECHK followed by IOC$SVAPTE_TO_PA. However, as described in (impact_svaptechk), the MMG_STD$SVAPTECHK routine will no longer accept a P0/P1 address. The new IOC_STD$VA_TO_PA routine will provide a direct way of computing the physical address from a process virtual address.

This routine will be coded in C and will be placed in the new SVAPTE2.C module. (MMG_STD$GET_PTE_FOR_VA)

Routine MMG_STD$GET_PTE_FOR_VA is a new routine that is being added for use in the Remote SDA SYSAP within SYS$SCS.

Routine MMG_STD$GET_PTE_FOR_VA attempts to obtain the Level-3 PTE containing a PFN that maps the specified virtual address for a specified process. If the requested PTE cannot be accessed either because the virtual address is not mapped or a needed page table page is not currently in physical memory, an error status is returned. Additionally, if the Level-3 PTE does not contain a useable PFN an error status is returned.

A successful return status from this routine means that the PFN field of the returned PTE contains the physical page number for the input virtual address. Note that there are page states where the PTE contains a useable PFN but the PTE$V_VALID bit is clear. Therefore, the PTE$V_VALID bit in the returned PTE might be clear. Note also, that this routine will return a PTE from the Global Page Table when the slave PTE has reverted to GPTX format and the master PTE in the GPT still contains a PFN.

This routine is somewhat similar to MMG_STD$CALC_VAPTE except that it does not assume that the virtual address is valid or that the necessary page tables are resident in memory. Because this routine does not assume the virtual address is valid, it uses the reserved system space window to traverse the specified process' page tables in a top-down fashion. It uses this method for all process-private virtual addresses even if the specified process happens to be the current process on this CPU. This allows this routine to locate the Level-3 PTE even if some of the intervening page table pages are in transition. However, for shared system space virtual addresses this routine uses the currently active page tables instead of the reserved system window to locate the corresponding Level-3 PTE. This is possible since shared system space page table pages a not pageable and will have PTE$V_VALID set if they are mapped.

This routine acquires and restores the MMG spinlock. This routine will declare a bugcheck if the reserved system space window is already in use. This routine releases and invalidates the window before returning.

The interface for MMG_STD$GET_PTE_FOR_VA will be: int mmg_std$get_pte_for_va (VOID_PQ const va, PHD *const phd, PTE_PQ pte_p)

(get_pte_arg) summarizes the use of the arguments.

(MMG_STD$GET_PTE_FOR_VA Arguments\get_pte_arg) (4\7\10\6) (Argument\Type\Access\Description) (va \VOID_PQ \Input\A 64-bit virtual address.) (phd \PHD * \Input\Pointer to the PHD for the desired process address space. If zero, the current process on the current CPU is assumed. This parameter is not used, and may be zero, if the virtual address is in shared system space.) (pte_p \PTE_PQ \Output\Address of Level-3 PTE value that is returned. A PTE value is returned only if the routine returns a successful condition value.)

The returned value of this routine is a system condition value:

(3\2\12) (\SS$_NORMAL\The PTE that maps the specified virtual address in the address space of the specified process contains a physical page number and was successfully returned.) (\SS$_ACCVIO\The PTE that maps the specified virtual address in the address space of the specified process could not be obtained, i.e. the specified virtual address is not mapped or one of the necessary page table pages is not currently resident, or the level-3 PTE did not contain a physical page number.)

This routine will be coded in C and will be placed in the new SVAPTE2.C module. (MMG_STD$IOLOCK, MMG$IOLOCK, MMG_STD$IOLOCK_BUF\mmg_iolock)

The interface for the MMG_STD$IOLOCK routine is: int mmg_std$iolock (void *buf, int bufsiz, int is_read, PCB *pcb, void **svapte_p)

This routine returns a 32-bit address by reference the (svapte_p) parameter which, depending on the routine status, may specify the address of the first PTE or the address of a location in the buffer that must be faulted in.

The new version of this routine must accept a 64-bit buffer address. In addition, the new version must also return either a 64-bit PTE or buffer address. This is an incompatible interface change because this return parameter is passed by reference. Thus, MMG_STD$IOLOCK has been removed and is replaced by the new MMG_STD$IOLOCK_BUF routine.

The interface for MMG_STD$IOLOCK_BUF is: int mmg_std$iolock_buf (VOID_PQ const buf, const int bufsiz, const int is_read, PCB *const pcb, PTE_PPQ va_pte_p, VOID **fault_va_p)

(iolock_arg) summarizes the use of the arguments.

(MMG_STD$IOLOCK_BUF Arguments\iolock_arg) (4\7\10\6) (Argument\Type\Access\Description) (buf \VOID_PQ \Input\64-bit pointer to the buffer that is to be locked.) (bufsiz \int \Input\Size of the buffer in bytes.) (is_read \int \Input\Contains the value 0 if buffer will be only written to the device, 1 if the buffer will be only read from device, 5 if the buffer will be modified by the device.) (pcb \PCB * \Input\Pointer to the process PCB.) (va_pte_p \PTE_PPQ \Output\Pointer to a 64-bit PTE address that is returned. If the returned value of the function is successful, then the address returned is the 64-bit virtual address of the first PTE that maps the buffer. For all other function return values the value returned in this parameter is undefined.) (fault_va_p\VOID_PPQ \Output\Pointer to a 64-bit address that is returned. If the returned value of the function is 0, then the address returned is the 64-bit address within the buffer that must be faulted in. For all other function return values the value returned in this parameter is undefined.)

The returned value of this routine is a system condition value or the value zero:

(3\2\12) (\Success \A successful VMS condition value indicates that the buffer has been locked and that the 64-bit virtual address of the first PTE that maps the buffer has been returned using the va_pte_p parameter.) (\0 \This return value means that a page fault is required for a page in the buffer. The virtual address of the page is returned using the fault_va_p parameter. Any portion of the buffer that may have been locked before this condition was detected has been unlocked before returning.) (\Failure \Standard VMS condition value that indicates the failure.)

Just like MMG_STD$IOLOCK, the MMG_STD$IOLOCK_BUF routine must be called in process context at IPL 2 and it acquires and releases the MMG spinlock.

Although the interfaces for the MMG_STD$IOLOCK_BUF and MMG_STD$IOLOCK routines are similar, there are important differences between these routines that go beyond the width of the address parameters. (numbered) The 32-bit address that is returned by MMG_STD$IOLOCK in the (svapte_p) parameter is valid regardless of process context. In contrast, the 64-bit address that is returned by MMG_STD$IOLOCK_BUF in the (va_pte_p) parameter may be valid only in the context of the current process. The new routines IOC_STD$FILL_DIOBM and IOC_STD$CREATE_DIOBM are designed to deal with this difference. The MMG_STD$IOLOCK routine locks into memory the level-3 page tables that contain the PTEs that map the buffer as well as the buffer pages. In contrast, MMG_STD$IOLOCK_BUF only locks the buffer pages. It does not lock the level-3 page tables because it would be difficult to unlock them in the absence of process context where MMG_STD$IOUNLOCK_BUF is called. Moreover, the mechanisms used by IOC_STD$FILL_DIOBM and IOC_STD$CREATE_DIOBM usually do not require the locking of the level-3 page tables. Only when the PTE window method is used by IOC_STD$FILL_DIOBM or IOC_STD$CREATE_DIOBM will these routines need to lock the level-3 page table pages into memory. When this case applies, the IOC_STD$RELEASE_DIOBM routine has enough information to unlock the level-3 page tables regardless of process context.

The existing callers of MMG_STD$IOLOCK need to be very aware of the first of these differences. The second difference is likely to be transparent to most callers.

Because the routine MMG$IOLOCK is simply a JSB-to-CALL jacket routine around MMG_STD$IOLOCK, the MMG$IOLOCK routine has also been removed.

Because the MMG_STD$IOLOCK_BUF routine will reuse much of the existing MMG_STD$IOLOCK code it will remain in MACRO-32 in the IOLOCK.MAR module. (CALL_IOLOCK macro)

The CALL_IOLOCK MACRO-32 macro facilitates the use of the MMG_STD$IOLOCK routine by code that was originally written to use the JSB-interface counterpart MMG$IOLOCK. The CALL_IOLOCK macro has implicit register inputs and outputs that correspond to the register inputs and outputs of the JSB-interface for the MMG$IOLOCK routine.

Because this macro uses registers for its inputs and outputs, it can be altered to use the full 64-bit values in these registers and it can call the MMG_STD$IOLOCK_BUF routine instead of MMG_STD$IOLOCK. Nevertheless, the CALL_IOLOCK macro has been modified to generate a suppressable interface warning at compile-time, because: (unnumbered) The full 64-bits of register R1 are now significant on return The returned PTE address is a 64-bit process virtual address Callers of MMG_STD$IOLOCK_BUF are very likely to need to call the new IOC_STD$FILL_DIOBM or IOC_STD$CREATE_DIOBM routines.

The format of the macro call is: CALL_IOLOCK [ INTERFACE_WARNING=YES|NO ]

By default the interface warning is enabled and generates the following warning at compile-time: %AMAC-W-GENWARN, generated WARNING: 0 CALL_IOLOCK interface has changed for 64-bit virtual addressing; set INTERFACE_WARNING=NO to disable messages. %AMAC-W-GENWARN, generated WARNING: 0 CALL_IOLOCK uses the 64-bit buffer address in R0 %AMAC-W-GENWARN, generated WARNING: 0 CALL_IOLOCK returns a 64-bit VA_PTE or fault VA in R1 %AMAC-W-GENWARN, generated WARNING: 0 CALL_IOLOCK does not lock the page table pages %AMAC-W-GENWARN, generated WARNING: 0 A call to IOC_STD$FILL_DIOBM may be required to derive a SVAPTE

The compile-time warning serves to identify the existing callers of this macro. Once the invoking code has been modified the warning can be suppressed by specifying INTERFACE_WARNING=NO. (MMG_STD$UNLOCK, MMG$UNLOCK, MMG_STD$IOUNLOCK_BUF\mmg_unlock)

The interface for the MMG_STD$UNLOCK routine is: void mmg_std$unlock (int npages, void *svapte)

The MMG$UNLOCK routine is simply a JSB-to-CALL jacket routine around (MMG_STD$\UNLOCK).

Because 32-bit PTE addresses that may point to PTE copies are sufficient for the needs of the MMG_STD$UNLOCK routine, there is no absolute requirement to change the interface of these routines. However, it is extremely likely that all callers of MMG_STD$UNLOCK and MMG$UNLOCK will need to use the new DIOBM structure and will need to call the new routine IOC_STD$RELEASE_DIOBM immediately after unlocking the memory buffer. Therefore, routine MMG_STD$UNLOCK has been renamed to MMG_STD$IOUNLOCK_BUF and the MMG$UNLOCK routine has been removed in order to make it difficult to miss the places where this source change is needed.

The interface for MMG_STD$IOUNLOCK_BUF is: void mmg_std$iounlock_buf (const int npages, PTE_PQ const va_pte);

Just like MMG_STD$UNLOCK, the MMG_STD$IOUNLOCK_BUF routine does not depend on process context. However, the IPL and spinlocks of the caller must allow this routine to acquire and restore the MMG spinlock.

Because the MMG_STD$IOUNLOCK_BUF routine will reuse much of the existing MMG_STD$UNLOCK code it will remain in MACRO-32 in the IOLOCK.MAR module. (CALL_UNLOCK macro)

The CALL_UNLOCK MACRO-32 macro facilitates the use of the MMG_STD$UNLOCK routine by code that was originally written to use the JSB-interface counterpart MMG$UNLOCK. The CALL_UNLOCK macro has implicit register inputs that correspond to the register inputs and outputs of the JSB-interface for the MMG$UNLOCK routine.

This macro has been modified to use the full 64-bits of the R3 input which contains the PTE address and the macro calls the new MMG_STD$IOUNLOCK_BUF routine instead of MMG_STD$UNLOCK. In addition, the CALL_UNLOCK macro has been modified to generate a suppressable interface warning at compile-time. The format of the macro call is: CALL_UNLOCK [ INTERFACE_WARNING=YES|NO ]

By default the interface warning is enabled and generates the following warning at compile-time: %AMAC-W-GENWARN, generated WARNING: 0 CALL_UNLOCK interface has changed for 64-bit virtual addressing; set INTERFACE_WARNING=NO to disable messages. %AMAC-W-GENWARN, generated WARNING: 0 CALL_UNLOCK uses the 64-bit PTE address in R3 %AMAC-W-GENWARN, generated WARNING: 0 CALL_UNLOCK does not unlock the page table pages %AMAC-W-GENWARN, generated WARNING: 0 A call to IOC_STD$RELEASE_DIOBM may be required to derive a SVAPTE

(MMG_STD$SVAPTECHK, MMG$SVAPTECHK\mmg_svaptechk)

The current versions of the MMG_STD$SVAPTECHK and MMG$SVAPTECHK routines compute a 32-bit (svapte) for either a process or system space address. Starting with the Theta release these routines will be restricted to a S0/S1 system space address and will no longer accept an address in P0/P1 space. The MMG_STD$SVAPTECHK and MMG$SVAPTECHK routines will check the full 64-bits of the input address and will declare a bugcheck for an input address that is not in S0/S1 space. For S0/S1 input addresses these routines will return a 32-bit system virtual address of the PTE through the SPT window.

The existing interface is: void mmg_std$svaptechk (void *va, PCB *pcb, PHD *phd, void **svapte_p);

The new interface for this routine will be: void mmg_std$svaptechk (VOID_PQ va, PCB *pcb, PHD *phd, PTE **svapte_p);

The majority of callers of this routine use it with an S0/S1 address and will not need to change. The instances on the OpenVMS Alpha masterpack that do need to change are discussed in (impact_svaptechk).

The MMG_STD$SVAPTECHK routine will be coded in C and will be placed in the new SVAPTE2.C module. The MMG$SVAPTECHK routine is simply a JSB-to-CALL jacket routine around MMG_STD$SVAPTECHK and will remain in the SVAPTE.MAR module. (Components Impacted by Infrastructure Changes\infrastruct_changes)

This section describes the source changes that are required to components on the OpenVMS Alpha masterpack as a result of the infrastructure changes described in this chapter. These sources changes are required in order for the affected components to continue to provide 32-bit functionality with the Theta release. (infrastruct_summary) provides a summary of these infrastructure changes. (Impact of IRPE Changes\impact_irpe)

As described in (irpe_struct), the IRPE will only be able to manage a single additional locked down buffer instead of two. The general approach to this change is to use a chain of additional IRPE structures.

Current users of the IRPE may be depending on the fact that a buffer locked for direct I/O could be fully described by the (irp$l_svapte), (irp$l_boff), and (irp$l_bcnt) values. For example, it is not uncommon for an IRPE to be used in this fashion: (numbered) The second buffer that will be eventually associated with the IRPE is locked first by calling EXE_STD$READLOCK with the IRP. The (irp$l_svapte), (irp$l_boff), and (irp$l_bcnt) values are copied from the IRP into the IRPE. The (irp$l_svapte) cell is then cleared. The locked region is now completely described by the IRPE. The first buffer is locked by calling EXE_STD$READLOCK with the IRP again. A driver-specific error callback routine is required for the EXE_STD$READLOCK calls. This error routine calls MMG_STD$UNLOCK to unlock any region associated with the IRP and deallocates the IRPE.

The above approach will no longer work correctly. As described in (direct_io), the DIOBM structure that's embedded in the IRP will be needed as well. Moreover, it may not be sufficient to simply copy the DIOBM from the IRP to the IRPE. In particular, the (irp$l_svapte) may need to be modified if the DIOBM is moved.

The general approach to this change is to lock the buffer using the IRPE directly. This approach is shown in some detail in the following example: irpe->irpe$b_type = DYN$C_IRPE; irpe->irpe$l_driver_p0 = (int) irp; status = exe_std$readlock( irp, pcb, ucb, ccb, buf1, buf1_len, lock_err_rtn ); if( !$VMS_STATUS_SUCCESS(status) ) return status; irpe->irpe$b_rmod = irp->irp$b_rmod; status = exe_std$readlock( (IRP *)irpe, pcb, ucb, ccb, buf2, buf2_len, lock_err_rtn ); if( !$VMS_STATUS_SUCCESS(status) ) return status; (callout) The IRPE needs to be unambiguously identified as an IRPE because the error callback routine depends on being able to distinguish an IRP from an IRPE. The IRPE needs to contain a pointer to the original IRP for this I/O request, again, for potential use by the error callback routine. Here, a driver-specific cell in the IRPE is used. The first buffer is locked using the IRP. If EXE_STD$READLOCK cannot lock the entire buffer into memory the following occurs: (alphabetic) The error callback routine, LOCK_ERR_RTN, is invoked. Depending on the error status, either the I/O is aborted or backed out for automatic retry. In any event the IRP is deallocated. EXE_STD$READLOCK returns the SS$_FDT_COMPL warning status. The caller's access mode must be copied into the IRPE in preparation for locking the second buffer using the IRPE. The second buffer is locked using the IRPE. If this fails, the error callback routine LOCK_ERR_RTN is called with the IRPE.

The above approach is easily generalized to more buffers and IRPEs. The only thing that was omitted above is the code that allocates and links together the IRPEs. The associated error callback routine is shown below in its entirety and can handle an arbitrary number of IRPEs. void lock_err_rtn (IRP *const lock_irp, PCB *const pcb, UCB *const ucb, CCB *const ccb, const int errsts, IRP **real_irp_p ) { IRP *irp; if( lock_irp->irp$b_type == DYN$C_IRPE ) irp = (IRP *) ((IRPE *)lock_irp)->irpe$l_driver_p0; else irp = lock_irp; exe_std$lock_err_cleanup (irp); *real_irp_p = irp; return; } (callout) The (lock_irp) parameter may either be an IRP or an IRPE depending on the data structure that was used with EXE_STD$READLOCK. Before returning from this error callback routine we need to provide the original IRP via the (real_irp_p) parameter so that the I/O can be properly terminated. If this routine has been passed an IRPE, we can get a pointer to the original IRP from the (irpe$l_driver_p0) cell because we put it there. The new EXE_STD$LOCK_ERR_CLEANUP routine does all the needed unlocking and deallocation of IRPEs. We provide the address of the original IRP to our caller.

The following drivers are affected by the IRPE changes: SYS$DKDRIVER, SYS$FYDRIVER, SYS$GKDRIVER, and SYS$MKDRIVER.

The support code for the SCSI diagnose function that is shared by SYS$DKDRIVER, SYS$GKDRIVER, and SYS$MKDRIVER, is affected by the IRPE changes. This code, which is discussed in (gkdriver), uses an IRPE and the EXE_STD$READLOCK routine to lock down the sense buffer. A number of changes, similar to those outlined above, will be required to the DKMK.C module in the [SCSI] facility due to the IRPE changes.

The SYS$DKDRIVER FDT routines for the IO$_AUDIO function use an IRPE structure to manage two additional locked buffers. This code will need to be changed to use a chain of two IRPEs instead of a single IRPE and will need to use the approach outlined above.

The SYS$FYDRIVER allocates an extra IRP that it uses as an IRPE to manage an additional locked buffer. A number of simple source changes, again similar to those outlined above, will be required to the FYDRIVER.MAR module in the [DUP] facility due to the IRPE changes. (Impact of MMG_STD$IOLOCK, MMG_STD$UNLOCK Changes\impact_iolock)

The interface changes to the MMG_STD$IOLOCK and MMG_STD$UNLOCK routines are described in (mmg_iolock) and (mmg_unlock). The general approach to these changes is to use the corresponding replacement routines and the new DIOBM structure. The following images are affected by these changes: SYS$IPC_SERVICE, SYS$DKDRIVER, SYS$FYDRIVER, SYS$GYADRIVER, SYS$GYBDRIVER, and PROCESS_MANAGEMENT.

The SYS$IPC_SERVICE execlet uses these routines to lock and unlock the caller's buffer that is passed to the OpenVMS Alpha LAN drivers via the VCI. The changes to the LAN VCI are described in (lan_vci). Simple source changes to the SCATP$SUBS.MAR module in the [IPC] facility will be made to use the new MMG_STD$IOLOCK_BUF routine instead of MMG$IOLOCK and to use the embedded DIOBM structure in the VCRP to derive a 32-bit (svapte) by calling IOC_STD$FILL_DIOBM. The call to MMG$UNLOCK will be replaced by a call to MMG_STD$IOUNLOCK_BUF followed by a call to IOC_STD$RELEASE_DIOBM with the embedded DIOBM in the VCRP.

The SYS$DKDRIVER uses the MMG_STD$UNLOCK routine on error paths in its audio support FDT routines. This code unlocks the additional buffers that were locked down with an IRPE structure. As described in (impact_irpe), the call to MMG$UNLOCK will be replaced by an approach which uses the new EXE_STD$LOCK_ERR_CLEANUP routine.

The SYS$FYDRIVER also uses the MMG_STD$UNLOCK on error paths to unlock the additional buffer that was locked down with an IRPE structure. As described in (impact_irpe), the call to MMG$UNLOCK will be replaced by an approach which uses the new EXE_STD$LOCK_ERR_CLEANUP routine.

The SYS$GYADRIVER and SYS$GYBDRIVER drivers support an I/O function that locks a DMA buffer into memory such that the buffer remains locked after successful completion of this function. These drivers support a separate I/O function that unlocks the DMA buffer. The caller of the I/O function provides the address of a DMAREQ structure which contains inputs and outputs. For example, this structure contains the address and size of the DMA buffer.

The FDT routines GXA$$DMA_SETUP and GYA$$DMA_SETUP in the [R5_DRIVER] GXADRIVER.MAR and [R5_DRIVER]GYBDRIVER.MAR modules use the MMG_STD$IOLOCK routine to lock the DMA buffer. They save the 32-bit (svapte) of the DMA buffer in the low-order longword of the (dmareq$q_identifier) cell. The FDT routines GXA$$DMA_SHUTDOWN and GYA$$DMA_SHUTDOWN use the MMG_STD$UNLOCK routine and the value in the low-order longword of the (dmareq$q_identifier) cell to unlock the DMA buffer. Fortunately, the PTE address saved in (dmareq$q_identifier) is not used for anything else and this user-visible cell is already a quadword. The calls to MMG_STD$IOLOCK will be replaced by calls to MMG_STD$IOLOCK_BUF and the 64-bit (va_pte) will be saved in the (dmareq$q_identifier) cell. Similarly, the calls to MMG_STD$UNLOCK will be replaced by calls to MMG_STD$IOUNLOCK_BUF using the (dmareq$q_identifier) value as input.

Because all PTE addresses returned by MMG_STD$IOLOCK are in S0/S1 space, the GXA$$DMA_SHUTDOWN and GYA$$DMA_SHUTDOWN routines check the sign-bit of the low-order longword of the (dmareq$q_identifier) cell. This sign-bit check will need to be changed to a test that verifies that the address contained in the (dmareq$q_identifier) cell is in page table space.

An additional required change to the GXA$$DMA_SETUP and GYA$$DMA_SETUP routines is described in (impact_svaptechk).

The use of MMG$IOLOCK and MMG$UNLOCK in the PROCESS_MANAGEMENT execlet needs to be handled differently than all the other cases described in this section. The LOCK_CTX_PAGES routine in the PROCESS_SCAN.MAR module needs to make the pageable PSCANCTX structure safe for access from IPL$_SCS. The complimentary routine UNLOCK_CTX_PAGES is called to indicate that the current interval of elevated access to the PSCANCTX structure has ended. During this interval the PSCANCTX structure must remain in the process working set to avoid page faults. Currently, routines LOCK_CTX_PAGES and UNLOCK_CTX_PAGES use MMG$IOLOCK and MMG$UNLOCK on the PSCANCTX structure. This is an inappropriate use of the MMG$IOLOCK routine because MMG$IOLOCK locks the page range into physical memory and does not lock it into the process working set.

Therefore the LOCK_CTX_PAGES routine will be modified to copy the input PSCANCTX structure into nonpaged pool. The structure is small and there are no other independent pointers to it that need to be maintained. Routine LOCK_CTX_PAGES will return with R6 pointing to the nonpaged pool copy. The existing (pscanctx$m_locked) flag will be set in the nonpaged copy and the existing (pscanctx$l_svapte) cell will be used to contain a pointer to the original PSCANCTX structure. Similarly, the UNLOCK_CTX_PAGES routine will be modified to copy the contents of the nonpaged pool version of the PSCANCTX structure back to the original, deallocate the nonpaged pool version, and return with R6 pointing back to the original. (Impact on Code that Clears IRP$L_SVAPTE\impact_clr_svapte)

Existing code that clears the (irp$l_svapte) cell may be depending on assumptions that will no longer be valid.

Currently, a buffer locked for direct I/O can be fully described by the (irp$l_svapte), (irp$l_boff), and (irp$l_bcnt) values. A driver can save these values and then clear the (irp$l_svapte) cell prior to sending the IRP to I/O postprocessing. This prevents IOC$IOPOST from unlocking the buffer. The driver can then continue to use the saved copies of the (irp$l_svapte), (irp$l_boff), and (irp$l_bcnt) values even though the $QIO operation has been completed and the original IRP has been deallocated.

As described in (direct_io), starting with the Theta release a DIOBM structure is required in the general case to provide a 32-bit system virtual address for a process PTE. The DIOBM that is used to derive a valid (irp$l_svapte) value is embedded in the IRP. Therefore, although clearing the (irp$l_svapte) cell will still prevent the unlocking of the buffer, the saved (irp$l_svapte) value becomes invalid as soon as the IRP is deallocated or reused.

Specific instances of this practice on the OpenVMS Alpha masterpack have been described and addressed in (impact_irpe) and (impact_iolock). This section outlines the general alternatives for dealing with this change because this technique is known to be used in privileged layered products.

References that clear (irp$l_svapte) need to be inspected to determine which of the following is applicable: (numbered) If the code clears (irp$l_svapte) as part of initializing an IRP, the code can remain unchanged. If the code clears (irp$l_svapte) in order to lock another buffer with the IRP, the code is best modified to lock each buffer directly with its own structure. This approach is described in detail in (impact_irpe). If the code clears (irp$l_svapte) to keep the buffer locked after the IRP is deallocated, but does not save the prior (irp$l_svapte) value or make any subsequent references to the prior (irp$l_svapte) value, the code can remain unchanged. If you believe this case applies make sure that the prior (irp$l_svapte) value is not being used to eventually unlock the buffer. If the code clears (irp$l_svapte) to keep the buffer locked after the IRP is deallocated, but the prior (irp$l_svapte) value is only used in a limited number of source references that can all be changed and all these references are in the context of the original process that issued the $QIO, the 64-bit (irp$pq_va_pte) value can be saved and used instead of the invalid (irp$l_svapte) value. The changes to the GXA$$DMA_SETUP and GXA$$DMA_SHUTDOWN routines described in (impact_iolock) and (impact_svaptechk) are an example of this approach. If the code clears (irp$l_svapte) to keep the buffer locked after the IRP is deallocated, requires a 32-bit (irp$l_svapte)-like value that persists, and used an explicit call to IOC_STD$FILL_DIOBM to set up the DIOBM within the IRP, the IOC_STD$CREATE_DIOBM routine can be used instead to allocate and initialize an separate DIOBM that is independent of the IRP. Because this DIOBM is not embedded in the IRP, the (irp$l_svapte) value will remain valid as long as the buffer remains locked and the separate DIOBM exists.

The code will need to save a pointer to this separate DIOBM and release it immediately after the buffer is eventually unlocked. Whenever a separate DIOBM is used the (irp$l_svapte) cell must be cleared before the IRP is sent to postprocessing. This is because I/O postprocessing releases the embedded DIOBM in the IRP when it unlocks the user buffer and the attempt to release an unused DIOBM will result in a bug check. If the code clears (irp$l_svapte) to keep the buffer locked after the IRP is deallocated, requires a 32-bit (irp$l_svapte)-like value that persists, and the embedded DIOBM in the IRP was set up as a result of an indirect call to IOC_STD$FILL_DIOBM, an independent DIOBM can be substituted so long as this is done while still in the original process context at IPL 2. This is illustrated in the following example: { DIOBM *my_diobm; ioc_std$release_diobm( &irp->irp$r_diobm ); ioc_std$create_diobm( irp->irp$pq_va_pte, pte_count, 0, &irp->irp$l_svapte, &my_diobm ); }

The embedded DIOBM is released and an independent DIOBM is created for the locked buffer. Because the created DIOBM is not embedded in the IRP, the (irp$l_svapte) value will remain valid as long as the buffer remains locked and the separate DIOBM exists. The code will need to save the pointer to this created DIOBM and release it immediately after the buffer is eventually unlocked.

Whenever a separate DIOBM is used the (irp$l_svapte) cell must be cleared before the IRP is sent to postprocessing. This is because I/O postprocessing releases the embedded DIOBM in the IRP when it unlocks the user buffer and the attempt to release an unused DIOBM will result in a bug check.

Copying the embedded DIOBM is not recommended because the internal workings of the DIOBM are subject to change. (Impact of MMG_STD$SVAPTECHK Changes\impact_svaptechk)

The current versions of the MMG_STD$SVAPTECHK and MMG$SVAPTECHK routines compute a 32-bit (svapte) for either a process or system space address. As described in (equations_chapter) and (mmg_svaptechk), starting with the Theta release these routines will be restricted to a S0/S1 system space address and will no longer accept an address in P0/P1 space. The MMG_STD$SVAPTECHK and MMG$SVAPTECHK routines will declare a bugcheck for an input address in P0/P1 space. These routines will return a 32-bit system virtual address through the SPT window for an input address in S0/S1 space.

The MMG_STD$SVAPTECHK and MMG$SVAPTECHK routines are used by a number of device drivers and privileged components on the OpenVMS Alpha masterpack. In most instances no source changes are required since the input address is in nonpaged pool. However, there are four cases where the input address can be in P0/P1 space. These four cases are in modules that contribute to the following images: SYS$CPU_ROUTINES_*, SYS$GYADRIVER, SYS$GYBDRIVER, and NETDRIVER.

The 64-bit process-private virtual address of the level-3 PTE that maps a P0/P1 virtual address can be obtained using the new PTE_VA macro. Unfortunately, this macro is not a general solution since it does not address the cross-process PTE access problem. Therefore, the neccessary source changes depend on the manner in which the (svapte) output from MMG_STD$SVAPTECHK is used.

The INIT_CRAM routine in the [SYSLOA]MISC_SUPPORT.B32 module uses the (MMG$\SVAPTECHK) routine in its computation of the physical address of the hardware I/O mailbox structure within a CRAM that's in P0/P1 space. This routine will be changed to use the new IOC_STD$VA_TO_PA routine instead.

The FDT routines GXA$$DMA_SETUP and GYA$$DMA_SETUP in the [R5_DRIVER] GXADRIVER.MAR and [R5_DRIVER]GYBDRIVER.MAR modules compute the physical addresses of each page in a specified caller's DMA buffer. This computation uses the MMG$SVAPTECHK and IOC$SVAPTE_TO_PA routines. These two routines will be changed to use the new IOC_STD$VA_TO_PA routine instead.

The BUILD_DCB routine in the [NETACP]NETDRVNSP.MAR module uses the (MMG$\SVAPTECHK) routine to compute a value for the (dcb$l_svapte) cell from a caller's buffer address in the CXB. The PTE address in (dcb$l_svapte) must be expressable using 32-bits and must be valid regardless of process context. Fortunately, the caller's address is within the buffer that was locked down earlier in the CONV_TO_DIO routine via a call to EXE_STD$WRITELOCK and the EXE_STD$WRITELOCK routine derived a value for the (irp$l_svapte) cell using the DIOBM in the IRP. Therefore, instead of calling the MMG$SVAPTECHK routine, the BUILD_DCB routine will be changed to call the new routine EXE_STD$SVAPTE_IN_BUF, which will compute a value for the (dcb$l_svapte) cell based on the caller's address, the original buffer address in the (irp$l_qio_p1) cell, and the address in the (irp$l_svapte) cell. (Impact of PFN Database Entry Changes\impact_pfn)

There are changes to the use of the PFN database entry cells containing the page reference count and back link pointer. The (SYS$\PDDRIVER) and the DECwindows (SYS$\INDRIVER) drivers are the only drivers on the OpenVMS Alpha masterpack that are impacted by the PFN database changes. The simple source changes are described in (PFN_database_chapter). (Impact of IRP Changes\impact_irp)

All source code references to the (irp$l_ast), (irp$l_astprm), and (irp$l_iosb) cells will need to be changed. As described in (qio_iosb) and (qio_ast), these IRP cells will be removed and replaced by new cells.

A total of 30 source modules on the OpenVMS Alpha masterpack reference one of these cells. In some cases the intended reference is to the value of the $QIO (iosb), (astadr), or (astprm) parameters. Such references will need to be altered to match the 64-bit nature of these parameters. However, in the majority of cases these are references to arbitrary 32-bit parameters that were opportunistically placed in the (irp$l_ast), (irp$l_astprm), or (irp$l_iosb) cells of an internally allocated IRP. These references will need to be changed to use new names that will be defined for this purpose. In either case, the required source changes are localized and simple.

(irp_impact_sum) lists all the current references to these IRP cells on the OpenVMS Alpha masterpack and summarizes the necessary source changes.

(Components Affected by IRP Changes\irp_impact_sum) (multipage\wide) (5\10\10\8\15) (Facility and Module\Images\Reference\Use\Source Change) ([DRIVER]

DUDRIVER.MAR\SYS$DUDRIVER \irp$l_ast \IRP/CDRP assumes\Fix assumes) (\\irp$l_astprm\IRP/CDRP assumes\Fix assumes) ((5)) ([DRIVER]

DUTUSUBS.MAR\SYS$DUDRIVER

SYS$TUDRIVER \irp$l_ast \IRP/CDRP assumes\Fix assumes) (\\irp$l_astprm\IRP/CDRP assumes\Fix assumes) ((5)) ([DRIVER]

RTTDRIVER.MAR\SYS$RTTDRIVER \irp$l_ast \RTT UCB ptr\irp$l_iirp_p0) ((5)) ([DRIVER]

TUDRIVER.MAR\SYS$TUDRIVER \irp$l_ast \IRP/CDRP assumes\Fix assumes) (\\irp$l_astprm\IRP/CDRP assumes\Fix assumes) (\\cdrp$l_astprm\HRB ptr\cdrp$l_hrb) ((5)) ([DUP]

FYDRIVER.MAR\SYS$FYDRIVER \irp$l_ast \Ref to cloned IRP

IRP/CDRP assumes \irp$pq_acb64_ast

Fix assumes) (\\irp$l_astprm\Ref to cloned IRP

IRP/CDRP assumes \irp$q_acb64_astprm

Fix assumes) (\\irp$l_iosb \Ref to cloned IRP

IRP/CDRP assumes \irp$pq_iosb

Fix assumes) ((5)) ([LAD]

LADDRIVER.MAR\SYS$LADDRIVER \irp$l_ast \IOP ptr\irp$l_iirp_p0) (\\irp$l_astprm\S0 buf addr\irp$l_iirp_p1) ((5)) ([LAN]

LAN.MAR\SYS$ExDRIVER

SYS$FxDRIVER

SYS$IxDRIVER

SYS$HCDRIVER

Total of 13 drivers \irp$l_ast \LSB ptr\irp$l_iirp_p0) ((5)) ([LAN]

LAN_NM.MAR\NET$CSMACD

NET$FDDI

NET$TR \irp$l_ast \rout addr\irp$l_iirp_p0) (\\irp$l_astprm\EIB ptr\irp$l_iirp_p1) ((5)) ([MSCP]

MSCP.MAR\MSCP \irp$l_astprm\Local def of irp$l_hrb\Remove local def) (\\cdrp$l_astprm\Local def of cdrp$l_hrb\Remove local def) ((5)) ([MSCP]

TMSCP.MAR\TMSCP \irp$l_astprm\Local def of irp$l_hrb

HRB ptr \Remove local def

irp$l_hrb) (\\cdrp$l_astprm\Local def of cdrp$l_hrb \Remove local def) ((5)) ([NETACP]

NDDRIVER.MAR\NDDRIVER \irp$l_astprm\DWB ptr\irp$l_iirp_p1) (\\irp$l_iosb \CXB ptr\irp$l_iirp_p2) ((5)) ([NETACP]

NETDRVXPT.MAR\NETDRIVER \irp$l_ast \LPD index

Assumes for auto inc \irp$l_iirp_p0

Remove auto inc depend) (\\irp$l_astprm\RCB ptr

Assumes for auto inc \irp$l_iirp_p1

Remove auto inc depend) (\\irp$l_iosb \CXB ptr\irp$l_iirp_p2) ((5)) ([RTPAD]

CTDRIVER.MAR\SYS$CTDRIVER \irp$l_ast \CT UCB ptr\irp$l_iirp_p0) ((5)) ([SCSI]

DKDRIVER.MAR\SYS$DKDRIVER \irp$l_ast \Ref to IRPE\irpe$l_driver_p0) (\\irp$l_astprm\Ref to IRPE\irpe$l_driver_p1) ((5)) ([SDA]

DEVICE.MAR\SDA \irp$l_ast \IRP display\irp$pq_acb64_ast) (\\irp$l_iosb \IRP display\irp$pq_iosb) (\\cdrp$l_ast \CDRP display\cdrp$pq_acb64_ast) ((5)) ([SHADOW]

SHDRIVER.MAR\SYS$SHDRIVER \irp$l_astprm\Mount verify timeout\irp$l_mv_tmo) ((5)) ([SHADOW]

SHDSUBS.MAR\SYS$SHDRIVER \irp$l_iosb \Write log state\irp$l_cln_wle) ((5)) ([SHADOW]

SHD_MERGE.MAR\SYS$SHDRIVER \irp$l_iosb \TQE ptr

write log state \irp$l_cln_wle

irp$l_cln_wle) ((5)) ([SHADOW]

SHD_SYS.MAR\SYS$SHDRIVER \irp$l_astprm\Routine return addr\irp$l_iirp_p1) ((5)) ([SYS]

IOCIOPOST.MAR\IO_ROUTINES \irp$l_astprm\Swap IO KAST\irp$l_iirp_p1) (\\irp$l_iosb \$QIO\irp$pq_iosb) ((5)) ([SYS]

MBDRIVER.B32\SYSDEVICE \irp$l_iosb \Selective cancel\irp$pq_iosb) ((5)) ([SYS]

MOUNTVER.MAR\IO_ROUTINES \irp$l_ast \End action routine\irp$l_iirp_p0) (\\irp$l_astprm\Mount verify timeout\irp$l_mv_tmo) ((5)) ([SYS]

SWAPPER.MAR\SYS$VM \irp$l_astprm\Swap IO KAST\irp$l_iirp_p1) ((5)) ([SYS]

SYSCANCEL.MAR\IO_ROUTINES \irp$l_ast \IRP for IO$_DEACCESS\irp$pq_acb64_ast) (\\irp$l_astprm\IRP for IO$_DEACCESS\irp$q_acb64_astprm) (\\irp$l_iosb \IRP for IO$_DEACCESS\irp$pq_iosb) ((5)) ([SYS]

SYSQIOREQ.MAR\IO_ROUTINES \irp$l_ast \$QIO\irp$pq_acb64_ast) (\\irp$l_astprm\$QIO\irp$q_acb64_astprm) (\\irp$l_iosb \$QIO\irp$pq_iosb) ((5)) ([SYS]

SYSSNDJBC_

RESPONSE.B32\MESSAGE_

ROUTINES \irp$l_astprm\Param for KAST\irp$l_iirp_p1) ((5)) ([SYS]

SYSUPDSEC.MAR\SYS$VM \irp$l_ast \IRP for EXE$BUILDPKTW\irp$pq_acb64_ast) (\\irp$l_astprm\IRP for EXE$BUILDPKTW\irp$q_acb64_astprm) (\\irp$l_iosb \IRP for EXE$BUILDPKTW\irp$pq_iosb) ((5)) ([SYS]

VCC_CACHE.MAR\VCC \irp$l_ast \Assumes for

IOC$SIMREQCOM\ Remove assumes) (\\irp$l_iosb \Setup for IOC$SIMREQCOM\irp$pq_iosb) ((5)) ([SYS]

WRTMFYPAG.MAR\SYS$VM \irp$l_astprm\Swap IO KAST\irp$l_iirp_p1) ((5)) ([TTDRVR]

TTYSTRSTP.MAR\SYS$TTDRIVER \irp$l_ast \Save/restore across FORK\Use EXE$QUEUE_FORK) (\\irp$l_astprm\Save/restore across FORK\Use EXE$QUEUE_FORK) ((5)) ([TTDRVR]

TTYSUB.MAR\SYS$TTDRIVER \irp$l_iosb \Selective cancel\irp$pq_iosb) ((5))

(Impact Statements)

The various impacts emerging from this chapter are listed below. (Performance Impact)

The $QIO system service code path will be increased for existing 32-bit applications by the design outlined in this chapter. It is expected that this increase will be within the budgeted 2% performance degradation limit for the 64-bit Project. The contributors to the increased code path length are: (unnumbered) $QIO will always queue the IRP as 64-bit ACB64 with SCH$QAST. The IRP is larger and will require more memory accesses to complete its setup. A sign extension check on the (p1) parameter will be added. For the most commonly sized direct I/O transfers, some new checks and a PTE copy will be added when a buffer is locked down for direct I/O. For the most commonly sized direct I/O transfers, an additional check will be added during I/O postprocessing when a direct I/O buffer is unlocked. An extra check will be added for each buffered I/O read packet that is completed.

The following steps will be taken to minimize the impact to the existing 32-bit code path: (numbered) Wherever there is a run-time choice between a 32-bit and 64-bit code path, the 32-bit code path will be favored. In the standard version of IO_ROUTINES.EXE in contrast to the full-checking IO_ROUTINES_MON.EXE version, after a buffer is locked for direct I/O, the code that copies the PTEs into the embedded DIOBM in the IRP will be duplicated in-line to avoid the call to IOC_STD$FILL_DIOBM for the most commonly sized buffers. In the standard version of IO_ROUTINES.EXE, after a direct I/O buffer is unlocked, a check of DIOBM$M_PTE_WINDOW and DIOBM$M_AUX_INUSE will be duplicated in-line. In the usual case both of these bits will be clear in the (diobm$l_flags) cell in the embedded DIOBM and the call to IOC_STD$RELEASE_DIOBM can be avoided. Any remaining use of JSB-to-CALL jacket routines will be replaced with direct calls to the standard interface routines in the MACRO-32 I/O modules that need to be altered by this project. There are only a few of these opportunities. Additional .BRANCH_LIKELY directives will be added where they can help in the MACRO-32 I/O modules that need to be altered by this project. There are only a few of these opportunities. The inline function feature of the C compiler will be used where it improves the performance of frequently executed code paths. The quality of the code produced by the C compiler will be manually checked for the new C modules listed in this chapter.

The size of the nonpaged portion of the OpenVMS Alpha kernel will increase slightly due to the additional new code required to implement the 64-bit capabilities. However, this is not expected to increase the minimum memory requirements for OpenVMS Alpha in a significant way.

The 43% increase in the size of the IRP is significant but acceptable since the IRP is a transient consumer of nonpaged pool. However, this increase is likely to put additional pressure for the automatic expansion of nonpaged pool on marginally configured systems. (Verification Impact\impact_verif)

The I/O verification effort can be partioned into regression testing that is focused on the existing 32-bit functionality and testing that is focused on the newly implemented 64-bit functionality.

The number and complexity of the driver changes required to implement the changes described in this chapter are both significantly lower than what was required for the Epsilon release. Thus, for the most part, the existing general I/O and driver specific tests that were utilized for the verification of the Epsilon release will be adequate for the regression testing of 32-bit functionality in device drivers. The various tests detailed in the SCSI-2 Project Test Plan, LAN driver tests, mailbox driver tests, shadowing tests, the UETP device test phase, and the CDROM_AUDIO.EXE test of DK audio support, are the particularly important 32-bit regression tests. Additional tests will need to be located or written for the SYS$DUDRIVER and SYS$TUDRIVER diagnostic buffer support, and the MBDRIVER and SYS$TTDRIVER selective cancel support.

The I/O subsystem changes to solve the PTE access problem for direct I/O need to be well tested. The PTE copy method will be adequately tested by normal system operation under the 32-bit regression tests. However, specific tests will need to be found, or modified, to use large enough buffers to test the secondary DIOBM and PTE window code paths.

One error that callers of the new DIOBM routines might be prone to is failure to release a DIOBM when the corresponding memory is unlocked or when the mapping is no longer needed. These types of errors will generally not result in immediate faults. Their symptoms are likely to be slow nonpaged pool memory leaks or depletion of the system page table. The (diobm$v_inuse) flag bit check described in (diobm_struct) is designed to catch failures to release embedded DIOBM structures that are reused.

Verification of the 64-bit functionality will require modifications to existing tests to create buffers in the P2 and S2 spaces. The minimal requirement is that the SYS$QIOTST.EXE, EVX.EXE, the mailbox driver test images, a LAN $QIO test, and the SCSI diagnose function tests are enhanced to include specific tests of the new 64-bit functionality. A likely error in the 64-bit I/O support code or in 64-bit capable drivers is the inadvertent handling of a 64-bit address as a 32-bit quantity. It is desireable that such errors manifest themselves as kernel mode ACCVIOs instead of as a data corruption. Thus, these tests should insure that the lower-order 32-bits of any P2 or S2 buffer address do not constitute a valid address for that process in any mode. (Documentation Impact)

The changes that must be made to device drivers to support 64-bit addressing, the new and revised revised system routines, and changes to internal OpenVMS data structures of interest to device drivers, will need to be documented in the following OpenVMS manuals: (simple) (OpenVMS Alpha Device Support: Developer's Guide\italic) (OpenVMS Alpha Device Support: Reference\italic) (Creating an OpenVMS Alpha Step 2 Device Driver from an OpenVMS VAX Device Driver\italic)

Brief descriptions of these changes, recompiling and relinking information, and pointers to the appropriate manuals will also be included in the (OpenVMS Release Notes\italic) and (OpenVMS New Features\italic) manuals. Details about which changes will be included in each OpenVMS Alpha device driver manual can be found in the device driver docplan for the Theta release, which is currently being written.

The (OpenVMS I/O User's Reference Manual\italic) will include information about those drivers on the OpenVMS Alpha masterpack that will contain support for 64-bit addresses for the Theta release and those that will not. Because this book is scheduled to be published in an online-only format for the Theta release, this information will also be included in the (OpenVMS Release Notes) and (OpenVMS New Features) manuals.

The (LAN VCI Specification) will also require some revisions that will need to be marked as being specific to OpenVMS Alpha. Although the (LAN VCI Specification) is not part of the OpenVMS Documentation Set, it is utilized by other groups within Digital. (Revision History)

Change bars are used to identify all substantial changes and additions between the V1.1 and V1.2 versions of this document. These changes and additions reflect the implementation of this design in OpenVMS Alpha Version 7.0.

(simple)

(Revision V1.0, Sept 19, 1994\bold) (numbered) Szubowicz - Additional sections while review of X0.3 pending, Sept 14, 1994. Szubowicz - Completion of 64-bit IOSB address discussion, Sept 18, 1994. Szubowicz - Completion of ACB64 discussion, Sept 18, 1994. Szubowicz - Completion of IRP change impact section, Sept 18, 1994. Szubowicz - Incorporate comments from review of X0.3, Sept 19, 1994.

(Revision X0.3, Sept 12, 1994\bold) (numbered) Szubowicz - Additional sections while review of X0.2 pending, Aug 5, 1994. Szubowicz - Incorporate comments from review of X0.2, Sept 2, 1994. Szubowicz - Generalize DIOBM and replace IOC$SET_IRP_SVAPTE, Sept 2, 1994. Szubowicz - Completion of SCSI diagnose discussion, Sept 2, 1994. Szubowicz - Completion of diagnostic buffers discussion, Sept 9, 1994. Szubowicz - Completion of LAN VCI discussion, Sept 9, 1994. Szubowicz - Completion of LAN driver discussion, Sept 9, 1994. Szubowicz - Completion and additions to various sections, Sept 12, 1994.

(Revision X0.2, Aug 2, 1994\bold) (numbered) Szubowicz - Additional sections while review of X0.1 pending, July 20, 1994. Szubowicz - Start incorporating feedback from review of X0.1, Aug 1, 1994. Szubowicz - Completion of additional sections for review, Aug 2, 1994.

(Revision X0.1, July 18, 1994\bold) (numbered) Szubowicz - First partial draft for initial review, July 18, 1994.