EPICURE Design Note 3.9<P> <b> VMS System Services for QVI Support</b>

EPICURE Design Note 3.9

VMS System Services for QVI Support

David M. Kline

This document shows the calling sequences for the QVI routines on the 80386 DAE processors with C as well as for use on the VAX under VMS. In addition, several VME Common Memory structures are outlined. See Epicure Design Note 6 for more information on Common Memory data structures and formats.

Introduction

The data sources for the EPICURE system are the MicroVAX Front End and the VME-based Data Acquisition Engines (DAE). The MicroVAX is interfaced to the VME crate by the QBus/VME Interface (QVI) which allows VME address space to appear as if it were QBus memory. The MicroVAX and DAE processors communicate via the Common Memory (CM) area in a VME memory module. All communication between the MicroVAX and the DAE and between DAE modules is done by passing messages using queues in the CM. A set of user-written VMS system services supports access to the CM from the MicroVAX. A smaller set of routines provides support for the DAE processors to manipulate information in the Common Memory. These various services are required due to: The QVI services provide a means of encapsulating these needs and presenting a simpler interface to the Data Acquisition Server (DAS), the primary user of the QVI services. Similarly, the CM routines for the DAE processors provide a simple interface to the programmers and implement the same queue handling protocol as the QVI services.

A special device driver on the MicroVAX, the UICDRIVER, is needed to handling the fielding of interrupts from the QVI. This driver was derived from the Digital Connect-to-Interrupt driver and is designed to handle the Advanced Micro Devices 9519A Universal Interrupt Controller.

Descriptions of the QVI and CM Services

The QVI services are similar to the VMS system services. All the routines are functions returning a 32-bit VMS condition code as a status (with one exception). Scalar input arguments are passed by value; output or modified (read-write) arguments and input arrays are passed by reference (except as noted). The QVI services are divided into two classes, the QVI_US routines for most users and the QVI_CS core routines for special programs and diagnostics. Service routines for the DAE processors are based on a simple subset of the QVI_US routines called the CM (for Common Memory) routines. The CM routines return VMS status codes to indicate success or failure; input arguments are passed by value and output arguments have a pointer passed by value (standard C calling sequences).

Common Memory queues and blocks are referenced by ``handles'' which are either offsets relative to the start of the Common Memory or addresses within the Common Memory as mapped into the local process's virtual address space (VAS). In particular, the actual interpretation of the ``handles'' returned by the QVI_US routines is unimportant to the users of the QVI_US routines. This does not hold true for the QVI_CS routines where the documentation spells out whether a particular ``handle'' is an actual address or just an offset. The CM routines use 32-bit VMEBus addresses for Common Memory structures (normal startup of the 80386 DAE processors must setup for a 4 Gigabyte linear address space).

Common Memory Block Format

The Common Memory block which is entered or removed from a CM queue is called a CMB (for Common Memory Block). The CMB consists of two concatenated structures: the UMB contains the fields of importance to users, the CMH is the Common Memory Header containing information used only by the QVI services and the DAE modules. The fields of the UMB and The format of a CM block which is entered or removed from a CM queue is:

This structure is called a CMB for Common Memory Block. The CMB consists of two concatenated structures: the UMB contains the fields of importance to users, the CMH is the Common Memory Header containing information used only by the QVI services and the DAE modules. The fields of the UMB and CMH which are common to all types of CMBs are: list [cmb_r_cmh] This structure contains the header fields of the CMB: list [cmh_l_link] This longword is the queue link. It contains a pointer to the next entry in the queue or a 0 if this is the tail entry. Normally this field is only of concern to the QVI and CM routines. [cmh_l_rtnqid] This longword is set to the queue handle (qhdl) for the VAX return queue associated with the user process. The return qhdl is used to return the CMB to the originator upon completion of the actions requested by the CMB contents. [cmh_l_orgid] This longword contains the same value as the rtnqid longword for normal return queues. Such queues are normally associated with an interrupt attached to the destination process on the VAX or are polled by that process. If the return queue used is the multiplexed return queue, then the value in this longword is used by the process to locate the true destination process and its return queue (see the information on the Queue Demultiplexing Block below). [cmh_l_diqhdl] This longword contains the handle of the DAE input queue. The QVI_US_GET routine uses this field to route the CM block to its destination queue if it is to be recycled. The queue handle is taken from the QIB which specifies the default DAE input queue. Applications can override the default queue by specifying the altdiq parameter of the QVI_US_PUT routine.

[cmb_r_umb] This structure is the portion of the CMB manipulated by the user of the QVI or CM services. The fields of the UMB are: list [umb_l_flags] This is a bit-vector of flags in a longword. The lowest bit (bit 0) is used as the CYCLE bit. If this bit is 1, when the CMB is removed from the VAX return queue it is placed back on the default processing queue rather than released to the free queue (cycled for another processing pass).

Bit 1 is used by the DAE processors as the first time flag ( 1ST_TIME). This flag is used by the DAE Timer processor on cyclic requests to flag the first cycle (or the first time that the Timer has seen this request).

Bits 2-4 are used by the DAE Timer processor to support fast time plot control and data buffer processing and expunges. [umb_w_type] This word contains an identification code describing the data contents of this UMB and is of direct concern to the users of the QVI and CM routines. [umb_w_reqsiz] This word contains the requested UMB size in bytes. This may not be the actual size of the UMB (or enclosing CMB); there may be unused bytes (internal fragmentation) between the end of the data and the actual end of the UMB. [umb_r_data] This is the start of the data field of the UMB. The format and contents of this portion of the UMB are specific to the block type defined by the Common Memory user. The cmh_l_rtnqid field is sometimes of concern to the DAE programmer. This field identifies the return queue of the ``originator'' of the message and is sometimes used if the request is fatally flawed and cannot be processed. In this case, the return queue identifier is used to route the request immediately back to the originator, usually with the CYCLE bit cleared and a error status someplace in the data fields.

CMB Structure Definitions

There C structure definitions reflect those in (see below). The definition of the UMB0 structure is given here as a prototype definition for the user block. Common Memory users should supply their own definitions, replacing the umb_r_data field with definitions specific to their applications.

 
struct CMH {
    unsigned long cmh_l_link;
    unsigned long cmh_l_rtnqid;
    unsigned long cmh_l_orgid;
    unsigned long cmh_l_diqhdl;
    };

  
struct UMB0 {        /* Prototypical definition */
    unsigned long umb_l_flags;
    unsigned short umb_w_type;
    unsigned short umb_w_reqsiz;
    unsigned long umb_r_data[2];
    };
  
#define  UMB_M_CYCLE     0X00000001
#define  UMB_M_1ST_TIME  0X00000002
#define  UMB_M_SUSPEND   0X00000004
#define  UMB_M_AVAILABLE 0X00000008
#define  UMB_M_EXPNDG    0X00000010
struct CMB {
    struct CMH cmb_r_cmh;
    struct UMB0 cmb_r_umb;
    };

Multicast Block Format

Provision is made for a special form of a UMB for ``multicast'' messages which are routed to all the DAE processors for which entries appear in the Queues Table. This special UMB is constructed by the DAP$MULTICAST routines (see below); the QVI user provides a block type and up to 4 longwords of multicast parameters. The DAE programmer basically receives this like any other request but does have QVI-equivalent CM services for forwarding the multicast request to the next destination.

The multicast message is sent to the first DAE processor with a non-zero Queue Table entry. The Queue Table Index (QTI) for this entry is stored in the multicast message. Each destination picks up the current QTI from the multicast message and begins searching the Queue Table from that point forward (towards the end of the Queue Table) for the next non-zero entry which will be the next destination of the multicast message. When the end of the Queue Table is reached, the multicast message is returned via the return queue handle in the CMB header.

Locating the QVI Files and Linking With the QVI Services

The QVI code is stored under the project of the . The procedure in area of defines the logical names and which specify the current locations of the QVI include files (except for those which are stored under the logical name ) and the shareable image. The files include: list [CMDEF.H] Contains definitions for the Common Memory structures for VAX and 80386 C programs. Stored in . [CMDEF.S] Public Common Memory definitions for 68020 assembly code modules ( semi-Obsolete). [QVIDEF.H] Definitions of QVI and AMD 9519 Interrupt Controller hardware (used internally in the QVI routines). [QVIMSG.A86] Definitions of the QVI status code constants (as symbols QVI__xxxx) for 80386 assembly language modules. [QVIMSG.H] Definitions of the QVI status code constants (as symbols QVI__xxxx) for C programs. Stored in . [QVIMSG.S] Definitions of the QVI status code constants for 68020 assembly code. [QVIVAXC.OPT] Options file for VAX Linker to link with the QVIUSS shareable image. The QVI routines in the shareable image can be linked to by adding to the command line:
    $ link  ...,qvi_inc:qvivaxc/options,...
This options file specifies that both the and the (VAX C Run Time Library shareable image in ) be linked to the image.

The QVI procedure also defines the logical name which specifies the current location of the object code files for the 80386 (file types ). The available files are: list [CMQLOCK] Contains the queue lock routines with the Test and Set instructions. Must be linked with all DAE system software. [CMQ] Contains the basic CM routines for manipulating the Common Memory queues. Must be linked with all DAE system software. [CMQGET] Contains the optional CM routines used if the DAE system will be generating unsolicited requests and so needs access to the free list queues. [CMQPOOL] Contains the optional CM data pool services for locating a Common Memory DataPool and locking or unlocking a DataPool.

VAX QVI User Services

Several ``combined'' service routines are defined to provide a simple interface to the DAE for the Data Acquisition Server (DAS) and other similar processes. The details of the Core Services are hidden within the US calls. In addition, the initialization routine provides for connecting to a interrupt-driven queue and receiving the interrupt notifications via event flags or ASTs.

QVI_US_DAP$LOCATE

status = QVI_US_DAP$LOCATE( qti, qhdl ) Locate a queue by its DAP queue index and return the queue handle. This routine is usually called once and the queue handle saved for later use in QVI_US_DAP$MULTICAST. qti DAP Queue Table index (unsigned byte, 0..255). Passed by value. qhdl queue handle returned in a longword. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__NOQUE fatal, queue not found QVI__NOTINIT fatal, QVI_US services not initialized

QVI_US_DAP$MULTICAST

status = QVI_US_DAP$MULTICAST( blktyp, mcpars, [cmbhdl] ) Allocate a free CM block and build a multicast UMB into this block. The first longword of the multicast UMB (after the standard UMB header) contains the Queue Table Index of the current queue; this is followed by 4 longwords of multicast parameters specified by the caller. This routine initializes the QTI longword to the first non-zero QTI entry. The CM block is then placed on the CM queue specified by that QTI entry. As each destination processes the multicast message, it advances the QTI longword to the next non-zero entry in the QTI table and passes the block on to that destination until all the QTI entries have been visited; after which the block is returned to the VAX by the return queue identifier found in the CM block header. blktyp Block type for the multicast UMB. Passed by value. mcpars Parameters for the multicast message. A block of 4 longwords (16 bytes) passed by reference. cmbhdl optional longword in which to return a pointer to the CMB allocated from the free list and filled with the multicast UMB contents. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__QTIEMPTY success, no multicast as QTI empty QVI__NOFREE error, no free CM blocks of the needed size are available QVI__QLCKFAI error, failed to acquire queue lock QVI__IVQLINK fatal, invalid queue link, possible CM corruption QVI__NOTINIT fatal, QVI_US services not initialized

QVI_US_GET

status = QVI_US_GET( maxsize, umbbuf, [,blkhdl] ) Remove the CM block from the head of the VAX return queue specified in the QVI_US_INIT call and return the UMB contents from the CM block in the provided buffer. The CM block is either released to the free list or recycled depending on the value of the CYCLE flag. maxsize maximum expected UMB size. Passed by value. umbbuf address of a buffer in VAX memory to be filled with the contents of the UMB in the dequeued CM block. Passed by reference. blkhdl optional longword in which the block handle used to identify the dequeued CM block is returned. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__EMPTY warning, return queue was empty QVI__TRU warning, return block truncated as UMB too small QVI__QLCKFAI error, failed to acquire queue lock QVI__IVQLINK fatal, invalid queue link, possible CM corruption QVI__NOTINIT fatal, QVI_US services not initialized others as returned by QVI_CS and VMS services

QVI_US_INIT

status = QVI_US_INIT( qname [,efn] [,ast] [,astprm] [,astcnt] ) Initialize the QVI_US services, including mapping all needed global sections which were created during the Common Memory initialization. The logical name RDCS$QVI_DAE_QUEUE is translated to provide the name of the CM queue to which messages are queued by QVI_US_PUT if no explicit target queue is given. This default queue is also used by QVI_US_GET for messages with the CYCLE flag set. The RDCS$QVI_WASTE_QUEUE logical name provides the name of the CM queue used as the "toxic waste" queue when inserts of "defunct" blocks onto the free lists fail. Also, the name of the CM return queue specified in the call is used to form the RDCS$QVI_VAXQ_name logical name which should translate to the VMS device to assign an I/O channel for the interrupt handling if either an event flag or an AST routine is specified in the call to this service. The RDCS$QVI_DEMUX_QUEUE logical name gives the name of the multiplexed CM queue to allow QVI user processes using that queue to specify it as the return queue. This is done automatically by QVI_US_INIT if the queue name specified in the call is marked as a multiplexed queue (MUX bit in the queue header). qname queue name to be used by this process as its VAX return queue. The queue name is a 1-8 character string passed by descriptor. efn Optional event flag number to be set when a block appears on the VAX return queue for processing. Passed by value. ast Optional address of an AST routine to be invoked when a block appears on the VAX return queue for processing. Passed by reference (address of the procedure's entry mask). astprm Optional parameter to be passed to the AST routine. Passed by value. astcnt Optional parameter specifying a count of AST blocks to be preallocated for handling rapid interrupts. Default value of 10 is used. Passed by value. status returns a VMS condition code: SS$_NORMAL success QVI__CMINIT fatal, CM not initialized QVI__MAPERR fatal, failed to map CM properly QVI__NOQUE fatal, queue named not found others as returned by QVI_CS and VMS services

QVI_US_LOCATE

status = QVI_US_LOCATE( qname, qhdl ) Locate a named queue and return its queue handle. This service is typically used once per queue and the resulting queue handle saved for later use with QVI_US_PUT. qname queue name to be located. The queue name is a 1-8 character string passed by descriptor. qhdl Queue handle returned in a longword. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__NOQUE fatal, queue named not found QVI__NOTINIT fatal, QVI_US services not initialized others as returned by QVI_CS and VMS services

QVI_US_MODFLG

status = QVI_US_MODFLG( blkhdl [,rmask] [,smask] ) Modify the flag bits of the specified CM block. This is normally used to clear the CYCLE flag before queuing a multicast EXPUNGE request for that CM block. The CM block handle must have been saved from a previous QVI_US_PUT call. blkhdl block handle used to identify the CM block whose flag bits are to be modified. Passed by value. rmask mask of those UMB_L_FLAGS bits to be reset (cleared to zero). Passed by value. smask mask of those UMB_L_FLAGS bits to be set (to one). Passed by value. status returns a VMS condition code: SS$_NORMAL success QVI__NOTORG error, not originator of CM block QVI__BADBHDL fatal, bad block handle QVI__NOTINIT fatal, QVI_US services not initialized others as returned by QVI_CS and VMS services

QVI_US_PUT

status = QVI_US_PUT( umbbuf [,toqhdl] [,blkhdl] [,altdiq] ) Allocate a block of CM and copy the UMB (User Memory Block) contents into the CM block from the VAX buffer. The CM block is then placed on the specified target CM queue. umbbuf address of a buffer in VAX memory to be copied into the UMB portion of the CM block. Passed by reference. The UMB size will be taken from the umb_w_reqsiz word in the VAX buffer. toqhdl optional queue handle of the target CM queue. Passed by value. If not specified (or specified as 0), then the block will be placed on the default DAE queue. This argument is the queue handle returned from a previous call to QVI_US_LOCATE. blkhdl optional longword in which the block handle used to identify the allocated CM block is returned. Passed by reference. altdiq optional queue handle of the CM queue which will receive the CM block if the CYCLE bit is set. Passed by value. If the parameter is not supplied or contains a value of zero, the CM block is directed towards the default DAE input queue as specified by the RDCS$QVI_DAE_QUEUE logical. This argument is the queue handle return from a previous call to QVI_US_LOCATE. status returns a VMS condition code: SS$_NORMAL success QVI__NOFREE error, no free CM blocks of the required size QVI__QLCKFAI error, failed to acquire queue lock QVI__BADQHDL fatal, bad queue handle QVI__IVQLINK fatal, invalid queue link, possible CM corruption QVI__NOTINIT fatal, QVI_US services not initialized QVI__TOOBIG fatal, requested size exceeds that of the largest CM block others as returned by QVI_CS and VMS services

QVI_US_RESINM

status = QVI_US_RESINM( [efn] [,ast, astprm] ) This routine is called to reestablish the mechanism used to notify processes that an interrupt from the Qbus adapter has been received. efn integer value of the event flag number set when an interrupt is received. Passed by value. ast address of the function to execute when an interrupt occurs. Passed by reference. astprm integer value passed to the AST routine if the ``ast'' parameter is specified. Passed by value. status returns a VMS condition code: SS$_NORMAL success SS$_BADPARAM fatal, bad parameter value FALSE error, services not initialized others as returned by VMS and $QIO services

QVI_US_TEST

status = QVI_US_TEST( [size] ) Test the VAX return queue (specified in the QVI_US_INIT call) to see if any entries are currently queued. size optional longword in which the size of the UMB in the CM block at the head of the queue is returned. Passed by reference. If the queue is empty, then zero is returned. status returns a VMS condition code: SS$_NORMAL success QVI__EMPTY warning, return queue was empty QVI__QLCKFAI error, failed to acquire queue lock QVI__IVQLINK fatal, invalid queue link, possible CM corruption QVI__NOTINIT fatal, QVI_US services not initialized others as returned by QVI_CS and VMS services

QVI Core Services

The QVI Core Services (CS) are meant for direct use by the Common Memory initialization program and by diagnostics programs. In addition, several of the Core Services are used by the User-level Services (US routines) described above. In the US routines, queue headers and CM blocks are identified using ``handles'' which are meant to be transparent to the US users. In the CS routines, the handles are explicitly referred to as either offsets relative to the CM base or as addresses in the CM (in the local process's VAS). The CS routines locate the CM global section in the local VAS by the Common Memory Descriptor (cmdescr arguments in the routine descriptions). The CM Descriptor is a structure of 16 longwords (64 bytes) containing the base addresses (in the process's VAS) of the CM global section and other QVI-associated global sections along with other information needed by the QVI services. The US routines maintain a Common Memory descriptor in hidden static storage.

QVI_CS_CM2VAX

status = QVI_CS_CM2VAX( cmdescr, cmbptr, size, block ) Copy an array of longwords from a CM block into VAX memory. cmdescr CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAPCM service. Passed by reference. cmbptr pointer to the CM block to be copied. Consider the pointer as passed by value or that the CM block itself is passed by reference (address of the CM block appears in the argument list). size Size of the longword array in bytes. Passed by value. block address of target VAX buffer to receive the longwords from the CM block. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__IVCMDS fatal, invalid CM descriptor QVI__BADBHDL fatal, bad block handle

QVI_CS_CREAA

status = QVI_CS_CREAA( cmdescr, blksiz, blkcnt, qptr, curcmo, aadptr ) Create a Common Memory allocation area. This routine is meant for use by the CM initialization program or by stand-alone diagnostics. cmdescr address of a CM descriptor returned by the QVI_CS_MAKECM routine. Passed by reference. blksiz size, in bytes, of the blocks in the allocation area being defined. The size must be less than 65,535. Passed by value. blkcnt number of blocks requested for the area (less may be defined if the end of the CM is reached first). Passed by value. qptr pointer to header of free list queue for the new allocation area. The free list queue is populated with all the blocks in the new area. Passed by value. curcmo current Common Memory offset on input, modified to reflect new value after the new allocation area has been setup. Passed by reference. aadptr returns the address of the Allocation Area Descriptor for the new allocation area. Passed by reference. status returns a VMS condition code: SS$_NORMAL success SS$_NOPRIV fatal, no privilege for the requested operation QVI__BADQHDL fatal, bad CM queue handle QVI__CMALRINI fatal, CM already completed initialization QVI__IVCMDS fatal, invalid CM descriptor QVI__IVQLINK fatal, invalid queue link, possible CM corruption QVI__IVSIZE fatal, invalid CM block size QVI__OUTOFCM fatal, no free Allocation Area Descriptors remain This routine requires DIAGNOSE privilege to use.

QVI_CS_CREQH

status = QVI_CS_CREQH( cmdescr, qname, qptr ) Create and initialize a Common Memory queue header. This routine is meant for use by the Common Memory initialization program or by standalone diagnostics. cmdescr address of a CM descriptor returned by the QVI_CS_MAKECM routine. Passed by reference. qname queue name given as (up to 8) ASCII characters. Passed by fixed-length string descriptor. qptr pointer to the new queue header returned in a longword. Passed by reference. status returns a VMS condition code: SS$_NORMAL success SS$_NOPRIV fatal, no privilege for the requested operation QVI__CMALRINI fatal, CM already completed initialization QVI__IVCMDS fatal, invalid CM descriptor QVI__NOQUE fatal, no free queue headers left in CM This routine requires DIAGNOSE privilege to use.

QVI_CS_DAP$MULTICAST

status = QVI_CS_DAP$MULTICAST( cmdescr, qib, blktyp, mcpars, [cmbptr] ) Allocate a free CM block and build a multicast UMB into this block. The first longword of the multicast UMB (after the standard UMB header) contains the Queue Table Index of the current queue; this is followed by 4 longwords of multicast parameters specified by the caller. This routine initializes the QTI longword to the first non-zero QTI entry. The CM block is then placed on the CM queue specified by that QTI entry. As each destination processes the multicast message, it advances the QTI longword to the next non-zero entry in the QTI table and passes the block on to that destination until all the QTI entries have been visited; after which the block is returned to the VAX by the return queue identifier found in the CM block header. cmdescr CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAPCM service. Passed by reference. qib Queues Information Block containing default DAE queue header pointer, free queue table and the DAP Queues Table. Passed by reference. blktyp Block type for the multicast UMB. Passed by value. mcpars Parameters for the multicast message. A block of 4 longwords (16 bytes) passed by reference. cmbptr optional longword in which to return a pointer to the CMB allocated from the free list and filled with the multicast UMB contents. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__QTIEMPTY success, no multicast as the DAP Queue Table is empty QVI__IVCMDS fatal, invalid CM descriptor QVI__IVQLINK fatal, invalid queue link, possible CM corruption QVI__NOFREE error, no free CM blocks of the needed size are available QVI__QLCKFAI error, failed to acquire queue lock

QVI_CS_GET

status = QVI_CS_GET( cmdescr, qib, maxs, umbbuf, [qptr], [cmbptr] ) Remove the CM block from the head of the specified CM queue. If no explicit queue is specified, the VAX return queue specified in the Queues Information Block (QIB) is used. The contents of the UMB portion of the dequeued CM block (if any) are returned in the provided VAX UMB buffer. The CM block dequeued is either released to the CM free lists or recycled depending upon the UMB_M_CYCLE flag in the UMB header. A recycled CM block is placed on the DAE input queue as given in the CMH. cmdescr CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAPCM service. Passed by reference. qib Queues Information Block containing the default return queue header pointer and free queue table. Passed by reference. maxs size of user data return buffer (in bytes). Passed by value. umbbuf buffer for user data returned from the CMB removed from the head of the queue. Passed by reference. qptr optional pointer to queue header from which to remove the head entry, default is the return queue pointed to in the QIB. Passed by value. cmbptr optional longword in which to return a pointer to the CMB dequeued. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__EMPTY warning, return queue was empty QVI__TRU warning, return block truncated QVI__BADQHDL fatal, bad queue handle QVI__IVCMDS fatal, invalid CM descriptor QVI__IVQLINK fatal, invalid queue link, possible CM corruption QVI__IVSIZE fatal, invalid block size QVI__NOQUE fatal, no target or default queue given QVI__QLCKFAI error, failed to acquire queue lock

QVI_CS_INIT

status = QVI_CS_INIT( cmdescr ) Initializes the QVI control registers and creates the permanent global section which maps the QVI control registers. The pages of this global section are locked into the page tables to permit access at elevated IPLs. This service is meant for use by the Common Memory initialization program and by standalone diagnostics. cmdescr address of a 16 longword CM descriptor returned by this routine and used in other QVI_CS routines. Passed by reference. status returns a VMS condition code: SS$_NORMAL success SS$_NOPRIV fatal, no privilege for the requested operation QVI__MAPERR fatal, error mapping the QVI registers QVI__NOVMEPWR fatal, VME Bus is not powered others as returned by VMS services This routine requires SYSGBL, PRMGBL, PFNMAP and DIAGNOSE privileges to use.

QVI_CS_INSQT

status = QVI_CS_INSQT( cmdescr, cmbptr, qptr, genint ) Insert a Common Memory block onto the tail of a queue in the Common Memory. cmdescr CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAPCM service. Passed by reference. cmbptr pointer to the CM block within the mapped CM section. Passed by value. qptr pointer to CM queue header on which to insert the CM block. Passed by value. genint interrupt generation control flag. If 1 then the interrupt associated with the queue is triggered. If 0, then the interrupt (if any) is not triggered. status returns a VMS condition code: SS$_NORMAL success QVI__IVCMDS fatal, invalid CM descriptor QVI__IVQLINK fatal, invalid queue link, possible CM corruption QVI__BADBHDL fatal, bad block handle QVI__BADQHDL fatal, bad queue handle QVI__QLCKFAI fatal, failed to acquire queue lock

QVI_CS_INTERRUPT

status = QVI_CS_INTERRUPT( cmdescr, intno ) Generate an external mapped interrupt to a VME module using the QVI. The external mapped interrupts are generated by writing a mask of bits into a 16-bit control register on the QBus. cmdescr CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAPCM service. The variant form of the CM descriptor returned by the QVI_CS_VMEWINDOW routine is also acceptable. Passed by reference. intno external interrupt number (0-7). Passed by value. status returns a VMS condition code: SS$_NORMAL success SS$_BADPARAM fatal, bad interrupt number QVI__IVCMDS fatal, invalid CM descriptor

QVI_CS_LOCATE

status = QVI_CS_LOCATE( cmdescr, qname, qptr ) Locate a Common Memory queue header. cmdescr address of a CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAP routine. Passed by reference. qname queue name given as (up to 8) ASCII characters. Passed by fixed-length string descriptor. qptr pointer to the new queue header returned in a longword. This is the address of the queue header in the CM as mapped into the process's virtual address space. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__IVCMDS fatal, invalid CM descriptor QVI__NOQUE fatal, no queue found

QVI_CS_LOCKCM

status = QVI_CS_LOCKCM( cmdescr ) Lock the Common Memory global section into the paging tables to permit access at elevated IPLs. This service is meant for use by the CM initialization program and by stand-alone diagnostics. Requires that QVI_CS_MAKECM have already been called. cmdescr address of a 16 longword CM descriptor which was returned by QVI_CS_MAKECM. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__IVCMDS fatal, invalid CM descriptor QVI__MAPERR fatal, not all of CM locked others as returned by VMS services This routine requires PSWAPM privilege to use.

QVI_CS_MAKECM

status = QVI_CS_MAKECM( cmavme, size, cmdescr ) Create and map the permanent global sections for the Common Memory and the transient VME window global section into the process's virtual address space. This service is meant for use by the CM initialization program. Requires that QVI_CS_INIT have been called previously. cmavme VME address of the base of the Common Memory module. Must be aligned on a QVI boundary (multiple of 128 KBytes). Passed by value. size number of bytes of the Common Memory module to be used. Must be an integral number of Kbytes (an even number of VAX pages). Passed by value. cmdescr address of a 16 longword CM descriptor which was returned by QVI_CS_INIT and will be modified here. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__CMBASE fatal, CM base address not on QVI mapping boundary QVI__CMSIZEXC fatal, CM size exceeds QBus address space QVI__CMSIZODD fatal, CM size not even number of VAX pages QVI__IVCMDS fatal, invalid CM descriptor QVI__MAPERR fatal, not all of CM mapped others as returned by VMS services This routine requires SYSGBL, PRMGBL and PFNMAP privileges to use.

QVI_CS_MAKEFQT

status = QVI_CS_MAKEFQT( cmdescr, maxfq, fqtable ) Build a free queue location table to provide fast access to the free lists. cmdescr address of a CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAP routine. Passed by reference. maxfq maximum number of free list queues provided for in the table. Passed by value. fqtable free list queue table giving block sizes and pointers to the associated free queue headers. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__CMNOTINI fatal, Common Memory not initialized QVI__IVCMDS fatal, invalid CM descriptor QVI__TOOMNYFQ fatal, too many free queues for table

QVI_CS_MAPCM

status = QVI_CS_MAPCM( cmdescr ) Map the Common Memory, transient VME window and QVI control registers global sections into the current process's virtual address space. These global sections must have already been setup by a previous program (such as the CM initialization program). This service is used instead of QVI_US_INIT by those programs which depend upon the CM being initialized by a special program (usually at system startup). cmdescr address of a 16 longword block in which a CM descriptor is returned. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__CMNOTINI fatal, Common Memory not initialized QVI__MAPERR fatal, not all of a global section mapped or locked into the page tables QVI__NOVMEPWR fatal, VME Bus is not powered others as returned by VMS services

QVI_CS_MODIFLAGS

status = QVI_CS_MODIFLAGS( bp, [rstmsk], [setmsk] ) Modify the flag bits of the specified CM block. This is normally used the clear the CYCLE bit before queuing a CANCEL or EXPUNGE multicast request for a particular CM block. This is an internal routine for the QVI_US_MODFLG routine to do the flag modifications at elevated IPL. bp pointer to Common Memory block. Passed by value. rstmsk mask of flag bits to be cleared. Passed by value. setmsk mask of flag bits to be set. Passed by value. status returns a VMS condition code: SS$_NORMAL success SS$_ACCVIO fatal, no access to CMB flags

QVI_CS_POOLPOINTER

status = QVI_CS_POOLPOINTER( cmdescr, poolno, poolptr, poolsize ) Return pointer to selected Common Memory DataPool. cmdescr address of a 16 longword block returned by the QVI_CS_MAPCM service. Passed by reference. poolno selector number of Common Memory DataPool. Passed by value. poolptr address of a longword to receive a pointer to the base of the DataPool as mapped in current process virtual address space. Pointer to pool is passed by reference. poolsize address of a longword to receive size of the DataPool. Size is passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__NOPOOL error, no space allocated for selected data pool QVI__IVCMDS fatal, invalid CM descriptor QVI__BADPOOLNO fatal, bad CM data pool number others as returned by VMS services

QVI_CS_PUNCHVME

status = QVI_CS_PUNCHVME( cmdescr, vmeadr, [word], [noaswap] ) Generate an interrupt or a reset by touching a VME location. Normally VME bus accesses are done in Extended Supervisory Data access mode (32 bit address). However, if the VME address passed to this routine is a 16 bit address (the upper 16 bits are zero), then the VME location is touched in Short Supervisory access mode. The access modes refer to the VME address modifier codes generated on the VME bus along with the VME address. This routine extends the capabilities provided by the TOUCHVME routine (see below). cmdescr CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAPCM service. A variant CM descriptor returned by QVI_CS_VMEWINDOW is also acceptable. Passed by reference. vmeadr VME address to touch (with Clear Byte or Clear Word) to generate the interrupt or desired signal. Passed by value. word Select word operation if value is TRUE (1). Passed by value. Default (0) selects byte operation. noaswap This parameter is obsolete, a value must be specified but its value is ignored and not used. status returns a VMS condition code: SS$_NORMAL success QVI__NOTRNSWIN warning, no transient window SS$_BADPARAM fatal, bad interrupt number QVI__IVCMDS fatal, invalid CM descriptor

QVI_CS_PUT

status = QVI_CS_PUT( cmdescr, umbbuf, qib, [tqptr], [cmbptr], [altdiq] ) Allocate a free CM block and copy the UMB contents into this free block from the VAX UMB buffer. The CM block size is retrieved from the UMB UMB buffer size field. The CM block is then placed on the specified CM queue or the default DAE queue (given in the QIB) if no target queue handle is provided. The CM block is recycled to the queue handle as specified by the altdiq parameter if the CYCLE bit is set. cmdescr CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAPCM service. Passed by reference. umbbuf buffer of user data to be inserted into a CMB and placed on a queue for processing. Passed by reference. This data must have the structure of a UMB with the length of the UMB in the umb_w_reqsiz word. qib Queues Information Block containing default DAE queue header pointer and free queue table. Passed by reference. tqptr optional pointer to target queue header. If not given then the target is the default DAE queue from the QIB. Passed by value. cmbptr optional longword in which to return a pointer to the CMB allocated from the free list and queued to the target queue. Passed by reference. altdiq optional longword directing the CM block to be recycled on an alternate DAE input queue (DIQ). Passed by value. status returns a VMS condition code: SS$_NORMAL success QVI__NOFREE error, no free CM blocks of the needed size are available QVI__QLCKFAI error, failed to acquire queue lock QVI__BADQHDL fatal, bad queue handle QVI__IVCMDS fatal, invalid CM descriptor QVI__IVQLINK fatal, invalid queue link, possible CM corruption QVI__IVSIZE fatal, invalid block size QVI__NOQUE fatal, no target or default queue given QVI__TOOBIG fatal, requested UMB size exceeds that of the largest CM block

QVI_CS_REMQH

status = QVI_CS_REMQH( cmdescr, qptr, cmbptr ) Remove the entry from the head of a queue in the Common Memory. cmdescr CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAPCM service. Passed by reference. qptr pointer to queue header from which to remove the entry at the head of the queue. Passed by value. cmbptr returns a pointer to the CM block removed in a longword. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__EMPTY warning, queue is empty QVI__BADQHDL fatal, bad queue handle QVI__IVQLINK fatal, invalid queue link, possible CM corruption QVI__IVCMDS fatal, invalid CM descriptor QVI__QLCKFAI fatal, failed to acquire queue lock

QVI_CS_RESETVME

status = QVI_CS_RESETVME( cmdescr ) Use the QVI to generate a RESET on the VME bus. cmdescr address of a 16 longword block returned by the QVI_CS_INIT service. The variant form returned by the QVI_CS_VMEWINDOW routine is also acceptable. Passed by reference. status returns a VMS condition code: SS$_NORMAL success SS$_NOPRIV fatal, no privilege for requested operation QVI__IVCMDS fatal, invalid CM descriptor others as returned by VMS services The process must have DIAGNOSE privilege.

QVI_CS_SHUTDOWN

status = QVI_CS_SHUTDOWN( ) Shutdown the QVI services by deleting the permanent global sections used by these services. This service is meant for use by the CMShutdown program or stand-alone diagnostics. status returns a VMS condition code: SS$_NORMAL success SS$_NOPRIV fatal, no privilege for the requested operation others as returned by VMS services This routine requires SYSGBL, PRMGBL, PFNMAP and DIAGNOSE privileges to use.

QVI_CS_STATUS

status = QVI_CS_STATUS( cmdescr ) Return status from the QVI. cmdescr CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAPCM service. The variant form CM descriptor returned by QVI_CS_VMEWINDOW is also acceptable. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__VMEBUSBSY warning, a QVI operation is in progress on the VME bus QVI__IVCMDS fatal, invalid CM descriptor QVI__VMEBUSERR fatal, a VME bus error has occurred

QVI_CS_TEST

status = QVI_CS_TEST( cmdescr, qptr, [size] ) Test the specified queue to see if any entries are on it. cmdescr CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAPCM service. Passed by reference. qptr pointer to CM queue header. Passed by value. size returns the size of the UMB of the entry at the head of the queue (or 0 if the queue is empty). Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__EMPTY warning, queue was empty QVI__QLCKFAI error, failed to acquire queue lock QVI__BADQHDL fatal, bad queue handle QVI__IVQLINK fatal, invalid queue link possible CM corruption QVI__IVCMDS fatal, invalid CM descriptor

QVI_CS_TOUCHVME

status = QVI_CS_TOUCHVME( cmdescr, vmeadr ) Generate an interrupt or a reset by ``touching'' a VME location. Normally all VME bus accesses via the QVI are done in Extended Supervisory Data access mode with 32-bit addresses. However, if the VME address passed to this routine is a 16-bit address (upper 16-bits are zero), then the VME location is ``touched'' in Short Supervisory access mode. The access modes refer to the VME address modifier codes generated on the VME bus along with the VME address. This capability was added to permit the correct access to be made to the mailbox locations on the Heurikon 68020 processor boards. The generation of queue-associated interrupts by ``touching'' VME locations (internal to the INSQT, GET and PUT routines) is done in the same manner as for the TOUCHVME routine. If the VME interrupt address associated with a queue is a 16-bit address, a Short Supervisory VME address modifier is used. This routine has been superceded by the PUNCHVME routine (see above). cmdescr CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAPCM service. The variant form CM descriptor returned by the QVI_CS_VMEWINDOW routine is also acceptable. Passed by reference. vmeadr VME address to touch (with Clear Byte) to generate the interrupt or desired signal. Passed by value. status returns a VMS condition code: SS$_NORMAL success QVI__NOTRNSWIN warning, no transient window SS$_BADPARAM fatal, bad interrupt number QVI__IVCMDS fatal, invalid CM descriptor

QVI_CS_VAX2CM

status = QVI_CS_VAX2CM( cmdescr, block, size, cmbptr ) Copy an array of longwords from VAX memory into a CM block. cmdescr CM descriptor returned by the QVI_CS_MAKECM or QVI_CS_MAPCM service. Passed by reference. block address of a buffer of one or more longwords in VAX memory. Passed by reference. size Size of the longword buffer in bytes. Passed by value. cmbptr pointer to the CM block to be filled (pointer refers to the CM block as mapped by the CM global section into the process' virtual address space). Consider the pointer as passed by value or that the CM block itself is passed by reference (address of the CM block appears in the argument list). status returns a VMS condition code: SS$_NORMAL success QVI__IVCMDS fatal, invalid CM descriptor QVI__BADBHDL fatal, bad block handle QVI__IVSIZE fatal, not integral number of longwords

QVI_CS_VMEADRMOD

status = QVI_CS_VMEADRMOD( cmdescr, amod ) Set the VME address modifier of the roving VME window defined by the call to QVI_CS_VMEWINDOW to the selected value (or revert to the default). cmdescr address of a 16 longword block returned by from the QVI_CS_VMEWINDOW routine. Passed by reference. amod unsigned longword giving the VME address modifier code (see definitions in QVIDEF.H file) for the roving VME window. If 0 is passed, the VME address modifier is reset to the initialization value of QVI_C_ESDA for Extended Supervisory Data Access. status returns a VMS condition code: SS$_NORMAL success QVI__NOVME fatal, VME window not initialized QVI__NOTQVIPLUS fatal, not supported except for QVI-Plus

QVI_CS_VMEMAP

status = QVI_CS_VMEMAP( cmdescr, vmeadr ) Set the VME base address of the roving VME window defined by the call to QVI_CS_VMEWINDOW. cmdescr address of a 16 longword block returned by from the QVI_CS_VMEWINDOW routine. Passed by reference. vmeadr unsigned longword giving the base VME address of the window into the VME address space. The low-order 17 bits of the VME address are ignored. Passed by value. status returns a VMS condition code: SS$_NORMAL success QVI__NOVME fatal, VME window not initialized

QVI_CS_VMEPOINTER

address = QVI_CS_VMEPOINTER( cmdescr, vmeadr ) Return the VAX virtual address (in the process' virtual address space) which corresponds to the VME address as mapped by the roving VME window. The VME window has to have been setup by a call to QVI_CS_VMEMAP to map a range of VME addresses (including the VME address specified to this routine). cmdescr address of a 16 longword block returned by from the QVI_CS_VMEWINDOW routine. Passed by reference. vmeadr unsigned longword giving the VME address to be located. Passed by value. address VAX virtual address in the process' virtual address space which corresponds to the VME address as mapped by a QVI window. If the CM descriptor was not initialized, if the VMEMAP routine was not called or if the VME address given by vmeadr is not accessible within the QVI window, then an address of 0 is returned.

QVI_CS_VMEWINDOW

status = QVI_CS_VMEWINDOW( cmdescr ) Setup a ``roving'' VME window by allocating the ``rover'' QVI map register. This VME window is then under the control of the process and can be moved in VME address space by using the QVI_CS_VMEMAP routine. The ``rover'' QVI map register is allocated by taking out a system-wide lock on the resource named QVI_VME_WINDOW. A PFN (page frame number) section near the top of Qbus address space will be created; the size of this section is that of 1 QVI map register (128 Kbytes). The lock on the QVI_VME_WINDOW resource is only released when the program is exited, for this reason, the common memory descriptor used by the QVI_VME_WINDOW must be allocated in static memory, not on the stack. cmdescr address of a 16 longword block returned by this routine with the QVI addresses. This variant form of the CM descriptor must be used with the QVI_CS_VMEMAP routine and is acceptable to the QVI_CS_INTERRUPT, QVI_CS_STATUS, and QVI_CS_RESETVME routines. This block must be allocated in static storage due to existence of an exit handler block within the common memory descriptor. Passed by reference. status returns a VMS condition code: SS$_NORMAL success SS$_NOPRIV fatal, no privilege for the requested operation QVI__VMEINUSE fatal, VME window in use by another process others as returned by QVI_CS and VMS services This routine requires PFNMAP and DIAGNOSE privileges to use.

Basic Services for 80386 Code

The CM routines are linked with the DAE code itself and provide services at the level of the VAX QVI_US routines. The CM routines locate Common Memory blocks and queues by their VMEBus address in the memory module used to support the Common Memory.

cm_dapmcast

status = cm_dapmcast( cmbptr ) Insert a Common Memory block with a DAP Multicast message the next destination queue of the message. The next destination queue is given by either the next non-empty entry in the DAP Queue Table (as specified by the QTI within the Multicast message) or is the originator's return queue. By convention, DAP Multicast messages originate in the host MicroVAX. cmbptr pointer to CM block with the Multicast message. Passed by value (or consider the CM block as passed by reference). status returns a VMS condition code: SS$_NORMAL success QVI__CMNOTINI fatal, Common Memory not initialized QVI__QLCKFAI fatal, failed to acquire queue lock

cm_dapqloc

status = cm_dapqloc( qti, qhdl ) Locate a Common Memory queue by its Queue Table Index (QTI) as used in the Data Access Protocol (DAP) packets. qti queue table index given as a byte. Passed by value. qhdl returns a pointer to the queue header. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__CMNOTINI fatal, Common Memory not initialized QVI__NOQUE fatal, could not find named queue

cm_insqt

status = cm_insqt( cmbptr, qptr, genint ) Insert a Common Memory block onto the tail of a queue in Common Memory. cmbptr pointer to the CM block. Passed by value (or consider the CM block as passed by reference). Note that the pointer is to the CMB, not the UMB which is contained within the CMB. qptr pointer to CM queue header on which to insert the CM block or the offset of the queue header relative to the base of the CM. Passed by value (or consider the CM queue header as passed by reference). genint interrupt generation control flag. If 1 then the interrupt associated with the queue is triggered. If 0, then the interrupt (if any) is not triggered. Passed by value. status returns a VMS condition code: SS$_NORMAL success QVI__BADBHDL fatal, bad pointer to CM block QVI__BADQHDL fatal, bad pointer to CM queue header QVI__CMNOTINI fatal, Common Memory not initialized QVI__QLCKFAI fatal, failed to acquire queue lock

cm_locate

status = cm_locate( qname, qhdl ) Locate a Common Memory queue header. qname queue name given as (up to 8) ASCII characters. Passed by reference (a C string terminated by a NUL character). qhdl pointer to the new queue header returned in a longword. This is the address of the queue header in the CM. Passed by reference. status returns as VMS condition code: SS$_NORMAL success QVI__NOQUE fatal, no queue found

cm_remqh

status = cm_remqh( qptr, cmbptr ) Remove entry from the head of a Common Memory queue. qptr pointer to CM queue header from which to remove the CM block. Passed by value (consider the CM queue header as passed by reference). cmbptr address of longword to return pointer to the block removed from the head of the queue. Passed by reference. Note that the pointer is to the CMB, not to the UMB which is contained within the CMB. status returns a VMS condition code: SS$_NORMAL success QVI__EMPTY warning, queue is empty QVI__BADQHDL fatal, bad pointer to CM queue header QVI__CMNOTINI fatal, Common Memory not initialized QVI__QLCKFAI fatal, failed to acquire queue lock

cm_tstq

status = cm_tstq( qptr ) Test the status of a Common Memory queue. qptr pointer to CM queue header. Passed by value (consider the CM queue header as passed by reference). status returns a VMS condition code: SS$_NORMAL success QVI__EMPTY warning, queue is empty QVI__BADQHDL fatal, bad pointer to CM queue header QVI__CMNOTINI fatal, Common Memory not initialized QVI__QLCKFAI fatal, failed to acquire queue lock

Additional 80386 Services

These CM services are an optional addition to those listed above. Normally, the DAE processors receive requests from the VAX and pass responses back to the VAX in the same CMB as the request arrived in. In order to allow the DAE processors to generate unsolicited messages, these additional routines interface the DAE processors to the free block lists in the Common Memory. These routines assume that the VAX will be the sink for these messages and depend on the MicroVAX to restore the exhausted block to its free list.

cm_get_block

status = cm_get_block( size, qhdl, cmbptr ) Allocate a block from the Common Memory free lists. size requested size of the UMB to be allocated from the CM free lists. Passed by value. The size will be stored in the standard field in the UMB header of the allocated block. The caller must fill in the UMB block type. qhdl queue pointer, returned by cm_locate(), of a queue owned by a VAX process which is the ultimate destination of the message in the block being requested. cmbptr address of longword to return pointer to the block removed from a free list queue. Passed by reference. Note that the pointer returned is to the CMB, not the UMB which is contained within the CMB. status returns a VMS condition code: SS$_NORMAL success QVI__NOFREE error, no free CM blocks QVI__CMNOTINI fatal, Common Memory not initialized QVI__IVSIZE fatal, invalid UMB size request QVI__QLCKFAI fatal, failed to acquire queue lock QVI__TOOBIG fatal, size exceeds largest CM block size

cm_get_init

status = cm_get_init() Perform necessary one-time-only initializations for the cm_get_block() routine. This includes building a list of the free lists in static storage which is sorted by the size of the blocks on the free lists. status returns a VMS condition code: SS$_NORMAL success QVI__CMNOTINI fatal, Common Memory not initialized QVI__TOOMNYFQ fatal, too many free queues for table

Other optional CM services deal with Common Memory DataPools. A DataPool is a section of Common Memory set aside for the use of a group of cooperating processes (usually on multiple processors) as a data storage area. The usual setup is for one process to collect data, reformat it and deposit in the DataPool. Another process will then pick data out of the DataPool in response to user data acquisition requests.

cm_lockpool

status = cm_lockpool( pn ) Lock the selected data pool against updates by other processors. pn number of Common Memory DataPool. Passed by value. status returns a VMS condition code: SS$_NORMAL success, pool locked by this processor QVI__LOCKED warning, pool is already locked QVI__BADPOOLNO fatal, bad CM data pool number

cm_poolpointer

status = cm_poolpointer( pn, pp ) Return address of selected Common Memory DataPool area. pn number of Common Memory DataPool. Passed by value. pp address of a longword to return the pointer to the Common Memory DataPool. Passed by reference. status returns a VMS condition code: SS$_NORMAL success QVI__NOPOOL error, no space allocated for selected data pool QVI__CMNOTINI fatal, Common Memory not initialized QVI__BADPOOLNO fatal, bad CM data pool number

cm_unlockpool

status = cm_unlockpool( pn ) Release the lock on the selected data pool to allow updates by other processors. pn number of Common Memory DataPool. Passed by value. status returns a VMS condition code: SS$_NORMAL success, pool locked by this processor QVI__NOTLOCKED warning, pool was already unlocked QVI__BADPOOLNO fatal, bad CM data pool number

CM Initialization

The Common Memory is setup from the VAX program called CMInitializer. This program is run whenever the VAX is booted or the DAE is reset and restarted (without booting the VAX). The CMInitializer program must run in a process with the necessary privileges to run the various QVI_CS services (CMKRNL, PFNMAP and DIAGNOSE) along with others as deemed necessary. The CMInitializer performs the following actions in roughly the listed order:
  1. Read a text file of parameters using the logical name . The format of this file is described below.
  2. Create a permanent global section named if not already present. The global section is created using PFN (Page Frame Number) mapping of the QBus addresses used for the main CM window. In either case, map the global section into current process VAS P0 region.
  3. Initialize the QVI control registers to map the QBus addresses of the CM to the actual VME addresses of the CM memory board. Also create a permanent global section named to map the QVI control registers (access limited to kernel mode).
  4. Zero all of the VME memory module locations (including the entire Common Memory region).
  5. Initialize the CM global area locations and build the CM queue headers, allocation area descriptors and other fixed structures.
  6. Initialize CM free queues and place all the CM blocks on their respective free queues.

Format of Parameter Descriptions

The parameters file is located by the logical name. The defaults for the file specification of the parameters file are:
     SYS_STARTUP:CM_PARAMETERS.INI
Each line of this file contains the description of a single parameter using DCL-like syntax:
 
    parameter-name[/qualifier(s)]  value[,value...]
Optional arguments are indicated by square brackets ([...]) in the syntax descriptions. Depending upon the parameter, values can be decimal numbers, hexadecimal numbers (%X...), non-delimited symbol names of alphanumeric characters (including ``$'' and ``_''), text strings enclosed in double quotes ("...") or keywords. Comments may be included with the parameters. All characters after an exclamation mark (``!'') to the end of the line are ignored and treated as comments. Multiple spaces and tabs outside of quoted text are treated as a single space. Lowercase characters are converted to uppercase, except within quoted text.

CMInitializer Parameters

list [ADDRESS address] Specifies an address: list [/CM] the base address of the memory board on the VME bus to be used for the Common Memory. [/EXTERNAL_INTERRUPT] Specifies the VME address of the QVI's external interrupt register. [BLOCKS queue-name] Specifications for a free block area. The argument is the name of the queue header for the free list of these blocks. list [/SIZE=n] Size, in bytes, of each of this class of blocks. [/COUNT=n] Number of blocks to be created in this class. [/AVAILABLE] Use remainder of available Common Memory for blocks of this free list.

Note, and are mutually exclusive and only one can be used on a given BLOCKS command. Similarly, only a single BLOCKS command in a parameters file can use the qualifier. [CLEARMEMORY size] Specifies the amount of memory in the VME memory module to be cleared to zeroes. Size is given in Kbytes. [DATAPOOL n size] Specifies that DataPool number n is to be initialized with a size of size bytes. [EXIT] Terminates parameters command file. [LDD name] Specifies the node name whose Listener Data Descriptor (LDD) is to be setup. The ``DEFS'' string is passed as the name parameter to specify defaults values. The defaults are used if a particular qualifier isn't specified for a given name, or if the current node doesn't match any of the names defined by the LDD command. Furthermore, ``DEFS'' be specified before any other LDD command definitions. list [/ID=number] Specifies the Listener ARCnet node number (0-255). [/DAE=number] Specifies the number (0-255) of seconds that must elapse before the DAE data is considered stale. [/FTP=number] Specifies the number (0-255) of seconds that must elapse before the FTP data is considered stale. [MUXQUEUE name] Specifies the name of the multiplexed return queue (if any). [QUEUE name] Defines a named queue whose header is to be setup. Queue names are alphanumeric symbol names (``$'' and ``_'' permitted). The case of the queue name is unimportant as all the queue names are kept in uppercase. list [/VME=address] Specifies the address of a VME location used to generate the interrupt associated with this queue. The interrupt is triggered when an entry is made on the queue to signal the destination that a request is available on its input queue. [/EXTERNAL=number] Specifies the number (0-7) of a QVI mapped external interrupt associated with this queue. This interrupt is generated by writing a 1 to the selected bit number in a register. [/DEMUX] Specifies that this is a VAX return queue fed via the multiplexed return queue and the process. [/NONE] No interrupt is associated with the queue (normally used only for free list queues or input queues watched by a polling algorithm). [/DEVICE=device] Specifies the name of a VAX device with the UIC driver for handling interrupts for this queue. Used for input queues for VAX processes only. [/DAP_INDEX=number] Specifies that this queue is to be entered in the DAP queue table at the specified index number. [/NOBYTE_OPERATION] Specifies that the hardware generating the interrupt will only respond to word operations (otherwise a byte access will be used). Only one of the qualifiers , , or may be present ( is taken by default if no qualifier is present). The , and qualifiers are not allowed with (either an explicit or one implied by default) or . Similarly, can only be used with the qualifier (if is used, the default is ). [RESET] Generate a VME bus reset. [SET keyword] Select an option: list [CHECK_ONLY] Read and validate the parameters, but do not actually initialize the CM. [VERIFY] List the commands as they are read. [TEST_MODE] Used for testing CMI.

[SHOW keyword] Select an output option: list [BUILD] Show details during the initialization of the Common Memory. [PARAMETERS] Show a table of the initialization parameters after the commands are read and before the CM is initialized. [SUMMARY] Show a summary of the initialization operations. [SIZE Kbytes] Specifies the size of the CM in Kbytes.

The following is an example of a command procedure used to initialize the Common Memory. The first part of the procedure defines the logical names which CMInitializer will cross-check against its input parameters.

$ DEFINE := DEFINE /NOLOG
$ SET PROCESS /PRIVILEGE=SYSNAM
$!
$! Define logical names to identify default queue to send packets to
$! Data Acquisition Engine and to hold packets incase of INSQ failures.
$!
$ DEFINE /SYSTEM	RDCS$QVI_DAE_QUEUE	TIMER
$ DEFINE /SYSTEM	RDCS$QVI_WASTE_QUEUE	$TOXIC$
$!
$! Define logical names for VAX devices associated with CM queues used
$! as "input" to VAX processes; devices are used with Connect-to-Interrupt.
$!
$ DEFINE /SYSTEM	RDCS$QVI_VAXQ_DASRET	VAXQA0:
$ DEFINE /SYSTEM	RDCS$QVI_VAXQ_TSRET	VAXQB0:
$ DEFINE /SYSTEM	RDCS$QVI_VAXQ_HERMES	VAXQC0:
$ DEFINE /SYSTEM	RDCS$QVI_VAXQ_FEEDER	VAXQF0:
$ DEFINE /SYSTEM	RDCS$QVI_VAXQ_ECHOBACK	VAXQG0:
$!
$! Initialize the common memory with parameters in the specified file.
$!
$ SET PROCESS /PRIVILEGE=(CMKRNL,DIAGNOSE,PSWAPM,PRMGBL,SYSGBL,PFNMAP,SYSLCK)
$ DEFINE /USER_MODE	CM_PARAMETERS	SYS$INPUT:
$ RUN CMI
address %XE0000000 /cm				!CM VME card address
address	%XFF00E010 /external_interrupt		!Mapped External Interrupts
size	3072					!Use 3 MB of memory
clear	4096					!Clear all 4 MB of memory
!
! Queues for free lists:
!
queue	$256 /none
queue	$1K /none
queue	$4k /none
queue	$tiny /none
blocks	$4k /size=4096 /count=150
blocks	$1k /size=1048 /count=300
blocks	$256 /size=280 /count=500
blocks	$tiny /size=128 /available
!
! Listener parameters:
! The defaults MUST be defined first!
!
ldd     defs    /id=1 /dae=120 /ftp=120 !Setup listener defaults
ldd     huey    /id=1                   !For HUEY
ldd     dewey   /id=2                   !For DEWEY
ldd     louie   /id=3                   !For LOUIE
ldd     webby   /id=4                   !For WEBBY
!
! Action queues:
!
queue	$toxic$ /none
queue	dasret /vme=%XFF00E000 /device=vaxqa0: /nobyte	!DAS return queue
queue	tsret /vme=%XFF00E002 /device=vaxqb0: /nobyte	!TS return queue
queue	camac /external=1 /dap_index=2			!CAMAC module's queue
queue	timer /external=0 /dap_index=1			!Timer module's queue
queue	Hermes /vme=%XFF00E004 /device=vaxqc0: /nobyte	!Message handler queue
exit
$ EXIT

Internals

Logical Names

A set of logical names of the form are used to specify special-purpose CM queues and to associate VAX return (or input) queues with a set of VMS device names (see the section on the UICDRIVER below). CMInitializer cross-checks its input parameters against these logical names. The Common Memory initialization procedure example in section illustrates some of these logical name definitions. The special logical names used by the QVI services are: list [RDCS$QVI_DAE_QUEUE] gives the name of the default DAE queue in Common Memory. This is the queue that blocks with the CYCLE bit set are placed on after being removed from a VAX return queue. [RDCS$QVI_WASTE_QUEUE] gives the name of the ``toxic waste'' Common Memory queue. The ``toxic waste'' queue provides a place for the QVI services on the VAX (and possibly their equivalents in the DAE processing elements) to place CM blocks which would otherwise be ``lost''. Some of the QVI services use this queue when problems arise in queuing blocks to other queues; the ``toxic waste'' queue is used rather than dropping the CM block on the floor which would result in the lose of the CM resources. The ``toxic waste'' queue is not associated with an interrupt, but a periodic VAX process will attempt to empty the ``toxic waste'' queue and recover the blocks (restore them to the free lists). [RDCS$QVI_DEMUX_QUEUE] gives the name of the multiplexed VAX return queue. This is the input queue for the process. [RDCS$QVI_VAXQ_qname] where ``qname'' is the name of a Common Memory queue. The equivalence string of the logical name is the name of the VAX device used to process the interrupts associated with the specified VAX return queue.

UICDRIVER and VAX Interrupt Devices

Interrupts associated with the VAX input queues are handled using VMS devices supported by the driver for the AMD 9519A Universal Interrupt Controller chip. The is a modified and simplified Connect-to-Interrupt driver. The association between the VAX device name and the interrupt vector is setup at system startup by (see the example below). The QVI interrupt services associate a VAX device name with an interrupt level number in the AMD9519 Interrupt Controller Chip by the controller letter in the device name. Thus controller letters ``A'' through ``H'' map into the 9519 interrupt levels 0 through 7. The interrupt vector to be loaded into the 9519's response memory is located in the Interrupt Dispatch Block (IDB) of the system's I/O database as setup by . A startup file for to define 8 devices for the 8 interrupt levels on the QVI is:
$ RUN SYS$SYSTEM:SYSGEN
!
! NOTE: The CSR addresses here are of the Command Register of the
!	AMD9519 Interrupt Controller, NOT of the 1st QVI register.
!
CONNECT VAXQA0 /ADAPTER=UB0 /DRIVERNAME=UICDRIVER /CSR=%O777102 /VECTOR=%O700
CONNECT VAXQB0 /ADAPTER=UB0 /DRIVERNAME=UICDRIVER /CSR=%O777102 /VECTOR=%O704
CONNECT VAXQC0 /ADAPTER=UB0 /DRIVERNAME=UICDRIVER /CSR=%O777102 /VECTOR=%O710
CONNECT VAXQD0 /ADAPTER=UB0 /DRIVERNAME=UICDRIVER /CSR=%O777102 /VECTOR=%O714
CONNECT VAXQE0 /ADAPTER=UB0 /DRIVERNAME=UICDRIVER /CSR=%O777102 /VECTOR=%O720
CONNECT VAXQF0 /ADAPTER=UB0 /DRIVERNAME=UICDRIVER /CSR=%O777102 /VECTOR=%O724
CONNECT VAXQG0 /ADAPTER=UB0 /DRIVERNAME=UICDRIVER /CSR=%O777102 /VECTOR=%O730
CONNECT VAXQH0 /ADAPTER=UB0 /DRIVERNAME=UICDRIVER /CSR=%O777102 /VECTOR=%O734
EXIT
$ EXIT

At system startup, the arms the chip but does not enable any of the interrupt levels. A level is enabled and its vector is loaded into the chip once an I/O operation is started with the I/O function code (same function code as used by the VMS Connect-to-Interrupt Driver supplied by Digital). Similarly once the I/O operation is completed or cancelled, the interrupt level is disabled on the chip.

The following is a short description of calling the . Serious users are directed to the description of the VMS Connect-to-Interrupt driver in the VAX/VMS Device Driver manual.

status = SYS$QIO( [efn], chan, func, [iosb], [astadr], [astprm], [p1], [p2], [p3], [p4], [p5], [p6])

The standard VMS $QIO system service when used with the takes the following arguments. Note that there is a distinction between the completion of the I/O operation and device interrupts. The $QIO call can be setup to receive a single interrupt and then have the I/O request complete. A more normal mode of operation, as used by the QVI_US routines, is to have multiple device interrupts reported without the I/O request completing. efn number of event flag set on completion of the I/O request. Passed by value. chan channel number assigned to one of the devices using the $ASSIGN system service. Passed by value. func I/O function code of IO$_CONINTREAD. Passed by value. iosb I/O status block set on completion of the I/O request. Passed by reference. astadr AST routine called upon completion of the I/O request. Passed by reference. astprm parameter for the I/O completion AST. Passed by value. p1 this parameter is ignored by the . Passed by value. p2 optionally specifies the interrupt level number if the flag in the p3 argument. Passed by value. p3 longword containing flags and an optional event flag number. This event flag is set on each device interrupt (as distinct from the efn parameter above). Passed by value. p4 AST routine called on each device interrupt (address of routine's entry mask). Passed by reference. p5 AST parameter to be passed to the device interrupt AST specified in p4. Passed by value. p6 number of AST control blocks to preallocate in anticipation of fast, recurrent interrupts from the device. Passed by value. status returns a VMS condition code: SS$_NORMAL success. SS$_BADPARAM number of preallocated AST control blocks in the p6 argument exceeds 65535. SS$_DISCONNECT a connection is already outstanding for the device or the driver cannot reallocate AST control blocks quickly enough. SS$_EXQUOTA process has exceeded its direct I/O limit quota or its AST limit quota. SS$_ILLEFC an illegal event flag number was specified. SS$_INSFMEM insufficient system dynamic memory is available to complete the system service. SS$_UNASEFC the process is not associated with the cluster containing the specified event flag.

list [CIN$M_EFN] set event flag on interrupt. [CIN$M_USECAL] p2 parameter contains the interrupt level number. [CIN$M_REPEAT] leave process connected to the interrupt vector until the connection is canceled and repeatedly report interrupts for this single I/O operation. [CIN$M_AST] queue p4 AST routine on interrupt. [CIN$M_EFNUM] high-order word specifies the number of the event flag to be set when an interrupt occurs.

KerrMcGee Process

This detached VMS process is planned to monitor the integrity of the Common Memory and the ``toxic waste'' queue in particular. Currently, only updates the time-of-year clink value in the Common Memory global area approximately every 21 minutes to keep the value in synchrony with the VAX system time.

DeMuxer Process

This detached VMS process has the multiplexed queue as its input queue. When an entry is made on this queue, is awakened by an interrupt and proceeds to empty the queue. As each entry is removed, the originator identifier in the CM block is used to locate the Queue Demultiplexing Block (QDB, see below) which contains a pointer to the true destination queue for the CM block. The QDB also identifies the VMS process associated with this return queue; simulates an interrupt to this process by using the Declare External Process AST routine in the Epicure System Services (ESS).

Queue Organization, Queue Headers and Queue Operations

A CM queue is a singly-linked FIFO list. The head pointer is the CM offset (from the base of Common Memory) to the first entry on the queue (or 0 if the queue is empty). The first longword of each queue entry contains the CM offset of the next entry; the last entry contains a 0 in the link longword (see Section 2.1, Format of a Common Memory Block). The tail pointer is the CM offset to the last (tail) entry on the queue (of 0 if the queue is empty). A CM queue header occupies 8 longwords (32 bytes). The format of a CM queue header (as seen on the VAX) is:

The fields of the CM queue header are: list [cqh_b_lock] Lock byte. The LCK bit is used to lock the queue during manipulations (by a on the VAX, a the 68020 and a on the 80386). list [CQH_V_LOCK] Offset to the lock bit in the lock byte.

[cqh_b_flags] Byte of bit flags: list [CQH_V_INT] Offset to the INT bit. This bit is set if an interrupt is associated with the queue (thus the cqh_l_intid field contains valid information). [CQH_V_EXT] Offset to the EXT bit. This bit indicates whether the interrupt is an external interrupt (EXT=1) or an interrupt triggered by touching a VME address (EXT=0). The EXT bit thus describes the contents of the cqh_l_intid field. [CQH_V_WRD] If set, a word instruction to the specified VME address is used to generate the associated interrupt. [CQH_V_DAS] Obsolete.

[cqh_l_headp] Offset to entry at head of queue. [cqh_l_tailp] Offset to entry at tail of queue. [cqh_w_curcnt] Count of current queue entries. [cqh_w_maxcnt] Count of maximum number of entries on queue since initialization (or last reset). [cqh_l_intid] Interrupt address on VME bus or a bit number for the external interrupt register (on the QVI board). This interrupt is associated with this queue to inform the destination processor of an entry on the queue. [cqh_q_name] Queue name given as 1-8 uppercase ASCII characters, padded with blanks. [cqh_l_putcnt] Unsigned count of the insert operations performed to the queue since the counter was zeroed (initially zeroed at CM initialization).

  
/*
 As seen by the VAX and the 80386:
*/
struct CQH {
    unsigned char cqh_b_lock;
    unsigned char cqh_b_flags;
    unsigned : 16;
    unsigned long cqh_l_headp;
    unsigned long cqh_l_tailp;
    unsigned short cqh_w_curcnt;
    unsigned short cqh_w_maxcnt;
    unsigned long cqh_l_intid;
    unsigned long cqh_q_name[2];
    unsigned long cqh_l_putcnt;
    };

  
/*
 As seen by the 68020:
*/
struct CQH {
    unsigned : 16;
    unsigned char cqh_b_flags;
    unsigned char cqh_b_lock;
    unsigned long cqh_l_headp;
    unsigned long cqh_l_tailp;
    unsigned short cqh_w_maxcnt;
    unsigned short cqh_w_curcnt;
    unsigned long cqh_l_intid;
    unsigned long cqh_q_name[2];
    unsigned long cqh_l_putcnt;
    };

  
/*
 Common to all processors:
*/
#define CQH_V_LOCK  7
#define CQH_M_LOCK  0X80
#define CQH_V_INT   0
#define CQH_M_INT   0X01
#define CQH_V_EXT   1
#define CQH_M_EXT   0X02
#define CQH_V_WRD   6
#define CQH_M_WRD   0X40
The CM queues are manipulated with the following sequence of operations:
  1. The queue reserve lock is set. This is done with a instruction on the 68020 against the lock byte of the queue header at offset CQH_B_LOCK. The 80386 uses a byte instruction with the prefix on that same byte with the register loaded with (this may change in the future to a instruction). The VAX sets the reserve lock with the instruction (Interlocked Branch on Bit Set and Set bit) on the bit at offset in the lock byte at offset . The offsets will be defined so that the , and instructions are manipulating the same bit in the Common Memory.

    Before the VAX issues the instruction, the QVI is preset to stretch the VMEBus cycle since the results in separate read and write QBus cycles. The QVI preset will keep the VMEBus busy until the next write operation (the write cycle from the in this case).

  2. The requested queue operation (insert entry at tail or remove entry from head) is performed by updating all the affected pointers.
  3. The counters (current and maximum number of entries, count of queue inserts) are updated.
  4. The queue reserve lock is cleared by clearing the lock byte with a Clear Byte instruction.

VAX Structures

This section describes some of the VAX-based data structures associated with the QVI services. These are internal to the QVI_US routines (maintained in local own storage) and are explicit arguments to the QVI_CS routines.

Common Memory Descriptor

A CM descriptor occupies 16 longwords (64 bytes). The CM descriptor basically describes the QVI and CM global sections as mapped into a process (each process has its own CM descriptor). The format of a CM descriptor is:

The fields of the CM descriptor are: list [cmd_l_check] Longword with validation check value. Used to validate CM descriptor as initialized. [cmd_a_base] Pointer to base of the CM global section as mapped into the process's virtual address space (VAS). This pointer, like all non-system space virtual addresses, is valid only for a the current process. This field also holds the pointer to the base of the ``roving'' VME window section created by the QVI_CS_VMEWINDOW service (see below). [cmd_a_qvi] Pointer to QVI registers global section as mapped by this process. [cmd_a_top] Address of the top of the CM global section. [cmd_a_cqhbot] Pointer to the CM queue header array in the CM global section. Used to validate queue handles. [cmd_a_cqhtop] Pointer to end of the CM queue header array in the CM global section. Used to validate queue handles. [cmd_a_baabot] Pointer to the base of the CM block allocation areas in the CM global section. Used to validate block handles. [cmd_a_baatop] Pointer to the top of the CM block allocation areas in the CM global section. Used to validate block handles. [cmd_a_itwmr] Pointer to the QVI map register used for the ``transient'' window by the QVI services. A primary use of this window will be to trigger interrupts which require the touching of specific VME addresses. This window will be moved (at elevated IPL) to map the VME address to be touched. [cmd_a_itw] Pointer to the ``transient'' window address range as mapped into the virtual address space of the VAX process. See the above explanation for cmd_a_itwmr. [cmd_a_mapreg] This field overlays cmd_a_cqhbot in the variant Common Memory descriptor produced by the QVI_CS_VMEWINDOW routine; a more detailed explanation is given below. This field stores the pointer to the QVI map register used by the ``roving'' VME window and is used by the QVI_CS_VMEMAP routine. [cmd_l_vwba] This field overlays cmd_a_cqhbot in the variant Common Memory descriptor produced by the QVI_CS_VMEWINDOW routine. This field stores the VME base address of the QVI window. It is setup by the QVI_CS_VMEMAP routine and used in the QVI_CS_VMEPOINTER routine. [cmd_l_exitsts] This field overlays cmd_a_top in the variant Common Memory descriptor procedure by the QVI_CS_VMEWINDOW routine. This field stores the exit status for the internally-declared exit handler used to release the lock on the ``roving'' VME window. [cmd_r_ehblk] This is the exit handler block passed to the $DCLEXH system service by the VME_CS_VMEWINDOW routine to setup the internal exit handler.

struct CMDescriptor {  /* Normal format */
    unsigned long cmd_l_check;
    address cmd_a_base;
    struct qvi_r_csrs *cmd_a_qvi;
    address cmd_a_top;
    struct CQH *cmd_a_cqhbot;
    struct CQH *cmd_a_cqhtop;
    address cmd_a_baabot;
    address cmd_a_baatop;
    unsigned short *cmd_a_itwmr;
    address cmd_a_itw;
    };

struct CMDescriptor {  /* VMEWINDOW variant */
    unsigned long cmd_l_check;
    address cmd_a_base;
    struct qvi_r_csrs *cmd_a_qvi;
    unsigned long cmd_l_exitsts;
    unsigned short *cmd_a_mapreg;
    unsigned long cmd_l_vwba;
    address cmd_a_baabot;
    address cmd_a_baatop;
    unsigned short *cmd_a_itwmr;
    address cmd_a_itw;
    struct {
      address ehb_a_link;
      unsigned long (*exit_handler)();
      unsigned long ehb_l_argcnt;
      unsigned long *ehb_a_exitsts;
      unsigned long ehb_l_lockid;
      } cmd_r_ehblk;
    };
The validation check field holds a 32-bit coded integer to describe the ``state'' of the Common Memory descriptor. The check value permits the Common Memory descriptor to have two states of partial and complete initialization. The partial initialization state is setup by the QVI_CS_INIT routine and reflects that the only valid field of the Common Memory descriptor is the pointer to the QVI registers. In the complete initialization state, all the Common Memory descriptor fields are valid. In addition, the validation check can hold a third value indicating that the Common Memory descriptor is the variant produced by the QVI_CS_VMEWINDOW routine. In this variant, the only valid fields are the pointers to the QVI registers and the QVI mapping register used for the ``roving'' VME window, the pointer to the base of (now) the VME window section in the process's VAS and (after a call to QVI_CS_VMEMAP) the VME base address field. Some routines (including QVI_CS_INTERRUPT, QVI_CS_RESETVME and QVI_CS_STATUS) will accept any valid form of the Common Memory descriptor (either state or the variant). The QVI_CS_VMEMAP routine will only accept the variant form and QVI_CS_MAPCM only accepts the partially initialized state. All other routines require a fully initialized Common Memory descriptor.

Queues Information Block

The Queues Information Block (QIB) contains process-specific information on Common Memory queues. An internal copy is maintained by the QVI_US routines and passed in the calling sequences of the QVI_CS_GET and QVI_CS_PUT routines. The fields of the Queues Information Block are:

list [myqh] Pointer to the CM queue header for the VAX return queue for this process. Used as the default return queue by QVI_CS_GET. Used by QVI_CS_PUT to set the return queue handle in CMBs put onto DAE queues. If the multiplexed queue is used, then this points to the real return queue for this specific process (queue without interrupts). [retqh] Pointer to actual CM return queue. If the multiplexed return queue is not used, then this has the same value as myqh, otherwise it points to the input queue of the process. [myid] Longword containing this process's originator identifier to be placed in CMBs put on DAE queues. If the multiplexed return queue is being used, then this is a pointer to the Queue Demux Block (QDB) in the CM for this process. If a normal return queue is used, then this has the same value as myqh. [daeqh] Pointer to the CM queue header defined as the default DAE queue. Used by QVI_CS_GET for reCYCLEd CMBs. [twqh] Pointer to the CM queue header defined as the ``toxic waste'' queue. Used by QVI_CS_GET and QVI_CS_PUT to avoid dropping CM blocks on the floor and losing them as available resources. This queue is periodically examined and emptied by a separate VAX process (). [fqtable] Free list queue table of quadword descriptors of the free queues. Each quadword contains the free block size and a pointer to the free list queue for blocks of that size (see the structure, below). Sorted by block size for efficient searching. [dapqtbl] DAP queue table copied from CM with queue header offsets converted to handles. Used by the QVI_US_DAP$LOCATE routine.

struct QIB {
    struct CQH *myqh;
    unsigned long myid;
    struct CQH *daeqh;
    struct CQH *twqh;
    struct FQL fqtable[QIB_C_MAXFQS];
    struct CQH *dapqtbl[QIB_C_MAXDQS];
    };

  
struct FQL {
    unsigned long fql_l_size;
    struct CQH *fql_a_qhdr;
    };

Queue Demultiplexing Block

The Queue Demux Block (QDB) is stored in the Common Memory, but only used by the MicroVAX. It is used by the process to redirect CMBs from the input queue (the multiplexed return queue) to the return queues of the real destination processes. The format of the QDB is:

list [qdb_l_pid] Owning process identification. [qdb_l_astadr] Notification AST address in the destination process. [qdb_l_rtnqoff] Offset to header of the destination process return queue in Common Memory. [qdb_b_flags] Flag bits. Currently only the bit is defined. If the flag is set, the DeMuxer process will empty the destination process return queue (to the free lists) if the destination process does not exist.

struct QDB {
    unsigned long qdb_l_pid;
    unsigned long qdb_l_astadr;
    unsigned long qdb_l_rtnqoff;
    unsigned char qdb_b_flags;
    };

#define QDB_V_EINXP 0 #define QDB_M_EINXP 1

Keywords: EPICURE, VME, QVI, Common_Memory.

Distribution:

Normal

Security, Privacy, Legal

rwest@fsus04.fnal.gov