|
|
|
|
|
DDT Intercept Establisher Routines and Device Configuration Notification Routines
These routines, when used in third-party kernel-mode applications such as disk caching products and SCSI disk-shadowing applications, enable these applications to run in an OpenVMS SCSI or Fibre Channel multipath configuration. Any third-party applications that rely on altering the DDT of the OpenVMS Alpha SCSI disk-class driver (SYS$DKDRIVER.EXE), the SCSI tape-class driver (SYS$MKDRIVER), or the SCSI generic-class driver (SYS$GKDRIVER) will require source changes to use these new routines.
If you are using a third-party disk-caching product or disk-shadowing application, avoid using it in an OpenVMS SCSI or Fibre Channel multipath configuration until you confirm that the application has been revised to use these new routines.
These new routines provide a solution to a problem that developed after the introduction of SCSI and Fibre Channel multipath support in OpenVMS Alpha Version 7.2-1. Customer were advised to avoid using these third-party SCSI disk-caching and disk-shadowing applications when their SCSI devices were configured for multipath failover. The new routines enable providers of third-party application providers to modify their applications so that they function correctly.
DDT Intercept Establisher
Routines
New routines establish the DDT intercepts. Third-party applications
that modified the DDT directly can be modified to use the appropriate
establisher routines, so that they function properly in an OpenVMS
SCSI or Fibre Channel configuration. These routines establish intercepts
on a per-UCB basis.
At a given entry point, there can be multiple declarations of DDT intercepts. The following figure illustrates multiple DDT declarations.
Figure 1 DDT Intercepts |
The new DDT intercept establisher routines are:
If there are multiple declarations of DDT intercepts, they are called in descending order, from the highest level DDT (DDT$K_ITCLVL_TOP) to the lowest-level DDT (DDT$K_ITCLVL_DRVR).
Although the standard driver cancel, altstart, start, and mntver routines do not return a status, the intermediate routines must return either SS$_SUPERSEDE or SS$_CHAINW status. Any other return value results in a bugcheck. As the return value suggests, the SS$_SUPERSEDE return value from the intermediate routine supersedes the lower-level call to the DDT intercept routines. The SS$_CHAINW return value from the intermediate routine causes the next lower-level DDT intercept routines to be called.
The intercept DDTs are placed in the DDT chain according to their level. The top-level DDT is always the dispatcher DDT, and the bottom-level DDT is always the driver-level DDT. Other DDTs are placed in descending order between the top-level DDT and the driver-level DDT.
Intercept Levels
The following intercept levels are currently defined and reserved
for use by HP:
DDT$K_ITCLVL_TOP 32767
DDT$K_ITCLVL_HSM 24576
DDT$K_ITCLVL_MPDEV 4096
DDT$K_ITCLVL_DRVR 0
The valid intercept levels are from 4097 to 32766, except for 24576, which is reserved for the HSM interval. You can define as many intercepts as needed in that range.
Restrictions
The following restrictions exist:
Routines
The following pages provide the functional description of
each routine.
Establishes DDT$PS_START_2 intercept.
This routine establishes the intercept of the DDT$PS_START_2 routine.
Calling Conventionint ioc_std$establish_ddt_start (UCB *ucb, int (*start_itc_routine)(IRP *irp,
UCB *ucb), int level,int flag)
ucb |
Pointer to a UCB whose DDT$PS_START_2 is to
be intercepted. |
start_itc_routine |
The intercepting start routine. This
routine is called before the driver's start routine. The
calling convention of the start routine is the same as the standard
DDT$PS_START_2 routine, except that this routine must return one
of the following status values: SS$_CHAINW - The next start routine should be called. Any other return value results in a bugcheck. |
level |
Level of DDT to be intercepted. Currently,
multipath does not support an intercept level below MPDEV intercept. |
flag |
Placeholder for future development; must be
zero. |
SS$NORMAL
DDT intercept added successfully.
This routine may also return various other error
status values,
including
any status returned on a failure to allocate pool.
Caller must be in kernel mode, IPL at or below UCB fork IPL.
Almost all use of the DDT within OpenVMS requires holding the UCB fork lock. This is why this routine acquires and conditionally releases the UCB fork lock to change the DDT.
IOC_STD$ESTABLISH_DDT_ALTSTART
Establishes DDT$PS_ALTSTART_2 intercept.
This routine establishes the intercept of the DDT$PS_ALTSTART_2 routine.
Calling Conventionint ioc_std$establish_ddt_altstart (UCB *ucb, int (*altstart_itc_routine)(IRP *irp,
UCB *ucb), int level,int flag)
ucb |
Pointer to a UCB whose DDT$PS_ALTSTART_2 is
to be intercepted. |
altstart_itc_routine |
The intercepting altstart routine. This
routine is called before the driver's altstart routine.
The calling convention of the altstart routine is the same as the
standard DDT$PS_ALTSTART_2 routine, except that this routine must return
one of the following status values: SS$_CHAINW - The next altstart routine should be called. Any other return value results in a bugcheck. |
level |
Level of DDT to be intercepted. Currently,
multipath does not support an intercept level below MPDEV intercept. |
flag |
Placeholder for future development; must be
zero. |
SS$NORMAL DDT
intercept added successfully.
This routine may also return various other error status
values,
including
any status returned on a failure to allocate nonpaged pool.
Caller must be in kernel mode, IPL at or below UCB fork IPL.
Almost all use of the DDT within OpenVMS requires holding the UCB fork lock. This is why this routine acquires and conditionally releases the UCB fork lock to change the DDT.
Establishes DDT$PS_CANCEL_2 intercept.
This routine establishes the intercept of the DDT$PS_CANCEL_2 routine.
Calling Conventionint ioc_std$establish_ddt_cancel (UCB *ucb, int (*cancel_itc_routine)(int chan,
IRP *irp,PCB *pcb,UCB *ucb, int reason), int level,int flag)
ucb |
Pointer to a UCB whose DDT$PS_CANCEL_2 is to
be intercepted. |
cancel_itc_routine |
The intercepting cancel routine. This
routine is called before the driver's cancel routine. The
calling convention of the cancel routine is the same as the standard DDT$PS_CANCEL_2
routine, except that this routine must return one of the following
status values: SS$_CHAINW - The next cancel routine should be called. Any other return value results in a bugcheck. |
level |
Level of DDT to be intercepted. Currently,
multipath does not support an intercept level below MPDEV intercept. |
flag |
Placeholder for future development; must be
zero. |
SS$NORMAL DDT
intercept added successfully.
This routine may also return various other error status
values,
including
any status returned on a failure to allocate nonpaged pool.
Caller must be in kernel mode, IPL at or below UCB fork IPL.
Almost all use of the DDT within OpenVMS requires holding the UCB fork lock. This is why this routine acquires and conditionally releases the UCB fork lock to change the DDT.
Establishes DDT$PS_MNTVER_2 intercept.
This routine establishes the intercept of the DDT$PS_MNTVER_2 routine.
Calling Conventionint ioc_std$establish_ddt_mntver (UCB *ucb, int(*mntver_itc_routine)(IRP *irp,
UCB *ucb), int level,int flag)
ucb |
Pointer to a UCB whose DDT$PS_MNTVER_2 is to
be intercepted. |
mntver_itc_routine |
The intercepting mntver routine. This
routine is called before the driver's mntver routine. The
calling convention of the mntver routine is the same as the standard DDT$PS_MNTVER_2
routine, except that this routine must return one of the following
status values: SS$_CHAINW - The next mntver routine should be called. Any other return value results in a bugcheck. |
level |
Level of DDT to be intercepted. Currently,
multipath does not support an intercept level below MPDEV intercept. |
flag |
Placeholder for future development; must be
zero. |
SS$NORMAL DDT
intercept added successfully.
This routine may also return various other error status
values,
including
any status returned on a failure to allocate pool.
Caller must be in kernel mode, IPL at or below UCB fork IPL.
Almost all use of the DDT within OpenVMS requires holding the UCB fork lock. This is why this routine acquires and conditionally releases the UCB fork lock to change the DDT.
Device
Registration Callback Routines
OpenVMS Alpha Version 7.3-2 also introduces a kernel-mode
API for notification of device configuration by way of a callback.
This API was designed to enhance the functionality provided by the
new IOC_STD$ESTABLISH_DDT_xxx routines, which
provide a mechanism to intercept calls through a driver dispatch
table (DDT).
This API provides a kernel mode "registration" routine, IOC_STD$DEVCONFIG_REGISTER, that privileged code can call, and a complementary routine, IOC_STD$DEVCONFIG_DEREGISTER, to revoke the registration. The registration routine specifies a device class and a callback routine address. Subsequently, when any new device of that class is configured, the specified callback routine is called before the device becomes visible to other threads of execution.
The callback routine can call any of the IOC_STD$ESTABLISH_DDT_xxx routines for that device and thus guarantees that the driver intercept is in place before any I/O could possibly be issued to the driver.
Delivers a notification via a callback when a new device of a specified device class is configured on this system.
IOC_STD$DEVCONFIG_REGISTER is the registration routine that delivers a notification via a callback when a new device of a specified device class is configured on this system. The callback notification occurs when a device is first configured on a system. Notification is not provided when an additional path or a new MSCP server is added for an existing device.The notification mechanism remains in effect until it is revoked by a call to the IOC_STD$DEVCONFIG_DEREGISTER routine.
Calling Conventionint
ioc_std$devconfig_register( int flags, int devclass, void
(*devconfigured)(UCB *ucb, int64 user_param), int64 user_param, int64
*ret_handle );
flags |
Reserved for future enhancements. Must be zero.
All other values result in a SS$BADPARAM error. |
devclass |
The device class value, DC$_xxx from
devdef.h in STARLET, for which notification is desired. Any value
greater than 0 and less than 256 is supported. All other values
result in a SS$BADPARAM error. |
devconfigured |
Address of the caller's desired callback
routine, which must be in S0/S1 space. When a new device is configured,
this routine is called after the device UCB has been linked into
the I/O database and sufficiently initialized so that the I/O database mutex
is about to be released. This is after the appropriate driver's
structure initialization routine has been called but before the
driver's unit initialization is called. The IPL is at the UCB
fork IPL, and the UCB fork lock is held. |
user_param |
Arbitrary 64-bit integer parameter that is
passed to the callback routine. Can be used by the callback routine
as a context parameter. The same combination of devclass value, devconfigured value,
and user_param value cannot be registered twice. |
ret_handle |
64-bit "handle" that can
be used with the ioc_std$devconfig_deregister routine to revoke
this notification request. The caller should treat the ret_handle value
as an "opaque" quantity. A ret_handle value
of zero is returned if the routine fails. |
SS$_NORMAL
Notification was successfully delivered.
SS$_BADPARAM The flags or devclass parameter
values are invalid.
SS$_IVADDR
The callback routine address is not in S0/S1 space.
SS$_CBKEXISTS Callback
already exists for this combination of devclass, devconfigured,
and
user_param values.
Multiple registration request for exactly the same notification
routine, device class, and
parameter are not allowed.Other return values: Other error
return values are possible, including any error return from an attempt
to
allocate nonpaged
pool.
This routine must be called from kernel mode, process context, IPL 2 or lower. It returns at the entry IPL. This routine declares an SPLIPLHIGH fatal bugcheck if the entry IPL is greater than 2.
Access to the list of registered device configuration callbacks is protected by the I/O database mutex. Therefore, this routine acquires the I/O database mutex for write access and may put the calling process into a resource wait state. This routine releases the I/O database mutex and restore the entry IPL before returning to the caller.
IOC_STD$DEVCONFIG_DEREGISTER revokes a device configuration notification callback that was previously enabled by a call to IOC_STD$DEVCONFIG_REGISTER.
Calling Conventionint ioc_std$devconfig_deregister( int64 ret_handle );
ret_handle |
64-bit "handle" that was
returned by a prior call to ioc_std$devconfig_deregister. |
SS$_NORMAL
Successfully revoked notification.
SS$NOSUCHCBK
Did not find a registered device configuration
callback with the specified handle,
or the handle value is invalid.
This routine must be called from kernel mode, process context, IPL 2 or lower. It returns at the entry IPL. This routine will declare a SPLIPLHIGH fatal bugcheck if the entry IPL is greater than 2.Access to the list of registered device configuration callbacks is protected by the I/O database mutex. Therefore, this routine acquires the I/O database mutex for write access and may put the calling process into a resource wait state. This routine releases the I/O database mutex before returning to the caller.
Device
Configuration Callback Routine
Functional Description
The device configuration callback routine is a caller-specified routine. It is established as a device configuration callback routine by a call to the IOC_STD_$DEVCONFIG_REGISTER register routine.
The device configuration callback routine is called after a new device UCB has been linked into the I/O database and sufficiently initialized such that the I/O database mutex is about to be released. This is after the appropriate driver's structure initialization routine has been called but before the driver's unit init routine is called.
The device configuration routine must be accessible in system context. Therefore, the address of the device configuration routine must be in S0/S1 space. This is enforced by the IOC_STD$DEVCONFIG_REGISTER routine.
The callback is not invoked when an additional path or a new MSCP server is added for an existing device, even though an additional UCB could be created for the new path.
Calling Conventionvoid (*devconfigured)(UCB *ucb, int64 user_param );
ucb |
Address of the UCB that was just linked into
the I/O database. |
user_param |
64-bit value that was specified on the call
to ioc_std$devconfig_register that established this callback routine. |
None.
The device configuration callback routine is called in kernel mode at UCB fork IPL, with the UCB fork lock held. The I/O database mutex is held for write access.
Note that the environment of the device configuration routine is not appropriate for calls to IOC_STD$DEVCONFIG_REGISTER and IOC_STD$DECVCONFIG_DEREGISTER
|
|