2003-02-20 Till Straumann <strauman@slac.stanford.edu>

PR 349/bsps
	* shared/README.universe, shared/vmeUniverse/README.porting
	shared/vmeUniverse/README.universe, shared/vmeUniverse/vmeUniverse.c,
	shared/vmeUniverse/vmeUniverse.h: Update of the VME universe driver.
This commit is contained in:
Joel Sherrill
2003-02-20 21:35:57 +00:00
parent 4f3e4f33db
commit 20b349f15f
4 changed files with 340 additions and 78 deletions

View File

@@ -1,3 +1,10 @@
2003-02-20 Till Straumann <strauman@slac.stanford.edu>
PR 349/bsps
* shared/README.universe, shared/vmeUniverse/README.porting
shared/vmeUniverse/README.universe, shared/vmeUniverse/vmeUniverse.c,
shared/vmeUniverse/vmeUniverse.h: Update of the VME universe driver.
2002-10-28 Eugeny S. Mints <Eugeny.Mints@oktet.ru>
* ide_ctrl.c: New file.

View File

@@ -0,0 +1,88 @@
#
# $Id$
#
The vmeUniverse driver needs some support from the BSP for
a) PCI configuration space access
b) PCI interrupt acknowledgement
c) PCI interrupt handler installation
The driver was developed using the powerpc/shared/ BSP
(it also supports vxWorks) and by default uses that BSP's
a) PCI access API
b,c) irq handling API (AKA 'new' style BSP_install_rtems_irq_handler()
API).
Some hooks exist in the driver to ease porting to other BSPs.
The following information has been assembled when answering a
question regarding a ppcn_60x BSP port:
I looked through the ppcn_60x BSP. Here's what I found:
- this BSP does NOT adhere to neither the 'old' nor the 'new' API
but provides its own (startup/setvec.c: set_vector()).
- the BSP has a 'driver' for vmeUniverse although mine is far more
complete (including support for VME interrupts, DMA etc.).
- Porting my driver to your BSP should not be too hard:
1) vmeUniverse needs PCI configuration space support from the
BSP:
a) a routine 'pciFindDevice' (need to be macro-aliased
to the proper routine/wrapper of your BSP) who scans
PCI config space for the universe bridge.
You could add 'libbsp/powerpc/shared/pci/pcifinddevice.c'
to your BSP substituting the pci_read_config_xxx calls
by the ones present on your BSP (see step 2))
b) routines to read PCI config registers (byte and longword)
[on your BSP these are PCIConfigRead32/PCIConfigRead8;
hence you could replace the macros on top with
#define pciConfigInLong PCIConfigRead32
2) vmeUniverse needs to know how to acknowledge a PCI interrupt
In your case, nothing needs to be done
#define BSP_PIC_DO_EOI do {} while (0)
3) Install the VME ISR dispatcher: replace the 'new' style
interrupt installer (BSP_install_rtems_irq_handler()) by
a proper call to 'set_vector()'
4) I might have missed something...
I attach the latest version of the vmeUniverse driver in case you want
to try to do the port (should be easy).
For the sake of ease of maintenance, I just added a few hooks making it
possible to override some things without having to modify the driver code.
1,2) PCI config space access macros may be overriden via CFLAGS
when compiling vmeUniverse.c, hence:
CFLAGS += -DBSP_PIC_DO_EOI=do{}while(0)
CFLAGS += -DBSP_PCI_CONFIG_IN_LONG=PCIConfigRead32
CFLAGS += -DBSP_PCI_CONFIG_IN_BYTE=PCIConfigRead8
(you still need to supply BSP_pciFindDevice)
3) create your own version of vmeUniverseInstallIrqMgr():
copy to a separate file and replace
BSP_rtems_install_irq_handler() by a proper call to set_vector.
4) Send me email :-)
USAGE NOTE: To fully initialize the driver, the following steps can/must
be performed:
vmeUniverseInit(); /* MANDATORY: Driver Initialization */
vmeUniverseReset(); /* OPTIONAL: Reset most registers to a known state;
* if this step is omitted, firmware setup is
* preserved
*/
vmeUniverseMasterPortCfg(...); /* OPTIONAL: setup the master windows
* (current setup preserved if omitted)
*/
vmeUniverseSlavePortCfg(...); /* OPTIONAL: setup the slave windows
* (current setup preserved if omitted)
*/
vmeUniverseInstallIrqMgr(); /* NEEDED FOR VME INTERRUPT SUPPRORT
* initialize the interrupt manager.
* NOTE: you need to call your own
* version of this routine here
*/
For an example of init/setup, consult libbsp/powerpc/shared/vme/vmeconfig.c

View File

@@ -6,7 +6,51 @@
*/
#if 0
/*
* $Log$
* Revision 1.34 2003/02/10 23:20:05 till
* - added some macro magic to make porting easier (ppcn_60x BSP in mind)
* - made mgrInstalled public (vmeUniverseIrqMgrInstalled) so BSPs can
* supply their own versions of the mgrInstall() routine.
* - added READMEs to CVS
*
* Revision 1.33.2.1 2003/02/10 23:01:40 till
* - added some macro magic to make porting easier (ppcn_60x BSP in mind)
* - made mgrInstalled public (vmeUniverseIrqMgrInstalled) so BSPs can
* supply their own versions of the mgrInstall() routine.
*
* Revision 1.32 2002/09/05 02:50:41 till
* - use k_vsprintf(), not vsprintf() during early boot (RTEMS)
*
* Revision 1.31 2002/08/16 23:35:15 strauman
* - fixed typos
*
* Revision 1.30 2002/08/16 22:53:37 till
* - made address translation more generic; allow to look for reverse mappings
* also.
* - removed vmeUniverseLocalToBus() and vmeUniverseBusToLocal() and made
* vmeUniverseXlateAddr() public instead.
*
* Revision 1.29 2002/08/16 22:16:25 till
* - tweak U2SPEC (fix Joerger vtr10012_8 problem) the same
* way the synergy BSP does (rev 2 chips only)
*
* Revision 1.28 2002/08/15 23:16:01 till
* - bugfix: vmeUniverseISRGet() dereferenced a possibly NULL pointer
*
* Revision 1.25 2002/07/19 05:18:40 till
* - CVS log: again a problem. Cannot embed /_* *_/ comments in the log
* because the log has to be commented as a whole. I had tried
* #if 0 #endif - doesn't work because cpp expands char constants???
* WHAT A NUISANCE
*
* Revision 1.24 2002/07/19 02:44:14 till
* - added a new parameter to the IRQ manager install routine:
* the main interrupt's line can now also be specified (reading
* from PCI config does not always work - some boards don't
* have correct information there - PMC's will have a similar
* problem, though!)
*
* Revision 1.21 2002/04/11 06:54:48 till
* - silenced message about 'successfully configured a port'
*
@@ -32,14 +76,13 @@
*
* Revision 1.15 2002/01/23 06:15:30 till
* - changed master port data width to 64 bit.
* /* NOTE: reading the CY961 (Echotek ECDR814) with VDW32
* * generated bus errors when reading 32-bit words
* * - very weird, because the registers are 16-bit
* * AFAIK.
* * - 32-bit accesses worked fine on vxWorks which
* * has the port set to 64-bit.
* * ????????
* */
* NOTE: reading the CY961 (Echotek ECDR814) with VDW32
* generated bus errors when reading 32-bit words
* - very weird, because the registers are 16-bit
* AFAIK.
* - 32-bit accesses worked fine on vxWorks which
* has the port set to 64-bit.
* ????????
*
* Revision 1.14 2002/01/11 19:30:54 till
* - added more register defines to header
@@ -55,7 +98,7 @@
*
* Revision 1.11 2002/01/08 03:59:52 till
* - vxworks always defines _LITTLE_ENDIAN, fixed the conditionals
* so it should work on __vxworks and on __rtems now.
* so it should work on __vxworks and on __rtems__ now.
* - rtems uprintf wrapper reverts to printk if stdio is not yet
* initialized (uses _impure_ptr->__sdidinit)
* - tested bus address translation utility routines
@@ -89,7 +132,7 @@
*
* Revision 1.1.1.1 2001/07/12 23:15:19 till
* - cvs import
*
*/
#endif
#include <stdio.h>
@@ -137,16 +180,23 @@
/* we rely on a vxWorks definition here */
#define VX_AM_SUP 4
#ifdef __rtems
#ifdef __rtems__
#include <stdlib.h>
#include <rtems/bspIo.h> /* printk */
#include <bsp/pci.h>
#include <bsp.h>
#define pciFindDevice BSP_pciFindDevice
#define pciConfigInLong pci_read_config_dword
#define pciConfigInByte pci_read_config_byte
/* allow the BSP to override the default routines */
#ifndef BSP_PCI_FIND_DEVICE
#define BSP_PCI_FIND_DEVICE BSP_pciFindDevice
#endif
#ifndef BSP_PCI_CONFIG_IN_LONG
#define BSP_PCI_CONFIG_IN_LONG pci_read_config_dword
#endif
#ifndef BSP_PCI_CONFIG_IN_BYTE
#define BSP_PCI_CONFIG_IN_BYTE pci_read_config_byte
#endif
typedef unsigned int pci_ulong;
#define PCI_TO_LOCAL_ADDR(memaddr) ((pci_ulong)(memaddr) + PCI_MEM_BASE)
@@ -155,11 +205,16 @@ typedef unsigned int pci_ulong;
#elif defined(__vxworks)
typedef unsigned long pci_ulong;
#define PCI_TO_LOCAL_ADDR(memaddr) (memaddr)
#define PCI_INTERRUPT_LINE 0x3c
#define BSP_PCI_FIND_DEVICE pciFindDevice
#define BSP_PCI_CONFIG_IN_LONG pciConfigInLong
#define BSP_PCI_CONFIG_IN_BYTE pciConfigInByte
#else
#error "vmeUniverse not ported to this architecture yet"
#endif
#ifndef PCI_INTERRUPT_LINE
#define PCI_INTERRUPT_LINE 0x3c
#endif
volatile LERegister *vmeUniverse0BaseAddr=0;
int vmeUniverse0PciIrqLine=-1;
@@ -192,7 +247,7 @@ WRITE_LE(
#elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
/* offset is in bytes and MUST not end up in r0 */
__asm__ __volatile__("stwbrx %1, %0, %2" :: "b"(off),"r"(val),"r"(adrs));
#elif defined(__rtems)
#elif defined(__rtems__)
st_le32((volatile unsigned long*)(((unsigned long)adrs)+off), val);
#else
#error "little endian register writing not implemented"
@@ -221,7 +276,7 @@ READ_LE0(volatile LERegister *adrs)
register unsigned long rval;
__asm__ __volatile__("lwbrx %0, 0, %1":"=r"(rval):"r"(adrs));
return rval;
#elif defined(__rtems)
#elif defined(__rtems__)
return ld_le32((volatile unsigned long*)adrs);
#else
#error "little endian register reading not implemented"
@@ -254,17 +309,18 @@ return READ_LE0((volatile LERegister *)(((unsigned long)adrs)+off));
#define UNIV_REV(base) (READ_LE(base,2*sizeof(LERegister)) & 0xff)
#ifdef __rtems
#ifdef __rtems__
static int
uprintk(char *fmt, va_list ap)
{
int rval;
extern int k_vsprintf(char *, char *, va_list);
/* during bsp init, there is no malloc and no stdio,
* hence we assemble the message on the stack and revert
* to printk
*/
char buf[200];
rval = vsprintf(buf,fmt,ap);
rval = k_vsprintf(buf,fmt,ap);
if (rval > sizeof(buf))
BSP_panic("vmeUniverse/uprintk: buffer overrun");
printk(buf);
@@ -280,7 +336,7 @@ uprintf(FILE *f, char *fmt, ...)
va_list ap;
int rval;
va_start(ap, fmt);
#ifdef __rtems
#ifdef __rtems__
if (!f || !_impure_ptr->__sdidinit) {
/* Might be called at an early stage when
* stdio is not yet initialized.
@@ -307,7 +363,7 @@ int bus,dev,fun;
pci_ulong busaddr;
unsigned char irqline;
if (pciFindDevice(
if (BSP_PCI_FIND_DEVICE(
PCI_VENDOR_TUNDRA,
PCI_DEVICE_UNIVERSEII,
instance,
@@ -315,17 +371,17 @@ unsigned char irqline;
&dev,
&fun))
return -1;
if (pciConfigInLong(bus,dev,fun,PCI_UNIVERSE_BASE0,&busaddr))
if (BSP_PCI_CONFIG_IN_LONG(bus,dev,fun,PCI_UNIVERSE_BASE0,&busaddr))
return -1;
if ((unsigned long)(busaddr) & 1) {
/* it's IO space, try BASE1 */
if (pciConfigInLong(bus,dev,fun,PCI_UNIVERSE_BASE1,&busaddr)
if (BSP_PCI_CONFIG_IN_LONG(bus,dev,fun,PCI_UNIVERSE_BASE1,&busaddr)
|| ((unsigned long)(busaddr) & 1))
return -1;
}
*pbase=(volatile LERegister*)PCI_TO_LOCAL_ADDR(busaddr);
if (pciConfigInByte(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline))
if (BSP_PCI_CONFIG_IN_BYTE(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline))
return -1;
else
vmeUniverse0PciIrqLine = irqline;
@@ -608,6 +664,7 @@ showUniversePort(
typedef struct XlatRec_ {
unsigned long address;
unsigned long aspace;
unsigned reverse; /* find reverse mapping of this port */
} XlatRec, *Xlat;
/* try to translate an address through the bridge
@@ -653,6 +710,15 @@ unsigned long cntrl, start, bound, offst, mask, x;
offst = READ_LE0(preg++) & mask;
/* translate address to the other bus */
if (l->reverse) {
/* reverse mapping, i.e. for master ports we map from
* VME to PCI, for slave ports we map from VME to PCI
*/
if (l->address >= start && l->address < bound) {
l->address+=offst;
return 1;
}
} else {
x = l->address - offst;
if (x >= start && x < bound) {
@@ -660,6 +726,7 @@ unsigned long cntrl, start, bound, offst, mask, x;
l->address = x;
return 1;
}
}
return 0;
}
@@ -711,31 +778,26 @@ showUniversePorts(int ismaster, FILE *f)
mapOverAll(ismaster,showUniversePort,f);
}
static int xlate(int ismaster, unsigned long as, unsigned long aIn, unsigned long *paOut)
int
vmeUniverseXlateAddr(
int master, /* look in the master windows */
int reverse, /* reverse mapping; for masters: map local to VME */
unsigned long as, /* address space */
unsigned long aIn, /* address to look up */
unsigned long *paOut/* where to put result */
)
{
int rval;
XlatRec l;
l.aspace = as;
l.address = aIn;
l.reverse = reverse;
/* map result -1/0/1 to -2/-1/0 with 0 on success */
rval = mapOverAll(ismaster,xlatePort,(void*)&l) - 1;
rval = mapOverAll(master,xlatePort,(void*)&l) - 1;
*paOut = l.address;
return rval;
}
/* public functions */
int
vmeUniverseLocalToBusAdrs(unsigned long as, unsigned long localAdrs, unsigned long *pbusAdrs)
{
return xlate(0,as,localAdrs,pbusAdrs);
}
int
vmeUniverseBusToLocalAdrs(unsigned long as, unsigned long busAdrs, unsigned long *plocalAdrs)
{
return xlate(1,as,busAdrs,plocalAdrs);
}
void
vmeUniverseReset(void)
{
@@ -765,6 +827,21 @@ vmeUniverseReset(void)
/* disable VME bus image of VME CSR */
vmeUniverseWriteReg(0, UNIV_REGOFF_VCSR_CTL);
/* I had problems with a Joerger vtr10012_8 card who would
* only be accessible after tweaking the U2SPEC register
* (the t27 parameter helped).
* I use the same settings here that are used by the
* Synergy VGM-powerpc BSP for vxWorks.
*/
if (2==UNIV_REV(vmeUniverse0BaseAddr))
vmeUniverseWriteReg(UNIV_U2SPEC_DTKFLTR |
UNIV_U2SPEC_MASt11 |
UNIV_U2SPEC_READt27_NODELAY |
UNIV_U2SPEC_POSt28_FAST |
UNIV_U2SPEC_PREt28_FAST,
UNIV_REGOFF_U2SPEC);
/* disable interrupts, reset routing */
vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_EN);
vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP0);
@@ -924,7 +1001,7 @@ register unsigned long *p=ptr+num;
"stwbrx 0, 0, %0\n"
: "=r"(p) : "r"(p) : "r0"
);
#elif defined(__rtems)
#elif defined(__rtems__)
p--; st_le32(p, *p);
#else
#error "vmeUniverse: endian conversion not implemented for this architecture"
@@ -935,7 +1012,7 @@ register unsigned long *p=ptr+num;
/* RTEMS interrupt subsystem */
#ifdef __rtems
#ifdef __rtems__
#include <bsp/irq.h>
typedef struct
@@ -944,16 +1021,18 @@ UniverseIRQEntryRec_ {
void *usrData;
} UniverseIRQEntryRec, *UniverseIRQEntry;
static UniverseIRQEntry universeHdlTbl[257]={0};
static UniverseIRQEntry universeHdlTbl[UNIV_NUM_INT_VECS]={0};
static int mgrInstalled=0;
int vmeUniverseIrqMgrInstalled=0;
static int vmeIrqUnivOut=-1;
static int specialIrqUnivOut=-1;
VmeUniverseISR
vmeUniverseISRGet(unsigned long vector, void **parg)
{
if (vector>255) return 0;
if (vector>=UNIV_NUM_INT_VECS ||
! universeHdlTbl[vector])
return 0;
if (parg)
*parg=universeHdlTbl[vector]->usrData;
return universeHdlTbl[vector]->isr;
@@ -962,10 +1041,29 @@ vmeUniverseISRGet(unsigned long vector, void **parg)
static void
universeSpecialISR(void)
{
UniverseIRQEntry ip;
/* try the special handler */
if ((ip=universeHdlTbl[UNIV_SPECIAL_IRQ_VECTOR])) {
ip->isr(ip->usrData, UNIV_SPECIAL_IRQ_VECTOR);
register UniverseIRQEntry ip;
register unsigned vec;
register unsigned long status;
status=vmeUniverseReadReg(UNIV_REGOFF_LINT_STAT);
/* scan all LINT bits except for the 'normal' VME interrupts */
/* do VOWN first */
vec=UNIV_VOWN_INT_VEC;
if ( (status & UNIV_LINT_STAT_VOWN) && (ip=universeHdlTbl[vec]))
ip->isr(ip->usrData,vec);
/* now continue with DMA and scan through all bits;
* we assume the vectors are in the right order!
*
* The initial right shift brings the DMA bit into position 0;
* the loop is left early if there are no more bits set.
*/
for (status>>=8; status; status>>=1) {
vec++;
if ((status&1) && (ip=universeHdlTbl[vec]))
ip->isr(ip->usrData,vec);
}
/* clear all special interrupts */
vmeUniverseWriteReg(
@@ -1092,16 +1190,25 @@ my_isOn(const rtems_irq_connect_data *arg)
}
int
vmeUniverseInstallIrqMgr(int vmeOut, int specialOut, int specialIrqPicLine)
vmeUniverseInstallIrqMgr(int vmeOut,
int vmeIrqPicLine,
int specialOut,
int specialIrqPicLine)
{
rtems_irq_connect_data aarrggh;
/* check parameters */
if ((vmeIrqUnivOut=vmeOut) < 0 || vmeIrqUnivOut > 7) return -1;
if ((specialIrqUnivOut=specialOut) > 7) return -2;
if (specialIrqPicLine < 0) return -3;
if (specialOut >=0 && specialIrqPicLine < 0) return -3;
/* give them a chance to override buggy PCI info */
if (vmeIrqPicLine >= 0) {
uprintf(stderr,"Overriding main IRQ line PCI info with %i\n",
vmeIrqPicLine);
vmeUniverse0PciIrqLine=vmeIrqPicLine;
}
if (mgrInstalled) return -4;
if (vmeUniverseIrqMgrInstalled) return -4;
aarrggh.on=my_no_op; /* at _least_ they could check for a 0 pointer */
aarrggh.off=my_no_op;
@@ -1142,7 +1249,7 @@ rtems_irq_connect_data aarrggh;
UNIV_LINT_MAP1_DMA(specialIrqUnivOut)
),
UNIV_REGOFF_LINT_MAP1);
mgrInstalled=1;
vmeUniverseIrqMgrInstalled=1;
return 0;
}
@@ -1152,7 +1259,7 @@ vmeUniverseInstallISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
{
UniverseIRQEntry ip;
if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !mgrInstalled)
if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !vmeUniverseIrqMgrInstalled)
return -1;
ip=universeHdlTbl[vector];
@@ -1170,7 +1277,7 @@ vmeUniverseRemoveISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
{
UniverseIRQEntry ip;
if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !mgrInstalled)
if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !vmeUniverseIrqMgrInstalled)
return -1;
ip=universeHdlTbl[vector];
@@ -1185,7 +1292,7 @@ UniverseIRQEntry ip;
int
vmeUniverseIntEnable(unsigned int level)
{
if (!mgrInstalled || level<1 || level>7)
if (!vmeUniverseIrqMgrInstalled || level<1 || level>7)
return -1;
vmeUniverseWriteReg(
(vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) |
@@ -1198,7 +1305,7 @@ vmeUniverseIntEnable(unsigned int level)
int
vmeUniverseIntDisable(unsigned int level)
{
if (!mgrInstalled || level<1 || level>7)
if (!vmeUniverseIrqMgrInstalled || level<1 || level>7)
return -1;
vmeUniverseWriteReg(
(vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) &

View File

@@ -14,16 +14,25 @@
#include <vme.h>
#else
/* vxworks compatible addressing modes */
#define VME_AM_STD_SUP_ASCENDING 0x3f
#define VME_AM_STD_SUP_PGM 0x3e
#define VME_AM_STD_USR_ASCENDING 0x3b
#define VME_AM_STD_USR_PGM 0x3a
#define VME_AM_STD_SUP_DATA 0x3d
#define VME_AM_STD_USR_DATA 0x39
#define VME_AM_EXT_SUP_ASCENDING 0x0f
#define VME_AM_EXT_SUP_PGM 0x0e
#define VME_AM_EXT_USR_ASCENDING 0x0b
#define VME_AM_EXT_USR_PGM 0x0a
#define VME_AM_EXT_SUP_DATA 0x0d
#define VME_AM_EXT_USR_DATA 0x09
#define VME_AM_SUP_SHORT_IO 0x2d
#define VME_AM_USR_SHORT_IO 0x29
#define VME_AM_IS_SHORT(a) (((a) & 0xf0) == 0x20)
#define VME_AM_IS_STD(a) (((a) & 0xf0) == 0x30)
#define VME_AM_IS_EXT(a) (((a) & 0xf0) == 0x00)
#endif
typedef unsigned long LERegister; /* emphasize contents are little endian */
@@ -338,6 +347,18 @@ typedef struct VmeUniverseDMAPacketRec_ {
# define UNIV_MISC_CTL_SYSCON (1<<17) /* (R/W) 1:universe is system controller */
# define UNIV_MISC_CTL_V64AUTO (1<<16) /* (R/W) 1:initiate VME64 auto id slave participation */
/* U2SPEC described in VGM manual */
/* NOTE: the Joerger vtr10012_8 needs the timing to be tweaked!!!! READt27 must be _no_delay_
*/
#define UNIV_REGOFF_U2SPEC 0x4fc
# define UNIV_U2SPEC_DTKFLTR (1<<12) /* DTAck filter: 0: slow, better filter; 1: fast, poorer filter */
# define UNIV_U2SPEC_MASt11 (1<<10) /* Master parameter t11 (DS hi time during BLT and MBLTs) */
# define UNIV_U2SPEC_READt27_DEFAULT (0<<8) /* VME master parameter t27: (latch data after DTAck + 25ns) */
# define UNIV_U2SPEC_READt27_FAST (1<<8) /* VME master parameter t27: (latch data faster than 25ns) */
# define UNIV_U2SPEC_READt27_NODELAY (2<<8) /* VME master parameter t27: (latch data without any delay) */
# define UNIV_U2SPEC_POSt28_FAST (1<<2) /* VME slave parameter t28: (faster time of DS to DTAck for posted write) */
# define UNIV_U2SPEC_PREt28_FAST (1<<0) /* VME slave parameter t28: (faster time of DS to DTAck for prefetch read) */
/* Location Monitor control register */
#define UNIV_REGOFF_LM_CTL 0xf64
# define UNIV_LM_CTL_EN (1<<31) /* image enable */
@@ -489,15 +510,21 @@ vmeUniverseMasterPortCfg(
/* translate an address through the bridge
*
* vmeUniverseLocalToBusAdrs() yields a VME a address that reflects
* vmeUniverseXlateAddr(0,0,addr,as,&result)
* yields a VME a address that reflects
* a local memory location as seen from the VME bus through the universe
* VME slave.
*
* likewise does vmeUniverseBusToLocalAdrs() translate a VME bus addr
* (through the VME master) to the PCI side of the bridge.
* likewise does vmeUniverseXlateAddr(1,0,addr,as,&result)
* translate a VME bus addr (through the VME master) to the
* PCI side of the bridge.
*
* a valid address space modifier must be specified.
*
* The 'reverse' parameter may be used to find a reverse
* mapping, i.e. the pci address in a master window can be
* found if the respective vme address is known etc.
*
* RETURNS: translated address in *pbusAdrs / *plocalAdrs
*
* 0: success
@@ -505,11 +532,13 @@ vmeUniverseMasterPortCfg(
* -2: invalid modifier
*/
int
vmeUniverseLocalToBusAdrs(unsigned long am, unsigned long localAdrs, unsigned long *pbusAdrs);
int
vmeUniverseBusToLocalAdrs(unsigned long am, unsigned long busAdrs, unsigned long *plocalAdrs);
vmeUniverseXlateAddr(
int master, /* look in the master windows */
int reverse, /* reverse mapping; for masters: map local to VME */
unsigned long as, /* address space */
unsigned long addr, /* address to look up */
unsigned long *paOut/* where to put result */
);
/* configure a VME slave (PCI master) port */
int
@@ -556,7 +585,7 @@ vmeUniverseResetBus(void)
UNIV_REGOFF_MISC_CTL);
}
#ifdef __rtems
#ifdef __rtems__
/* VME Interrupt Handler functionality */
/* we dont use the current RTEMS/BSP interrupt API for the
@@ -608,15 +637,38 @@ int
vmeUniverseIntDisable(unsigned int level);
/* use this special vector to connect a handler to the
/* use these special vectors to connect a handler to the
* universe specific interrupts (such as "DMA done",
* VOWN, error irqs etc.)
* NOTE: The wrapper clears all status LINT bits (except
* for regular VME irqs). Also note that it is the user's
* responsibility to enable the necessary interrupts in
* LINT_EN
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* DO NOT CHANGE THE ORDER OF THESE VECTORS - THE DRIVER
* DEPENDS ON IT
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*
*/
#define UNIV_SPECIAL_IRQ_VECTOR 256
#define UNIV_VOWN_INT_VEC 256
#define UNIV_DMA_INT_VEC 257
#define UNIV_LERR_INT_VEC 258
#define UNIV_VERR_INT_VEC 259
#define UNIV_VME_SW_IACK_INT_VEC 260
#define UNIV_PCI_SW_INT_VEC 261
#define UNIV_SYSFAIL_INT_VEC 262
#define UNIV_ACFAIL_INT_VEC 263
#define UNIV_MBOX0_INT_VEC 264
#define UNIV_MBOX1_INT_VEC 265
#define UNIV_MBOX2_INT_VEC 266
#define UNIV_MBOX3_INT_VEC 267
#define UNIV_LM0_INT_VEC 268
#define UNIV_LM1_INT_VEC 269
#define UNIV_LM2_INT_VEC 270
#define UNIV_LM3_INT_VEC 271
#define UNIV_NUM_INT_VECS 272
/* the universe interrupt handler is capable of routing all sorts of
* (VME) interrupts to 8 different lines (some of) which may be hooked up
@@ -634,13 +686,18 @@ vmeUniverseIntDisable(unsigned int level);
*
* Hence the manager sets up routing VME interrupts to 1 or 2 universe
* OUTPUTS. However, it must also be told to which PIC INPUTS they
* are wired. The first PIC input line is read from PCI config space
* but the second must be passed to this routine.
* are wired.
* Optionally, the first PIC input line can be read from PCI config space
* but the second must be passed to this routine. Note that the info read
* from PCI config space is wrong for many boards!
*
* PARAMETERS:
* vmeIRQunivOut: to which output pin (of the universe) should the 7
* vmeIrqUnivOut: to which output pin (of the universe) should the 7
* VME irq levels be routed.
* specialIRQunivOut: to which output pin (of the universe) should the
* vmeIrqPicLine: specifies to which PIC input the 'main' output is
* wired. If passed a value < 0, the driver reads this
* information from PCI config space ("IRQ line").
* specialIrqUnivOut: to which output pin (of the universe) should the
* internally irqs be routed. Use 'vmeIRQunivOut'
* if < 0.
* specialIrqPicLine: specifies to which PIC input the 'special' output
@@ -651,7 +708,10 @@ vmeUniverseIntDisable(unsigned int level);
*
*/
int
vmeUniverseInstallIrqMgr(int vmeIrqUnivOut, int specialIrqUnivOut, int specialIrqPicLine);
vmeUniverseInstallIrqMgr(int vmeIrqUnivOut,
int vmeIrqPicLine,
int specialIrqUnivOut,
int specialIrqPicLine);
#endif