devLibVME.h

API for accessing hardware devices, mosty over VMEbus.

API for accessing hardware devices. The original APIs here were for written for use with VMEbus but additional routines were added for ISA-bus (but not fully implemented inside EPICS Base and may never have been actually used).

Author

Marty Kraimer, Jeff Hill

If all VMEbus drivers register with these routines then addressing conflicts caused by multiple device/drivers trying to use the same VME addresses will be detected. This API also makes it easy for a single driver to be written that works on both VxWorks and RTEMS.

Deprecated Interfaces

enum epicsInterruptType

Values:

enumerator intVME
enumerator intVXI
enumerator intISA
long devConnectInterrupt(epicsInterruptType intType, unsigned vectorNumber, void (*pFunction)(void*), void *parameter)

Note

This routine has been deprecated. It exists for backwards compatibility purposes only. Please use one of devConnectInterruptVME(), devConnectInterruptPCI(), devConnectInterruptISA() instead. devConnectInterrupt() will be removed in a future release.

long devDisconnectInterrupt(epicsInterruptType intType, unsigned vectorNumber, void (*pFunction)(void*))

Note

This routine has been deprecated. It exists for backwards compatibility purposes only. Please use one of devDisconnectInterruptVME(), devDisconnectInterruptPCI(), devDisconnectInterruptISA() instead. devDisconnectInterrupt() will be removed in a future release.

long devEnableInterruptLevel(epicsInterruptType intType, unsigned level)

Note

This routine has been deprecated. It exists for backwards compatibility purposes only. Please use one of devEnableInterruptLevelVME(), devEnableInterruptLevelPCI(), devEnableInterruptLevelISA() instead. devEnableInterruptLevel() will be removed in a future release.

long devDisableInterruptLevel(epicsInterruptType intType, unsigned level)

Note

This routine has been deprecated. It exists for backwards compatibility purposes only. Please use one of devDisableInterruptLevelVME(), devDisableInterruptLevelISA(), devDisableInterruptLevelPCI() instead. devDisableInterruptLevel() will be removed in a future release.

long locationProbe(epicsAddressType addrType, char *pLocation)

Note

This routine has been deprecated. It exists for backwards compatibility purposes only. Please use devNoResponseProbe() instead. locationProbe() will be removed in a future release.

VME Interrupt Management

Routines to manage VME interrupts.

long devConnectInterruptVME(unsigned vectorNumber, void (*pFunction)(void*), void *parameter)

Connect an ISR up to a VME interrupt vector.

Interrupt Service Routines (ISRs) are normally written in C, and get passed a context parameter given with them to this connection routine.

There are many restrictions on the routines that an ISR may call; see epicsEvent.h, epicsInterrupt.h, epicsMessageQueue.h, epicsRingBytes.h, epicsRingPointer.h and epicsTime.h for some APIs known to be suitable. It is safest just to trigger a high-priority task to handle any complex work that must happen as a result of the interrupt.

Parameters:
  • vectorNumber – VME interrupt vector number.

  • pFunction – The ISR to be called.

  • parameter – Context parameter for the ISR.

Returns:

0, or an error status value.

long devDisconnectInterruptVME(unsigned vectorNumber, void (*pFunction)(void*))

Disconnect an ISR from its VME interrupt vector.

Device drivers may disconnect an ISR they connected earlier using this routine. In addition to taking the vectorNumber the ISR itself is required and used as a check to prevent a driver from inadvertently removing an interrupt handler that it didn’t install.

On a PowerPC target running VxWorks, this routine will always return with an error status.

Parameters:
  • vectorNumber – VME interrupt vector number.

  • pFunction – The ISR to be disconnected.

Returns:

0, or an error status value.

int devInterruptInUseVME(unsigned vectorNumber)

Determine if a VME interrupt vector is in use.

On a PowerPC target running VxWorks this routine will always return false, indicating that a vector is unused.

Parameters:

vectorNumber – Interrupt vector number.

Returns:

True if vector has an ISR attached, otherwise false.

long devEnableInterruptLevelVME(unsigned level)

Enable a VME interrupt level onto the CPU.

The VMEbus allows multiple CPU boards to be installed in the same backplane. When this is done, the different VME interrupt levels must be assigned to the CPUs since they cannot be shared. This routine tells the VME interface that it should connect interrupts from the indicated interrupt level to a CPU interrupt line.

Parameters:

level – VMEbus interrupt level to enable, 1-7.

Returns:

0, or an error status value.

long devDisableInterruptLevelVME(unsigned level)

Disable a VME interrupt level.

This routine is the reverse of devEnableInterruptLevelVME().

Note

This routine should not normally be used, even by a driver that enabled the interrupt level. Disabling a VME interrupt level should only be done by software that knows for certain that no other interrupting device is also using that VME interrupt level.

Parameters:

level – VMEbus interrupt level to disable, 1-7.

Returns:

0, or an error status value.

Memory for VME DMA Operations

These routines manage memory that can be directly accessed from the VMEbus in the A24 address space by another bus master such as a DMA controller.

void *devLibA24Malloc(size_t size)

malloc() for VME drivers that support DMA.

Allocate memory of a given size from a region that can be accessed from the VMEbus in the A24 address space.

Parameters:

size – How many bytes to allocate

Returns:

A pointer to the memory allocated, or NULL.

void *devLibA24Calloc(size_t size)

calloc() for VME drivers that support DMA.

Allocate and zero-fill a block of memory of a given size from a region that can be accessed from the VMEbus in the A24 address space.

Parameters:

size – How many bytes to allocate and zero.

Returns:

A pointer to the memory allocated, or NULL.

void devLibA24Free(void *pBlock)

free() for VME drivers that support DMA.

Free a block of memory that was allocated using either devLibA24Malloc() or devLibA24Calloc().

Parameters:

pBlock – Block to be released.

ISA Interrupt Management

Routines to manage ISAbus interrupts.

Note

These routines may not have been used for a very long time; some appear to have never been implemented at all. They may vanish with no notice from future versions of EPICS Base. Nobody is using the PC’s ISA-bus any more are they?

long devConnectInterruptISA(unsigned interruptLevel, void (*pFunction)(void*), void *parameter)

Connect ISR to a ISA interrupt.

Warning

Not implemented!

Parameters:
  • interruptLevel – Bus interrupt level to connect to.

  • pFunction – C function pointer to connect to.

  • parameter – Parameter to the called function.

Returns:

Returns success or error.

long devDisconnectInterruptISA(unsigned interruptLevel, void (*pFunction)(void*))

Disconnect ISR from a ISA interrupt level.

Warning

Not implemented!

Parameters:
  • interruptLevel – Interrupt level.

  • pFunction – C function pointer that was connected.

Returns:

returns success or error.

int devInterruptLevelInUseISA(unsigned interruptLevel)

Determine if an ISA interrupt level is in use

Warning

Not implemented!

Parameters:

interruptLevel – Interrupt level.

Returns:

Returns True/False.

long devEnableInterruptLevelISA(unsigned level)

Enable ISA interrupt level

Parameters:

level – Interrupt level.

Returns:

Returns True/False.

long devDisableInterruptLevelISA(unsigned level)

Disable ISA interrupt level

Parameters:

level – Interrupt level.

Returns:

Returns True/False.

Enums

enum epicsAddressType

The available bus address types.

Values:

enumerator atVMEA16

VME short I/O.

enumerator atVMEA24

VME standard I/O.

enumerator atVMEA32

VME extended I/O.

enumerator atISA

Memory mapped ISA access.

enumerator atVMECSR

VME-64 CR/CSR address space.

enumerator atLast

Invalid, must be the last entry.

Functions

long devAddressMap(void)

Print a map of registered bus addresses.

Display a table of registered bus address ranges, including the owner of each registered address.

Returns:

0, or an error status value

long devBusToLocalAddr(epicsAddressType addrType, size_t busAddr, volatile void **ppLocalAddr)

Translate a bus address to a pointer the CPU can use.

Given a bus address, returns a pointer to that location in the CPU’s memory map, or an error if direct access isn’t currently possible.

Parameters:
  • addrType – The bus address type.

  • busAddr – Bus address to be translated.

  • *ppLocalAddr – Where to put the CPU pointer.

Returns:

0, or an error status value.

long devReadProbe(unsigned wordSize, volatile const void *ptr, void *pValueRead)

Probe the bus for reading from a specific address.

Performs a bus-error-safe wordSize atomic read from a specific address and returns an error if this caused a bus error.

Parameters:
  • wordSize – The word size to read: 1, 2, 4 or 8 bytes.

  • ptr – Pointer to the location in the CPU’s memory map to read.

  • pValueRead – Where to put the value read.

Returns:

0, or an error status value if the location could not be accessed or the read caused a bus error.

long devNoResponseProbe(epicsAddressType addrType, size_t base, size_t size)

Read-probe a range of bus addresses, looking for empty space.

Verifies that no device responds at any naturally aligned addresses within the given range. Tries to read every aligned address at every word size between char and long over the entire range, returning success only if none of the reads succeed.

Warning

This routine may be slow and have a very bad effect on a busy VMEbus. Every read probe of an unused address will hold onto the VMEbus for the global bus timeout period.

Parameters:
  • addrType – The bus address type.

  • base – First address base to probe.

  • size – Range of bus addresses to test, in bytes.

Returns:

0 if no devices respond, or an error status value.

long devWriteProbe(unsigned wordSize, volatile void *ptr, const void *pValueWritten)

Probe the bus for writing to a specific address.

Performs a bus-error-safe wordSize atomic write to a specific address and returns an error if this caused a bus error.

Parameters:
  • wordSize – The word size to write: 1, 2, 4 or 8 bytes.

  • ptr – Pointer to the location in the CPU’s memory map to write to.

  • pValueWritten – The value to write.

Returns:

0, or an error status value if the location could not be accessed or the write caused a bus error.

long devRegisterAddress(const char *pOwnerName, epicsAddressType addrType, size_t logicalBaseAddress, size_t size, volatile void **pPhysicalAddress)

Register a bus address range with a name.

The devLib code keeps a list of all bus address ranges registered with this routine and returns an error if a later call attempts to register any addresses that overlap with a range already registered. The call to registering a range also converts the given base address into a pointer in the CPU address space for the driver to use (see devBusToLocalAddr()).

Parameters:
  • pOwnerName – Name of a driver that will own this range.

  • addrType – The bus address type.

  • logicalBaseAddress – The bus start address.

  • size – Number of bytes to reserve.

  • pPhysicalAddress – Where to put the converted CPU pointer.

Returns:

0, or an error status.

long devUnregisterAddress(epicsAddressType addrType, size_t logicalBaseAddress, const char *pOwnerName)

Release a bus address range previously registered.

Release an address range that was previously registered by a call to devRegisterAddress() or devAllocAddress().

Parameters:
  • addrType – The bus address type.

  • logicalBaseAddress – The bus start address.

  • pOwnerName – The name of the driver that owns this range.

Returns:

0, or an error status.

long devAllocAddress(const char *pOwnerName, epicsAddressType addrType, size_t size, unsigned alignment, volatile void **pLocalAddress)

Allocate and register an unoccupied address block.

Asks devLib to allocate an address block of a particular address type. This is useful for devices that appear in more than one address space and can program the base address of one window using registers found in another window. As with devRegisterAddress() this call also converts the new base address into a pointer in the CPU address space for the driver to use (see devBusToLocalAddr()).

Note

This routine calls devNoResponseProbe() to find an unoccupied block in the bus address space, so using it may have a bad effect on a busy VMEbus at allocation time; see the warning above.

Parameters:
  • pOwnerName – Name of a driver that will own this range.

  • addrType – The bus address type.

  • size – Number of bytes to be allocated.

  • alignment – How many low bits in the address must all be zero.

  • pLocalAddress – Where to put the CPU pointer.

Returns:

0, or an error status value.

Variables

const char *epicsAddressTypeName[]

A string representation of each of the bus address types.