Vmebus API
Vmebus API
Vmebus API
ATL-D-ES-0004
Version 1.5
17 June 2002
Abstract
This note defines an application program interface (API) for the use of VMEbus in the Read-Out
Driver (ROD) system. The API will be used in the ROD Crate DAQ in order to communicate with
the ROD(s) and other equipment in the ROD crate which is also to be controlled. The API con-
tains functions related to the use of the VMEbus master mapping, the VMEbus errors, the VME-
bus slave mapping, the VMEbus block transfers and the VMEbus interrupts.
Table of Contents
1 Introduction 3
1.1 Description of the API 3
1.2 Design Issues 3
1.3 Implementation Issues 4
1.4 Organization of this Document 5
2 Application Program Interface 7
2.1 Overview 7
2.2 Type Definitions 9
2.3 Functions for Return Codes 10
2.4 General Functions 13
2.5 VMEbus CR/CSR Access 15
2.6 VMEbus Master Mapping and Single Cycles 17
2.7 VMEbus Error Handler 26
2.8 VMEbus Slave Mapping 29
2.9 VMEbus Block Transfers 34
2.10 VMEbus Interrupts 45
3 Programming Examples 57
3.1 Example 1: Functions for Return Codes 57
3.2 Example 2: CR/CSR Space 58
3.3 Example 3: Master Mapping - Safe Access 59
3.4 Example 4: Master Mapping - Fast Access 61
3.5 Example 5: Master Mapping - Bus Error Handler 63
3.6 Example 6: Slave Mapping 65
3.7 Example 7: Block Transfer - Detailed Functions 66
3.8 Example 8: Block Transfer - Integrated Function 68
3.9 Example 9: Interrupts - Synchronous Method 70
3.10 Example 10: Interrupts - Asynchronous Method 72
3.11 Example 11: Interrupts - Generate Interrupts 74
4 VMEbus Utility Programs 75
4.1 VMEbus Configuration Utility 75
4.2 VMEbus Test and Debug Utility 75
4.3 VMEbus Scanning Facility 75
5 Ideas for a C++ Binding 76
5.1 Types 77
5.2 VMEbus library/driver 78
5.3 VMEbus Master Mapping 80
5.4 VMEbus Slave Mapping 81
5.5 VMEbus Block Transfer 82
5.6 VMEbus Interrupts 83
-2-
1 Introduction
This note defines an application program interface (API) for the use of VMEbus in the Read-
Out Driver (ROD) system. The API will be used in the ROD Crate DAQ (see EDMS note
ATL-D-ES-0007) in order to communicate with the ROD(s) and other equipment in the ROD
crate which is also to be controlled.
The API contains functions related to the following uses of the VMEbus:
• master mappings and single cycles;
• bus error handling;
• slave mappings;
• block transfers;
• interrupts.
The API further contains type definitions, functions to handle the return codes and general
functions for the use of the VMEbus.
The API assumes the presence of an operating system and of high-level language compilers on
the ROD Crate Processor.
-3-
- The return code is equal to 0 if the function has terminated without error. The return code
is different from 0 in case the function terminated with an error.
- The return code is of a type compatible with “unsigned int”. It can be a complex data
type, if the VMEbus API is implemented with libraries which use a complex type for the
return code.
- The return code can be translated into a flat “int” type (à la UNIX errno.h) for comparison
with meaningful symbols.
- A textual representation of the return code can be printed to “stdout” or to a string by the
application program.
5. Known limitations
- No Read-Modify-Write functions are defined in the API. Those can be added later if
needed.
- Each VMEbus vector can only be used by one process.
- No functions are defined in the API to notify the application program of VMEbus fail-
ures, e.g. signalled by SYSFAIL or ACFAIL. Those can be added later if needed.
5. Blocking functions
-4-
The API’s blocking functions, e.g. waiting for the end of a VMEbus block transfer or for a
VMEbus interrupt shall be implemented in an efficient way. The response time between the
external VMEbus event and the return of the function in the application program shall be
minimised.
6. Interrupts
Since it is not known if the VMEbus interrupters in a system are of type Release-On-
Acknowledge (ROAK) or Release-On-Register-Access (RORA), the implementation of the
API shall associate VMEbus interrupt levels exclusively to either of the two types. When a
VMEbus interrupt from a level associated to ROAK interrupters is received the implementa-
tion does not alter the state of the level. When a a VMEbus interrupt from a level associated
to RORA interrupters is received, the implementation disables that level. The level must be
re-enabled by the application program using a function of the API. It is supposed that the
association of levels to interrupter types can statically be modified using the VMEbus con-
figuration utility, see Section 4.1. The same utility will also be used to statically activate the
interrupt levels.
7. Multi-processing and multi-threading
The implementation of the API shall allow for several application programs and multiple
threads within the same application program to use all functions of the API concurrently.
This might require the implementation of one or more drivers for all or parts of the API.
8. Logging
The implementation of the API shall log serious errors with a central logging facility, e.g. a
global file or kernel messages. The implementation of the API shall also log events of the
VMEbus of general interest with the logging facility.
9. Language binding
C was chosen for the language binding of the API as presented in Sections 2 and 3. Some
ideas on a possible C++ language binding or wrapping are presented in Section 5.
10.Data types
For passing data in and out of a VMEbus master mapping using single cycles, separate
functions are proposed for the following types, included from types.h (BSD), see
Section 2.6:
- “unsigned int” or “u_int” (32 bit),
- “unsigned short” or “u_short” (16 bit) and
- “unsigned char” or “u_char” (8 bit).
The user knows the types of values and defines them in the application program. The com-
piler shall be used to enforce type safety for the function calls. For the C++ binding or
wrapping, polymorphic class methods can be used.
Section 2 contains the definition of the API. For each function the section gives a detailed
description of all input and output parameters, a description of the functionality and the return
codes. The section contains sub-section for the type definitions used by the API, functions con-
cerning the return codes, general functions and functions for the CR/CSR access, master map-
ping, bus error handling, slave mapping, block transfers and interrupts.
-5-
Section 3 contains programming examples which show how the API is to be used. The exam-
ples cover all important cases for return codes, CR/CSR access, master mapping, bus error
handling, slave mapping, block transfers and interrupts.
Section 4 contains a description of the utility programs which accompany the API implementa-
tion. Some implementations will require a VMEbus configuration utility. For all implementa-
tions there shall be a test and debugging, as well as a scanning utility.
Section 5 gives some ideas on a possible C++ language binding or wrapping of the API. The
public members of the classes are shown.
-6-
2 Application Program Interface
2.1 Overview
The following list is an overview of all type and function definitions in the VMEbus API:
Type Definitions
• u_int, u_short, u_char
• VME_ErrorCode_t
• VME_BusErrorInfo_t
• VME_MasterMap_t
• VME_SlaveMap_t
• VME_BlockTransferItem_t
• VME_BlockTransferList_t
• VME_InterruptItem_t
• VME_InterruptList_t
• VME_InterruptInfo_t
Functions for Return Codes
• VME_ErrorPrint
• VME_ErrorString
• VME_ErrorNumber
General Functions
• VME_Open
• VME_Close
CR/CSR Access
• VME_ReadCRCSR
• VME_WriteCRCSR
Bus Error Handling
• VME_BusErrorRegisterSignal
• VME_BusErrorInfoGet
Master Mapping and Single Cycles
• VME_MasterMap
• VME_MasterMapVirtualAddress
• VME_ReadSafeUInt, VME_ReadSafeUShort, VME_ReadSafeUChar
• VME_WriteSafeUInt, VME_WriteSafeUShort, VME_WriteSafeUChar
• VME_ReadFastUInt, VME_ReadFastUShort, VME_ReadFastUChar
• VME_WriteFastUInt, VME_WriteFastUShort, VME_WriteFastUChar
• VME_MasterUnmap
• VME_MasterMapDump
-7-
Slave Mapping
• VME_SlaveMap
• VME_SlaveMapVmebusAddress
• VME_SlaveUnmap
• VME_SlaveMapDump
Block Transfer
• VME_BlockTransferInit
• VME_BlockTransferStart
• VME_BlockTransferWait
• VME_BlockTransferEnd
• VME_BlockTransfer
• VME_BlockTransferStatus
• VME_BlockTransferRemaining
• VME_BlockTransferDump
Interrupts
• VME_InterruptLink
• VME_InterruptWait
• VME_InterruptRegisterSignal
• VME_InterruptInfoGet
• VME_InteruptReenable
• VME_InterruptUnlink
• VME_InterruptGenerate
• VME_InterruptDump
-8-
2.2 Type Definitions
The following types are defined in “vme_rcc.h” for general use throughout the API:
Other Types
-9-
2.3 Functions for Return Codes
VME_ErrorPrint()
Synopsis
#include “vme_rcc.h”
u_int VME_ErrorPrint(VME_ErrorCode_t error_code);
Parameters
Description
Return Values
Programming Example
Notes
none
- 10 -
VME_ErrorString()
Synopsis
#include “vme_rcc.h”
u_int VME_ErrorString(VME_ErrorCode_t error_code, char* error_string);
Parameters
Description
Return Values
Programming Example
Notes
none
- 11 -
VME_ErrorNumber()
Synopsis
#include “vme_rcc.h”
u_int VME_ErrorNumber(VME_ErrorCode_t error_code, int* error_number);
Parameters
Description
The VME_ErrorNumber() function converts the possibly complex error_code into a flat error
number error_number. The flat error number can then be used for comparison with the return
codes defined in this API. The return code VME_SUCCESS (≡ 0) can always be used for com-
parison.
Return Values
Programming Example
Notes
none
- 12 -
2.4 General Functions
VME_Open()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_Open(void);
Parameters
none
Description
The VME_Open() function opens the VMEbus library/driver and allocates the resources
required to use the VMEbus. This function must be called prior to any other function of the
VMEbus API.
Return Values
Programming Example
Notes
none
- 13 -
VME_Close()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_Close(void);
Parameters
none
Description
The VME_Close() releases all resources which were allocated in a VME_Open() function call
and closes the VMEbus library/driver. This function is the last function of the API to be called
by the application program.
Return Values
Programming Example
Notes
none
- 14 -
2.5 VMEbus CR/CSR Access
VME_ReadCRCSR()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_ReadCRCSR(int slot_number, u_int crcsr_field,
u_int* value);
Parameters
Description
The VME_ReadCRCSR() functions reads a value from the field at crcsr_field in the CR/CSR
space of the VMEbus slave at slot slot_number. The symbolic constant VME_MYSLOT
(defined in “vme_rcc.h”) allows access of the CR/CSR space of the VMEbus slave the applica-
tion program runs on.
Symbolic constants for crcsr_field are provided in the “vme_rcc.h” file, see also the VME64
and VME64x standard. The VME_ReadCRCSR() function knows how many bytes, between 1
and 4, must be read for each value.
Return Values
VME_BUSERROR A VMEbus error occurred during the read from CR/CSR space.
Programming Example
Notes
The mapping of the CR/CSR space can be configured statically using the VMEbus configura-
tion utility, see Section 4.1.
- 15 -
VME_WriteCRCSR()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_WriteCRCSR(int slot_number, u_int crcsr_field,
u_int value);
Parameters
Description
The VME_WriteCRCSR() functions writes a value to the field at crcsr_field in the CR/CSR
space of the VMEbus slave at slot slot_number. The symbolic constant VME_MYSLOT
(defined in “vme_rcc.h”) allows access of the CR/CSR space of the VMEbus slave the applica-
tion program runs on.
Symbolic constants for crcsr_field are provided in the “vme_rcc.h” file, see also the VME64
and VME64x standard. The VME_WriteCRCSR() function knows how many bytes, between
1 and 4, must be written for each value.
Return Values
Programming Example
Notes
The mapping of the CR/CSR space can be configured statically using the VMEbus configura-
tion utility, see Section 4.1.
- 16 -
2.6 VMEbus Master Mapping and Single Cycles
VME_MasterMap_t
Synopsis
in vme_rcc.h:
typedef struct {
u_int vmebus_address;
u_int window_size;
u_int address_modifier;
u_int options;
} VME_MasterMap_t;
Fields
u_int address_modifier address modifier to be used when accessing the master mapping
u_int options other options, include read prefetching and write posting
Description
The VME_MasterMap_t type is used to hold input information on a master mapping for use in
a VME_MasterMap() function call. The type definition is provided in the “vme_rcc.h” file.
... ...
options is a bit-wise combination of the following parameters and possibly some other imple-
mentation-specific ones (all defined in “vme_rcc.h”):
VME_RP read prefetching
Programming Example
Notes
none
- 17 -
VME_MasterMap()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_MasterMap(VME_MasterMap_t* master_map, int*
master_mapping);
Parameters
Description
Return Values
Programming Example
Notes
Some parameters for the master mapping, e.g. for static mapping or for byte swapping, can be
configured statically using the VMEbus configuration utility, see Section 4.1.
- 18 -
VME_MasterMapVirtualAddress()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_MasterMapVirtualAddress(int master_mapping, u_int*
virtual_address);
Parameters
Description
Return Values
Programming Example
Notes
none
- 19 -
VME_ReadSafe()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_ReadSafeUInt(int master_mapping, u_int
address_offset, u_int* value);
VME_ErrorCode_t VME_ReadSafeUShort(int master_mapping, u_int
address_offset, u_short* value);
VME_ErrorCode_t VME_ReadSafeUChar(int master_mapping, u_int
address_offset, u_char* value);
Parameters
Description
Return Values
VME_SUCCESS The value was read successfully from the master mapping.
VME_RANGE The address offset is outside the window for the master mapping.
VME_ALIGN The address offset is not correctly aligned with respect to the type.
Programming Example
Notes
none
- 20 -
VME_WriteSafe()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_WriteSafeUInt(int master_mapping, u_int
address_offset, u_int value);
VME_ErrorCode_t VME_ReadSafeUShort(int master_mapping, u_int
address_offset, u_short value);
VME_ErrorCode_t VME_ReadSafeUChar(int master_mapping, u_int
address_offset, u_char value);
Parameters
Description
Return Values
VME_RANGE The address offset is outside the window for the master mapping.
VME_ALIGN The address offset is not correctly aligned with respect to the type.
Programming Example
Notes
none
- 21 -
VME_ReadFast()
Synopsis
#include “vme_rcc.h”
void VME_ReadFastUInt(int master_mapping, u_int address_offset,
u_int* value);
void VME_ReadFastUShort(int master_mapping, u_int address_offset,
u_short* value);
void VME_ReadFastUChar(int master_mapping, u_int address_offset,
u_char* value);
Parameters
Description
Return Values
none
Programming Example
Notes
The value read by the VME_ReadFastXXX() functions can be invalid, if a VMEbus error
occurred.
- 22 -
VME_WriteFast()
Synopsis
#include “vme_rcc.h”
void VME_WriteFastUInt(int master_mapping, u_int address_offset, u_int
value);
void VME_WriteFastUShort(int master_mapping, u_int address_offset,
u_short value);
void VME_WriteFastUChar(int master_mapping, u_int address_offset,
u_char value);
Parameters
Description
Return Values
none
Programming Example
Notes
The value might not be written by the VME_WriteFastXXX() functions, if a VMEbus error
occurred.
- 23 -
VME_MasterUnmap()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_MasterUnmap(int master_mapping);
Parameter
Description
Return Values
Programming Example
Notes
none
- 24 -
VME_MasterMapDump()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_MasterMapDump(void);
Parameter
none
Description
The VME_MasterMapDump() function dumps system parameters for all VMEbus master
mappings to “stdout”.
Return Values
Programming Example
Notes
none
- 25 -
2.7 VMEbus Error Handler
VME_BusErrorRegisterSignal()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_BusErrorRegisterSignal(int signal_number);
Parameters
Description
a signal with number signal_number will be sent to the process calling this function. If the
process wants to handle the signal it must install a signal handler. Installing a signal handler is
not part of this API. The value 0 for signal_number is used to “unregister” a signal from the
VMEbus library/driver.
Return Values
Programming Example
Notes
none
- 26 -
VME_BusErrorInfo_t
Synopsis
in vme_rcc.h:
typedef struct {
u_int vmebus_address;
u_int address_modifier;
u_int multiple;
} VME_BusErrorInfo_t;
Fields
Description
The VME_BusErrorInfo_t type is used to retrieve information on a VMEbus error. The type
definition is provided in the “vme_rcc.h” file.
Programming Example
Notes
none
- 27 -
VME_BusErrorInfoGet()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_BusErrorInfoGet(VME_BusErrorInfo_t*
bus_error_info);
Parameters
Description
Return Values
Programming Example
Notes
This function is intended for use in the bus error signal handling function, see
VME_BusErrorRegisterSignal().
- 28 -
2.8 VMEbus Slave Mapping
VME_SlaveMap_t
Synopsis
in vme_rcc.h:
typedef struct {
u_int system_iobus_address;
u_int window_size;
u_int address_width;
u_int options;
} VME_SlaveMap_t;
Fields
u_int options other options, include read prefetching and write posting
Description
The VME_SlaveMap_t type is used to input information on a slave mapping for use in a
VME_SlaveMap() function call. The type definition is provided in the “vme_rcc.h” file.
system_iobus_address must point at contiguous, locked and properly aligned user space. The
user space can also be a physical resource, e.g. FIFO of the VMEbus master. Obtaining
system_iobus_address for user space is not part of this API.
address_width is one of the following parameters (defined in “vme_rcc.h”):
VME_A32 32-bit addressing
options is a bit-wise combination of the following parameters and possibly some other imple-
mentation-specific ones (all defined in “vme_rcc.h”):
VME_RP read prefetching
Programming Example
For a programming example see Section 3.6.
Notes
none
- 29 -
VME_SlaveMap()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_SlaveMap(VME_SlaveMap_t* slave_map, int*
slave_mapping);
Parameters
Description
The VME_SlaveMap() function creates a slave mapping defined by slave_map and returns the
identifier slave_mapping which is to be used in subsequent function calls.
Return Values
Programming Example
Notes
Some parameters for the slave mapping, e.g. for static mapping or for byte swapping, can be
configured statically using the VMEbus configuration utility, see Section 4.1.
The window size of the created slave mapping will be at least as large as the size requested; it
might be larger.
- 30 -
VME_SlaveMapVmebusAddress()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_SlaveMapVmebusAddress(int slave_mapping, u_int*
vmebus_address);
Parameters
Description
Return Values
Programming Example
Notes
none
- 31 -
VME_SlaveUnmap()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_SlaveUnmap(int slave_mapping);
Parameters
Description
Return Values
Programming Example
Notes
none
- 32 -
VME_SlaveMapDump()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_SlaveMapDump(void);
Parameters
none
Description
The VME_SlaveMapDump() function dumps system parameters for all VMEbus slave map-
pings to “stdout”.
Return Values
Programming Example
Notes
none
- 33 -
2.9 VMEbus Block Transfers
VME_BlockTransferItem_t
Synopsis
in vme_rcc.h:
typedef struct {
u_int vmebus_address;
u_int system_iobus_address;
u_int size_requested;
u_int control_word;
u_int size_remaining;
u_int status_word;
} VME_BlockTransferItem_t;
Fields
u_int control_word direction and type of block transfer; the type includes address
mode and specifies possibly enhanced transfer protocols
u_int size_remaining size of remaining transfer in number of bytes
Description
system_iobus_address must point to contiguous, locked and properly aligned memory. The
memory management is not part of this API.
control_word specifies the direction and type of block transfer. The type includes the address
mode and specifies possibly enhanced transfer protocols. control_word contains one of the fol-
lowing parameters (defined in “vme_rcc.h”):
VME_DMA_D32W transfer data from system I/O bus to VMEbus using 32-bit words
VME_DMA_D32R transfer data from VMEbus to system I/O bus using 32-bit words
VME_DMA_D64W transfer data from system I/O bus to VMEbus using 64-bit words
VME_DMA_D64R transfer data from VMEbus to system I/O bus using 64bit words
- 34 -
VME_DMA_2EVMER transfer data from system I/O bus to VMEbus using 2eVME mode
VME_DMA_2EVMEW transfer data from VMEbus to system I/O bus using 2eVME mode
VME_DMA_2ESSTR transfer data from system I/O bus to VMEbus using 2eSST mode
VME_DMA_2ESSTW transfer data from VMEbus to system I/O bus using 2eSST mode
control_word must be ORed bit-wise with one of the following address modes:
VME_A32 transfer data using 32-bit addressing
Programming Example
Notes
The block transfer list used by the application program can be independent of an another block
transfer list used by the VMEbus library/driver internally. This is because the actual block
transfers carried out by the VMEbus library/driver might differ from the requested ones due to
boundary and alignment restrictions.
On the Tundra Universe II VMEbus bridge chip, the PCI and VMEbus addresses must be
aligned on a 4-byte boundary. In addition, the difference between the PCI and the VMEbus
addresses must be a multiple of 8 byte.
- 35 -
VME_BlockTransferList_t
Synopsis
in vme_rcc.h:
typedef struct {
int number_of_items;
VME_BlockTransferItem_t list_of_items [VME_MAXBLOCK];
} VME_BlockTransferList_t;
Fields
Description
The VME_BlockTransferList_t type is used to define VMEbus block transfers. The type defi-
nition and the maximum number of blocks VME_MAXBLOCK are provided in the
“vme_rcc.h” file.
Programming Example
Notes
A single block transfer must use a block transfer list with only one VME_BlockTransferItem_t
at list_of_items[0] and number_of_items = 1.
- 36 -
VME_BlockTransferInit()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_BlockTransferInit(VME_BlockTransferList_t*
block_transfer_list, int* block_transfer);
Parameters
Description
Return Values
VME_NOMEM There is not enough memory to allocate the resources for the
required block transfer list.
VME_TOOLONG The internally generated block transfer list is too long.
Programming Example
Notes
none
- 37 -
VME_BlockTransferStart()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_BlockTransferStart(int block_transfer);
Parameters
Description
Return Values
Programming Example
Notes
This function shall not be blocking. The implementation of this function shall return immedi-
ately, either indicating that the resources of the DMA engine(s) are not available at the moment
(VME_DMABUSY), or by using internal queuing of tasks.
- 38 -
VME_BlockTransferWait()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_BlockTransferWait(int block_transfer, int
time_out, VME_BlockTransferList_t* block_transfer_list);
Parameters
Description
Return Values
Programming Example
Notes
- 39 -
VME_BlockTransferEnd()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_BlockTransferEnd(int block_transfer);
Parameters
Description
The VME_BlockTransferEnd() function releases the resources allocated for the block transfer
associated to block_transfer. It must be called at the end of a block transfer. The identifier
block_transfer shall not be used after this function call.
Return Values
Programming Example
Notes
none
- 40 -
VME_BlockTransfer()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_BlockTransfer(VME_BlockTransferList_t*
block_transfer_list, int time_out);
Parameters
Description
Return Values
Programming Example
Notes
This function is generally blocking. The value 0 for time_out in this function shall not be used
because the VME_BlockTransferWait() function will return immediately and the
VME_BlockTransferEnd() function will be called regardless of the state of the transfer.
- 41 -
VME_BlockTransferStatus()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_BlockTransferStatus(VME_BlockTransferList_t*
block_transfer_list, int position_of_block, VME_ErrorCode_t* status);
Parameters
Description
The VME_BlockTransferStatus() function returns the status code for the block transfer at
position_of_block in block_transfer_list. This function is added for convenience, the function
is equivalent to the following statement:
status = block_transfer_list.list_of_items[position_of_block].status_word;
Return Values
VME_RANGE The position is outside the range of the block transfer list.
Programming Example
Notes
none
- 42 -
VME_BlockTransferRemaining()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_BlockTransferRemaining(VME_BlockTransferList_t
block_transfer_list, int position_of_block, u_int* remaining);
Parameters
Description
Return Values
VME_RANGE The position is outside the range of the block transfer list.
Programming Example
Notes
none
- 43 -
VME_BlockTransferDump()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_BlockTransferDump(void);
Parameters
none
Description
The VME_BlockTransferDump() function dumps the status of the DMA engine(s) to “stdout”.
Return Values
Programming Example
Notes
none
- 44 -
2.10 VMEbus Interrupts
VME_InterruptItem_t
Synopsis
in vme_rcc.h:
typedef struct {
u_char vector;
u_int level;
u_int type;
} VME_InterruptItem_t;
Fields
Description
The VME_InterruptItem_t type is used to describe a single interrupt in a list of interrupts. Each
interrupt is defined by the vector, the level and the type of the VMEbus interrupt that the appli-
cation program requests to be linked to.
type specifies the interrupt handling to be used for the interrupt. The following types are
defined (in “vme_rcc.h”):
VME_INT_ROAK “Release-On-Acknowledge”
VME_INT_RORA “Release-On-Register-Access”
Programming Example
Notes
The interrupt handling type is required in order to distinguish VMEbus interrupters of RORA
and ROAK type. The interrupt handling type can be configured statically using the VMEbus
configuration utility, see Section 4.1. Usually, the type will be allowed to be configured indi-
vidually for each VMEbus interrupt level. A given level must therefore only be used by VME-
bus interrupts of the associated type.
- 45 -
VME_InterruptList_t
Synopsis
in vme_rcc.h:
typedef struct {
int number_of_items;
VME_InterruptItem_t list_of_items [VME_MAXINTERRUPT];
} VME_InterruptList_t;
Fields
Description
The VME_InterruptList_t type is used to define a list of interrupts. The type definition and the
maximum number of interrupts VME_MAXINTERRUPT are provided in the “vme_rcc.h” file.
Programming Example
Notes
A single interrupt must use an interrupt list with only one VME_InterruptItem_t at
list_of_items[0] with number_of_items = 1.
- 46 -
VME_InterruptLink()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_InterruptLink(VME_InterruptList*
vmebus_interrupt_list, int* interrupt);
Parameters
Description
The VME_InterruptLink() function creates a link between a list of VMEbus interrupts and the
application program. It returns the identifier interrupt which is to be used in subsequent func-
tion calls.
By default, after creation of the interrupt link, the application program applies a synchronous
method waiting for interrupts using the VME_InterruptWait() function. If the application pro-
gram wants to apply an asynchronous method, the VME_InterruptRegisterSignal() function
must be used.
Return Values
VME_INTCONF The list of interrupts was not linked to the application program
because an interrupt is in conflict with the static configuration.
VME_INTUSED The list of interrupts cannot be linked to the application program
because an interrupt is already being used.
others specific to the implementation
Programming Example
Notes
- 47 -
after the VMEbus Acknowledge cycle; the VMEbus driver therefore does not disable reception of
subsequent interrupts. A RORA (“Release-On-Register-Access”) type of VMEbus interrupter
releases the interrupt only after access to a register of the VMEbus module; the VMEbus driver
therefore disables reception of subsequent interrupts on the same VMEbus interrupt level.
Some parameters for the VMEbus interrupts, e.g. for interrupt levels and the interrupt handling
types, can be configured statically using the VMEbus configuration utility, see Section 4.1. The
VME_InterruptLink() function checks if the requested VMEbus interrupt level has been enabled
and configured for the requested type. A given VMEbus vector can only be used by one process.
- 48 -
VME_InterruptInfo_t
Synopsis
in vme_rcc.h:
typedef struct {
u_char vector;
u_int level;
u_int type;
u_int multiple;
} VME_InterruptInfo_t;
Fields
u_int multiple flag indicating if the VMEbus interrupt occurred multiple times
Description
Programming Example
Notes
none
- 49 -
VME_InterruptWait()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_InterruptWait(int interrupt, int time_out,
VME_InterruptInfo_t* interrupt_info);
Parameters
Description
Return Values
Programming Example
Notes
- 50 -
VME_InterruptRegisterSignal()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_InterruptRegisterSignal(int interrupt, int
signal_number);
Parameters
Description
Return Values
Programming Example
Notes
none
- 51 -
VME_InterruptInfoGet()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_InterruptInfoGet(int interrupt,
VME_InterruptInfo_t* interrupt_info);
Parameters
Description
The VME_InterruptInfoGet() function must be called for each interrupt, either after a
VME_InterruptWait() function or in a signal handler associated to that interrupt using the
VME_InterruptRegisterSignal() function.
Return Values
Programming Example
Notes
none
- 52 -
VME_InterruptReenable()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_InterruptReenable(int interrupt);
Parameters
Description
The VME_InterruptReenable() function must be called in case the interrupt received came
from a RORA interrupter. If it came from a ROAK interrupter the interrupt will be automati-
cally be re-enabled by the VMEbus library/driver.
Return Values
Programming Example
Notes
The VMEbus configuration utility is used to associate VMEbus interrupt levels to either of the
two different types of VMEbus interrupters. When the VMEbus library/driver receives an
interrupt from a level which has been associated to RORA interrupters it disables that level.
The application program will receive the interrupt after a call to the VME_InterruptWait()
function or using a signal handler previously installed with the VME_InterruptSignal-
Register() function. After handling the interrupt, the application program must call the
VME_InterruptReenable() function in order to re-enable the associated VMEbus level.
- 53 -
VME_InterruptUnlink()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_InterruptUnlink(int interrupt);
Parameters
Description
The VME_InterruptUnlink() function deletes the link between the VMEbus interrupts associ-
ated to interrupt and the application program. The identifier interrupt shall not be used after
this function call.
Return Values
Programming Example
Notes
none
- 54 -
VME_InterruptGenerate()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_InterruptGenerate(u_char vector, u_int level);
Parameters
Description
The VME_InterruptGenerate() function generates a VMEbus interrupt at level level with vec-
tor vector. This function can be used in order to send an interrupt to another VMEbus interrupt
handler.
Return Values
Programming Example
Notes
Some parameters for VMEbus interrupt generation, e.g. for the interrupt level, can be config-
ured statically using the VMEbus configuration utility, see Section 4.1.
- 55 -
VME_InterruptDump()
Synopsis
#include “vme_rcc.h”
VME_ErrorCode_t VME_InterruptDump(void);
Parameters
none
Description
Return Values
Programming Example
Notes
none
- 56 -
3 Programming Examples
#include “vme_rcc.h”
...
VME_ErrorCode_t error_code;
char error_string[VME_MAXSTRING];
u_int error_number;
...
error_code = VME_Open();
if(error_code != VME_SUCCESS) {
/* compare error code to VME_SUCCESS */
VME_ErrorPrint(error_code);
/* print error code to stdout */
return(error_code);
}
...
error_code = VME_Close();
if(error_code != VME_SUCCESS) {
/* compare error code to VME_SUCCESS */
VME_ErrorString(error_code,error_string);
/* print error code to char string */
error_code = VME_Close();
VME_ErrorNumber(error_code,error_number);
/* convert error code to error number */
if(error_number == VME_NOTOPEN) {
/* compare error number to return value */
- 57 -
3.2 Example 2: CR/CSR Space
#include “vme_rcc.h”
...
int slot_number = 5;
u_int module_identifier;
u_int vmebus_address = 0x22000000;
VME_ErrorCode_t error_code;
...
VME_ErrorPrint(error_code);
return(error_code);
}
...
VME_ErrorPrint(error_code);
return(error_code);
}
- 58 -
3.3 Example 3: Master Mapping - Safe Access
#include “vme_rcc.h”
...
VME_MasterMap_t master_map;
int master_mapping;
u_int value_u_int;
u_int address_offset = 0x200;
VME_ErrorCode_t error_code;
u_int error_number;
...
master_map.vmebus_address = 0x22000000;
master_map.window_size = 0x00800000;
master_map.address_modifier = VME_AM09;
master_map.options = 0;
/* fill master mapping input information */
VME_ErrorPrint(error_code);
return(error_code);
}
...
VME_ErrorNumber(error_code, &erorr_number);
if(error_number != VME_BUSERROR) {
printf(“ERROR in example program: bus error\n”);
}
return(error_code);
}
...
- 59 -
value_u_int = 0xFFFFFFFF;
if(error_code = VME_WriteSafeUInt(master_mapping, address_offset,
value_u_int)) {
/* write safely to the master mapping */
VME_ErrorNumber(error_code, &erorr_number);
if(error_number != VME_BUSERROR) {
printf(“ERROR in example program: bus error\n”);
}
return(error_code);
}
...
VME_MasterMapDump();
/* dump system parameters for all master mappings */
...
if(error_code = VME_MasterUnmap(master_mapping)) {
/* delete the master mapping */
VME_ErrorPrint(error_code);
return(error_code);
}
- 60 -
3.4 Example 4: Master Mapping - Fast Access
#include “vme_rcc.h”
...
VME_MasterMap_t master_map;
int master_mapping;
u_int virtual_address;
u_int value_u_int;
u_int address_offset = 0x200;
VME_ErrorCode_t error_code;
...
master_map.vmebus_address = 0x22000000;
master_map.window_size = 0x00800000;
master_map.address_modifier = VME_AM09;
master_map.options = 0;
/* fill master mapping input information */
VME_ErrorPrint(error_code);
return(error_code);
}
VME_MasterMapVirtualAddress(master_mapping, &virtual_address);
/* get virtual address for the master mapping */
...
value_u_int = 0xFFFFFFFF;
VME_WriteSafeUInt(master_mapping, address_offset, value_u_int);
/* write fast to the master mapping, ignore bus error */
/* alternatively use */
*(u_int *)(virtual_address + address_offset) = 0xFFFFFFFF;
...
- 61 -
if(error_code = VME_MasterUnmap(master_mapping)) {
/* delete the master mapping */
VME_ErrorPrint(error_code);
return(error_code);
}
- 62 -
3.5 Example 5: Master Mapping - Bus Error Handler
#include “vme_rcc.h”
#include <signal.h>
...
if(error_code = VME_BusErrorInfoGet(&bus_error_info) {
/* get information on bus error */
VME_ErrorPrint(error_code);
return(error_code);
}
VME_MasterMap_t master_map;
int master_mapping;
u_int value_u_int;
u_int address_offset = 0x200;
VME_ErrorCode_t error_code;
...
master_map.vmebus_address = 0x22000000;
master_map.window_size = 0x00800000;
master_map.address_offset = VME_AM09;
master_map.options = 0;
/* fill master mapping input information */
VME_ErrorPrint(error_code);
return(error_code);
}
...
- 63 -
/* install bus error handler for signal,
not part of this API, see function sigaction() */
...
if(error_code = VME_BusErrorRegisterSignal(SIGBUS)) {
/* register signal for bus error handling */
VME_ErrorPrint(error_code);
return(error_code);
}
...
if(error_code = VME_BusErrorRegisterSignal(0)) {
/* un-register signal for bus error handling */
VME_ErrorPrint(error_code);
return(error_code);
}
...
if(error_code = VME_MasterUnmap(master_mapping)) {
/* delete the master mapping */
VME_ErrorPrint(error_code);
return(error_code);
}
- 64 -
3.6 Example 6: Slave Mapping
#include “vme_rcc.h”
...
VME_SlaveMap_t slave_map;
int slave_mapping;
u_int vmebus_address;
VME_ErrorCode_t error_code;
...
slave_map.window_size = 0x00800000;
slave_map.address_modifier = VME_AM09;
slave_map.options = 0;
/* fill master mapping input information */
VME_ErrorPrint(error_code);
return(error_code);
}
...
VME_SlaveMapVmebusAddress(slave_mapping, &vmebus_address);
/* get VMEbus address for the slave mapping,
to be used by a VMEbus master */
...
/* read from and write to user space,
not part of this API */
...
VME_SlaveMapDump();
/* dump system parameters for all slave mappings */
...
if(error_code = VME_SlaveUnmap(slave_mapping)) {
/* delete the slave mapping */
VME_ErrorPrint(error_code);
return(error_code);
}
- 65 -
3.7 Example 7: Block Transfer - Detailed Functions
#include “vme_rcc.h”
...
u_int pci_address;
VME_BlockTransferList_t block_transfer_list;
int block_transfer;
VME_ErrorCode_t status;
int remaining;
int time_out = 10;
/* time-out about 10 msec */
VME_ErrorCode_t error_code;
char error_string[VME_MAXSTRING];
...
block_transfer_list.list_of_items[0].vmebus_address = 0x22000200;
block_transfer_list.list_of_items[0].system_iobus_address = pci_address;
block_transfer_list.list_of_items[0].size_requested = 0x100;
block_transfer_list.list_of_items[0].control_word = VME_DMA_D32R;
/* fill parameters for first block transfer */
block_transfer_list.list_of_items[1].vmebus_address = 0x23000200;
block_transfer_list.list_of_items[1].system_iobus_address= pci_address + 0x100;
block_transfer_list.list_of_items[1].size_requested = 0x100;
block_transfer_list.list_of_items[1].control_word = VME_DMA_D32R;
/* fill parameters for second block transfer */
block_transfer_list.number_of_items = 2;
/* total number of block transfers */
if(error_code = VME_BlockTransferInit(&block_transfer_list,
&block_transfer) {
/* initialise block transfer */
VME_ErrorPrint(error_code);
return(error_code);
}
...
- 66 -
if(error_code = VME_BlockTransferStart(block_transfer) {
/* start block transfer */
VME_ErrorPrint(error_code);
return(error_code);
}
...
if(!VME_BlockTransferStatus(block_transfer_list,i,&status)) {
/* check status of each block transfer */
VME_ErrorString(status,error_string);
printf(“ERROR in example program: block = %d, status = %s\n”,
i,error_string);
}
if(!VME_BlockTransferRemaining(block_transfer_list,i,&remaining)) {
/* check remaining words of each block transfer */
VME_BlockTransferDump();
/* dump system parameters for all DMA engines */
...
if(error_code = VME_BlockTransferEnd(block_transfer) {
/* end block transfer */
VME_ErrorPrint(error_code);
return(error_code);
}
- 67 -
3.8 Example 8: Block Transfer - Integrated Function
#include “vme_rcc.h”
...
u_int pci_address;
VME_BlockTransferList_t block_transfer_list;
int block_transfer;
VME_ErrorCode_t status;
int remaining;
int time_out = 10;
/* time-out about 10 msec */
VME_ErrorCode_t error_code;
char error_string[VME_MAXSTRING];
...
block_transfer_list.list_of_items[0].vmebus_address = 0x22000200;
block_transfer_list.list_of_items[0].system_iobus_address = pci_address;
block_transfer_list.list_of_items[0].size_requested = 0x100;
block_transfer_list.list_of_items[0].control_word = VME_DMA_D32R;
/* fill parameters for first block transfer */
block_transfer_list.list_of_items[1].vmebus_address = 0x23000200;
block_transfer_list.list_of_items[1].system_iobus_address= pci_address + 0x100;
block_transfer_list.list_of_items[1].size_requested = 0x100;
block_transfer_list.list_of_items[1].control_word = VME_DMA_D32R;
/* fill parameters for second block transfer */
block_transfer_list.number_of_items = 2;
/* total number of block transfers */
- 68 -
if(error_code = VME_BlockTransfer(&block_transfer_list, time_out) {
/* integrated function for block transfer */
if(!VME_BlockTransferStatus(block_transfer_list,i,&status)) {
/* check status of each block transfer */
VME_ErrorString(status,error_string);
printf(“ERROR in example program: block = %d, status = %s\n”,
i,error_string);
}
if(!VME_BlockTransferRemaining(block_transfer_list,i,&remaining)) {
/* check remaining words of each block transfer */
- 69 -
3.9 Example 9: Interrupts - Synchronous Method
#include “vme_rcc.h”
...
VME_InterruptList_t interrupt_list;
int interrupt;
VME_InterruptInfo_t interrupt_info;
int time_out = 100000;
/* time-out about 100 sec */
VME_ErrorCode_t error_code;
u_int error_number;
...
interrupt_list.list_of_items[0].vector = 0x11;
interrupt_list.list_of_items[0].level = 1;
interrupt_list.list_of_items[0].type = VME_INT_RORA;
/* fill parameters for first interrupt */
interrupt_list.list_of_items[1].vector = 0x22;
interrupt_list.list_of_items[1].level = 2;
interrupt_list.list_of_items[1].type = VME_INT_ROAK;
/* fill parameters for second interrupt */
interrupt_list.number_of_items = 2;
/* total number of interrupts */
VME_ErrorPrint(error_code);
return(error_code);
}
...
- 70 -
if(error_code = VME_InterruptWait(interrupt, time_out, &interrupt_info){
/* wait for interrupt */
VME_ErrorNumber(error_code,error_number);
/* convert error code to error number */
if(error_number == VME_TIMEOUT) {
/* compare error number to return value */
if(error_code = VME_InterruptInfoGet(&interrupt_info) {
/* get information on interrupt */
VME_ErrorPrint(error_code);
return(error_code);
}
if(interrupt_info.level == 1) {
/* interrupt from a level assigned to RORA interrupters? */
if(error_code = VME_InterruptRenable(interrupt) {
/* re-enable interrupt => can wait again on interrupt */
VME_ErrorPrint(error_code);
return(error_code);
}
}
...
VME_InterruptDump();
/* dump system parameters for all VMEbus interrupts */
...
if(error_code = VME_InterruptUnlink(interrupt) {
/* unlink VMEbus interrupt list from application program */
VME_ErrorPrint(error_code);
return(error_code);
}
- 71 -
3.10 Example 10: Interrupts - Asynchronous Method
#include “vme_rcc.h”
#include <signal.h>
...
int global_interrupt;
...
if(error_code = VME_InterruptInfoGet(&interrupt_info) {
/* get information on interrupt */
VME_ErrorPrint(error_code);
return(error_code);
}
if(interrupt_info.level == 1) {
/* interrupt from a level assigned to RORA interrupters? */
if(error_code = VME_InterruptRenable(global_interrupt) {
/* re-enable interrupt => can wait again on interrupt */
VME_ErrorPrint(error_code);
return(error_code);
}
}
...
}
...
VME_InterruptList_t interrupt_list;
VME_InterruptInfo_t interrupt_info;
int time_out = 100000;
/* time-out about 100 sec */
VME_ErrorCode_t error_code;
u_int error_number;
...
/* continued on next page */
- 72 -
interrupt_list.list_of_items[0].vector = 0x11;
interrupt_list.list_of_items[0].level = 1;
interrupt_list.list_of_items[0].type = VME_INT_RORA;
/* fill parameters for first interrupt */
interrupt_list.list_of_items[1].vector = 0x22;
interrupt_list.list_of_items[1].level = 2;
interrupt_list.list_of_items[1].type = VME_INT_ROAK;
/* fill parameters for second interrupt */
interrupt_list.number_of_items = 2;
/* total number of interrupts */
VME_ErrorPrint(error_code);
return(error_code);
}
...
if(error_code = VME_InterruptRegisterSignal(global_interrupt,SIGBUS) {
/* register SIGBUS signal for VMEbus interrupt list */
VME_ErrorPrint(error_code);
return(error_code);
}
...
/* install example interrupt handler for SIGBUS signal,
not part of this API, see function sigaction() */
if(error_code = VME_InterruptRegisterSignal(global_interrupt,0) {
/* (un-)register signal for VMEbus interrupt list */
VME_ErrorPrint(error_code);
return(error_code);
}
if(error_code = VME_InterruptUnlink(global_interrupt) {
/* unlink VMEbus interrupt list from application program */
VME_ErrorPrint(error_code);
return(error_code);
}
- 73 -
3.11 Example 11: Interrupts - Generate Interrupts
#include “vme_rcc.h”
#include <signal.h>
...
u_int level = 1;
u_int vector = 0x11;
VME_ErrorCode_t error_code;
...
VME_ErrorPrint(error_code);
return(error_code);
}
- 74 -
4 VMEbus Utility Programs
Two utility programs can accompany the API implementation: a utility program to configure
the VMEbus statically must accompany the VMEbus API, if the implementation requires this.
A utility program to test and debug the VMEbus (and the API implementation) and a facility to
scan the VMEbus address space shall always accompany the VMEbus API.
The VMEbus configuration utility is intended to be run at boot time when the ROD Crate
Processor is started.
The VMEbus test and debug facility (“vmescope”) must allow to test and debug the VMEbus
(and the API implementation). It has, in particular, to provide means to perform the following
functions:
• dump system parameters of the VMEbus bridge;
• create VMEbus master and slave mapping and read and write single values;
• perform VMEbus block transfers;
• receive VMEbus interrupts.
The VMEbus scanning facility (“vmescan”) must allow to scan the VMEbus and to report any
found VMEbus modules. It has, in particular, to perform the following functions:
• scan the whole VMEbus address space;
• scan the whole VMEbus CR/CSR space.
- 75 -
5 Ideas for a C++ Binding
This section presents some first ideas on a possible C++ binding or wrapping of the VMEbus
API. It shows the public members of the classes along with some of the private members.
- 76 -
5.1 Types
// block transfer
typedef VME_BlockTransferItem_t VMEBlockTransferItem;
typedef VME_BlockTransferList_t VMEBlockTransferList;
typedef VME_BlockTransferInfo_t VMEBlockTransferInfo;
- 77 -
5.2 VMEbus library/driver
class VME {
public:
// singleton members
static VME* Open();
static u_int Close();
// factory members
VMEMasterMap* MasterMap(u_int vmebus_address, u_int window_size
u_int address_modifier, u_int options);
u_int MasterUnmap(VME_MasterMap* master_map);
// status dumps
u_int MasterMapDump() const;
u_int SlaveMapDump() const;
u_int BlockTransferDump() const;
u_int InterruptDump() const;
- 78 -
private:
VME();
~VME();
// internals
...
};
- 79 -
5.3 VMEbus Master Mapping
class VMEMasterMap {
public:
// members for safe access
u_int ReadSafe(u_int address_offset, u_int* value);
u_int WriteSafe(u_int address_offset, u_int data);
// helpers
u_int VirtualAddress(u_int* virtual_address) const;
u_int Dump() const;
// friends
friend class VME;
private:
VME_MasterMap(u_int vmebus_address, u_int window_size,
u_int address_modifier, u_int options);
~VME_MasterMap();
int my_identifier;
VME_MasterMap_t my_master_map;
int my_status;
// internals
...
};
- 80 -
5.4 VMEbus Slave Mapping
class VMESlaveMap {
public:
// helpers
u_int VmebusAddress(u_int* vmebus_address) const;
u_int Dump() const;
// friend
friend class VME;
private:
VME_SlaveMap(u_int system_iobus_address, u_int window_size,
u_int address_width, u_int options);
~VME_SlaveMap();
int my_identifier;
VME_SlaveMap_t my_slave_map;
u_int my_status;
// internals
...
};
- 81 -
5.5 VMEbus Block Transfer
class VMEBlockTransfer {
public:
// main members
u_int Start();
u_int Wait(int time_out);
// helpers
u_int Status(int position_of_block, u_int* status);
u_int Remaining(int position_of_block, int* remaining);
u_int Dump() const;
// friend
friend class VME;
private:
VME_BlockTransfer(const VMEBlockTransferList&
block_transfer_list);
~VME_BlockTransfer();
int my_identifier;
VMEBlockTransferList my_block_transfer_list;
u_int my_status;
// internals
...
};
- 82 -
5.6 VMEbus Interrupts
class VMEInterrupt {
public:
// main members
u_int Wait(int time_out, VMEInterruptInfo& interrupt_info);
u_int SignalRegister(int signal_number);
u_int InfoGet(VMEInterruptInfo& interrupt_info);
u_int Reenable();
// helper
u_int Dump() const;
// friend
friend class VME;
private:
VME_Interrupt(const VMEinterruptList& interrupt_list);
~VME_Interrupt();
int my_identifier;
VMEInterruptListt my_interrupt_list;
u_int my_status;
// internals
...
};
- 83 -