drvIpac - Industry Pack Driver

Version 2.1
Andrew Johnson
See also the following Module Drivers supplied which use drvIpac:

1. Introduction

This document describes the software interface to a generic Industry Pack (IPAC) driver module for vxWorks, written as part of a CANbus EPICS device driver for the Gemini and UKIRT telescopes. The original purpose of the generic IPAC driver was to ensure that the CANbus driver would not be restricted to use with a single carrier board but could be used with different carriers as required, including with more than one type of carrier board simultaneously. The use of the generic driver also ensures that additional IPAC modules and drivers for other interfaces can be added without affecting the functioning of the CANbus driver.

To provide a generic IPAC carrier board interface for each IPAC module driver, all control of or requests for information about the carrier board goes via the IPAC driver which in turn calls the IPAC Carrier driver written for the particular type of carrier board. This carrier driver should be simple to write, comprising three or four short subroutines and an interface structure. On VMEbus, carrier drivers are available for the GreenSpring VIPC310, 610 and 616 boards, and a driver for the Motorola MVME162 that also works on the MVME172. On ISAbus the GreenSpring ATC40 carrier is now supported by a driver from Jeff Hill.

At present the IPAC driver is limited (by the size of an internal array) to controlling a maximum of 21 carrier boards, but this limitation should be easy to dispense with completely without altering any of its interfaces. Although designed primarily to be used from within an EPICS system, the software has been written to allow it to be used independent of the presence of EPICS in other vxWorks-based applications.

Installation

From version 2.0 onwards the drvIpac subsystem has been separated from the CANbus driver but provided within an EPICS <supporttop> application which can also be used to build IPAC module drivers. To install and use the the ipac support, obtain a copy of the tar file or (if you have remote CVS permissions at APS) export the software from the CVS repository where it resides as epics/unbundled/ipac - CVS tags of the form `V2-1' mark the particular file versions required for each release. These instructions assume you already have EPICS R3.13.x installed and built (this software should work with EPICS R3.13.0.beta11 and later). Two steps are then required to install and build the software:
  1. Edit the config/RELEASE file and set the correct path for EPICS_BASE at your site.
  2. Run gnumake in the top level directory.
If you don't need all of the module drivers included with the distribution, you may wish to edit the top level Makefile and comment out the lines mentioning driver directories you don't need.

Bus Issues

From version 2-1 this software supports little-endian as well as big-endian busses, and provides a means of isolating module drivers from some of the differences between interrrupt handling on different busses.

The endian problem only exists when accessing I/O registers and the IPAC ID PROM using byte addresses. If all accesses occur using 16-bit read/write cycles then the problem disappears. This is usually done by changing the structure that declares the structure of a module's registers to use short instead of char and removing the `padding' char members that separate the registers (this change has been made to the ipac_idProm_t structure which is declared in drvIpac.h). This done the other changes are generally minor, usually consisting of masking off the top 8 bits of every value read from the hardware.

Some busses such as ISAbus do not support interrupt vectors and require a different approach to connecting Interrupt Service Routines up to the relevent hardware interrupts, although the IndustryPack standard does require that any IP module that generates interrupts should provide a vector. On ISA bus carriers this vector can be read by the carrier driver to work out which module caused the interrupt. A module driver should not need to know about the particular bus type its carrier is on, thus ipac now provides the routine ipmIntConnect to allow it to pass such issues off to the carrier driver to handle. The interface to this is very similar to the standard vxWorks intConnect routine.


2. IPAC Driver Usage

The driver provides a C header file drvIpac.h for use by both module and carrier drivers.
#include "drvIpac.h"
This header file declares the necessary structures, enumerated types and functions provided by the driver. These are individually documented below. This header #includes the vxWorks ANSI header file types.h thus the -I C pre-processor switch must be used to indicate the location of the vxWorks headers to the compiler.

If it is necessary to build a copy of the driver for use without EPICS, the drvIpac.c file should be compiled with the -DNO_EPICS switch to disable the EPICS-specific code.


ipacAddCarrier

Used to register a carrier board and the appropriate carrier driver software for it with the IPAC Driver.
int ipacAddCarrier(ipac_carrier_t *pcarrier, char *cardParams);

Parameters

ipac_carrier_t *pcarrier
Pointer to the carrier driver structure which is the only interface to the IPAC Carrier driver. The same structure is used for every instance of the same type of carrier board. The carriers already supported provide the following structures which can be used here:
Board Type Carrier Driver pcarrier
GreenSpring VIPC 310 drvVipc310 &vipc310
GreenSpring VIPC610 drvVipc610 &vipc610
GreenSpring VIPC610-01 drvVipc610_01 &vipc610_01
GreenSpring VIPC616 drvVipc616 &vipc616
GreenSpring ATC40 drvAtc40 &atc40
Motorola MVME162/172 drvIpMv162 &ipmv162
char *cardParams
String containing board-specific initialisation parameters which is passed to the carrier driver. For carrier boards which rely on jumpers to set the board address (e.g. the GreenSpring carrier boards), the settings for each particular board will be reflected in the parameter settings given here when registering that carrier. For boards such as the MVME162 where the addresses can be changed by the driver, this string may be used to indicate how the board should be initialised. See the specific documentation for each carrier driver (section 4 below) for the parameter string syntax.

Description

This routine will usually be called from the vxWorks (EPICS) start-up script. Some types of carrier may need additional initialisation before or after registering, but this method using the card parameter string should be sufficient for most carriers. Note that only the carrier initialise routine is called at this stage. The order in which carriers are registered with this routine defines the carrier number which they will be allocated, starting from zero for the first board registered.

The code checks that the carrier descriptor table looks sensible, calls the initialise routine with the given card parameters, then saves the carrier private pointer and carrier table address in an internal array. The card number allows the same descriptor table to be used for all carriers of the same type.

It may be necessary to remove a carrier temporarily from a system in some circumstances without wanting to have to change the carrier number allocated to higher numbered carriers. To allow this, it is legal to call this routine with a NULL (zero) carrier table address, which switches in the null carrier table instead. When this facility is used any module driver which attempts to access a slot on this carrier will be given error status returns by the module interface routines.

Returns

Symbol/Value Meaning
0 OK
S_IPAC_tooMany Carrier Info Table full
S_IPAC_badTable Carrier Table invalid
(others values) from carrier initialisation routine.

Examples


ipacReport

Prints a report on stdout giving the status of all known IPAC carriers.
int ipacReport(int interest);

Parameters

int interest
Interest level, defines how much information to provide in the report.

Description

Prints information on each known carrier board and slot according to the specified interest level. Level 0 lists all the carriers defined, with the number of IPAC slots each one supports. Level 1 gives details on each slot on the carriers: the Manufacturer and Model ID bytes of the installed module if one is present, and the Carrier Driver's report for that slot (see ipmReport below). Level 2 adds the CPU address of each memory space for the slot.

Returns

Symbol/Value Meaning
0 OK.


ipacInitialise

Initialise the IPAC driver.
int ipacInitialise(int after);

Parameters

int after
Not currently used, provided for compatibility with EPICS driver initialisation routine.

Description

Null routine, does nothing.

Returns

Symbol/Value Meaning
0 OK.


3. Calls for use by IPAC Module Drivers

The routines documented below are provided for use by the module drivers which use the services of the generic IPAC driver. In general it is expected that these routines will only be used at initialisation time. The module driver should be informed by other means which carrier and slot the particular IPAC module it is to control is installed in, although it should be possible to search each carrier and slot number in turn for the module using the Manufacturer and Model ID codes.

ipmBaseAddr

Returns Base CPU address of selected IP address space
void *ipmBaseAddr(ushort_t carrier, ushort_t slot, ipac_addr_t space);

Parameters

ushort_t carrier
Carrier number; identifies a particular carrier board in the system. The carriers are given numbers sequentially starting from zero according to the order in which they were registered by calling ipacAddCarrier.
ushort_t slot
Slot number; identifies the particular IP slot on the carrier board, starting from zero. The number of slots available varies with the type of the carrier board - the VIPC310 and MVME172 provide 2, the VIPC610, VIPC616, ATC40 and MVME162 each have four slots.
Together these two parameters uniquely identify a specific IPAC module in the system, and these are used in this way by all of the following routines.
ipac_addr_t space
Value identifying the IP address space to be queried. This parameter is an enumerated type, and must be one of the following values which are defined in the header file:
IP Address Space space
ID Prom Space ipac_addrID
Register Space ipac_addrIO
32-bit Register Space ipac_addrIO32
Memory Space ipac_addrMem

Description

Checks its input parameters, then calls the carrier driver. This will return a pointer to the location of the address space indicated by the space parameter.

All IP modules must provide an ID prom to indicate the module type (space = ipac_addrID). Most modules need register I/O locations, which are in the I/O space (space = ipac_addrIO). Some types of module also provide memory (space = ipac_addrMem), but if this is not required the carrier may allow it to be disabled, in which case the carrier driver will return a NULL for this address space. Some carriers also provide a 32-bit wide I/O space for accessing 32-bit registers on Dual-slot IP modules (space = ipac_addrIO32); carriers which do not support this will return NULL for this space.

Returns

void *
Pointer to the beginning of the IP address space for the given carrier/slot, or NULL pointer.

ipmCheck

Check on the presence of an IPAC module at the given carrier and slot number.
int ipmCheck(ushort_t carrier, ushort_t slot);

Parameters

ushort_t carrier, ushort_t slot
Module identification - see above

Description

Does a quick check to make sure the carrier and slot numbers are legal, probes the IDprom space to ensure an IPAC is installed, and checks that the IDprom starts with the "IPAC" identifier.

Returns

Symbol/Value Meaning
0 OK
S_IPAC_badAddress Bad carrier or slot number
S_IPAC_badDriver Carrier driver returned NULL ID address
S_IPAC_noModule No IP module installed
S_IPAC_noIpacId "IPAC" identifier not found


ipmValidate

Validates a particular IPAC module type at the given carrier & slot number.
int ipmValidate(ushort_t carrier, ushort_t slot,
                uchar_t manufacturerId, uchar_t modelId);

Parameters

ushort_t carrier, ushort_t slot
Module identification - see above
uchar_t manufacturerId
IPAC Manufacturer Identification Number, as allocated by GreenSpring. This number should be given in the Programmer's Documentation for the IPAC module.
uchar_t modelId
IPAC Model Identification Number, as allocated by the module manufacturer. This number should be given in the Programmer's Documentation for the IPAC module.

Description

Uses ipmCheck to ensure the carrier and slot numbers are legal, probe the IDprom and check that the IDprom looks like an IPAC module. Then calculates and verifies the CRC for the ID Prom, and compares the manufacturer and model ID values in the Prom to the ones given.

The manufacturer and model identification numbers allow a Module Driver to ensure that the correct hardware has been installed in the particular slot which the driver has been told to control. If a driver supports more than one type of module, it should check each module type individually by calling ipmValidate with each manufacturer/model pair it can control until it finds a match.

Returns

Symbol/Value Meaning
0 OK
S_IPAC_badCRC CRC Check failed
S_IPAC_badModule Manufacturer or model IDs wrong
S_IPAC_badAddress Bad carrier or slot number
S_IPAC_badDriver Carrier driver returned NULL ID address
S_IPAC_noModule No IP module installed
S_IPAC_noIpacId "IPAC" identifier not found


ipmIrqCmd

Manipulate the carrier board interrupt controller.
int ipmIrqCmd(ushort_t carrier, ushort_t slot,
              ushort_t irqNumber, ipac_irqCmd_t cmd);

Parameters

ushort_t carrier, ushort_t slot
Module identification - see above
ushort_t irqNumber
The IPAC specification provides two interrupt lines for each module. This parameter identifies the interrupt to the Carrier Driver. It should have the value 0 or 1 only.
ipac_irqCmd_t cmd
This parameter gives the action required, and is an enumerated type defined in the header file. Because some carrier boards do not provide software access to their interrupt controllers, there is only one command which must be supported by all carriers. Module Drivers can be written to utilise the additional functions if they are available.

Description

Checks input parameters, then passes the interrupt command request to the equivalent Carrier Driver routine. The driver is only required to support the command ipac_irqEnable; for other commands it may return the status code S_IPAC_notImplemented and do nothing. Commands available are as follows:
 
Command Description cmd
Selects Interrupt Priority 0 (disabled) ipac_irqLevel0
Selects Interrupt Priority 1 ipac_irqLevel1
Selects Interrupt Priority 2 ipac_irqLevel2
Selects Interrupt Priority 3 ipac_irqLevel3
Selects Interrupt Priority 4 ipac_irqLevel4
Selects Interrupt Priority 5 ipac_irqLevel5
Selects Interrupt Priority 6 ipac_irqLevel6
Selects Interrupt Priority 7 (non-maskable) ipac_irqLevel7
Returns current Interrupt Priority, 0 to 7 ipac_irqGetLevel
Enable interrupts from module ipac_irqEnable
Disable interrupts from module ipac_irqDisable
Returns current interrupt signal state ipac_irqPoll

The Interrupt Priority (often also known as interrupt level) commands are defined to be numerically the same as the level number they select. Level 0 effectively disables the interrupt. Level 7 is not recommended within vxWorks as it is non-maskable and can cause the kernel to panic. The irqGetLevel command returns the level currently set. Carrier boards which have fixed interrupt levels will not support setting the interrupt level but the driver may still able to return the level number.

The irqEnable command must be supported by all Carrier Drivers, and must be called by all Module Drivers if they wish to use interrupts. The Carrier Driver routine is responsible for calling the vxWorks sysIntEnable routine if this is required to allow IPAC interrupts to be seen by the CPU. The corresponding irqDisable command is not necessarily supported by all carriers however -- the module driver must disable interrupts using the control registers on the IP module itself if this is necessary. A Carrier Driver must not implement the irqDisable command as a call to the vxWorks sysIntDisable routine because this would stop any other devices which still need this interrupt level from working.

Returns

Symbol/Value Meaning
0 OK
S_IPAC_badAddress No such carrier or slot
S_IPAC_notImplemented Driver does not support that command

Other values may also be returned depending on the Driver and command used.


ipmIntConnect

Connects a module driver Interrupt Service Routine to a particular interrupt vector number.
int ipmIntConnect (ushort_t carrier, ushort_t slot, ushort_t vecNum, 
                   void (*routine)(int parameter), int parameter);

Parameters

ushort_t carrier, ushort_t slot
Module identification - see above
ushort_t vecNum
Interrupt vector number
void (*routine)(int parameter)
Modules Interrupt Service Routine to be connected
int parameter
Context parameter passed to Interrupt Service Routine

Description

Checks input parameters, then passes the request to the carrier driver routine.  If no carrier routine is provided it uses the standard vxWorks intConnect routine instead.  This is not quite a direct replacement for the vxWorks intConnect call; as well as providing the carrier and slot numbers the module driver must not use the INUM_TO_IVEC(vecNum) macro but just pass the vector number to this routine.

VxWorks' interrupt vectoring mechanism varies between bus types, and ipmIntConnect allows a module driver to connect its routine to an interrupt vector from a particular IPAC module without knowing the requirements of the particular bus type. Some carrier drivers will need to maintain a private interrupt dispatch table if the bus type (i.e. ISA) does not support interrupt vectoring.

Returns

int
Symbol/Value Meaning
0 OK
S_IPAC_badAddress No such carrier, slot or vector

Other values may also be returned depending on the Driver and vector used.


ipmReport

Returns a printable string giving the status/settings of the given slot.
char *ipmReport(ushort_t carrier, ushort_t slot);

Parameters

ushort_t carrier, ushort_t slot
Module identification - see above

Description

Generates a report string describing the given IPAC slot. If a module is installed, it includes the manufacturer and model ID numbers. If the report function is supported by the carrier driver this report string is appended. This function is uses a single internal static character array to hold the report string, thus the value will be corrupted if two tasks use this routine simultaneously.

Returns

char *
Pointer to a static, printable string.

Sample Output

This string is made up of three parts. The first two elements before the colon give the carrier and slot number of the slot. If a module is installed, the manufacturer and model IDs follow as two hex numbers. Finally if the Carrier Driver contains a report function it is called and the string it returns is appended after the hyphen.

4. IPAC Carrier Drivers

GreenSpring VIPC310

This board is probably the simplest possible VME-based IPAC Carrier available. A 3U VME card, it provides two IP slots (although it cannot support 32-bit accesses to dual-slot IP modules), and allows no control over the slot interrupt controllers from software. The base addresses for the card are set using a series of jumpers on the board which select both the VME short I/O base address (used for the IPAC ID Prom and Register spaces) and the VME Standard base address (used for the IPAC Memory space if required). Additional jumpers allow the size of the IPAC Memory to be selected. The interrupts are at priority levels fixed by the hardware.

The IPAC Carrier Driver for this board is found in the file drvVipc310.c which exports only the symbol vipc310 for use as the carrier descriptor table with ipacAddCarrier.

Configuration Parameter String Format

The parameter string should comprise a hexadecimal number (an 0x or 0X at the start is optional) optionally followed by a comma and a decimal integer. The first number is the I/O Base Address of the card in the VME A16 address space. The factory default setting for the card gives an I/O Base Address of 0x6000, and this value will be used if the string is empty or NULL. If supplied the second number in the parameter string gives the size in Kbytes of the memory space allocated to each IP module.

The Memory Base Address of the VIPC310 card is set using the same jumpers as the I/O base address and is always 256 times the I/O base address, but in the VME A24 address space. The factory default for the memory base address is thus 0x600000.

If the memory size parameter is omitted or set to zero then neither IP module provides any memory space. Legal memory size values are 0, 64, 128, 256, 512, 1024 or 2048. The memory size interacts with the memory base address such that it is possible to set the existence of memory in either slot independently by suitable adjustment of the base address.

Configuration Examples

ipacAddCarrier(&vipc310, "0x6000")
This indicates that the carrier has its I/O base set to 0x6000, and neither slot uses any memory space.
ipacAddCarrier(&vipc310, "1000,512")
Here the I/O base is set to 0x1000, and there is 512 Kbytes of memory on each module, with the IP module A memory at 0x100000 and module B at 0x180000.
ipacAddCarrier(&vipc310, "0xfe00, 128")
The I/O Base is at 0xfe00, and hence the carrier board Memory Base address is 0xfe0000. However because the memory size is set to give each module 128 Kbytes of memory space, module A cannot be selected (128 K = 0x020000, so the module Memory Base would be decoded at 0xfc0000 but can't be accessed there because this is below the Memory Base address for the board).

Interrupt Commands Supported

The board uses fixed interrupt levels, and provides no software control over the interrupt generator. The only commands thus supported are a request of the interrupt level associated with a particular slot and interrupt number, or to enable interrupts by making sure the CPU's VMEbus interrupter is listening on the necessary level.
 
cmd Value Returned
ipac_irqGetLevel slot interrupt level (1, 2, 4 or 5)
ipac_irqEnable 0 = OK
(other commands) S_IPAC_notImplemented


GreenSpring VIPC610

This board is a four-slot, 6U carrier, but otherwise very similar to the VIPC310. A seperate driver is also provided for the VIPC610-01 option which changes the Interrupt Priority levels for the IP slots so they are equivalent to a pair of VIPC310 carrier boards, different to the interrupt levels for a standard VIPC610 board.

The IPAC Carrier Drivers for the two board versions are found in the files drvVipc610.c and drvVipc610_01.c which export the symbols vipc610 and vipc610_01 respectively for use as the carrier descriptor tables with ipacAddCarrier.

Note that as from version 1.1 of this software vipc610_01 is a new name for the original vipc610 symbol which has been changed to allow support for the standard board. Use of the wrong symbol may result in interrupts from modules in slots B through D being ignored.

Configuration Parameter String Format

The parameter string should comprise a hexadecimal number (an 0x or 0X at the start is optional) optionally followed by a comma and a decimal integer. The first number is the I/O Base Address of the card in the VME A16 address space. The factory default setting for the card gives an I/O Base Address of 0x6000, and this value will be used if the string is empty or NULL. If supplied the second number in the parameter string gives the size of the memory space in Kbytes allocated to each IP module.

The Memory Base Address of the VIPC610 card is set using the same jumpers as the I/O Base Address and is always 256 times the I/O Base Address, but in the VME A24 address space. The factory default for the Memory Base address is thus 0x600000.

If the memory size parameter is omitted or set to zero then none of the IP modules on the carrier provide any memory space. Legal memory size values are 0, 64?, 128, 256, 512, 1024 or 2048. The memory size interacts with the Memory Base Address setting such that it is possible to exclude memory from the lower slots while still providing access to memory in the later slots by suitable adjustment of the base address.

Configuration Examples

ipacAddCarrier(&vipc610, "0x6000")
This indicates that the VIPC610 carrier board has its I/O base set to 0x6000, and none of the slots provide memory space.
ipacAddCarrier(&vipc610_01, "1000,128")
Here the I/O base is set to 0x1000, and there is 128Kbytes of memory on each module, with the IP module A memory at 0x100000, module B at 0x120000, module C at 0x140000 and D at 0x160000. The board is actually a VIPC610-01.
ipacAddCarrier(&vipc610, "7000,1024")
The I/O base is at 0x7000, and hence the carrier memory base is 0x700000. However because the memory size is set to 1024 Kbytes, modules A, B and C cannot be selected (1024 K = 0x100000, so they are decoded at 0x400000, 0x500000 and 0x600000 but can't be accessed because these are below the base address for the board).

Interrupt Commands Supported

The board uses fixed interrupt levels, and provides no software control over the interrupt generator. The only commands thus supported are a request of the interrupt level associated with a particular slot and interrupt number, or to enable interrupts by making sure the CPU's VMEbus interrupter is listening on the necessary level. Note that the VIPC610-01 uses different interrupt levels to the straight VIPC610.
 
cmd Value Returned
ipac_irqGetLevel slot interrupt level
ipac_irqEnable 0 = OK
(other commands) S_IPAC_notImplemented


GreenSpring VIPC616

The only differences between this carrier and the VIPC610 relate to the VME addressing capabilities of the card which can now support memory IP modules in the VME A32 address space. It is possible to use the VIP610 driver to control a VIPC616 board, but the use of this specific driver is recommended. This driver should also be used for the VIPC618 carrier which is schematically identical to the VIPC616 but uses different I/O connectors for the IP module signals.

Configuration Parameter String Format

The parameter string should comprise a hexadecimal number (an 0x or 0X at the start is not required) optionally followed by a comma and another hexadecimal number, and then possibly another comma and a decimal integer. The first number is the I/O Base Address of the card in the VME A16 address space. The factory default setting for the card gives an I/O Base Address of 0x6000, and this value will be used if the string is empty or NULL.

The meaning of the second number depends upon whether the third (decimal) integer is present in the string or not. If there is no third number then the second number gives the Memory Base Address of the card in the VME A32 space. In this case each module is allocated a fixed 8 Mbytes of memory space by the carrier.

If all three numbers are given then the second number is the Memory Base Address of the card in VME A24 address space, and the third number gives the size of the memory space in Kbytes allocated to each IP module. This is the VIPC610 compatibility mode, and the Memory Base Address and Memory Size parameters are used and interact in exactly the same way as with the VIPC610.

Configuration Examples

ipacAddCarrier(&vipc616, "0x6000")
This indicates that the board has its I/O base set to 0x6000, and none of the slots provide memory space.

[I'm not sure that this example is correct; ommitting the MBA may result in an error. I don't have a VIPC616 to check this out with, so the driver is untested.]
ipacAddCarrier(&vipc616, "1000,8000000")
Here the I/O base is set to 0x1000, and each module is allocated 8Mb of VME A32 memory space starting at 0x80000000. This puts IP module A memory at 0x80000000, module B at 0x80800000, module C at 0x81000000 and D at 0x81800000.
ipacAddCarrier(&vipc616, "7000,700000,1024")
The I/O base is at 0x7000 and the carrier memory base is at 0x700000 in the VME A24 address space. However because the memory size is set to 1024 Kbytes, modules A, B and C cannot be selected (1024 K = 0x100000, so they are decoded at 0x400000, 0x500000 and 0x600000 but can't be accessed because these are below the base address).

Interrupt Commands Supported

The board uses fixed interrupt levels, and provides no software control over the interrupt generator. The only commands thus supported are a request of the interrupt level associated with a particular slot and interrupt number, or to enable interrupts by making sure the CPU's VMEbus interrupter is listening on the necessary level.
 
cmd Value Returned
ipac_irqGetLevel slot interrupt level
ipac_irqEnable 0 = OK
(other commands) S_IPAC_notImplemented


GreenSpring ATC40

The GreenSpring ATC40 is an IP carrier board for the ISAbus, which is a little-endian architecture unlike the VMEbus. Providing support for this board has required some changes to the drvIpac software which are described in the Bus Issues section above. Unless similar precautions are taken when writing module drivers these will not be compatible with little-endian systems. This carrier driver was written by Peregrine McGehee and Jeff Hill, who should be approached directly for support. Note that the carrier driver source file drvIpac/drvAtc40.c will only compile properly for x86 CPUs, and as shipped this file is commented out in drvIpac/Makefile.Vx.

Motorola MVME162 and MVME172

The Motorola MVME162 CPU board provides four IP slots in addition to the MC68040 CPU, memory and I/O. Slot pairs can be used with 32-bit dual-slot IP modules, and the IPIC chip which controls the interface supports all of the IPAC Driver interrupter commands. The Motorola MVME172 CPU board uses exactly the same IPIC chip and thus is compatible with the MVME162, although physically it only has two IP slots. The same software can be used on either board, although slots C and D on an MVME172 will always appear to be empty.

When this CPU board is used the IPAC carrier driver drvIpMv162.c can control the IP slots on the board. The ipacAddCarrier carrier descriptor table parameter is ipmv162 for this driver. The carrier initialisation routine has the following additional return-code meanings (see also ipacInitialise above):
 

Symbol/Value Meaning
S_IPAC_tooMany IpMv162 carrier already registered
S_IPAC_badDriver IPIC chip not found
S_IPAC_badAddress Parameter string error, or address not reachable

Configuration Parameter String Format

The parameter string is used to initialise the IPIC registers which allow detailed control of several settings for each slot. The string consists of a series of single characters to determine the slot and setting to be controlled and one or more numeric parameters for each setting. The string is parsed sequentially from left to right, and the characters and their parameters have the following meanings:
A, B, C and D
These select the IP slot (also identified as slots 0 through 3) which is to be controlled by the following commands, up to the appearance of the next of these slot selection characters.
l=level1[,level2]
Sets the interrupt level for the slot interrupters to the decimal values given by level1 and level2 respectively. If the second IP interrupt is not used by the particular module the ,level2 part may be omitted and this interrupt will be disabled. The default setting is for both interrupts to be disabled.
m=base,size
Enables the slot memory space and sets the base address for the slot to the hexadecimal value given by base, with extent given by the size parameter in kilobytes. NB size cannot be omitted.
r=recovery
This programs the slot recovery timer on the IPIC chip to be at least recovery microseconds (legal values are between 0 and 8 inclusive). This option should only be required with some early IP module designs.
w=width
The IPIC chip can alter the way in which the IP module memory space is addressed and is controlled using this option. By default or with a w=16 setting the memory will be initialised to be 16 bits wide with direct mapping of CPU addresses to IP memory addresses. By using the setting w=8 it is possible to access only the odd bytes of the IP memory space, i.e. only the 8 least significant bits of the data bus are used (other carrier boards may not support this type of operation so this facility should be used with care). The w=32 setting permits the memory space on double-width IP modules to be accessed using 32-bit transfers; this should be used on the even-numbered slot of the pair only.
Other characters will be ignored without affecting the parsing of the remainder of the parameter string.

Configuration Example

The above example initialises slots 0 and 1 only - slots 2 and 3 are not used or their modules require register and ID Prom access only in this particular application.

Slot 0 is set up for a slow (recovery time 2µs) memory board with 1 Mbyte of 8-bit wide RAM, addressed at 0x80000000 and with interrupt priorities set for levels 5 and 3.

Slot 1 has no memory space, and just a single interrupt at priority level 2.

Interrupt Commands Supported

The IPIC chip allows a lot of control over the IP interrupters, thus all commands perform the requested action. The ipmIrqCmd return values for the commands are:
 
cmd Value Returned
ipac_irqGetLevel current slot interrupt level
ipac_irqPoll >0 if the interrupt line is active, else 0
other calls 0 = OK


5. Interface to IPAC Carrier Drivers

Writing a new Carrier Driver is quite simple, and requires just three subroutines to be produced (the report function is optional). The driver will need some of the definitions in the drvIpac.h file.
#include "drvIpac.h"
All routines should be re-entrant, and no static variables should be used unless (like the mv162) only one carrier board of this type is possible in a particular system. In this case re-entrancy is still essential, but static variables may be used to hold information about the carrier provided these are protected from simultaneous updates by different tasks.

The sole interface between the Carrier Driver and the IPAC driver is through the ipac_carrier_t typedef structure given in the header file. Note that this has changed slightly since version 2.0 with the addition of the carrier parameter to the initialise routine, and the new intConnect routine. This is defined as follows:

typedef struct {
    char *carrierType;                 /* String describing carrier board type */
    ushort_t numberSlots;              /* Number of IPAC devices this carrier can hold */
    int (*initialise)(char *cardParams, void **cPrivate, ushort_t carrier);
                                       /* Initialise carrier and return *cPrivate */
    char *(*report)(void *cPrivate, ushort_t slot);
                                       /* Return string giving status of this slot */
    void *(*baseAddr)(void *cPrivate, ushort_t slot, ipac_addr_t space);
                                       /* Return base addresses for this slot */
    int (*irqCmd)(void *cPrivate, ushort_t slot, ushort_t irqNumber,
                  ipac_irqCmd_t cmd);  /* Interrupt control */
    int (*intConnect)(void *cPrivate, ushort_t slot, ushort_t vecNum,
                      void (*routine)(int parameter), int parameter);
                                       /* Connect routine to interrupt vector */
} ipac_carrier_t;
The first two structure members provide fixed information about the carrier to the IPAC driver. carrierType is a string which is printed by the report function to identify the type of carrier board, and numberSlots indicates how many IPAC slots this particular type of carrier provides.

The remaining structure members are function pointers to the routines which control the carrier board. The cPrivate parameter passed to these functions points to a structure which must be defined and allocated by the carrier driver and can be used to hold information about a particular carrier board (for example the board base address). The IPAC driver stores the cPrivate pointer which is returned by the initialise routine, and passes the same pointer back to the other routines when referring to that particular carrier board at a later stage.

The intConnect function pointer may be set to NULL if the standard vxWorks intConnect provides all the funtionality needed to install an interrupt vector - this is probably only needed for ISA bus carriers.

The other parameters to the routines are identical to those described in detail in the corresponding IPAC Driver routines above. The IPAC Driver performs parameter checking on the slot and irqNumber parameters before calling the Carrier Driver routine, so these values can be used with confidence.

The simplest way to write a carrier driver is to copy the VIPC310 or MVME162 driver and modify one of these for the new board type. The MVME162 driver interfaces to the IPIC chip and can be used as a basis for carrier drivers which provide extensive control over the IPAC slots. The VIPC310 board is totally dumb, and thus provides the simplest possible example of a carrier driver.


Andrew Johnson <anjohnson@iee.org>