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:
-
Edit the config/RELEASE file and set the correct path for EPICS_BASE at
your site.
-
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
int
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
ipacAddCarrier(&vipc610_01, "0x6000,256");
ipacAddCarrier(NULL, "");
ipacAddCarrier(&vipc310, "0x6800");
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
int
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
int
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
int
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
int
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
int
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
"C0 S1 : 0xB1/0x01 - M0 L4,5"
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
ipacAddCarrier &ipmv162, "A:m=0x80000000,1024 l=5,3 w=8 r=2 B:l=2"
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>