Index: c/src/lib/libbsp/shared/ChangeLog
===================================================================
--- c/src/lib/libbsp/shared/ChangeLog	(revision 0d776cd24743625f2888d04d72188b2e3f416a3e)
+++ c/src/lib/libbsp/shared/ChangeLog	(revision 6fae45804d1a552e19c735cd75ee2d462a00f254)
@@ -1,2 +1,12 @@
+2001-05-14	Till Straumann <strauman@slac.stanford.edu>
+
+	* vmeUniverse/README.universe, vmeUniverse/vmeUniverse.c,
+	vmeUniverse/vmeUniverse.h: New files.
+	* Makefile.am: Modified to reflect addition of files.
+	* Per PR214, contributes a driver for the TUNDRA UNIVERSE
+	VME-PCI bridge to libbsp/shared.  
+	NOTE: This driver is maintained _outside_ RTEMS by Till.  Please
+	forward future modifications to him.
+
 2002-03-27	Ralf Corsepius <corsepiu@faw.uni-ulm.de>
 
Index: c/src/lib/libbsp/shared/Makefile.am
===================================================================
--- c/src/lib/libbsp/shared/Makefile.am	(revision 0d776cd24743625f2888d04d72188b2e3f416a3e)
+++ c/src/lib/libbsp/shared/Makefile.am	(revision 6fae45804d1a552e19c735cd75ee2d462a00f254)
@@ -7,5 +7,6 @@
 
 EXTRA_DIST = bootcard.c bspclean.c bsplibc.c bsppost.c console-polled.c \
-    console.c gnatinstallhandler.c main.c sbrk.c tod.c tod.h
+    console.c gnatinstallhandler.c main.c sbrk.c tod.c tod.h \
+	vmeUniverse/vmeUniverse.c vmeUniverse/vmeUniverse.h
 
 include $(top_srcdir)/../../../../automake/subdirs.am
Index: c/src/lib/libbsp/shared/vmeUniverse/README.universe
===================================================================
--- c/src/lib/libbsp/shared/vmeUniverse/README.universe	(revision 6fae45804d1a552e19c735cd75ee2d462a00f254)
+++ c/src/lib/libbsp/shared/vmeUniverse/README.universe	(revision 6fae45804d1a552e19c735cd75ee2d462a00f254)
@@ -0,0 +1,19 @@
+The universe II driver is in a separate subdir
+because it is maintained at SSRL outside of the
+rtems CVS tree (it supports other OSes as well)
+
+Till Straumann <strauman@slac.stanford.edu> 1/2002
+
+NOTES:
+This driver is maintained _outside_ rtems.
+Please forward future modifications to me.
+
+A BSP that wants to use the vmeUniverse driver
+must implement the following headers / functionality:
+ - <bsp/pci.h> offering an API like 'libbsp/powerpc/shared/pci'
+ - <bsp/irq.h> offering the 'new style' RTEMS irq API
+   (like 'libbsp/powerpc/shared/irq').
+
+The BSP should then use "VPATH magic" (to use Joel's
+words :-) to reach the vmeUniverse.* files in the
+universe subdir.
Index: c/src/lib/libbsp/shared/vmeUniverse/vmeUniverse.c
===================================================================
--- c/src/lib/libbsp/shared/vmeUniverse/vmeUniverse.c	(revision 6fae45804d1a552e19c735cd75ee2d462a00f254)
+++ c/src/lib/libbsp/shared/vmeUniverse/vmeUniverse.c	(revision 6fae45804d1a552e19c735cd75ee2d462a00f254)
@@ -0,0 +1,1212 @@
+/* $Id$ */
+
+/* Routines to configure the VME interface
+ * Author: Till Straumann <strauman@slac.stanford.edu>
+ *         Nov 2000, Oct 2001, Jan 2002
+ */
+
+#if 0
+ * $Log$
+ * Revision 1.21  2002/04/11 06:54:48  till
+ *  - silenced message about 'successfully configured a port'
+ *
+ * Revision 1.20  2002/03/27 21:14:50  till
+ *  - fix: handler table holds pointers, so hdlrTbl[vector]->usrData etc.
+ *    not hdlrTbl[vector].usrData...
+ *
+ * Revision 1.19  2002/03/09 00:14:36  till
+ *  - added vmeUniverseISRGet() to retrieve the currently installed
+ *    ISR for a given vector
+ *  - swapped the argument order for ISRs to (usrarg, vector)
+ *
+ * Revision 1.18  2002/02/07 19:53:48  till
+ *  - reverted back to publish base_addr/irq_line as variables rather than
+ *    through functions: the irq_line is read by the interrupt dispatcher...
+ *
+ * Revision 1.17  2002/01/24 08:28:10  till
+ *  - initialize driver when reading base address or irq line.
+ *    however, this requires the pci driver to be working already.
+ *
+ * Revision 1.16  2002/01/24 08:21:48  till
+ *  - replaced public global vars for base address/irq line by routines.
+ *
+ * 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.
+ *      *       ????????
+ *      */
+ *
+ * Revision 1.14  2002/01/11 19:30:54  till
+ *  - added more register defines to header
+ *  - completed vmeUniverseReset
+ *
+ * Revision 1.13  2002/01/11 05:06:18  till
+ *  - fixed VMEISR failing to check (lint_stat & msk) when determining
+ *    the highes level...
+ *  - tested interrupt handling & nesting. Seems to work.
+ *
+ * Revision 1.12  2002/01/11 02:25:55  till
+ *  - added interrupt manager
+ *
+ * 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.
+ *  - rtems uprintf wrapper reverts to printk if stdio is not yet
+ *    initialized (uses _impure_ptr->__sdidinit)
+ *  - tested bus address translation utility routines
+ *
+ * Revision 1.9  2002/01/05 02:36:32  till
+ *  - added vmeUniverseBusToLocalAdrs / vmeUniverseLocalToBusAdrs for address
+ *    space translations.
+ *  - include bsp.h under rtems to hack around the libcpu/powerpc/shared/io.h
+ *    #define _IO_BASE & friends problem.
+ *
+ * Revision 1.8  2002/01/04 04:12:51  till
+ *  - changed some rtems/pci related names
+ *
+ * Revision 1.7  2002/01/04 03:06:30  till
+ *  - added further register definitions
+ *
+ * Revision 1.6  2001/12/20 04:42:44  till
+ *  - fixed endianness stuff; theoretically, PPC could be LITTLE_ENDIAN...
+ *
+ * Revision 1.4  2001/12/19 01:59:02  till
+ *  - started adding interrupt stuff
+ *  - private implementation of PCI scanning if necessary
+ *
+ * Revision 1.3  2001/07/27 22:22:51  till
+ *  - added more DMA support routines and defines to include file
+ *  - xxxPortsShow can now print to a given file descriptor argument
+ *
+ * Revision 1.2  2001/07/26 18:06:13  till
+ *  - ported to RTEMS
+ *  - fixed a couple of wrong pointer calculations.
+ *
+ * Revision 1.1.1.1  2001/07/12 23:15:19  till
+ *  - cvs import
+ *
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "vmeUniverse.h"
+
+#define UNIV_NUM_MPORTS		8 /* number of master ports */
+#define UNIV_NUM_SPORTS		8 /* number of slave ports */
+
+#define PCI_VENDOR_TUNDRA	0x10e3
+#define PCI_DEVICE_UNIVERSEII	0
+#define PCI_UNIVERSE_BASE0	0x10
+#define PCI_UNIVERSE_BASE1	0x14
+
+#define UNIV_REGOFF_PCITGT0_CTRL 0x100
+#define UNIV_REGOFF_PCITGT4_CTRL 0x1a0
+#define UNIV_REGOFF_VMESLV0_CTRL 0xf00
+#define UNIV_REGOFF_VMESLV4_CTRL 0xf90
+
+#define UNIV_CTL_VAS16		(0x00000000)
+#define UNIV_CTL_VAS24		(0x00010000)
+#define UNIV_CTL_VAS32		(0x00020000)
+#define UNIV_CTL_VAS		(0x00070000)
+
+#define UNIV_MCTL_EN		(0x80000000)
+#define UNIV_MCTL_PWEN		(0x40000000)
+#define UNIV_MCTL_PGM		(0x00004000)
+#define UNIV_MCTL_VCT		(0x00000100)
+#define UNIV_MCTL_SUPER		(0x00001000)
+#define UNIV_MCTL_VDW32		(0x00800000)
+#define UNIV_MCTL_VDW64		(0x00c00000)
+
+#define UNIV_MCTL_AM_MASK	(UNIV_CTL_VAS | UNIV_MCTL_PGM | UNIV_MCTL_SUPER)
+
+#define UNIV_SCTL_EN		(0x80000000)
+#define UNIV_SCTL_PWEN		(0x40000000)
+#define UNIV_SCTL_PREN		(0x20000000)
+#define UNIV_SCTL_PGM		(0x00800000)
+#define UNIV_SCTL_DAT		(0x00400000)
+#define UNIV_SCTL_SUPER		(0x00200000)
+#define UNIV_SCTL_USER		(0x00100000)
+
+#define UNIV_SCTL_AM_MASK	(UNIV_CTL_VAS | UNIV_SCTL_PGM | UNIV_SCTL_DAT | UNIV_SCTL_USER | UNIV_SCTL_SUPER)
+
+/* we rely on a vxWorks definition here */
+#define VX_AM_SUP		4
+
+#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
+
+typedef unsigned int pci_ulong;
+#define PCI_TO_LOCAL_ADDR(memaddr) ((pci_ulong)(memaddr) + PCI_MEM_BASE)
+
+
+#elif defined(__vxworks)
+typedef unsigned long pci_ulong;
+#define PCI_TO_LOCAL_ADDR(memaddr) (memaddr)
+#define PCI_INTERRUPT_LINE	0x3c
+#else
+#error "vmeUniverse not ported to this architecture yet"
+#endif
+
+
+volatile LERegister *vmeUniverse0BaseAddr=0;
+int vmeUniverse0PciIrqLine=-1;
+
+#if 0
+/* public access functions */
+volatile LERegister *
+vmeUniverseBaseAddr(void)
+{
+	if (!vmeUniverse0BaseAddr) vmeUniverseInit();
+	return vmeUniverse0BaseAddr;
+}
+
+int
+vmeUniversePciIrqLine(void)
+{
+	if (vmeUniverse0PciIrqLine<0) vmeUniverseInit();
+	return vmeUniverse0PciIrqLine;
+}
+#endif
+
+static inline void
+WRITE_LE(
+	unsigned long val,
+	volatile LERegister    *adrs,
+	unsigned long off)
+{
+#if (__LITTLE_ENDIAN__ == 1)
+	*(volatile unsigned long*)(((unsigned long)adrs)+off)=val;
+#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)
+	st_le32((volatile unsigned long*)(((unsigned long)adrs)+off), val);
+#else
+#error "little endian register writing not implemented"
+#endif
+}
+
+#if defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)
+#define SYNC __asm__ __volatile__("sync")
+#else
+#define SYNC
+#warning "SYNC instruction unknown for this architecture"
+#endif
+
+/* registers should be mapped to guarded, non-cached memory; hence 
+ * subsequent stores are ordered. eieio is only needed to enforce
+ * ordering of loads with respect to stores.
+ */
+#define EIEIO_REG
+
+static inline unsigned long
+READ_LE0(volatile LERegister *adrs)
+{
+#if (__LITTLE_ENDIAN__ == 1)
+	return *(volatile unsigned long *)adrs;
+#elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
+register unsigned long rval;
+__asm__ __volatile__("lwbrx %0, 0, %1":"=r"(rval):"r"(adrs));
+	return rval;
+#elif defined(__rtems)
+	return ld_le32((volatile unsigned long*)adrs);
+#else
+#error "little endian register reading not implemented"
+#endif
+}
+
+static inline unsigned long
+READ_LE(volatile LERegister *adrs, unsigned long off)
+{
+#if (__LITTLE_ENDIAN__ == 1)
+	return  *((volatile LERegister *)(((unsigned long)adrs)+off));
+#elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
+register unsigned long rval;
+	/* offset is in bytes and MUST not end up in r0 */
+__asm__ __volatile__("lwbrx %0, %2, %1"
+				: "=r"(rval)
+				: "r"(adrs), "b"(off));
+#if 0
+__asm__ __volatile__("eieio");
+#endif
+return rval;
+#else
+return READ_LE0((volatile LERegister *)(((unsigned long)adrs)+off));
+#endif
+}
+
+#define PORT_UNALIGNED(addr,port) \
+	( (port)%4 ? ((addr) & 0xffff) : ((addr) & 4095) ) 
+
+
+#define UNIV_REV(base) (READ_LE(base,2*sizeof(LERegister)) & 0xff)
+	
+#ifdef __rtems
+static int
+uprintk(char *fmt, va_list ap)
+{
+int		rval;
+/* 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);
+	if (rval > sizeof(buf))
+			BSP_panic("vmeUniverse/uprintk: buffer overrun");
+	printk(buf);
+	return rval;
+}
+#endif
+
+
+/* private printing wrapper */
+static int
+uprintf(FILE *f, char *fmt, ...)
+{
+va_list	ap;
+int	rval;
+	va_start(ap, fmt);
+#ifdef __rtems
+	if (!f || !_impure_ptr->__sdidinit) {
+		/* Might be called at an early stage when
+		 * stdio is not yet initialized.
+		 * There is no vprintk, hence we must assemble
+		 * to a buffer.
+		 */
+		rval=uprintk(fmt,ap);
+	} else 
+#endif
+	{
+		rval=vfprintf(f,fmt,ap);
+	}
+	va_end(ap);
+	return rval;
+}
+
+int
+vmeUniverseFindPciBase(
+	int instance,
+	volatile LERegister **pbase
+	)
+{
+int bus,dev,fun;
+pci_ulong busaddr;
+unsigned char irqline;
+
+	if (pciFindDevice(
+			PCI_VENDOR_TUNDRA,
+			PCI_DEVICE_UNIVERSEII,
+			instance,
+			&bus,
+			&dev,
+			&fun))
+		return -1;
+	if (pciConfigInLong(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)
+		   || ((unsigned long)(busaddr) & 1))
+			return -1;
+	}
+	*pbase=(volatile LERegister*)PCI_TO_LOCAL_ADDR(busaddr);
+
+	if (pciConfigInByte(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline))
+		return -1;
+	else
+		vmeUniverse0PciIrqLine = irqline;
+
+	return 0;
+}
+
+/* convert an address space selector to a corresponding
+ * universe control mode word
+ */
+
+static int
+am2mode(int ismaster, unsigned long address_space, unsigned long *pmode)
+{
+unsigned long mode=0;
+	if (!ismaster) {
+		mode |= UNIV_SCTL_DAT | UNIV_SCTL_PGM;
+		mode |= UNIV_SCTL_USER;
+	}
+	switch (address_space) {
+		case VME_AM_STD_SUP_PGM:
+		case VME_AM_STD_USR_PGM:
+			if (ismaster)
+				mode |= UNIV_MCTL_PGM ;
+			else {
+				mode &= ~UNIV_SCTL_DAT;
+			}
+			/* fall thru */
+		case VME_AM_STD_SUP_DATA:
+		case VME_AM_STD_USR_DATA:
+			mode |= UNIV_CTL_VAS24;
+			break;
+
+		case VME_AM_EXT_SUP_PGM:
+		case VME_AM_EXT_USR_PGM:
+			if (ismaster)
+				mode |= UNIV_MCTL_PGM ;
+			else {
+				mode &= ~UNIV_SCTL_DAT;
+			}
+			/* fall thru */
+		case VME_AM_EXT_SUP_DATA:
+		case VME_AM_EXT_USR_DATA:
+			mode |= UNIV_CTL_VAS32;
+			break;
+
+		case VME_AM_SUP_SHORT_IO:
+		case VME_AM_USR_SHORT_IO:
+			mode |= UNIV_CTL_VAS16;
+			break;
+
+		case 0: /* disable the port alltogether */
+			break;
+
+		default:
+			return -1;
+	}
+	if (address_space & VX_AM_SUP)
+		mode |= (ismaster ? UNIV_MCTL_SUPER : UNIV_SCTL_SUPER);
+	*pmode = mode;
+	return 0;
+}
+
+static int
+disableUniversePort(int ismaster, int portno, volatile unsigned long *preg, void *param)
+{
+unsigned long cntrl;
+	cntrl=READ_LE0(preg);
+	cntrl &= ~(ismaster ? UNIV_MCTL_EN : UNIV_SCTL_EN);
+	WRITE_LE(cntrl,preg,0);
+	SYNC; /* make sure this command completed */
+	return 0;
+}
+
+static int
+cfgUniversePort(
+	unsigned long	ismaster,
+	unsigned long	port,
+	unsigned long	address_space,
+	unsigned long	vme_address,
+	unsigned long	local_address,
+	unsigned long	length)
+{
+#define base vmeUniverse0BaseAddr
+volatile LERegister *preg=base;
+unsigned long	p=port;
+unsigned long	mode=0;
+
+	/* check parameters */
+	if (port >= (ismaster ? UNIV_NUM_MPORTS : UNIV_NUM_SPORTS)) {
+		uprintf(stderr,"invalid port\n");
+		return -1;
+	}
+	/* port start, bound addresses and offset must lie on 64k boundary
+	 * (4k for port 0 and 4)
+	 */
+	if ( PORT_UNALIGNED(local_address,port) ) {
+		uprintf(stderr,"local address misaligned\n");
+		return -1;
+	}
+	if ( PORT_UNALIGNED(vme_address,port) ) {
+		uprintf(stderr,"vme address misaligned\n");
+		return -1;
+	}
+	if ( PORT_UNALIGNED(length,port) ) {
+		uprintf(stderr,"length misaligned\n");
+		return -1;
+	}
+
+	/* check address space validity */
+	if (am2mode(ismaster,address_space,&mode)) {
+		uprintf(stderr,"invalid address space\n");
+		return -1;
+	}
+
+	/* get the universe base address */
+	if (!base && vmeUniverseInit()) {
+		return -1;
+	}
+
+	/* find out if we have a rev. II chip */
+	if ( UNIV_REV(base) < 2 ) {
+		if (port>3) {
+			uprintf(stderr,"Universe rev. < 2 has only 4 ports\n");
+			return -1;
+		}
+	}
+
+	/* finally, configure the port */
+
+	/* find the register set for our port */
+	if (port<4) {
+		preg += (ismaster ? UNIV_REGOFF_PCITGT0_CTRL : UNIV_REGOFF_VMESLV0_CTRL)/sizeof(LERegister);
+	} else {
+		preg += (ismaster ? UNIV_REGOFF_PCITGT4_CTRL : UNIV_REGOFF_VMESLV4_CTRL)/sizeof(LERegister);
+		p-=4;
+	}
+	preg += 5 * p;
+
+	/* temporarily disable the port */
+	disableUniversePort(ismaster,port,preg,0);
+
+	/* address_space == 0 means disable */
+	if (address_space != 0) {
+		unsigned long start,offst;
+		/* set the port starting address;
+		 * this is the local address for the master
+		 * and the VME address for the slave
+		 */
+		if (ismaster) {
+			start=local_address;
+			/* let it overflow / wrap around 0 */
+			offst=vme_address-local_address;
+		} else {
+			start=vme_address;
+			/* let it overflow / wrap around 0 */
+			offst=local_address-vme_address;
+		}
+#undef TSILL
+#ifdef TSILL
+		uprintf(stderr,"writing 0x%08x to 0x%08x + 4\n",start,preg);
+#else
+		WRITE_LE(start,preg,4);
+#endif
+		/* set bound address */
+		length+=start;
+#ifdef TSILL
+		uprintf(stderr,"writing 0x%08x to 0x%08x + 8\n",length,preg);
+#else
+		WRITE_LE(length,preg,8);
+#endif
+		/* set offset */
+#ifdef TSILL
+		uprintf(stderr,"writing 0x%08x to 0x%08x + 12\n",offst,preg);
+#else
+		WRITE_LE(offst,preg,12);
+#endif
+		/* calculate configuration word and enable the port */
+		/* 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.
+                 *       ????????
+                 */
+		if (ismaster)
+			mode |= UNIV_MCTL_EN | UNIV_MCTL_PWEN | UNIV_MCTL_VDW64 | UNIV_MCTL_VCT;
+		else 
+			mode |= UNIV_SCTL_EN | UNIV_SCTL_PWEN | UNIV_SCTL_PREN;
+
+#ifdef TSILL
+		uprintf(stderr,"writing 0x%08x to 0x%08x + 0\n",mode,preg);
+#else
+		EIEIO_REG;	/* make sure mode is written last */
+		WRITE_LE(mode,preg,0);
+		SYNC;		/* enforce completion */
+#endif
+
+#ifdef TSILL
+		uprintf(stderr,
+			"universe %s port %lu successfully configured\n",
+				ismaster ? "master" : "slave",
+				port);
+#endif
+
+#ifdef __vxworks
+		if (ismaster)
+			uprintf(stderr,
+			"WARNING: on the synergy, sysMasterPortsShow() may show incorrect settings (it uses cached values)\n");
+#endif
+	}
+	return 0;
+#undef base
+}
+
+
+static int
+showUniversePort(
+		int		ismaster,
+		int		portno,
+		volatile LERegister *preg,
+		void		*parm)
+{
+	FILE *f=parm ? (FILE *)parm : stdout;
+	unsigned long cntrl, start, bound, offst, mask;
+
+	cntrl = READ_LE0(preg++);
+#undef TSILL
+#ifdef TSILL
+	uprintf(stderr,"showUniversePort: *(0x%08x): 0x%08x\n",preg-1,cntrl);
+#endif
+#undef TSILL
+
+	/* skip this port if disabled */
+	if (!(cntrl & (ismaster ? UNIV_MCTL_EN : UNIV_SCTL_EN)))
+		return 0;
+
+	/* for the master `start' is the PCI address,
+	 * for the slave  `start' is the VME address
+	 */
+	mask = ~PORT_UNALIGNED(0xffffffff,portno);
+
+	start = READ_LE0(preg++)&mask;
+	bound = READ_LE0(preg++)&mask;
+	offst = READ_LE0(preg++)&mask;
+
+	offst+=start; /* calc start on the other bus */
+
+	if (ismaster) {
+		uprintf(f,"%i:    0x%08lx 0x%08lx 0x%08lx ",
+			portno,offst,bound-start,start);
+	} else {
+		uprintf(f,"%i:    0x%08lx 0x%08lx 0x%08lx ",
+			portno,start,bound-start,offst);
+	}
+
+	switch (cntrl & UNIV_CTL_VAS) {
+		case UNIV_CTL_VAS16: uprintf(f,"A16, "); break;
+		case UNIV_CTL_VAS24: uprintf(f,"A24, "); break;
+		case UNIV_CTL_VAS32: uprintf(f,"A32, "); break;
+		default: uprintf(f,"A??, "); break;
+	}
+
+	if (ismaster) {
+		uprintf(f,"%s, %s",
+			cntrl&UNIV_MCTL_PGM ?   "Pgm" : "Dat",
+			cntrl&UNIV_MCTL_SUPER ? "Sup" : "Usr");
+	} else {
+		uprintf(f,"%s %s %s %s", 
+			cntrl&UNIV_SCTL_PGM ?   "Pgm," : "    ",
+			cntrl&UNIV_SCTL_DAT ?   "Dat," : "    ",
+			cntrl&UNIV_SCTL_SUPER ? "Sup," : "    ",
+			cntrl&UNIV_SCTL_USER  ? "Usr" :  "");
+	}
+	uprintf(f,"\n");
+	return 0;
+}
+
+typedef struct XlatRec_ {
+	unsigned long	address;
+	unsigned long	aspace;
+} XlatRec, *Xlat;
+
+/* try to translate an address through the bridge
+ *
+ * IN:  l->address, l->aspace
+ * OUT: l->address (translated address)
+ *
+ * RETURNS: -1: invalid space
+ *           0: invalid address (not found in range)
+ *           1: success
+ */
+
+static int
+xlatePort(int ismaster, int port, volatile LERegister *preg, void *parm)
+{
+Xlat	l=(Xlat)parm;
+unsigned long cntrl, start, bound, offst, mask, x;
+
+	cntrl = READ_LE0(preg++);
+
+	/* skip this port if disabled */
+	if (!(cntrl & (ismaster ? UNIV_MCTL_EN : UNIV_SCTL_EN)))
+		return 0;
+
+	/* check for correct address space */
+	if ( am2mode(ismaster,l->aspace,&offst) ) {
+		uprintf(stderr,"vmeUniverse WARNING: invalid adressing mode 0x%x\n",
+		               l->aspace);
+		return -1;
+	}
+	if ( (cntrl & (ismaster ? UNIV_MCTL_AM_MASK : UNIV_SCTL_AM_MASK))
+	    != offst )
+		return 0; /* mode doesn't match requested AM */
+
+	/* OK, we found a matching mode, now we must check the address range */
+	mask = ~PORT_UNALIGNED(0xffffffff,port);
+
+	/* for the master `start' is the PCI address,
+	 * for the slave  `start' is the VME address
+	 */
+	start = READ_LE0(preg++) & mask;
+	bound = READ_LE0(preg++) & mask;
+	offst = READ_LE0(preg++) & mask;
+
+	/* translate address to the other bus */
+	x = l->address - offst;
+
+	if (x >= start && x < bound) {
+		/* valid address found */
+		l->address = x;
+		return 1;
+	}
+	return 0;
+}
+
+
+static int
+mapOverAll(int ismaster, int (*func)(int,int,volatile LERegister *,void*), void *arg)
+{
+#define base	vmeUniverse0BaseAddr
+volatile LERegister	*rptr;
+unsigned long	port;
+int	rval;
+
+	/* get the universe base address */
+	if (!base && vmeUniverseInit()) {
+		uprintf(stderr,"unable to find the universe in pci config space\n");
+		return -1;
+	}
+	rptr = (base + 
+		(ismaster ? UNIV_REGOFF_PCITGT0_CTRL : UNIV_REGOFF_VMESLV0_CTRL)/sizeof(LERegister));
+#undef TSILL
+#ifdef TSILL
+	uprintf(stderr,"mapoverall: base is 0x%08x, rptr 0x%08x\n",base,rptr);
+#endif
+#undef TSILL
+	for (port=0; port<4; port++) {
+		if ((rval=func(ismaster,port,rptr,arg))) return rval;
+		rptr+=5; /* register block spacing */
+	}
+
+	/* only rev. 2 has 8 ports */
+	if (UNIV_REV(base)<2) return -1;
+
+	rptr = (base + 
+		(ismaster ? UNIV_REGOFF_PCITGT4_CTRL : UNIV_REGOFF_VMESLV4_CTRL)/sizeof(LERegister));
+	for (port=4; port<UNIV_NUM_MPORTS; port++) {
+		if ((rval=func(ismaster,port,rptr,arg))) return rval;
+		rptr+=5; /* register block spacing */
+	}
+	return 0;
+#undef base
+}
+
+static void
+showUniversePorts(int ismaster, FILE *f)
+{
+	if (!f) f=stdout;
+	uprintf(f,"Universe %s Ports:\n",ismaster ? "Master" : "Slave");
+	uprintf(f,"Port  VME-Addr   Size       PCI-Adrs   Mode:\n");
+	mapOverAll(ismaster,showUniversePort,f);
+}
+
+static int xlate(int ismaster, unsigned long as, unsigned long aIn, unsigned long *paOut)
+{
+int	rval;
+XlatRec l;
+	l.aspace = as;
+	l.address = aIn;
+	/* map result -1/0/1 to -2/-1/0 with 0 on success */
+	rval = mapOverAll(ismaster,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)
+{
+	/* disable/reset special cycles (ADOH, RMW) */
+	vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_CTL);
+	vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_ADDR);
+	vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_EN);
+
+	/* set coupled window timeout to 0 (release VME after each transaction)
+	 * CRT (coupled request timeout) is unused by Universe II
+	 */
+	vmeUniverseWriteReg(UNIV_LMISC_CRT_128_US, UNIV_REGOFF_LMISC);
+
+	/* disable/reset DMA engine */
+	vmeUniverseWriteReg(0, UNIV_REGOFF_DCTL);
+	vmeUniverseWriteReg(0, UNIV_REGOFF_DTBC);
+	vmeUniverseWriteReg(0, UNIV_REGOFF_DLA);
+	vmeUniverseWriteReg(0, UNIV_REGOFF_DVA);
+	vmeUniverseWriteReg(0, UNIV_REGOFF_DCPP);
+
+	/* disable location monitor */
+	vmeUniverseWriteReg(0, UNIV_REGOFF_LM_CTL);
+
+	/* disable universe register access from VME bus */
+	vmeUniverseWriteReg(0, UNIV_REGOFF_VRAI_CTL);
+
+	/* disable VME bus image of VME CSR */
+	vmeUniverseWriteReg(0, UNIV_REGOFF_VCSR_CTL);
+
+	/* disable interrupts, reset routing */
+	vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_EN);
+	vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP0);
+	vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP1);
+
+	vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_EN);
+	vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_MAP0);
+	vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_MAP1);
+
+	vmeUniverseDisableAllSlaves();
+
+	vmeUniverseDisableAllMasters();
+	
+	vmeUniverseWriteReg(UNIV_VCSR_CLR_SYSFAIL, UNIV_REGOFF_VCSR_CLR);
+
+	/* clear interrupt status bits */
+	vmeUniverseWriteReg(UNIV_LINT_STAT_CLR, UNIV_REGOFF_LINT_STAT);
+	vmeUniverseWriteReg(UNIV_VINT_STAT_CLR, UNIV_REGOFF_VINT_STAT);
+
+	vmeUniverseWriteReg(UNIV_V_AMERR_V_STAT, UNIV_REGOFF_V_AMERR);
+
+	vmeUniverseWriteReg(
+		vmeUniverseReadReg(UNIV_REGOFF_PCI_CSR) |
+		UNIV_PCI_CSR_D_PE | UNIV_PCI_CSR_S_SERR | UNIV_PCI_CSR_R_MA |
+		UNIV_PCI_CSR_R_TA | UNIV_PCI_CSR_S_TA,
+		UNIV_REGOFF_PCI_CSR);
+
+	vmeUniverseWriteReg(UNIV_L_CMDERR_L_STAT, UNIV_REGOFF_L_CMDERR);
+
+	vmeUniverseWriteReg(
+		UNIV_DGCS_STOP | UNIV_DGCS_HALT | UNIV_DGCS_DONE |
+		UNIV_DGCS_LERR | UNIV_DGCS_VERR | UNIV_DGCS_P_ERR,
+		UNIV_REGOFF_DGCS);
+}
+
+int
+vmeUniverseInit(void)
+{
+int rval;
+	if ((rval=vmeUniverseFindPciBase(0,&vmeUniverse0BaseAddr))) {
+		uprintf(stderr,"unable to find the universe in pci config space\n");
+	} else {
+		uprintf(stderr,"Universe II PCI-VME bridge detected at 0x%08x, IRQ %i\n",
+				(unsigned int)vmeUniverse0BaseAddr, vmeUniverse0PciIrqLine);
+	}
+	return rval;
+}
+
+void
+vmeUniverseMasterPortsShow(FILE *f)
+{
+	showUniversePorts(1,f);
+}
+
+void
+vmeUniverseSlavePortsShow(FILE *f)
+{
+	showUniversePorts(0,f);
+}
+
+int
+vmeUniverseMasterPortCfg(
+	unsigned long	port,
+	unsigned long	address_space,
+	unsigned long	vme_address,
+	unsigned long	local_address,
+	unsigned long	length)
+{
+	return cfgUniversePort(1,port,address_space,vme_address,local_address,length);
+}
+
+int
+vmeUniverseSlavePortCfg(
+	unsigned long	port,
+	unsigned long	address_space,
+	unsigned long	vme_address,
+	unsigned long	local_address,
+	unsigned long	length)
+{
+	return cfgUniversePort(0,port,address_space,vme_address,local_address,length);
+}
+
+void
+vmeUniverseDisableAllSlaves(void)
+{
+	mapOverAll(0,disableUniversePort,0);
+}
+
+void
+vmeUniverseDisableAllMasters(void)
+{
+	mapOverAll(1,disableUniversePort,0);
+}
+
+int
+vmeUniverseStartDMA(
+	unsigned long local_addr,
+	unsigned long vme_addr,
+	unsigned long count)
+{
+
+	if (!vmeUniverse0BaseAddr && vmeUniverseInit()) return -1;
+	if ((local_addr & 7) != (vme_addr & 7)) {
+		uprintf(stderr,"vmeUniverseStartDMA: misaligned addresses\n");
+		return -1;
+	}
+
+	{
+	/* help the compiler allocate registers */
+	register volatile LERegister *b=vmeUniverse0BaseAddr;
+	register unsigned long dgcsoff=UNIV_REGOFF_DGCS,dgcs;
+
+	dgcs=READ_LE(b, dgcsoff);
+
+	/* clear status and make sure CHAIN is clear */
+	dgcs &= ~UNIV_DGCS_CHAIN;
+	WRITE_LE(dgcs,
+		      b, dgcsoff);
+	WRITE_LE(local_addr,
+		      b, UNIV_REGOFF_DLA);
+	WRITE_LE(vme_addr,
+		      b, UNIV_REGOFF_DVA);
+	WRITE_LE(count,
+		      b, UNIV_REGOFF_DTBC);
+	dgcs |= UNIV_DGCS_GO;
+	EIEIO_REG; /* make sure GO is written after everything else */
+	WRITE_LE(dgcs,
+		      b, dgcsoff);
+	}
+	SYNC; /* enforce command completion */
+	return 0;
+}
+
+unsigned long
+vmeUniverseReadReg(unsigned long offset)
+{
+unsigned long rval;
+	rval = READ_LE(vmeUniverse0BaseAddr,offset);
+	return rval;
+}
+
+void
+vmeUniverseWriteReg(unsigned long value, unsigned long offset)
+{
+	WRITE_LE(value, vmeUniverse0BaseAddr, offset);
+}
+
+void
+vmeUniverseCvtToLE(unsigned long *ptr, unsigned long num)
+{
+#if !defined(__LITTLE_ENDIAN__) || (__LITTLE_ENDIAN__ != 1)
+register unsigned long *p=ptr+num;
+	while (p > ptr) {
+#if (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
+		__asm__ __volatile__(
+			"lwzu 0, -4(%0)\n"
+			"stwbrx 0, 0, %0\n"
+			: "=r"(p) : "r"(p) : "r0"
+			);
+#elif defined(__rtems)
+		p--; st_le32(p, *p);
+#else
+#error	"vmeUniverse: endian conversion not implemented for this architecture"
+#endif
+	}
+#endif
+}
+
+/* RTEMS interrupt subsystem */
+
+#ifdef __rtems
+#include <bsp/irq.h>
+
+typedef struct
+UniverseIRQEntryRec_ {
+		VmeUniverseISR	isr;
+		void			*usrData;
+} UniverseIRQEntryRec, *UniverseIRQEntry;
+
+static UniverseIRQEntry universeHdlTbl[257]={0};
+
+static int mgrInstalled=0;
+static int vmeIrqUnivOut=-1;
+static int specialIrqUnivOut=-1;
+
+VmeUniverseISR
+vmeUniverseISRGet(unsigned long vector, void **parg)
+{
+	if (vector>255) return 0;
+	if (parg)
+		*parg=universeHdlTbl[vector]->usrData;
+	return universeHdlTbl[vector]->isr;
+}
+
+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);
+	}
+	/* clear all special interrupts */
+	vmeUniverseWriteReg(
+					~((UNIV_LINT_STAT_VIRQ7<<1)-UNIV_LINT_STAT_VIRQ1),
+					UNIV_REGOFF_LINT_STAT
+					);
+
+/*
+ *	clear our line in the VINT_STAT register
+ *  seems to be not neccessary...
+	vmeUniverseWriteReg(
+					UNIV_VINT_STAT_LINT(specialIrqUnivOut),
+					UNIV_REGOFF_VINT_STAT);
+ */
+}
+
+/*
+ * interrupts from VME to PCI seem to be processed more or less
+ * like this:
+ *
+ *
+ *   VME IRQ ------ 
+ *                  & ----- LINT_STAT ---- 
+ *                  |                       &  ---------- PCI LINE
+ *                  |                       |
+ *                  |                       | 
+ *       LINT_EN --------------------------- 
+ *
+ *  I.e. 
+ *   - if LINT_EN is disabled, a VME IRQ will not set LINT_STAT.
+ *   - while LINT_STAT is set, it will pull the PCI line unless
+ *     masked by LINT_EN.
+ *   - VINT_STAT(lint_bit) seems to have no effect beyond giving
+ *     status info.
+ *
+ *  Hence, it is possible to
+ *    - arm (set LINT_EN, routing etc.)
+ *    - receive an irq (sets. LINT_STAT)
+ *    - the ISR then:
+ *      	  * clears LINT_EN, results in masking LINT_STAT (which
+ *      	    is still set to prevent another VME irq at the same
+ *      	    level to be ACKEd by the universe.
+ *      	  * do PCI_EOI to allow nesting of higher VME irqs.
+ *      	    (previous step also cleared LINT_EN of lower levels)
+ *      	  * when the handler returns, clear LINT_STAT
+ *      	  * re-enable setting LINT_EN.
+ */
+
+static void
+universeVMEISR(void)
+{
+UniverseIRQEntry ip;
+unsigned long lvl,msk,lintstat,linten,status;
+
+		/* determine the highest priority IRQ source */
+		lintstat=vmeUniverseReadReg(UNIV_REGOFF_LINT_STAT);
+		for (msk=UNIV_LINT_STAT_VIRQ7, lvl=7;
+			 lvl>0;
+			 lvl--, msk>>=1) {
+			if (lintstat & msk) break;
+		}
+		if (!lvl) {
+				/* try the special handler */
+				universeSpecialISR();
+
+				/* 
+				 * let the pic end this cycle
+				 */
+				BSP_PIC_DO_EOI;
+
+				return;
+		}
+		linten = vmeUniverseReadReg(UNIV_REGOFF_LINT_EN);
+
+		/* mask this and all lower levels */
+		vmeUniverseWriteReg(
+						linten & ~((msk<<1)-UNIV_LINT_STAT_VIRQ1),
+						UNIV_REGOFF_LINT_EN
+						);
+
+		/* end this interrupt
+		 * cycle on the PCI bus, so higher level interrupts can be
+		 * caught from now on...
+		 */
+		BSP_PIC_DO_EOI;
+
+		/* get vector and dispatch handler */
+		status = vmeUniverseReadReg(UNIV_REGOFF_VIRQ1_STATID - 4 + (lvl<<2));
+		/* determine the highest priority IRQ source */
+
+		if (status & UNIV_VIRQ_ERR) {
+				/* TODO: log error message - RTEMS has no logger :-( */
+		} else if (!(ip=universeHdlTbl[status & UNIV_VIRQ_STATID_MASK])) {
+				/* TODO: log error message - RTEMS has no logger :-( */
+		} else {
+				/* dispatch handler, it must clear the IRQ at the device */
+				ip->isr(ip->usrData, status&UNIV_VIRQ_STATID_MASK);
+		}
+
+		/* clear this interrupt level */
+		vmeUniverseWriteReg(msk, UNIV_REGOFF_LINT_STAT);
+/*
+ *  this seems not to be necessary; we just leave the
+ *  bit set to save a couple of instructions...
+		vmeUniverseWriteReg(
+					UNIV_VINT_STAT_LINT(vmeIrqUnivOut),
+					UNIV_REGOFF_VINT_STAT);
+*/
+
+
+		/* re-enable the previous level */
+		vmeUniverseWriteReg(linten, UNIV_REGOFF_LINT_EN);
+}
+
+/* STUPID API */
+static void
+my_no_op(const rtems_irq_connect_data * arg)
+{}
+
+static int
+my_isOn(const rtems_irq_connect_data *arg)
+{
+		return (int)vmeUniverseReadReg(UNIV_REGOFF_LINT_EN);
+}
+
+int
+vmeUniverseInstallIrqMgr(int vmeOut, 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 (mgrInstalled) return -4;
+
+	aarrggh.on=my_no_op; /* at _least_ they could check for a 0 pointer */
+	aarrggh.off=my_no_op;
+	aarrggh.isOn=my_isOn;
+	aarrggh.hdl=universeVMEISR;
+	aarrggh.name=vmeUniverse0PciIrqLine + BSP_PCI_IRQ0;
+	if (!BSP_install_rtems_irq_handler(&aarrggh))
+			BSP_panic("unable to install vmeUniverse irq handler");
+	if (specialIrqUnivOut > 0) {
+			/* install the special handler to a separate irq */
+			aarrggh.hdl=universeSpecialISR;
+			aarrggh.name=specialIrqPicLine + BSP_PCI_IRQ0;
+			if (!BSP_install_rtems_irq_handler(&aarrggh))
+				BSP_panic("unable to install vmeUniverse secondary irq handler");
+	} else {
+		specialIrqUnivOut = vmeIrqUnivOut;
+	}
+	/* setup routing */
+
+	vmeUniverseWriteReg(
+		(UNIV_LINT_MAP0_VIRQ7(vmeIrqUnivOut) |
+		 UNIV_LINT_MAP0_VIRQ6(vmeIrqUnivOut) |
+		 UNIV_LINT_MAP0_VIRQ5(vmeIrqUnivOut) |
+		 UNIV_LINT_MAP0_VIRQ4(vmeIrqUnivOut) |
+		 UNIV_LINT_MAP0_VIRQ3(vmeIrqUnivOut) |
+		 UNIV_LINT_MAP0_VIRQ2(vmeIrqUnivOut) |
+		 UNIV_LINT_MAP0_VIRQ1(vmeIrqUnivOut) |
+		 UNIV_LINT_MAP0_VOWN(specialIrqUnivOut)
+		),
+		UNIV_REGOFF_LINT_MAP0);
+	vmeUniverseWriteReg(
+		(UNIV_LINT_MAP1_ACFAIL(specialIrqUnivOut) |
+		 UNIV_LINT_MAP1_SYSFAIL(specialIrqUnivOut) |
+		 UNIV_LINT_MAP1_SW_INT(specialIrqUnivOut) |
+		 UNIV_LINT_MAP1_SW_IACK(specialIrqUnivOut) |
+		 UNIV_LINT_MAP1_VERR(specialIrqUnivOut) |
+		 UNIV_LINT_MAP1_LERR(specialIrqUnivOut) |
+		 UNIV_LINT_MAP1_DMA(specialIrqUnivOut)
+		),
+		UNIV_REGOFF_LINT_MAP1);
+	mgrInstalled=1;
+	return 0;
+}
+
+
+int
+vmeUniverseInstallISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
+{
+UniverseIRQEntry ip;
+
+		if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !mgrInstalled)
+				return -1;
+
+		ip=universeHdlTbl[vector];
+
+		if (ip || !(ip=(UniverseIRQEntry)malloc(sizeof(UniverseIRQEntryRec))))
+				return -1;
+		ip->isr=hdl;
+		ip->usrData=arg;
+		universeHdlTbl[vector]=ip;
+		return 0;
+}
+
+int
+vmeUniverseRemoveISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
+{
+UniverseIRQEntry ip;
+
+		if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !mgrInstalled)
+				return -1;
+
+		ip=universeHdlTbl[vector];
+
+		if (!ip || ip->isr!=hdl || ip->usrData!=arg)
+				return -1;
+		universeHdlTbl[vector]=0;
+		free(ip);
+		return 0;
+}
+
+int
+vmeUniverseIntEnable(unsigned int level)
+{
+		if (!mgrInstalled || level<1 || level>7)
+				return -1;
+		vmeUniverseWriteReg(
+				(vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) | 
+				 (UNIV_LINT_EN_VIRQ1 << (level-1))
+				),
+				UNIV_REGOFF_LINT_EN);
+		return 0;
+}
+
+int
+vmeUniverseIntDisable(unsigned int level)
+{
+		if (!mgrInstalled || level<1 || level>7)
+				return -1;
+		vmeUniverseWriteReg(
+				(vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) & 
+				 ~ (UNIV_LINT_EN_VIRQ1 << (level-1))
+				),
+				UNIV_REGOFF_LINT_EN);
+		return 0;
+}
+
+
+#endif
Index: c/src/lib/libbsp/shared/vmeUniverse/vmeUniverse.h
===================================================================
--- c/src/lib/libbsp/shared/vmeUniverse/vmeUniverse.h	(revision 6fae45804d1a552e19c735cd75ee2d462a00f254)
+++ c/src/lib/libbsp/shared/vmeUniverse/vmeUniverse.h	(revision 6fae45804d1a552e19c735cd75ee2d462a00f254)
@@ -0,0 +1,662 @@
+/* $Id$ */
+#ifndef VME_UNIVERSE_UTIL_H
+#define VME_UNIVERSE_UTIL_H
+
+/* Routines to configure and use the Tundra Universe VME bridge
+ * Author: Till Straumann <strauman@slac.stanford.edu>
+ *         Nov 2000, July 2001
+ */
+
+/* Register definitions */
+/* NOTE: all registers contents in PCI space are LITTLE ENDIAN */
+
+#ifdef __vxworks
+#include <vme.h>
+#else
+/* vxworks compatible addressing modes */
+#define	VME_AM_STD_SUP_PGM	0x3e
+#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_PGM	0x0e
+#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
+#endif
+
+typedef unsigned long LERegister; /* emphasize contents are little endian */
+
+/* NOTE: DMA packet descriptors MUST be 32 byte aligned */
+typedef struct VmeUniverseDMAPacketRec_ {
+	LERegister	dctl __attribute__((aligned(32)));
+	LERegister	dtbc;
+	LERegister	dla;
+	LERegister	dummy1;
+	LERegister	dva;
+	LERegister	dummy2;
+	LERegister	dccp;
+	LERegister	dummy3;
+} VmeUniverseDMAPacketRec, *VmeUniverseDMAPacket;
+
+/* PCI CSR register */
+#define		UNIV_REGOFF_PCI_CSR		0x4
+# define	UNIV_PCI_CSR_D_PE		(1<<31)	/* detected parity error; write 1 to clear */
+# define	UNIV_PCI_CSR_S_SERR		(1<<30)	/* SERR (signalled error) asserted; write 1 to clear */
+# define	UNIV_PCI_CSR_R_MA		(1<<29)	/* received master abort; write 1 to clear */
+# define	UNIV_PCI_CSR_R_TA		(1<<28)	/* received target abort; write 1 to clear */
+# define	UNIV_PCI_CSR_S_TA		(1<<27)	/* signalled target abort; write 1 to clear */
+# define	UNIV_PCI_CSR_DEVSEL_MASK (3<<25)	/* device select timing (RO) */
+# define	UNIV_PCI_CSR_DP_D		(1<<24)	/* data parity error detected; write 1 to clear */
+# define	UNIV_PCI_CSR_TFBBC		(1<<23)	/* target fast back to back capable (RO) */
+# define	UNIV_PCI_CSR_MFBBC		(1<<9)	/* master fast back to back capable (RO) */
+# define	UNIV_PCI_CSR_SERR_EN	(1<<8)	/* enable SERR driver */
+# define	UNIV_PCI_CSR_WAIT		(1<<7)	/* wait cycle control (RO) */
+# define	UNIV_PCI_CSR_PERESP		(1<<6)	/* parity error response enable */
+# define	UNIV_PCI_CSR_VGAPS		(1<<5)	/* VGA palette snoop (RO) */
+# define	UNIV_PCI_CSR_MWI_EN		(1<<4)	/* Memory write and invalidate enable (RO) */
+# define	UNIV_PCI_CSR_SC			(1<<3)	/* special cycles (RO) */
+# define	UNIV_PCI_CSR_BM			(1<<2)	/* master enable (MUST SET TO ENABLE VME SLAVES) */
+# define	UNIV_PCI_CSR_MS			(1<<1)	/* target memory enable */
+# define	UNIV_PCI_CSR_IOS		(1<<0)	/* target IO enable */
+
+/* Special cycle (ADOH, RMW) control register */
+#define		UNIV_REGOFF_SCYC_CTL	0x170	/* write 0 to disable */
+# define	UNIV_SCYC_CTL_LAS_IO	(1<<2)	/* PCI address space (1: IO, 0: mem) */
+# define	UNIV_SCYC_CTL_SCYC_RMW	(1<<0)	/* do a RMW cycle when reading  PCI address */
+# define	UNIV_SCYC_CTL_SCYC_ADOH	(2<<0)	/* do a ADOH cycle when reading/writing  PCI address */
+
+/* Special cycle address register */
+#define		UNIV_REGOFF_SCYC_ADDR	0x174	/* PCI address (must be long word aligned) */
+
+/* Special cycle Swap/Compare/Enable */
+#define		UNIV_REGOFF_SCYC_EN	0x178	/* mask determining the bits involved in the compare and swap operations for VME RMW cycles */
+
+/* Special cycle compare data register */
+#define		UNIV_REGOFF_SCYC_CMP	0x17c	/* data to compare with word returned from VME RMW read */
+
+/* Special cycle swap data register */
+#define		UNIV_REGOFF_SCYC_SWP	0x180	/* If enabled bits of CMP match, corresponding SWP bits are written back to VME (under control of EN) */
+
+/* PCI miscellaneous register */
+#define		UNIV_REGOFF_LMISC	0x184
+# define	UNIV_LMISC_CRT_MASK	(7<<28)	/* Univ. I only, not used on II */
+# define	UNIV_LMISC_CRT_INF	(0<<28)	/* Coupled Request Timeout */
+# define	UNIV_LMISC_CRT_128_US	(1<<28)	/* Coupled Request Timeout */
+# define	UNIV_LMISC_CRT_256_US	(2<<28)	/* Coupled Request Timeout */
+# define	UNIV_LMISC_CRT_512_US	(3<<28)	/* Coupled Request Timeout */
+# define	UNIV_LMISC_CRT_1024_US	(4<<28)	/* Coupled Request Timeout */
+# define	UNIV_LMISC_CRT_2048_US	(5<<28)	/* Coupled Request Timeout */
+# define	UNIV_LMISC_CRT_4096_US	(6<<28)	/* Coupled Request Timeout */
+
+# define	UNIV_LMISC_CWT_MASK	(7<<24)	/* coupled window timer */
+# define	UNIV_LMISC_CWT_DISABLE	0	/* disabled (release VME after 1 coupled xaction) */
+# define	UNIV_LMISC_CWT_16	(1<<24)	/* 16 PCI clock cycles */
+# define	UNIV_LMISC_CWT_32	(2<<24)	/* 32 PCI clock cycles */
+# define	UNIV_LMISC_CWT_64	(3<<24)	/* 64 PCI clock cycles */
+# define	UNIV_LMISC_CWT_128	(4<<24)	/* 128 PCI clock cycles */
+# define	UNIV_LMISC_CWT_256	(5<<24)	/* 256 PCI clock cycles */
+# define	UNIV_LMISC_CWT_512	(6<<24)	/* 512 PCI clock cycles */
+
+/* PCI Command Error Log Register */
+#define		UNIV_REGOFF_L_CMDERR	0x18c
+# define	UNIV_L_CMDERR_CMDERR(reg) (((reg)>>28)&0xf) /* extract PCI cmd error log */
+# define	UNIV_L_CMDERR_M_ERR	(1<<27)	/* multiple errors have occurred */
+# define	UNIV_L_CMDERR_L_STAT	(1<<23)	/* PCI error log status valid (write 1 to clear and enable logging) */
+
+/* PCI Address Error Log */
+#define		UNIV_REGOFF_LAERR	0x190	/* PCI fault address (if L_CMDERR_L_STAT valid) */
+/* DMA Xfer Control Register */
+#define		UNIV_REGOFF_DCTL	0x200
+# define	UNIV_DCTL_L2V		(1<<31)	/* PCI->VME if set */
+# define	UNIV_DCTL_VDW_MSK	(3<<22)	/* VME max. width mask 0x00c00000 */
+# define	UNIV_DCTL_VDW_8		(0<<22)	/* VME max. width 8 */
+# define	UNIV_DCTL_VDW_16	(1<<22)	/* VME max. width 16 */
+# define	UNIV_DCTL_VDW_32	(2<<22)	/* VME max. width 32 */
+# define	UNIV_DCTL_VDW_64	(3<<22)	/* VME max. width 64 */
+# define	UNIV_DCTL_VAS_MSK	(7<<16)	/* VME AS mask 0x00070000 */
+# define	UNIV_DCTL_VAS_A16	(0<<16)	/* VME A16 */
+# define	UNIV_DCTL_VAS_A24	(1<<16)	/* VME A24 */
+# define	UNIV_DCTL_VAS_A32	(2<<16)	/* VME A32 */
+# define	UNIV_DCTL_PGM_MSK	(3<<14)	/* VME PGM/DATA mask 0x0000c000 */
+# define	UNIV_DCTL_PGM		(1<<14)	/* VME PGM(1)/DATA(0) */
+# define	UNIV_DCTL_SUPER_MSK	(3<<12)	/* VME SUPER/USR mask 0x00003000 */
+# define	UNIV_DCTL_SUPER		(1<<12)	/* VME SUPER(1)/USR(0) */
+# define	UNIV_DCTL_VCT		(1<<8)	/* VME enable BLT */
+# define	UNIV_DCTL_LD64EN	(1<<7)	/* PCI 64 enable  */
+
+/* DMA Xfer byte count register (is updated by DMA) */
+#define		UNIV_REGOFF_DTBC	0x204
+/* DMA Xfer local (PCI) address (direction is  set in DCTL) */
+#define		UNIV_REGOFF_DLA		0x208
+/* DMA Xfer VME address (direction is  set in DCTL)
+ * NOTE: (*UNIV_DVA) & ~7 == (*UNIV_DLA) & ~7 MUST HOLD
+ */
+#define		UNIV_REGOFF_DVA		0x210
+
+/* DMA Xfer VME command packet pointer
+ * NOTE: The address stored here MUST be 32-byte aligned
+ */
+#define		UNIV_REGOFF_DCPP	0x218
+/* these bits are only used in linked lists */
+# define	UNIV_DCCP_IMG_NULL	(1<<0)	/* last packet in list */
+# define	UNIV_DCCP_IMG_PROCESSED (1<<1)	/* packet processed */
+
+/* DMA Xfer General Control/Status register */
+#define		UNIV_REGOFF_DGCS	0x220
+# define	UNIV_DGCS_GO		(1<<31)	/* start xfer */
+# define	UNIV_DGCS_STOP_REQ	(1<<30) /* stop xfer (immediate abort) */
+# define	UNIV_DGCS_HALT_REQ	(1<<29) /* halt xfer (abort after current packet) */
+# define	UNIV_DGCS_CHAIN		(1<<27) /* enable linked list mode */
+# define	UNIV_DGCS_VON_MSK	(7<<20) /* VON mask */
+# define	UNIV_DGCS_VON_DONE	(0<<20) /* VON counter disabled (do until done) */
+# define	UNIV_DGCS_VON_256	(1<<20) /* VON yield bus after 256 bytes */
+# define	UNIV_DGCS_VON_512	(2<<20) /* VON yield bus after 512 bytes */
+# define	UNIV_DGCS_VON_1024	(3<<20) /* VON yield bus after 512 bytes */
+# define	UNIV_DGCS_VON_2048	(4<<20) /* VON yield bus after 1024 bytes */
+# define	UNIV_DGCS_VON_4096	(5<<20) /* VON yield bus after 4096 bytes */
+# define	UNIV_DGCS_VON_8192	(6<<20) /* VON yield bus after 8192 bytes */
+# define	UNIV_DGCS_VOFF_MSK	(15<<16) /* VOFF mask */
+# define	UNIV_DGCS_VOFF_0_US	(0<<16)	/* re-request VME master after 0 us */
+# define	UNIV_DGCS_VOFF_2_US	(8<<16)	/* re-request VME master after 2 us */
+# define	UNIV_DGCS_VOFF_4_US	(9<<16)	/* re-request VME master after 4 us */
+# define	UNIV_DGCS_VOFF_8_US	(10<<16)/* re-request VME master after 8 us */
+# define	UNIV_DGCS_VOFF_16_US	(1<<16)	/* re-request VME master after 16 us */
+# define	UNIV_DGCS_VOFF_32_US	(2<<16)	/* re-request VME master after 32 us */
+# define	UNIV_DGCS_VOFF_64_US	(3<<16)	/* re-request VME master after 64 us */
+# define	UNIV_DGCS_VOFF_128_US	(4<<16)	/* re-request VME master after 128 us */
+# define	UNIV_DGCS_VOFF_256_US	(5<<16)	/* re-request VME master after 256 us */
+# define	UNIV_DGCS_VOFF_512_US	(6<<16)	/* re-request VME master after 512 us */
+# define	UNIV_DGCS_VOFF_1024_US	(7<<16)	/* re-request VME master after 1024 us */
+/* Status Bits (write 1 to clear) */
+# define	UNIV_DGCS_ACT		(1<<15)	/* DMA active */
+# define	UNIV_DGCS_STOP		(1<<14)	/* DMA stopped */
+# define	UNIV_DGCS_HALT		(1<<13)	/* DMA halted */
+# define	UNIV_DGCS_DONE		(1<<11)	/* DMA done (OK) */
+# define	UNIV_DGCS_LERR		(1<<10)	/* PCI bus error */
+# define	UNIV_DGCS_VERR		(1<<9)	/* VME bus error */
+# define	UNIV_DGCS_P_ERR		(1<<8)	/* programming protocol error (e.g. PCI master disabled) */
+# define	UNIV_DGCS_STATUS_CLEAR\
+	(UNIV_DGCS_ACT|UNIV_DGCS_STOP|UNIV_DGCS_HALT|\
+	 UNIV_DGCS_DONE|UNIV_DGCS_LERR|UNIV_DGCS_VERR|UNIV_DGCS_P_ERR)
+# define	UNIV_DGCS_P_ERR		(1<<8)	/* programming protocol error (e.g. PCI master disabled) */
+/* Interrupt Mask Bits */
+# define	UNIV_DGCS_INT_STOP	(1<<6)	/* interrupt when stopped */
+# define	UNIV_DGCS_INT_HALT	(1<<5)  /* interrupt when halted */
+# define	UNIV_DGCS_INT_DONE	(1<<3)	/* interrupt when done */
+# define	UNIV_DGCS_INT_LERR	(1<<2)	/* interrupt on LERR */
+# define	UNIV_DGCS_INT_VERR	(1<<1)	/* interrupt on VERR */
+# define	UNIV_DGCS_INT_P_ERR	(1<<0)	/* interrupt on P_ERR */
+# define	UNIV_DGCS_INT_MSK	(0x0000006f) /* interrupt mask */
+
+/* DMA Linked List Update Enable Register */
+#define		UNIV_REGOFF_D_LLUE	0x224
+# define	UNIV_D_LLUE_UPDATE	(1<<31)
+
+
+/* PCI (local) interrupt enable register */
+#define		UNIV_REGOFF_LINT_EN	0x300
+# define	UNIV_LINT_EN_LM3	(1<<23)	/* location monitor 3 mask */
+# define	UNIV_LINT_EN_LM2	(1<<22)	/* location monitor 2 mask */
+# define	UNIV_LINT_EN_LM1	(1<<21)	/* location monitor 1 mask */
+# define	UNIV_LINT_EN_LM0	(1<<20)	/* location monitor 0 mask */
+# define	UNIV_LINT_EN_MBOX3	(1<<19)	/* mailbox 3 mask */
+# define	UNIV_LINT_EN_MBOX2	(1<<18)	/* mailbox 2 mask */
+# define	UNIV_LINT_EN_MBOX1	(1<<17)	/* mailbox 1 mask */
+# define	UNIV_LINT_EN_MBOX0	(1<<16)	/* mailbox 0 mask */
+# define 	UNIV_LINT_EN_ACFAIL	(1<<15)	/* ACFAIL irq mask */
+# define 	UNIV_LINT_EN_SYSFAIL	(1<<14)	/* SYSFAIL irq mask */
+# define 	UNIV_LINT_EN_SW_INT	(1<<13)	/* PCI (local) software irq */
+# define 	UNIV_LINT_EN_SW_IACK	(1<<12)	/* VME software IACK mask */
+# define	UNIV_LINT_EN_VERR	(1<<10)	/* PCI VERR irq mask */
+# define	UNIV_LINT_EN_LERR	(1<<9)	/* PCI LERR irq mask */
+# define	UNIV_LINT_EN_DMA	(1<<8)	/* PCI DMA irq mask */
+# define	UNIV_LINT_EN_VIRQ7	(1<<7)	/* VIRQ7 mask (universe does IACK automatically) */
+# define	UNIV_LINT_EN_VIRQ6	(1<<6)	/* VIRQ6 mask */
+# define	UNIV_LINT_EN_VIRQ5	(1<<5)	/* VIRQ5 mask */
+# define	UNIV_LINT_EN_VIRQ4	(1<<4)	/* VIRQ4 mask */
+# define	UNIV_LINT_EN_VIRQ3	(1<<3)	/* VIRQ3 mask */
+# define	UNIV_LINT_EN_VIRQ2	(1<<2)	/* VIRQ2 mask */
+# define	UNIV_LINT_EN_VIRQ1	(1<<1)	/* VIRQ1 mask */
+# define	UNIV_LINT_EN_VOWN	(1<<0)	/* VOWN mask */
+
+/* PCI (local) interrupt status register */
+#define		UNIV_REGOFF_LINT_STAT	0x304
+# define	UNIV_LINT_STAT_LM3	(1<<23)	/* location monitor 3 status */
+# define	UNIV_LINT_STAT_LM2	(1<<22)	/* location monitor 2 status */
+# define	UNIV_LINT_STAT_LM1	(1<<21)	/* location monitor 1 status */
+# define	UNIV_LINT_STAT_LM0	(1<<20)	/* location monitor 0 status */
+# define	UNIV_LINT_STAT_MBOX3	(1<<19)	/* mailbox 3 status */
+# define	UNIV_LINT_STAT_MBOX2	(1<<18)	/* mailbox 2 status */
+# define	UNIV_LINT_STAT_MBOX1	(1<<17)	/* mailbox 1 status */
+# define	UNIV_LINT_STAT_MBOX0	(1<<16)	/* mailbox 0 status */
+# define 	UNIV_LINT_STAT_ACFAIL	(1<<15)	/* ACFAIL irq status */
+# define 	UNIV_LINT_STAT_SYSFAIL	(1<<14)	/* SYSFAIL irq status */
+# define 	UNIV_LINT_STAT_SW_INT	(1<<13)	/* PCI (local) software irq */
+# define 	UNIV_LINT_STAT_SW_IACK	(1<<12)	/* VME software IACK status */
+# define	UNIV_LINT_STAT_VERR		(1<<10)	/* PCI VERR irq status */
+# define	UNIV_LINT_STAT_LERR		(1<<9)	/* PCI LERR irq status */
+# define	UNIV_LINT_STAT_DMA		(1<<8)	/* PCI DMA irq status */
+# define	UNIV_LINT_STAT_VIRQ7	(1<<7)	/* VIRQ7 status */
+# define	UNIV_LINT_STAT_VIRQ6	(1<<6)	/* VIRQ6 status */
+# define	UNIV_LINT_STAT_VIRQ5	(1<<5)	/* VIRQ5 status */
+# define	UNIV_LINT_STAT_VIRQ4	(1<<4)	/* VIRQ4 status */
+# define	UNIV_LINT_STAT_VIRQ3	(1<<3)	/* VIRQ3 status */
+# define	UNIV_LINT_STAT_VIRQ2	(1<<2)	/* VIRQ2 status */
+# define	UNIV_LINT_STAT_VIRQ1	(1<<1)	/* VIRQ1 status */
+# define	UNIV_LINT_STAT_VOWN		(1<<0)	/* VOWN status */
+# define	UNIV_LINT_STAT_CLR		(0xfff7ff)/* Clear all status bits */
+
+/* PCI (local) interrupt map 0 register */
+#define		UNIV_REGOFF_LINT_MAP0	0x308	/* mapping of VME IRQ sources to PCI irqs */
+# define	UNIV_LINT_MAP0_VIRQ7(lint)	(((lint)&0x7)<<(7*4))
+# define	UNIV_LINT_MAP0_VIRQ6(lint)	(((lint)&0x7)<<(6*4))
+# define	UNIV_LINT_MAP0_VIRQ5(lint)	(((lint)&0x7)<<(5*4))
+# define	UNIV_LINT_MAP0_VIRQ4(lint)	(((lint)&0x7)<<(4*4))
+# define	UNIV_LINT_MAP0_VIRQ3(lint)	(((lint)&0x7)<<(3*4))
+# define	UNIV_LINT_MAP0_VIRQ2(lint)	(((lint)&0x7)<<(2*4))
+# define	UNIV_LINT_MAP0_VIRQ1(lint)	(((lint)&0x7)<<(1*4))
+# define	UNIV_LINT_MAP0_VOWN(lint)	(((lint)&0x7)<<(0*4))
+
+#define		UNIV_REGOFF_LINT_MAP1	0x30c	/* mapping of internal / VME IRQ sources to PCI irqs */
+# define	UNIV_LINT_MAP1_ACFAIL(lint)	(((lint)&0x7)<<(7*4))
+# define	UNIV_LINT_MAP1_SYSFAIL(lint)	(((lint)&0x7)<<(6*4))
+# define	UNIV_LINT_MAP1_SW_INT(lint)	(((lint)&0x7)<<(5*4))
+# define	UNIV_LINT_MAP1_SW_IACK(lint)	(((lint)&0x7)<<(4*4))
+# define	UNIV_LINT_MAP1_VERR(lint)	(((lint)&0x7)<<(2*4))
+# define	UNIV_LINT_MAP1_LERR(lint)	(((lint)&0x7)<<(1*4))
+# define	UNIV_LINT_MAP1_DMA(lint)	(((lint)&0x7)<<(0*4))
+
+/* enabling of generation of VME bus IRQs, TODO */
+#define		UNIV_REGOFF_VINT_EN		0x310
+# define	UNIV_VINT_EN_DISABLE_ALL    0
+
+/* status of generation of VME bus IRQs, TODO */
+#define		UNIV_REGOFF_VINT_STAT	0x314
+# define	UNIV_VINT_STAT_LINT(lint)	(1<<((lint)&7))
+# define	UNIV_VINT_STAT_LINT_MASK	(0xff)
+# define	UNIV_VINT_STAT_CLR			(0xfe0f17ff)
+#define		UNIV_REGOFF_VINT_MAP0	0x318	/* VME destination of PCI IRQ source, TODO */
+#define		UNIV_REGOFF_VINT_MAP1	0x31c	/* VME destination of PCI IRQ source, TODO */
+#define		UNIV_REGOFF_VINT_STATID	0x320	/* our status/id response to IACK, TODO */
+
+#define		UNIV_REGOFF_VIRQ1_STATID 0x324	/* status/id of VME IRQ level 1 */
+#define		UNIV_REGOFF_VIRQ2_STATID 0x328	/* status/id of VME IRQ level 2 */
+#define		UNIV_REGOFF_VIRQ3_STATID 0x32c	/* status/id of VME IRQ level 3 */
+#define		UNIV_REGOFF_VIRQ4_STATID 0x330	/* status/id of VME IRQ level 4 */
+#define		UNIV_REGOFF_VIRQ5_STATID 0x334	/* status/id of VME IRQ level 5 */
+#define		UNIV_REGOFF_VIRQ6_STATID 0x338	/* status/id of VME IRQ level 6 */
+#define		UNIV_REGOFF_VIRQ7_STATID 0x33c	/* status/id of VME IRQ level 7 */
+# define	UNIV_VIRQ_ERR			(1<<8)	/* set if universe encountered a bus error when doing IACK */
+# define	UNIV_VIRQ_STATID_MASK		(0xff)
+
+#define		UNIV_REGOFF_LINT_MAP2	0x340	/* mapping of internal sources to PCI irqs */
+# define	UNIV_LINT_MAP2_LM3(lint)	(((lint)&0x7)<<7*4)	/* location monitor 3 */
+# define	UNIV_LINT_MAP2_LM2(lint)	(((lint)&0x7)<<6*4)	/* location monitor 2 */
+# define	UNIV_LINT_MAP2_LM1(lint)	(((lint)&0x7)<<5*4)	/* location monitor 1 */
+# define	UNIV_LINT_MAP2_LM0(lint)	(((lint)&0x7)<<4*4)	/* location monitor 0 */
+# define	UNIV_LINT_MAP2_MBOX3(lint)	(((lint)&0x7)<<3*4)	/* mailbox 3 */
+# define	UNIV_LINT_MAP2_MBOX2(lint)	(((lint)&0x7)<<2*4)	/* mailbox 2 */
+# define	UNIV_LINT_MAP2_MBOX1(lint)	(((lint)&0x7)<<1*4)	/* mailbox 1 */
+# define	UNIV_LINT_MAP2_MBOX0(lint)	(((lint)&0x7)<<0*4)	/* mailbox 0 */
+
+#define		UNIV_REGOFF_VINT_MAP2	0x344	/* mapping of internal sources to VME irqs */
+# define	UNIV_VINT_MAP2_MBOX3(vint)	(((vint)&0x7)<<3*4)	/* mailbox 3 */
+# define	UNIV_VINT_MAP2_MBOX2(vint)	(((vint)&0x7)<<2*4)	/* mailbox 2 */
+# define	UNIV_VINT_MAP2_MBOX1(vint)	(((vint)&0x7)<<1*4)	/* mailbox 1 */
+# define	UNIV_VINT_MAP2_MBOX0(vint)	(((vint)&0x7)<<0*4)	/* mailbox 0 */
+
+#define		UNIV_REGOFF_MBOX0	0x348	/* mailbox 0 */
+#define		UNIV_REGOFF_MBOX1	0x34c	/* mailbox 1 */
+#define		UNIV_REGOFF_MBOX2	0x350	/* mailbox 2 */
+#define		UNIV_REGOFF_MBOX3	0x354	/* mailbox 3 */
+
+#define		UNIV_REGOFF_SEMA0	0x358	/* semaphore 0 */
+#define		UNIV_REGOFF_SEMA1	0x35c	/* semaphore 0 */
+/* TODO define semaphore register bits */
+
+#define		UNIV_REGOFF_MAST_CTL	0x400	/* master control register */
+# define	UNIV_MAST_CTL_MAXRTRY(val)	(((val)&0xf)<<7*4)	/* max # of pci master retries */
+# define	UNIV_MAST_CTL_PWON(val)		(((val)&0xf)<<6*4)	/* posted write xfer count */
+# define	UNIV_MAST_CTL_VRL(val)		(((val)&0x3)<<22)	/* VME bus request level */
+# define	UNIV_MAST_CTL_VRM			(1<<21)	/* bus request mode (demand = 0, fair = 1) */
+# define	UNIV_MAST_CTL_VREL			(1<<20)	/* bus release mode (when done = 0, on request = 1) */
+# define	UNIV_MAST_CTL_VOWN			(1<<19)	/* bus ownership (release = 0, acquire/hold = 1) */
+# define	UNIV_MAST_CTL_VOWN_ACK		(1<<18)	/* bus ownership (not owned = 0, acquired/held = 1) */
+# define	UNIV_MAST_CTL_PABS(val)		(((val)&0x3)<<3*4)	/* PCI aligned burst size (32,64,128 byte / 0x3 is reserved) */
+# define	UNIV_MAST_CTL_BUS_NO(val)	(((val)&0xff)<<0*4)	/* PCI bus number */
+
+#define		UNIV_REGOFF_MISC_CTL	0x404	/* misc control register */
+# define	UNIV_MISC_CTL_VBTO(val)		(((val)&0x7)<<7*4)	/* VME bus timeout (0=disable, 16*2^(val-1) us) */
+# define	UNIV_MISC_CTL_VARB			(1<<26)	/* VME bus arbitration mode (0=round robin, 1= priority) */
+# define	UNIV_MISC_CTL_VARBTO(val)	(((val)&0x3)<<6*4)	/* arbitration time out: disable, 16us, 256us, reserved */
+# define	UNIV_MISC_CTL_SW_LRST		(1<<23)	/* software PCI reset */
+# define	UNIV_MISC_CTL_SW_SYSRST		(1<<22)	/* software VME reset */
+# define	UNIV_MISC_CTL_BI			(1<<20)	/* BI mode */
+# define	UNIV_MISC_CTL_ENGBI			(1<<19)	/* enable global BI mode initiator */
+# 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 */
+
+/* Location Monitor control register */
+#define		UNIV_REGOFF_LM_CTL		0xf64
+# define	UNIV_LM_CTL_EN				(1<<31)	/* image enable */ 
+# define	UNIV_LM_CTL_PGM				(1<<23)	/* program AM */
+# define	UNIV_LM_CTL_DATA			(1<<22)	/* data AM */
+# define	UNIV_LM_CTL_SUPER			(1<<21)	/* supervisor AM */
+# define	UNIV_LM_CTL_USER			(1<<20)	/* user AM */
+# define	UNIV_LM_CTL_VAS_A16			(0<<16)	/* A16 */
+# define	UNIV_LM_CTL_VAS_A24			(1<<16)	/* A16 */
+# define	UNIV_LM_CTL_VAS_A32			(2<<16)	/* A16 */
+
+/* Location Monitor base address */
+#define		UNIV_REGOFF_LM_BS		0xf68
+
+/* VMEbus register access image control register */
+#define		UNIV_REGOFF_VRAI_CTL	0xf70
+# define	UNIV_VRAI_CTL_EN			(1<<31)	/* image enable */ 
+# define	UNIV_VRAI_CTL_PGM			(1<<23)	/* program AM */
+# define	UNIV_VRAI_CTL_DATA			(1<<22)	/* data AM */
+# define	UNIV_VRAI_CTL_SUPER			(1<<21)	/* supervisor AM */
+# define	UNIV_VRAI_CTL_USER			(1<<20)	/* user AM */
+# define	UNIV_VRAI_CTL_VAS_A16		(0<<16)	/* A16 */
+# define	UNIV_VRAI_CTL_VAS_A24		(1<<16)	/* A16 */
+# define	UNIV_VRAI_CTL_VAS_A32		(2<<16)	/* A16 */
+
+/* VMEbus register acces image base address register */
+#define		UNIV_REGOFF_VRAI_BS		0xf74
+
+/* VMEbus CSR control register */
+#define		UNIV_REGOFF_VCSR_CTL	0xf80
+# define	UNIV_VCSR_CTL_EN			(1<<31)	/* image enable */
+# define	UNIV_VCSR_CTL_LAS_PCI_MEM	(0<<0)	/* pci mem space */
+# define	UNIV_VCSR_CTL_LAS_PCI_IO	(1<<0)	/* pci IO space */
+# define	UNIV_VCSR_CTL_LAS_PCI_CFG	(2<<0)	/* pci config space */
+
+/* VMEbus CSR translation offset */
+#define		UNIV_REGOFF_VCSR_TO		0xf84
+
+/* VMEbus AM code error log */
+#define		UNIV_REGOFF_V_AMERR		0xf88
+# define	UNIV_V_AMERR_AMERR(reg)		(((reg)>>26)&0x3f)	/* extract error log code */
+# define	UNIV_V_AMERR_IACK			(1<<25)	/* VMEbus IACK signal */
+# define	UNIV_V_AMERR_M_ERR			(1<<24)	/* multiple errors occurred */
+# define	UNIV_V_AMERR_V_STAT			(1<<23)	/* log status valid (write 1 to clear) */
+
+/* VMEbus address error log */
+#define		UNIV_REGOFF_VAERR		0xf8c		/* address of fault address (if MERR_V_STAT valid) */
+
+/* VMEbus CSR bit clear register */
+#define		UNIV_REGOFF_VCSR_CLR	0xff4
+# define	UNIV_VCSR_CLR_RESET			(1<<31)	/* read/negate LRST (can only be written from VME bus */
+# define	UNIV_VCSR_CLR_SYSFAIL		(1<<30)	/* read/negate SYSFAIL */
+# define	UNIV_VCSR_CLR_FAIL			(1<<29)	/* read: board has failed */
+
+/* VMEbus CSR bit set register */
+#define		UNIV_REGOFF_VCSR_SET		(0xff8)
+# define	UNIV_VCSR_SET_RESET			(1<<31)	/* read/assert LRST (can only be written from VME bus */
+# define	UNIV_VCSR_SET_SYSFAIL		(1<<30)	/* read/assert SYSFAIL */
+# define	UNIV_VCSR_SET_FAIL			(1<<29)	/* read: board has failed */
+
+/* VMEbus CSR base address register */
+#define		UNIV_REGOFF_VCSR_BS		0xffc
+#define		UNIV_VCSR_BS_MASK			(0xfff80000)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* base address and IRQ line of 1st universe bridge
+ * NOTE: vmeUniverseInit() must be called before
+ *       these may be used.
+ */
+extern volatile LERegister *vmeUniverse0BaseAddr;
+extern int vmeUniverse0PciIrqLine;
+
+
+/* Initialize the driver */
+int
+vmeUniverseInit(void);
+
+/* setup the universe chip, i.e. disable most of its
+ * mappings, reset interrupts etc.
+ */
+void
+vmeUniverseReset(void);
+
+/* avoid pulling stdio.h into this header.
+ * Applications that want a declaration of the
+ * following routines should
+ *  #include <stdio.h>
+ *  #define _VME_UNIVERSE_DECLARE_SHOW_ROUTINES
+ *  #include <vmeUniverse.h>
+ */
+#ifdef _VME_UNIVERSE_DECLARE_SHOW_ROUTINES
+/* print the current configuration of all master ports to 
+ * f (stderr if NULL)
+ */
+void
+vmeUniverseMasterPortsShow(FILE *f);
+
+/* print the current configuration of all slave ports to
+ * f (stderr if NULL)
+ */
+void
+vmeUniverseSlavePortsShow(FILE *f);
+#else
+void
+vmeUniverseMasterPortsShow();
+void
+vmeUniverseSlavePortsShow();
+#endif
+
+/* disable all master or slave ports, respectively */
+void
+vmeUniverseDisableAllMasters(void);
+
+void
+vmeUniverseDisableAllSlaves(void);
+
+/* configure a master port
+ *
+ *   port:	    port number 0..3  (0..7 for a UniverseII)
+ *
+ *   address_space: vxWorks compliant addressing mode identifier
+ *                  (see vme.h). The most important are:
+ *                    0x0d - A32, Sup, Data
+ *                    0x3d - A24, Sup, Data
+ *                    0x2d - A16, Sup, Data
+ *                  additionally, the value 0 is accepted; it will
+ *                  disable this port.
+ *   vme_address:   address on the vme_bus of this port.
+ *   local_address: address on the pci_bus of this port.
+ *   length:        size of this port.
+ *
+ *   NOTE: the addresses and length parameters must be aligned on a
+ *         2^16 byte (0x10000) boundary, except for port 4 (only available
+ *         on a UniverseII), where the alignment can be 4k (4096).
+ *
+ *   RETURNS: 0 on success, -1 on failure. Error messages printed to stderr.
+ */
+
+int
+vmeUniverseMasterPortCfg(
+	unsigned long	port,
+	unsigned long	address_space,
+	unsigned long	vme_address,
+	unsigned long	local_address,
+	unsigned long	length);
+
+/* translate an address through the bridge
+ *
+ * vmeUniverseLocalToBusAdrs() 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.
+ *
+ * a valid address space modifier must be specified.
+ *
+ * RETURNS: translated address in *pbusAdrs / *plocalAdrs
+ *
+ *          0:  success
+ *          -1: address/modifier not found in any bridge port
+ *          -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);
+
+
+/* configure a VME slave (PCI master) port */
+int
+vmeUniverseSlavePortCfg(
+	unsigned long	port,
+	unsigned long	address_space,
+	unsigned long	vme_address,
+	unsigned long	local_address,
+	unsigned long	length);
+
+/* start a (direct, not linked) DMA transfer
+ *
+ * NOTE:  DCTL and DGCS must be set up
+ *        prior to calling this routine
+ */
+int
+vmeUniverseStartDMA(
+	unsigned long local_addr,
+	unsigned long vme_addr,
+	unsigned long count);
+
+/* read a register in PCI memory space
+ * (offset being one of the declared constants)
+ */
+unsigned long
+vmeUniverseReadReg(unsigned long offset);
+
+/* write a register in PCI memory space */
+void
+vmeUniverseWriteReg(unsigned long value, unsigned long offset);
+
+/* convert an array of unsigned long values to LE (as needed
+ * when the universe reads e.g. DMA descriptors from PCI)
+ */
+void
+vmeUniverseCvtToLE(unsigned long *ptr, unsigned long num);
+
+/* reset the VME bus */
+static inline void
+vmeUniverseResetBus(void)
+{
+	vmeUniverseWriteReg(
+		vmeUniverseReadReg(UNIV_REGOFF_MISC_CTL) | UNIV_MISC_CTL_SW_SYSRST,
+		UNIV_REGOFF_MISC_CTL);
+}
+
+#ifdef __rtems
+/* VME Interrupt Handler functionality */
+
+/* we dont use the current RTEMS/BSP interrupt API for the
+ * following reasons:
+ *
+ *    - RTEMS/BSP API does not pass an argument to the ISR :-( :-(
+ *    - no separate vector space for VME vectors. Some vectors would
+ *      have to overlap with existing PCI/ISA vectors.
+ *    - RTEMS/BSP API allocates a structure for every possible vector
+ *    - the irq_on(), irq_off() functions add more bloat than helping.
+ *      They are (currently) only used by the framework to disable
+ *      interrupts at the device level before removing a handler
+ *      and to enable interrupts after installing a handler.
+ *      These operations may as well be done by the driver itself.
+ *
+ * Hence, we maintain our own (VME) handler table and hook our PCI
+ * handler into the standard RTEMS/BSP environment. Our handler then
+ * dispatches VME interrupts.
+ */
+
+typedef void (*VmeUniverseISR) (void *usrArg, unsigned long vector);
+
+/* install a handler for a VME vector
+ * RETURNS 0 on success, nonzero on failure.
+ */
+int
+vmeUniverseInstallISR(unsigned long vector, VmeUniverseISR handler, void *usrArg);
+
+/* remove a handler for a VME vector. The vector and usrArg parameters
+ * must match the respective parameters used when installing the handler.
+ * RETURNS 0 on success, nonzero on failure.
+ */
+int
+vmeUniverseRemoveISR(unsigned long vector, VmeUniverseISR handler, void *usrArg);
+
+/* query for the currently installed ISR and usr parameter at a given vector
+ * RETURNS: ISR or 0 (vector too big or no ISR installed)
+ */
+VmeUniverseISR
+vmeUniverseISRGet(unsigned long vector, void **parg);
+
+/* utility routines to enable/disable a VME IRQ level
+ *
+ * RETURNS 0 on success, nonzero on failure
+ */
+int
+vmeUniverseIntEnable(unsigned int level);
+int
+vmeUniverseIntDisable(unsigned int level);
+
+
+/* use this special vector 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
+ */
+#define UNIV_SPECIAL_IRQ_VECTOR	256
+
+/* the universe interrupt handler is capable of routing all sorts of
+ * (VME) interrupts to 8 different lines (some of) which may be hooked up
+ * in a (board specific) way to a PIC.
+ *
+ * This driver only supports at most two lines. It routes the 7 VME 
+ * interrupts to the main line and optionally, it routes the 'special'
+ * interrupts generated by the universe itself (DMA done, VOWN etc.)
+ * to a second line. If no second line is available, all IRQs are routed
+ * to the main line.
+ *
+ * Because the driver has no way to figure out which lines are actually
+ * wired to the PIC, this information has to be provided when installing
+ * the manager.
+ *
+ * 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. 
+ *
+ * PARAMETERS:
+ *       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
+ *                      internally irqs be routed. Use 'vmeIRQunivOut'
+ *                      if < 0.
+ *   specialIrqPicLine: specifies to which PIC input the 'special' output
+ *                      pin is wired. The wiring of the 'vmeIRQunivOut' to
+ *                      the PIC is determined by reading PCI config space.
+ *
+ * RETURNS: 0 on success, -1 on failure.
+ *						
+ */
+int
+vmeUniverseInstallIrqMgr(int vmeIrqUnivOut, int specialIrqUnivOut, int specialIrqPicLine);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
