Ticket #214: vmeuniverse.diff

File vmeuniverse.diff, 65.5 KB (added by strauman, on 12/03/06 at 13:31:12)

vmeuniverse.diff

Line 
1This patch (against rtems-ss-20020301) contributes
2a driver for the TUNDRA UNVERSE VME-PCI bridge to
3libbsp/shared.
4
5Author: Till Straumann <strauman@slac.stanford.edu>, 2001/2002
6
7NOTE: This driver is maintained _outside_ rtems by me.
8          Please forward future modifications to
9          <strauman@slac.stanford.edu>
10
11Index: c/src/lib/libbsp/shared/Makefile.am
12===================================================================
13RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libbsp/shared/Makefile.am,v
14retrieving revision 1.1.1.1
15retrieving revision 1.2
16***************
17*** 7,13 ****
18  SUBDIRS = include
19 
20  EXTRA_DIST = bootcard.c bspclean.c bsplibc.c bsppost.c console-polled.c \
21!     console.c gnatinstallhandler.c main.c sbrk.c tod.c tod.h
22 
23  include $(top_srcdir)/../../../../automake/subdirs.am
24  include $(top_srcdir)/../../../../automake/local.am
25--- 7,14 ----
26  SUBDIRS = include
27 
28  EXTRA_DIST = bootcard.c bspclean.c bsplibc.c bsppost.c console-polled.c \
29!     console.c gnatinstallhandler.c main.c sbrk.c tod.c tod.h \
30!       vmeUniverse/vmeUniverse.c vmeUniverse/vmeUniverse.h
31 
32  include $(top_srcdir)/../../../../automake/subdirs.am
33  include $(top_srcdir)/../../../../automake/local.am
34Index: c/src/lib/libbsp/shared/README.universe
35===================================================================
36RCS file: README.universe
37diff -N README.universe
38*** /dev/null   Thu Aug 24 02:00:32 2000
39--- /tmp/cvsqohsGx      Sun May  5 11:22:26 2002
40***************
41*** 0 ****
42--- 1,19 ----
43+ The universe II driver is in a separate subdir
44+ because it is maintained at SSRL outside of the
45+ rtems CVS tree (it supports other OSes as well)
46+
47+ Till Straumann <strauman@slac.stanford.edu> 1/2002
48+
49+ NOTES:
50+ This driver is maintained _outside_ rtems.
51+ Please forward future modifications to me.
52+
53+ A BSP that wants to use the vmeUniverse driver
54+ must implement the following headers / functionality:
55+  - <bsp/pci.h> offering an API like 'libbsp/powerpc/shared/pci'
56+  - <bsp/irq.h> offering the 'new style' RTEMS irq API
57+    (like 'libbsp/powerpc/shared/irq').
58+
59+ The BSP should then use "VPATH magic" (to use Joel's
60+ words :-) to reach the vmeUniverse.* files in the
61+ universe subdir.
62Index: c/src/lib/libbsp/shared/vmeUniverse/vmeUniverse.c
63===================================================================
64RCS file: vmeUniverse.c
65diff -N vmeUniverse.c
66*** /dev/null   Thu Aug 24 02:00:32 2000
67--- /tmp/cvs0AXe4C      Sun May  5 11:22:27 2002
68***************
69*** 0 ****
70--- 1,1212 ----
71+ /* $Id: vmeUniverse.c,v 1.21 2002/04/11 06:54:48 till Exp $ */
72+
73+ /* Routines to configure the VME interface
74+  * Author: Till Straumann <strauman@slac.stanford.edu>
75+  *         Nov 2000, Oct 2001, Jan 2002
76+  */
77+
78+ #if 0
79+  * $Log: vmeUniverse.c,v $
80+  * Revision 1.21  2002/04/11 06:54:48  till
81+  *  - silenced message about 'successfully configured a port'
82+  *
83+  * Revision 1.20  2002/03/27 21:14:50  till
84+  *  - fix: handler table holds pointers, so hdlrTbl[vector]->usrData etc.
85+  *    not hdlrTbl[vector].usrData...
86+  *
87+  * Revision 1.19  2002/03/09 00:14:36  till
88+  *  - added vmeUniverseISRGet() to retrieve the currently installed
89+  *    ISR for a given vector
90+  *  - swapped the argument order for ISRs to (usrarg, vector)
91+  *
92+  * Revision 1.18  2002/02/07 19:53:48  till
93+  *  - reverted back to publish base_addr/irq_line as variables rather than
94+  *    through functions: the irq_line is read by the interrupt dispatcher...
95+  *
96+  * Revision 1.17  2002/01/24 08:28:10  till
97+  *  - initialize driver when reading base address or irq line.
98+  *    however, this requires the pci driver to be working already.
99+  *
100+  * Revision 1.16  2002/01/24 08:21:48  till
101+  *  - replaced public global vars for base address/irq line by routines.
102+  *
103+  * Revision 1.15  2002/01/23 06:15:30  till
104+  *   - changed master port data width to 64 bit.
105+  *     /* NOTE: reading the CY961 (Echotek ECDR814) with VDW32
106+  *      *       generated bus errors when reading 32-bit words
107+  *      *       - very weird, because the registers are 16-bit
108+  *      *         AFAIK.
109+  *      *       - 32-bit accesses worked fine on vxWorks which
110+  *      *         has the port set to 64-bit.
111+  *      *       ????????
112+  *      */
113+  *
114+  * Revision 1.14  2002/01/11 19:30:54  till
115+  *  - added more register defines to header
116+  *  - completed vmeUniverseReset
117+  *
118+  * Revision 1.13  2002/01/11 05:06:18  till
119+  *  - fixed VMEISR failing to check (lint_stat & msk) when determining
120+  *    the highes level...
121+  *  - tested interrupt handling & nesting. Seems to work.
122+  *
123+  * Revision 1.12  2002/01/11 02:25:55  till
124+  *  - added interrupt manager
125+  *
126+  * Revision 1.11  2002/01/08 03:59:52  till
127+  *  - vxworks always defines _LITTLE_ENDIAN, fixed the conditionals
128+  *    so it should work on __vxworks and on __rtems now.
129+  *  - rtems uprintf wrapper reverts to printk if stdio is not yet
130+  *    initialized (uses _impure_ptr->__sdidinit)
131+  *  - tested bus address translation utility routines
132+  *
133+  * Revision 1.9  2002/01/05 02:36:32  till
134+  *  - added vmeUniverseBusToLocalAdrs / vmeUniverseLocalToBusAdrs for address
135+  *    space translations.
136+  *  - include bsp.h under rtems to hack around the libcpu/powerpc/shared/io.h
137+  *    #define _IO_BASE & friends problem.
138+  *
139+  * Revision 1.8  2002/01/04 04:12:51  till
140+  *  - changed some rtems/pci related names
141+  *
142+  * Revision 1.7  2002/01/04 03:06:30  till
143+  *  - added further register definitions
144+  *
145+  * Revision 1.6  2001/12/20 04:42:44  till
146+  *  - fixed endianness stuff; theoretically, PPC could be LITTLE_ENDIAN...
147+  *
148+  * Revision 1.4  2001/12/19 01:59:02  till
149+  *  - started adding interrupt stuff
150+  *  - private implementation of PCI scanning if necessary
151+  *
152+  * Revision 1.3  2001/07/27 22:22:51  till
153+  *  - added more DMA support routines and defines to include file
154+  *  - xxxPortsShow can now print to a given file descriptor argument
155+  *
156+  * Revision 1.2  2001/07/26 18:06:13  till
157+  *  - ported to RTEMS
158+  *  - fixed a couple of wrong pointer calculations.
159+  *
160+  * Revision 1.1.1.1  2001/07/12 23:15:19  till
161+  *  - cvs import
162+  *
163+ #endif
164+
165+ #include <stdio.h>
166+ #include <stdarg.h>
167+ #include "vmeUniverse.h"
168+
169+ #define UNIV_NUM_MPORTS               8 /* number of master ports */
170+ #define UNIV_NUM_SPORTS               8 /* number of slave ports */
171+
172+ #define PCI_VENDOR_TUNDRA     0x10e3
173+ #define PCI_DEVICE_UNIVERSEII 0
174+ #define PCI_UNIVERSE_BASE0    0x10
175+ #define PCI_UNIVERSE_BASE1    0x14
176+
177+ #define UNIV_REGOFF_PCITGT0_CTRL 0x100
178+ #define UNIV_REGOFF_PCITGT4_CTRL 0x1a0
179+ #define UNIV_REGOFF_VMESLV0_CTRL 0xf00
180+ #define UNIV_REGOFF_VMESLV4_CTRL 0xf90
181+
182+ #define UNIV_CTL_VAS16                (0x00000000)
183+ #define UNIV_CTL_VAS24                (0x00010000)
184+ #define UNIV_CTL_VAS32                (0x00020000)
185+ #define UNIV_CTL_VAS          (0x00070000)
186+
187+ #define UNIV_MCTL_EN          (0x80000000)
188+ #define UNIV_MCTL_PWEN                (0x40000000)
189+ #define UNIV_MCTL_PGM         (0x00004000)
190+ #define UNIV_MCTL_VCT         (0x00000100)
191+ #define UNIV_MCTL_SUPER               (0x00001000)
192+ #define UNIV_MCTL_VDW32               (0x00800000)
193+ #define UNIV_MCTL_VDW64               (0x00c00000)
194+
195+ #define UNIV_MCTL_AM_MASK     (UNIV_CTL_VAS | UNIV_MCTL_PGM | UNIV_MCTL_SUPER)
196+
197+ #define UNIV_SCTL_EN          (0x80000000)
198+ #define UNIV_SCTL_PWEN                (0x40000000)
199+ #define UNIV_SCTL_PREN                (0x20000000)
200+ #define UNIV_SCTL_PGM         (0x00800000)
201+ #define UNIV_SCTL_DAT         (0x00400000)
202+ #define UNIV_SCTL_SUPER               (0x00200000)
203+ #define UNIV_SCTL_USER                (0x00100000)
204+
205+ #define UNIV_SCTL_AM_MASK     (UNIV_CTL_VAS | UNIV_SCTL_PGM | UNIV_SCTL_DAT | UNIV_SCTL_USER | UNIV_SCTL_SUPER)
206+
207+ /* we rely on a vxWorks definition here */
208+ #define VX_AM_SUP             4
209+
210+ #ifdef __rtems
211+
212+ #include <stdlib.h>
213+ #include <rtems/bspIo.h>      /* printk */
214+ #include <bsp/pci.h>
215+ #include <bsp.h>
216+
217+ #define pciFindDevice BSP_pciFindDevice
218+ #define pciConfigInLong pci_read_config_dword
219+ #define pciConfigInByte pci_read_config_byte
220+
221+ typedef unsigned int pci_ulong;
222+ #define PCI_TO_LOCAL_ADDR(memaddr) ((pci_ulong)(memaddr) + PCI_MEM_BASE)
223+
224+
225+ #elif defined(__vxworks)
226+ typedef unsigned long pci_ulong;
227+ #define PCI_TO_LOCAL_ADDR(memaddr) (memaddr)
228+ #define PCI_INTERRUPT_LINE    0x3c
229+ #else
230+ #error "vmeUniverse not ported to this architecture yet"
231+ #endif
232+
233+
234+ volatile LERegister *vmeUniverse0BaseAddr=0;
235+ int vmeUniverse0PciIrqLine=-1;
236+
237+ #if 0
238+ /* public access functions */
239+ volatile LERegister *
240+ vmeUniverseBaseAddr(void)
241+ {
242+       if (!vmeUniverse0BaseAddr) vmeUniverseInit();
243+       return vmeUniverse0BaseAddr;
244+ }
245+
246+ int
247+ vmeUniversePciIrqLine(void)
248+ {
249+       if (vmeUniverse0PciIrqLine<0) vmeUniverseInit();
250+       return vmeUniverse0PciIrqLine;
251+ }
252+ #endif
253+
254+ static inline void
255+ WRITE_LE(
256+       unsigned long val,
257+       volatile LERegister    *adrs,
258+       unsigned long off)
259+ {
260+ #if (__LITTLE_ENDIAN__ == 1)
261+       *(volatile unsigned long*)(((unsigned long)adrs)+off)=val;
262+ #elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
263+       /* offset is in bytes and MUST not end up in r0 */
264+       __asm__ __volatile__("stwbrx %1, %0, %2" :: "b"(off),"r"(val),"r"(adrs));
265+ #elif defined(__rtems)
266+       st_le32((volatile unsigned long*)(((unsigned long)adrs)+off), val);
267+ #else
268+ #error "little endian register writing not implemented"
269+ #endif
270+ }
271+
272+ #if defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)
273+ #define SYNC __asm__ __volatile__("sync")
274+ #else
275+ #define SYNC
276+ #warning "SYNC instruction unknown for this architecture"
277+ #endif
278+
279+ /* registers should be mapped to guarded, non-cached memory; hence
280+  * subsequent stores are ordered. eieio is only needed to enforce
281+  * ordering of loads with respect to stores.
282+  */
283+ #define EIEIO_REG
284+
285+ static inline unsigned long
286+ READ_LE0(volatile LERegister *adrs)
287+ {
288+ #if (__LITTLE_ENDIAN__ == 1)
289+       return *(volatile unsigned long *)adrs;
290+ #elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
291+ register unsigned long rval;
292+ __asm__ __volatile__("lwbrx %0, 0, %1":"=r"(rval):"r"(adrs));
293+       return rval;
294+ #elif defined(__rtems)
295+       return ld_le32((volatile unsigned long*)adrs);
296+ #else
297+ #error "little endian register reading not implemented"
298+ #endif
299+ }
300+
301+ static inline unsigned long
302+ READ_LE(volatile LERegister *adrs, unsigned long off)
303+ {
304+ #if (__LITTLE_ENDIAN__ == 1)
305+       return  *((volatile LERegister *)(((unsigned long)adrs)+off));
306+ #elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
307+ register unsigned long rval;
308+       /* offset is in bytes and MUST not end up in r0 */
309+ __asm__ __volatile__("lwbrx %0, %2, %1"
310+                               : "=r"(rval)
311+                               : "r"(adrs), "b"(off));
312+ #if 0
313+ __asm__ __volatile__("eieio");
314+ #endif
315+ return rval;
316+ #else
317+ return READ_LE0((volatile LERegister *)(((unsigned long)adrs)+off));
318+ #endif
319+ }
320+
321+ #define PORT_UNALIGNED(addr,port) \
322+       ( (port)%4 ? ((addr) & 0xffff) : ((addr) & 4095) )
323+
324+
325+ #define UNIV_REV(base) (READ_LE(base,2*sizeof(LERegister)) & 0xff)
326+       
327+ #ifdef __rtems
328+ static int
329+ uprintk(char *fmt, va_list ap)
330+ {
331+ int           rval;
332+ /* during bsp init, there is no malloc and no stdio,
333+  * hence we assemble the message on the stack and revert
334+  * to printk
335+  */
336+ char  buf[200];
337+       rval = vsprintf(buf,fmt,ap);
338+       if (rval > sizeof(buf))
339+                       BSP_panic("vmeUniverse/uprintk: buffer overrun");
340+       printk(buf);
341+       return rval;
342+ }
343+ #endif
344+
345+
346+ /* private printing wrapper */
347+ static int
348+ uprintf(FILE *f, char *fmt, ...)
349+ {
350+ va_list       ap;
351+ int   rval;
352+       va_start(ap, fmt);
353+ #ifdef __rtems
354+       if (!f || !_impure_ptr->__sdidinit) {
355+               /* Might be called at an early stage when
356+                * stdio is not yet initialized.
357+                * There is no vprintk, hence we must assemble
358+                * to a buffer.
359+                */
360+               rval=uprintk(fmt,ap);
361+       } else
362+ #endif
363+       {
364+               rval=vfprintf(f,fmt,ap);
365+       }
366+       va_end(ap);
367+       return rval;
368+ }
369+
370+ int
371+ vmeUniverseFindPciBase(
372+       int instance,
373+       volatile LERegister **pbase
374+       )
375+ {
376+ int bus,dev,fun;
377+ pci_ulong busaddr;
378+ unsigned char irqline;
379+
380+       if (pciFindDevice(
381+                       PCI_VENDOR_TUNDRA,
382+                       PCI_DEVICE_UNIVERSEII,
383+                       instance,
384+                       &bus,
385+                       &dev,
386+                       &fun))
387+               return -1;
388+       if (pciConfigInLong(bus,dev,fun,PCI_UNIVERSE_BASE0,&busaddr))
389+               return -1;
390+       if ((unsigned long)(busaddr) & 1) {
391+               /* it's IO space, try BASE1 */
392+               if (pciConfigInLong(bus,dev,fun,PCI_UNIVERSE_BASE1,&busaddr)
393+                  || ((unsigned long)(busaddr) & 1))
394+                       return -1;
395+       }
396+       *pbase=(volatile LERegister*)PCI_TO_LOCAL_ADDR(busaddr);
397+
398+       if (pciConfigInByte(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline))
399+               return -1;
400+       else
401+               vmeUniverse0PciIrqLine = irqline;
402+
403+       return 0;
404+ }
405+
406+ /* convert an address space selector to a corresponding
407+  * universe control mode word
408+  */
409+
410+ static int
411+ am2mode(int ismaster, unsigned long address_space, unsigned long *pmode)
412+ {
413+ unsigned long mode=0;
414+       if (!ismaster) {
415+               mode |= UNIV_SCTL_DAT | UNIV_SCTL_PGM;
416+               mode |= UNIV_SCTL_USER;
417+       }
418+       switch (address_space) {
419+               case VME_AM_STD_SUP_PGM:
420+               case VME_AM_STD_USR_PGM:
421+                       if (ismaster)
422+                               mode |= UNIV_MCTL_PGM ;
423+                       else {
424+                               mode &= ~UNIV_SCTL_DAT;
425+                       }
426+                       /* fall thru */
427+               case VME_AM_STD_SUP_DATA:
428+               case VME_AM_STD_USR_DATA:
429+                       mode |= UNIV_CTL_VAS24;
430+                       break;
431+
432+               case VME_AM_EXT_SUP_PGM:
433+               case VME_AM_EXT_USR_PGM:
434+                       if (ismaster)
435+                               mode |= UNIV_MCTL_PGM ;
436+                       else {
437+                               mode &= ~UNIV_SCTL_DAT;
438+                       }
439+                       /* fall thru */
440+               case VME_AM_EXT_SUP_DATA:
441+               case VME_AM_EXT_USR_DATA:
442+                       mode |= UNIV_CTL_VAS32;
443+                       break;
444+
445+               case VME_AM_SUP_SHORT_IO:
446+               case VME_AM_USR_SHORT_IO:
447+                       mode |= UNIV_CTL_VAS16;
448+                       break;
449+
450+               case 0: /* disable the port alltogether */
451+                       break;
452+
453+               default:
454+                       return -1;
455+       }
456+       if (address_space & VX_AM_SUP)
457+               mode |= (ismaster ? UNIV_MCTL_SUPER : UNIV_SCTL_SUPER);
458+       *pmode = mode;
459+       return 0;
460+ }
461+
462+ static int
463+ disableUniversePort(int ismaster, int portno, volatile unsigned long *preg, void *param)
464+ {
465+ unsigned long cntrl;
466+       cntrl=READ_LE0(preg);
467+       cntrl &= ~(ismaster ? UNIV_MCTL_EN : UNIV_SCTL_EN);
468+       WRITE_LE(cntrl,preg,0);
469+       SYNC; /* make sure this command completed */
470+       return 0;
471+ }
472+
473+ static int
474+ cfgUniversePort(
475+       unsigned long   ismaster,
476+       unsigned long   port,
477+       unsigned long   address_space,
478+       unsigned long   vme_address,
479+       unsigned long   local_address,
480+       unsigned long   length)
481+ {
482+ #define base vmeUniverse0BaseAddr
483+ volatile LERegister *preg=base;
484+ unsigned long p=port;
485+ unsigned long mode=0;
486+
487+       /* check parameters */
488+       if (port >= (ismaster ? UNIV_NUM_MPORTS : UNIV_NUM_SPORTS)) {
489+               uprintf(stderr,"invalid port\n");
490+               return -1;
491+       }
492+       /* port start, bound addresses and offset must lie on 64k boundary
493+        * (4k for port 0 and 4)
494+        */
495+       if ( PORT_UNALIGNED(local_address,port) ) {
496+               uprintf(stderr,"local address misaligned\n");
497+               return -1;
498+       }
499+       if ( PORT_UNALIGNED(vme_address,port) ) {
500+               uprintf(stderr,"vme address misaligned\n");
501+               return -1;
502+       }
503+       if ( PORT_UNALIGNED(length,port) ) {
504+               uprintf(stderr,"length misaligned\n");
505+               return -1;
506+       }
507+
508+       /* check address space validity */
509+       if (am2mode(ismaster,address_space,&mode)) {
510+               uprintf(stderr,"invalid address space\n");
511+               return -1;
512+       }
513+
514+       /* get the universe base address */
515+       if (!base && vmeUniverseInit()) {
516+               return -1;
517+       }
518+
519+       /* find out if we have a rev. II chip */
520+       if ( UNIV_REV(base) < 2 ) {
521+               if (port>3) {
522+                       uprintf(stderr,"Universe rev. < 2 has only 4 ports\n");
523+                       return -1;
524+               }
525+       }
526+
527+       /* finally, configure the port */
528+
529+       /* find the register set for our port */
530+       if (port<4) {
531+               preg += (ismaster ? UNIV_REGOFF_PCITGT0_CTRL : UNIV_REGOFF_VMESLV0_CTRL)/sizeof(LERegister);
532+       } else {
533+               preg += (ismaster ? UNIV_REGOFF_PCITGT4_CTRL : UNIV_REGOFF_VMESLV4_CTRL)/sizeof(LERegister);
534+               p-=4;
535+       }
536+       preg += 5 * p;
537+
538+       /* temporarily disable the port */
539+       disableUniversePort(ismaster,port,preg,0);
540+
541+       /* address_space == 0 means disable */
542+       if (address_space != 0) {
543+               unsigned long start,offst;
544+               /* set the port starting address;
545+                * this is the local address for the master
546+                * and the VME address for the slave
547+                */
548+               if (ismaster) {
549+                       start=local_address;
550+                       /* let it overflow / wrap around 0 */
551+                       offst=vme_address-local_address;
552+               } else {
553+                       start=vme_address;
554+                       /* let it overflow / wrap around 0 */
555+                       offst=local_address-vme_address;
556+               }
557+ #undef TSILL
558+ #ifdef TSILL
559+               uprintf(stderr,"writing 0x%08x to 0x%08x + 4\n",start,preg);
560+ #else
561+               WRITE_LE(start,preg,4);
562+ #endif
563+               /* set bound address */
564+               length+=start;
565+ #ifdef TSILL
566+               uprintf(stderr,"writing 0x%08x to 0x%08x + 8\n",length,preg);
567+ #else
568+               WRITE_LE(length,preg,8);
569+ #endif
570+               /* set offset */
571+ #ifdef TSILL
572+               uprintf(stderr,"writing 0x%08x to 0x%08x + 12\n",offst,preg);
573+ #else
574+               WRITE_LE(offst,preg,12);
575+ #endif
576+               /* calculate configuration word and enable the port */
577+               /* NOTE: reading the CY961 (Echotek ECDR814) with VDW32
578+                *       generated bus errors when reading 32-bit words
579+                  *       - very weird, because the registers are 16-bit
580+                  *         AFAIK.
581+                *       - 32-bit accesses worked fine on vxWorks which
582+                  *         has the port set to 64-bit.
583+                  *       ????????
584+                  */
585+               if (ismaster)
586+                       mode |= UNIV_MCTL_EN | UNIV_MCTL_PWEN | UNIV_MCTL_VDW64 | UNIV_MCTL_VCT;
587+               else
588+                       mode |= UNIV_SCTL_EN | UNIV_SCTL_PWEN | UNIV_SCTL_PREN;
589+
590+ #ifdef TSILL
591+               uprintf(stderr,"writing 0x%08x to 0x%08x + 0\n",mode,preg);
592+ #else
593+               EIEIO_REG;      /* make sure mode is written last */
594+               WRITE_LE(mode,preg,0);
595+               SYNC;           /* enforce completion */
596+ #endif
597+
598+ #ifdef TSILL
599+               uprintf(stderr,
600+                       "universe %s port %lu successfully configured\n",
601+                               ismaster ? "master" : "slave",
602+                               port);
603+ #endif
604+
605+ #ifdef __vxworks
606+               if (ismaster)
607+                       uprintf(stderr,
608+                       "WARNING: on the synergy, sysMasterPortsShow() may show incorrect settings (it uses cached values)\n");
609+ #endif
610+       }
611+       return 0;
612+ #undef base
613+ }
614+
615+
616+ static int
617+ showUniversePort(
618+               int             ismaster,
619+               int             portno,
620+               volatile LERegister *preg,
621+               void            *parm)
622+ {
623+       FILE *f=parm ? (FILE *)parm : stdout;
624+       unsigned long cntrl, start, bound, offst, mask;
625+
626+       cntrl = READ_LE0(preg++);
627+ #undef TSILL
628+ #ifdef TSILL
629+       uprintf(stderr,"showUniversePort: *(0x%08x): 0x%08x\n",preg-1,cntrl);
630+ #endif
631+ #undef TSILL
632+
633+       /* skip this port if disabled */
634+       if (!(cntrl & (ismaster ? UNIV_MCTL_EN : UNIV_SCTL_EN)))
635+               return 0;
636+
637+       /* for the master `start' is the PCI address,
638+        * for the slave  `start' is the VME address
639+        */
640+       mask = ~PORT_UNALIGNED(0xffffffff,portno);
641+
642+       start = READ_LE0(preg++)&mask;
643+       bound = READ_LE0(preg++)&mask;
644+       offst = READ_LE0(preg++)&mask;
645+
646+       offst+=start; /* calc start on the other bus */
647+
648+       if (ismaster) {
649+               uprintf(f,"%i:    0x%08lx 0x%08lx 0x%08lx ",
650+                       portno,offst,bound-start,start);
651+       } else {
652+               uprintf(f,"%i:    0x%08lx 0x%08lx 0x%08lx ",
653+                       portno,start,bound-start,offst);
654+       }
655+
656+       switch (cntrl & UNIV_CTL_VAS) {
657+               case UNIV_CTL_VAS16: uprintf(f,"A16, "); break;
658+               case UNIV_CTL_VAS24: uprintf(f,"A24, "); break;
659+               case UNIV_CTL_VAS32: uprintf(f,"A32, "); break;
660+               default: uprintf(f,"A??, "); break;
661+       }
662+
663+       if (ismaster) {
664+               uprintf(f,"%s, %s",
665+                       cntrl&UNIV_MCTL_PGM ?   "Pgm" : "Dat",
666+                       cntrl&UNIV_MCTL_SUPER ? "Sup" : "Usr");
667+       } else {
668+               uprintf(f,"%s %s %s %s",
669+                       cntrl&UNIV_SCTL_PGM ?   "Pgm," : "    ",
670+                       cntrl&UNIV_SCTL_DAT ?   "Dat," : "    ",
671+                       cntrl&UNIV_SCTL_SUPER ? "Sup," : "    ",
672+                       cntrl&UNIV_SCTL_USER  ? "Usr" :  "");
673+       }
674+       uprintf(f,"\n");
675+       return 0;
676+ }
677+
678+ typedef struct XlatRec_ {
679+       unsigned long   address;
680+       unsigned long   aspace;
681+ } XlatRec, *Xlat;
682+
683+ /* try to translate an address through the bridge
684+  *
685+  * IN:  l->address, l->aspace
686+  * OUT: l->address (translated address)
687+  *
688+  * RETURNS: -1: invalid space
689+  *           0: invalid address (not found in range)
690+  *           1: success
691+  */
692+
693+ static int
694+ xlatePort(int ismaster, int port, volatile LERegister *preg, void *parm)
695+ {
696+ Xlat  l=(Xlat)parm;
697+ unsigned long cntrl, start, bound, offst, mask, x;
698+
699+       cntrl = READ_LE0(preg++);
700+
701+       /* skip this port if disabled */
702+       if (!(cntrl & (ismaster ? UNIV_MCTL_EN : UNIV_SCTL_EN)))
703+               return 0;
704+
705+       /* check for correct address space */
706+       if ( am2mode(ismaster,l->aspace,&offst) ) {
707+               uprintf(stderr,"vmeUniverse WARNING: invalid adressing mode 0x%x\n",
708+                              l->aspace);
709+               return -1;
710+       }
711+       if ( (cntrl & (ismaster ? UNIV_MCTL_AM_MASK : UNIV_SCTL_AM_MASK))
712+           != offst )
713+               return 0; /* mode doesn't match requested AM */
714+
715+       /* OK, we found a matching mode, now we must check the address range */
716+       mask = ~PORT_UNALIGNED(0xffffffff,port);
717+
718+       /* for the master `start' is the PCI address,
719+        * for the slave  `start' is the VME address
720+        */
721+       start = READ_LE0(preg++) & mask;
722+       bound = READ_LE0(preg++) & mask;
723+       offst = READ_LE0(preg++) & mask;
724+
725+       /* translate address to the other bus */
726+       x = l->address - offst;
727+
728+       if (x >= start && x < bound) {
729+               /* valid address found */
730+               l->address = x;
731+               return 1;
732+       }
733+       return 0;
734+ }
735+
736+
737+ static int
738+ mapOverAll(int ismaster, int (*func)(int,int,volatile LERegister *,void*), void *arg)
739+ {
740+ #define base  vmeUniverse0BaseAddr
741+ volatile LERegister   *rptr;
742+ unsigned long port;
743+ int   rval;
744+
745+       /* get the universe base address */
746+       if (!base && vmeUniverseInit()) {
747+               uprintf(stderr,"unable to find the universe in pci config space\n");
748+               return -1;
749+       }
750+       rptr = (base +
751+               (ismaster ? UNIV_REGOFF_PCITGT0_CTRL : UNIV_REGOFF_VMESLV0_CTRL)/sizeof(LERegister));
752+ #undef TSILL
753+ #ifdef TSILL
754+       uprintf(stderr,"mapoverall: base is 0x%08x, rptr 0x%08x\n",base,rptr);
755+ #endif
756+ #undef TSILL
757+       for (port=0; port<4; port++) {
758+               if ((rval=func(ismaster,port,rptr,arg))) return rval;
759+               rptr+=5; /* register block spacing */
760+       }
761+
762+       /* only rev. 2 has 8 ports */
763+       if (UNIV_REV(base)<2) return -1;
764+
765+       rptr = (base +
766+               (ismaster ? UNIV_REGOFF_PCITGT4_CTRL : UNIV_REGOFF_VMESLV4_CTRL)/sizeof(LERegister));
767+       for (port=4; port<UNIV_NUM_MPORTS; port++) {
768+               if ((rval=func(ismaster,port,rptr,arg))) return rval;
769+               rptr+=5; /* register block spacing */
770+       }
771+       return 0;
772+ #undef base
773+ }
774+
775+ static void
776+ showUniversePorts(int ismaster, FILE *f)
777+ {
778+       if (!f) f=stdout;
779+       uprintf(f,"Universe %s Ports:\n",ismaster ? "Master" : "Slave");
780+       uprintf(f,"Port  VME-Addr   Size       PCI-Adrs   Mode:\n");
781+       mapOverAll(ismaster,showUniversePort,f);
782+ }
783+
784+ static int xlate(int ismaster, unsigned long as, unsigned long aIn, unsigned long *paOut)
785+ {
786+ int   rval;
787+ XlatRec l;
788+       l.aspace = as;
789+       l.address = aIn;
790+       /* map result -1/0/1 to -2/-1/0 with 0 on success */
791+       rval = mapOverAll(ismaster,xlatePort,(void*)&l) - 1;
792+       *paOut = l.address;
793+       return rval;
794+ }
795+
796+ /* public functions */
797+ int
798+ vmeUniverseLocalToBusAdrs(unsigned long as, unsigned long localAdrs, unsigned long *pbusAdrs)
799+ {
800+       return xlate(0,as,localAdrs,pbusAdrs);
801+ }
802+
803+ int
804+ vmeUniverseBusToLocalAdrs(unsigned long as, unsigned long busAdrs, unsigned long *plocalAdrs)
805+ {
806+       return xlate(1,as,busAdrs,plocalAdrs);
807+ }
808+
809+ void
810+ vmeUniverseReset(void)
811+ {
812+       /* disable/reset special cycles (ADOH, RMW) */
813+       vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_CTL);
814+       vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_ADDR);
815+       vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_EN);
816+
817+       /* set coupled window timeout to 0 (release VME after each transaction)
818+        * CRT (coupled request timeout) is unused by Universe II
819+        */
820+       vmeUniverseWriteReg(UNIV_LMISC_CRT_128_US, UNIV_REGOFF_LMISC);
821+
822+       /* disable/reset DMA engine */
823+       vmeUniverseWriteReg(0, UNIV_REGOFF_DCTL);
824+       vmeUniverseWriteReg(0, UNIV_REGOFF_DTBC);
825+       vmeUniverseWriteReg(0, UNIV_REGOFF_DLA);
826+       vmeUniverseWriteReg(0, UNIV_REGOFF_DVA);
827+       vmeUniverseWriteReg(0, UNIV_REGOFF_DCPP);
828+
829+       /* disable location monitor */
830+       vmeUniverseWriteReg(0, UNIV_REGOFF_LM_CTL);
831+
832+       /* disable universe register access from VME bus */
833+       vmeUniverseWriteReg(0, UNIV_REGOFF_VRAI_CTL);
834+
835+       /* disable VME bus image of VME CSR */
836+       vmeUniverseWriteReg(0, UNIV_REGOFF_VCSR_CTL);
837+
838+       /* disable interrupts, reset routing */
839+       vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_EN);
840+       vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP0);
841+       vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP1);
842+
843+       vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_EN);
844+       vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_MAP0);
845+       vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_MAP1);
846+
847+       vmeUniverseDisableAllSlaves();
848+
849+       vmeUniverseDisableAllMasters();
850+       
851+       vmeUniverseWriteReg(UNIV_VCSR_CLR_SYSFAIL, UNIV_REGOFF_VCSR_CLR);
852+
853+       /* clear interrupt status bits */
854+       vmeUniverseWriteReg(UNIV_LINT_STAT_CLR, UNIV_REGOFF_LINT_STAT);
855+       vmeUniverseWriteReg(UNIV_VINT_STAT_CLR, UNIV_REGOFF_VINT_STAT);
856+
857+       vmeUniverseWriteReg(UNIV_V_AMERR_V_STAT, UNIV_REGOFF_V_AMERR);
858+
859+       vmeUniverseWriteReg(
860+               vmeUniverseReadReg(UNIV_REGOFF_PCI_CSR) |
861+               UNIV_PCI_CSR_D_PE | UNIV_PCI_CSR_S_SERR | UNIV_PCI_CSR_R_MA |
862+               UNIV_PCI_CSR_R_TA | UNIV_PCI_CSR_S_TA,
863+               UNIV_REGOFF_PCI_CSR);
864+
865+       vmeUniverseWriteReg(UNIV_L_CMDERR_L_STAT, UNIV_REGOFF_L_CMDERR);
866+
867+       vmeUniverseWriteReg(
868+               UNIV_DGCS_STOP | UNIV_DGCS_HALT | UNIV_DGCS_DONE |
869+               UNIV_DGCS_LERR | UNIV_DGCS_VERR | UNIV_DGCS_P_ERR,
870+               UNIV_REGOFF_DGCS);
871+ }
872+
873+ int
874+ vmeUniverseInit(void)
875+ {
876+ int rval;
877+       if ((rval=vmeUniverseFindPciBase(0,&vmeUniverse0BaseAddr))) {
878+               uprintf(stderr,"unable to find the universe in pci config space\n");
879+       } else {
880+               uprintf(stderr,"Universe II PCI-VME bridge detected at 0x%08x, IRQ %i\n",
881+                               (unsigned int)vmeUniverse0BaseAddr, vmeUniverse0PciIrqLine);
882+       }
883+       return rval;
884+ }
885+
886+ void
887+ vmeUniverseMasterPortsShow(FILE *f)
888+ {
889+       showUniversePorts(1,f);
890+ }
891+
892+ void
893+ vmeUniverseSlavePortsShow(FILE *f)
894+ {
895+       showUniversePorts(0,f);
896+ }
897+
898+ int
899+ vmeUniverseMasterPortCfg(
900+       unsigned long   port,
901+       unsigned long   address_space,
902+       unsigned long   vme_address,
903+       unsigned long   local_address,
904+       unsigned long   length)
905+ {
906+       return cfgUniversePort(1,port,address_space,vme_address,local_address,length);
907+ }
908+
909+ int
910+ vmeUniverseSlavePortCfg(
911+       unsigned long   port,
912+       unsigned long   address_space,
913+       unsigned long   vme_address,
914+       unsigned long   local_address,
915+       unsigned long   length)
916+ {
917+       return cfgUniversePort(0,port,address_space,vme_address,local_address,length);
918+ }
919+
920+ void
921+ vmeUniverseDisableAllSlaves(void)
922+ {
923+       mapOverAll(0,disableUniversePort,0);
924+ }
925+
926+ void
927+ vmeUniverseDisableAllMasters(void)
928+ {
929+       mapOverAll(1,disableUniversePort,0);
930+ }
931+
932+ int
933+ vmeUniverseStartDMA(
934+       unsigned long local_addr,
935+       unsigned long vme_addr,
936+       unsigned long count)
937+ {
938+
939+       if (!vmeUniverse0BaseAddr && vmeUniverseInit()) return -1;
940+       if ((local_addr & 7) != (vme_addr & 7)) {
941+               uprintf(stderr,"vmeUniverseStartDMA: misaligned addresses\n");
942+               return -1;
943+       }
944+
945+       {
946+       /* help the compiler allocate registers */
947+       register volatile LERegister *b=vmeUniverse0BaseAddr;
948+       register unsigned long dgcsoff=UNIV_REGOFF_DGCS,dgcs;
949+
950+       dgcs=READ_LE(b, dgcsoff);
951+
952+       /* clear status and make sure CHAIN is clear */
953+       dgcs &= ~UNIV_DGCS_CHAIN;
954+       WRITE_LE(dgcs,
955+                     b, dgcsoff);
956+       WRITE_LE(local_addr,
957+                     b, UNIV_REGOFF_DLA);
958+       WRITE_LE(vme_addr,
959+                     b, UNIV_REGOFF_DVA);
960+       WRITE_LE(count,
961+                     b, UNIV_REGOFF_DTBC);
962+       dgcs |= UNIV_DGCS_GO;
963+       EIEIO_REG; /* make sure GO is written after everything else */
964+       WRITE_LE(dgcs,
965+                     b, dgcsoff);
966+       }
967+       SYNC; /* enforce command completion */
968+       return 0;
969+ }
970+
971+ unsigned long
972+ vmeUniverseReadReg(unsigned long offset)
973+ {
974+ unsigned long rval;
975+       rval = READ_LE(vmeUniverse0BaseAddr,offset);
976+       return rval;
977+ }
978+
979+ void
980+ vmeUniverseWriteReg(unsigned long value, unsigned long offset)
981+ {
982+       WRITE_LE(value, vmeUniverse0BaseAddr, offset);
983+ }
984+
985+ void
986+ vmeUniverseCvtToLE(unsigned long *ptr, unsigned long num)
987+ {
988+ #if !defined(__LITTLE_ENDIAN__) || (__LITTLE_ENDIAN__ != 1)
989+ register unsigned long *p=ptr+num;
990+       while (p > ptr) {
991+ #if (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
992+               __asm__ __volatile__(
993+                       "lwzu 0, -4(%0)\n"
994+                       "stwbrx 0, 0, %0\n"
995+                       : "=r"(p) : "r"(p) : "r0"
996+                       );
997+ #elif defined(__rtems)
998+               p--; st_le32(p, *p);
999+ #else
1000+ #error        "vmeUniverse: endian conversion not implemented for this architecture"
1001+ #endif
1002+       }
1003+ #endif
1004+ }
1005+
1006+ /* RTEMS interrupt subsystem */
1007+
1008+ #ifdef __rtems
1009+ #include <bsp/irq.h>
1010+
1011+ typedef struct
1012+ UniverseIRQEntryRec_ {
1013+               VmeUniverseISR  isr;
1014+               void                    *usrData;
1015+ } UniverseIRQEntryRec, *UniverseIRQEntry;
1016+
1017+ static UniverseIRQEntry universeHdlTbl[257]={0};
1018+
1019+ static int mgrInstalled=0;
1020+ static int vmeIrqUnivOut=-1;
1021+ static int specialIrqUnivOut=-1;
1022+
1023+ VmeUniverseISR
1024+ vmeUniverseISRGet(unsigned long vector, void **parg)
1025+ {
1026+       if (vector>255) return 0;
1027+       if (parg)
1028+               *parg=universeHdlTbl[vector]->usrData;
1029+       return universeHdlTbl[vector]->isr;
1030+ }
1031+
1032+ static void
1033+ universeSpecialISR(void)
1034+ {
1035+ UniverseIRQEntry ip;
1036+       /* try the special handler */
1037+       if ((ip=universeHdlTbl[UNIV_SPECIAL_IRQ_VECTOR])) {
1038+               ip->isr(ip->usrData, UNIV_SPECIAL_IRQ_VECTOR);
1039+       }
1040+       /* clear all special interrupts */
1041+       vmeUniverseWriteReg(
1042+                                       ~((UNIV_LINT_STAT_VIRQ7<<1)-UNIV_LINT_STAT_VIRQ1),
1043+                                       UNIV_REGOFF_LINT_STAT
1044+                                       );
1045+
1046+ /*
1047+  *    clear our line in the VINT_STAT register
1048+  *  seems to be not neccessary...
1049+       vmeUniverseWriteReg(
1050+                                       UNIV_VINT_STAT_LINT(specialIrqUnivOut),
1051+                                       UNIV_REGOFF_VINT_STAT);
1052+  */
1053+ }
1054+
1055+ /*
1056+  * interrupts from VME to PCI seem to be processed more or less
1057+  * like this:
1058+  *
1059+  *
1060+  *   VME IRQ ------
1061+  *                  & ----- LINT_STAT ----
1062+  *                  |                       &  ---------- PCI LINE
1063+  *                  |                       |
1064+  *                  |                       |
1065+  *       LINT_EN ---------------------------
1066+  *
1067+  *  I.e.
1068+  *   - if LINT_EN is disabled, a VME IRQ will not set LINT_STAT.
1069+  *   - while LINT_STAT is set, it will pull the PCI line unless
1070+  *     masked by LINT_EN.
1071+  *   - VINT_STAT(lint_bit) seems to have no effect beyond giving
1072+  *     status info.
1073+  *
1074+  *  Hence, it is possible to
1075+  *    - arm (set LINT_EN, routing etc.)
1076+  *    - receive an irq (sets. LINT_STAT)
1077+  *    - the ISR then:
1078+  *              * clears LINT_EN, results in masking LINT_STAT (which
1079+  *                is still set to prevent another VME irq at the same
1080+  *                level to be ACKEd by the universe.
1081+  *              * do PCI_EOI to allow nesting of higher VME irqs.
1082+  *                (previous step also cleared LINT_EN of lower levels)
1083+  *              * when the handler returns, clear LINT_STAT
1084+  *              * re-enable setting LINT_EN.
1085+  */
1086+
1087+ static void
1088+ universeVMEISR(void)
1089+ {
1090+ UniverseIRQEntry ip;
1091+ unsigned long lvl,msk,lintstat,linten,status;
1092+
1093+               /* determine the highest priority IRQ source */
1094+               lintstat=vmeUniverseReadReg(UNIV_REGOFF_LINT_STAT);
1095+               for (msk=UNIV_LINT_STAT_VIRQ7, lvl=7;
1096+                        lvl>0;
1097+                        lvl--, msk>>=1) {
1098+                       if (lintstat & msk) break;
1099+               }
1100+               if (!lvl) {
1101+                               /* try the special handler */
1102+                               universeSpecialISR();
1103+
1104+                               /*
1105+                                * let the pic end this cycle
1106+                                */
1107+                               BSP_PIC_DO_EOI;
1108+
1109+                               return;
1110+               }
1111+               linten = vmeUniverseReadReg(UNIV_REGOFF_LINT_EN);
1112+
1113+               /* mask this and all lower levels */
1114+               vmeUniverseWriteReg(
1115+                                               linten & ~((msk<<1)-UNIV_LINT_STAT_VIRQ1),
1116+                                               UNIV_REGOFF_LINT_EN
1117+                                               );
1118+
1119+               /* end this interrupt
1120+                * cycle on the PCI bus, so higher level interrupts can be
1121+                * caught from now on...
1122+                */
1123+               BSP_PIC_DO_EOI;
1124+
1125+               /* get vector and dispatch handler */
1126+               status = vmeUniverseReadReg(UNIV_REGOFF_VIRQ1_STATID - 4 + (lvl<<2));
1127+               /* determine the highest priority IRQ source */
1128+
1129+               if (status & UNIV_VIRQ_ERR) {
1130+                               /* TODO: log error message - RTEMS has no logger :-( */
1131+               } else if (!(ip=universeHdlTbl[status & UNIV_VIRQ_STATID_MASK])) {
1132+                               /* TODO: log error message - RTEMS has no logger :-( */
1133+               } else {
1134+                               /* dispatch handler, it must clear the IRQ at the device */
1135+                               ip->isr(ip->usrData, status&UNIV_VIRQ_STATID_MASK);
1136+               }
1137+
1138+               /* clear this interrupt level */
1139+               vmeUniverseWriteReg(msk, UNIV_REGOFF_LINT_STAT);
1140+ /*
1141+  *  this seems not to be necessary; we just leave the
1142+  *  bit set to save a couple of instructions...
1143+               vmeUniverseWriteReg(
1144+                                       UNIV_VINT_STAT_LINT(vmeIrqUnivOut),
1145+                                       UNIV_REGOFF_VINT_STAT);
1146+ */
1147+
1148+
1149+               /* re-enable the previous level */
1150+               vmeUniverseWriteReg(linten, UNIV_REGOFF_LINT_EN);
1151+ }
1152+
1153+ /* STUPID API */
1154+ static void
1155+ my_no_op(const rtems_irq_connect_data * arg)
1156+ {}
1157+
1158+ static int
1159+ my_isOn(const rtems_irq_connect_data *arg)
1160+ {
1161+               return (int)vmeUniverseReadReg(UNIV_REGOFF_LINT_EN);
1162+ }
1163+
1164+ int
1165+ vmeUniverseInstallIrqMgr(int vmeOut, int specialOut, int specialIrqPicLine)
1166+ {
1167+ rtems_irq_connect_data aarrggh;
1168+
1169+       /* check parameters */
1170+       if ((vmeIrqUnivOut=vmeOut) < 0 || vmeIrqUnivOut > 7) return -1;
1171+       if ((specialIrqUnivOut=specialOut) > 7) return -2;
1172+       if (specialIrqPicLine < 0) return -3;
1173+
1174+       if (mgrInstalled) return -4;
1175+
1176+       aarrggh.on=my_no_op; /* at _least_ they could check for a 0 pointer */
1177+       aarrggh.off=my_no_op;
1178+       aarrggh.isOn=my_isOn;
1179+       aarrggh.hdl=universeVMEISR;
1180+       aarrggh.name=vmeUniverse0PciIrqLine + BSP_PCI_IRQ0;
1181+       if (!BSP_install_rtems_irq_handler(&aarrggh))
1182+                       BSP_panic("unable to install vmeUniverse irq handler");
1183+       if (specialIrqUnivOut > 0) {
1184+                       /* install the special handler to a separate irq */
1185+                       aarrggh.hdl=universeSpecialISR;
1186+                       aarrggh.name=specialIrqPicLine + BSP_PCI_IRQ0;
1187+                       if (!BSP_install_rtems_irq_handler(&aarrggh))
1188+                               BSP_panic("unable to install vmeUniverse secondary irq handler");
1189+       } else {
1190+               specialIrqUnivOut = vmeIrqUnivOut;
1191+       }
1192+       /* setup routing */
1193+
1194+       vmeUniverseWriteReg(
1195+               (UNIV_LINT_MAP0_VIRQ7(vmeIrqUnivOut) |
1196+                UNIV_LINT_MAP0_VIRQ6(vmeIrqUnivOut) |
1197+                UNIV_LINT_MAP0_VIRQ5(vmeIrqUnivOut) |
1198+                UNIV_LINT_MAP0_VIRQ4(vmeIrqUnivOut) |
1199+                UNIV_LINT_MAP0_VIRQ3(vmeIrqUnivOut) |
1200+                UNIV_LINT_MAP0_VIRQ2(vmeIrqUnivOut) |
1201+                UNIV_LINT_MAP0_VIRQ1(vmeIrqUnivOut) |
1202+                UNIV_LINT_MAP0_VOWN(specialIrqUnivOut)
1203+               ),
1204+               UNIV_REGOFF_LINT_MAP0);
1205+       vmeUniverseWriteReg(
1206+               (UNIV_LINT_MAP1_ACFAIL(specialIrqUnivOut) |
1207+                UNIV_LINT_MAP1_SYSFAIL(specialIrqUnivOut) |
1208+                UNIV_LINT_MAP1_SW_INT(specialIrqUnivOut) |
1209+                UNIV_LINT_MAP1_SW_IACK(specialIrqUnivOut) |
1210+                UNIV_LINT_MAP1_VERR(specialIrqUnivOut) |
1211+                UNIV_LINT_MAP1_LERR(specialIrqUnivOut) |
1212+                UNIV_LINT_MAP1_DMA(specialIrqUnivOut)
1213+               ),
1214+               UNIV_REGOFF_LINT_MAP1);
1215+       mgrInstalled=1;
1216+       return 0;
1217+ }
1218+
1219+
1220+ int
1221+ vmeUniverseInstallISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
1222+ {
1223+ UniverseIRQEntry ip;
1224+
1225+               if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !mgrInstalled)
1226+                               return -1;
1227+
1228+               ip=universeHdlTbl[vector];
1229+
1230+               if (ip || !(ip=(UniverseIRQEntry)malloc(sizeof(UniverseIRQEntryRec))))
1231+                               return -1;
1232+               ip->isr=hdl;
1233+               ip->usrData=arg;
1234+               universeHdlTbl[vector]=ip;
1235+               return 0;
1236+ }
1237+
1238+ int
1239+ vmeUniverseRemoveISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
1240+ {
1241+ UniverseIRQEntry ip;
1242+
1243+               if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !mgrInstalled)
1244+                               return -1;
1245+
1246+               ip=universeHdlTbl[vector];
1247+
1248+               if (!ip || ip->isr!=hdl || ip->usrData!=arg)
1249+                               return -1;
1250+               universeHdlTbl[vector]=0;
1251+               free(ip);
1252+               return 0;
1253+ }
1254+
1255+ int
1256+ vmeUniverseIntEnable(unsigned int level)
1257+ {
1258+               if (!mgrInstalled || level<1 || level>7)
1259+                               return -1;
1260+               vmeUniverseWriteReg(
1261+                               (vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) |
1262+                                (UNIV_LINT_EN_VIRQ1 << (level-1))
1263+                               ),
1264+                               UNIV_REGOFF_LINT_EN);
1265+               return 0;
1266+ }
1267+
1268+ int
1269+ vmeUniverseIntDisable(unsigned int level)
1270+ {
1271+               if (!mgrInstalled || level<1 || level>7)
1272+                               return -1;
1273+               vmeUniverseWriteReg(
1274+                               (vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) &
1275+                                ~ (UNIV_LINT_EN_VIRQ1 << (level-1))
1276+                               ),
1277+                               UNIV_REGOFF_LINT_EN);
1278+               return 0;
1279+ }
1280+
1281+
1282+ #endif
1283Index: c/src/lib/libbsp/shared/vmeUniverse/vmeUniverse.h
1284===================================================================
1285RCS file: vmeUniverse.h
1286diff -N vmeUniverse.h
1287*** /dev/null   Thu Aug 24 02:00:32 2000
1288--- /tmp/cvsuU8MD9      Sun May  5 11:22:28 2002
1289***************
1290*** 0 ****
1291--- 1,662 ----
1292+ /* $Id: vmeUniverse.h,v 1.15 2002/03/09 00:14:39 till Exp $ */
1293+ #ifndef VME_UNIVERSE_UTIL_H
1294+ #define VME_UNIVERSE_UTIL_H
1295+
1296+ /* Routines to configure and use the Tundra Universe VME bridge
1297+  * Author: Till Straumann <strauman@slac.stanford.edu>
1298+  *         Nov 2000, July 2001
1299+  */
1300+
1301+ /* Register definitions */
1302+ /* NOTE: all registers contents in PCI space are LITTLE ENDIAN */
1303+
1304+ #ifdef __vxworks
1305+ #include <vme.h>
1306+ #else
1307+ /* vxworks compatible addressing modes */
1308+ #define       VME_AM_STD_SUP_PGM      0x3e
1309+ #define       VME_AM_STD_USR_PGM      0x3a
1310+ #define       VME_AM_STD_SUP_DATA     0x3d
1311+ #define       VME_AM_STD_USR_DATA     0x39
1312+ #define       VME_AM_EXT_SUP_PGM      0x0e
1313+ #define       VME_AM_EXT_USR_PGM      0x0a
1314+ #define       VME_AM_EXT_SUP_DATA     0x0d
1315+ #define       VME_AM_EXT_USR_DATA     0x09
1316+ #define       VME_AM_SUP_SHORT_IO     0x2d
1317+ #define       VME_AM_USR_SHORT_IO     0x29
1318+ #endif
1319+
1320+ typedef unsigned long LERegister; /* emphasize contents are little endian */
1321+
1322+ /* NOTE: DMA packet descriptors MUST be 32 byte aligned */
1323+ typedef struct VmeUniverseDMAPacketRec_ {
1324+       LERegister      dctl __attribute__((aligned(32)));
1325+       LERegister      dtbc;
1326+       LERegister      dla;
1327+       LERegister      dummy1;
1328+       LERegister      dva;
1329+       LERegister      dummy2;
1330+       LERegister      dccp;
1331+       LERegister      dummy3;
1332+ } VmeUniverseDMAPacketRec, *VmeUniverseDMAPacket;
1333+
1334+ /* PCI CSR register */
1335+ #define               UNIV_REGOFF_PCI_CSR             0x4
1336+ # define      UNIV_PCI_CSR_D_PE               (1<<31) /* detected parity error; write 1 to clear */
1337+ # define      UNIV_PCI_CSR_S_SERR             (1<<30) /* SERR (signalled error) asserted; write 1 to clear */
1338+ # define      UNIV_PCI_CSR_R_MA               (1<<29) /* received master abort; write 1 to clear */
1339+ # define      UNIV_PCI_CSR_R_TA               (1<<28) /* received target abort; write 1 to clear */
1340+ # define      UNIV_PCI_CSR_S_TA               (1<<27) /* signalled target abort; write 1 to clear */
1341+ # define      UNIV_PCI_CSR_DEVSEL_MASK (3<<25)        /* device select timing (RO) */
1342+ # define      UNIV_PCI_CSR_DP_D               (1<<24) /* data parity error detected; write 1 to clear */
1343+ # define      UNIV_PCI_CSR_TFBBC              (1<<23) /* target fast back to back capable (RO) */
1344+ # define      UNIV_PCI_CSR_MFBBC              (1<<9)  /* master fast back to back capable (RO) */
1345+ # define      UNIV_PCI_CSR_SERR_EN    (1<<8)  /* enable SERR driver */
1346+ # define      UNIV_PCI_CSR_WAIT               (1<<7)  /* wait cycle control (RO) */
1347+ # define      UNIV_PCI_CSR_PERESP             (1<<6)  /* parity error response enable */
1348+ # define      UNIV_PCI_CSR_VGAPS              (1<<5)  /* VGA palette snoop (RO) */
1349+ # define      UNIV_PCI_CSR_MWI_EN             (1<<4)  /* Memory write and invalidate enable (RO) */
1350+ # define      UNIV_PCI_CSR_SC                 (1<<3)  /* special cycles (RO) */
1351+ # define      UNIV_PCI_CSR_BM                 (1<<2)  /* master enable (MUST SET TO ENABLE VME SLAVES) */
1352+ # define      UNIV_PCI_CSR_MS                 (1<<1)  /* target memory enable */
1353+ # define      UNIV_PCI_CSR_IOS                (1<<0)  /* target IO enable */
1354+
1355+ /* Special cycle (ADOH, RMW) control register */
1356+ #define               UNIV_REGOFF_SCYC_CTL    0x170   /* write 0 to disable */
1357+ # define      UNIV_SCYC_CTL_LAS_IO    (1<<2)  /* PCI address space (1: IO, 0: mem) */
1358+ # define      UNIV_SCYC_CTL_SCYC_RMW  (1<<0)  /* do a RMW cycle when reading  PCI address */
1359+ # define      UNIV_SCYC_CTL_SCYC_ADOH (2<<0)  /* do a ADOH cycle when reading/writing  PCI address */
1360+
1361+ /* Special cycle address register */
1362+ #define               UNIV_REGOFF_SCYC_ADDR   0x174   /* PCI address (must be long word aligned) */
1363+
1364+ /* Special cycle Swap/Compare/Enable */
1365+ #define               UNIV_REGOFF_SCYC_EN     0x178   /* mask determining the bits involved in the compare and swap operations for VME RMW cycles */
1366+
1367+ /* Special cycle compare data register */
1368+ #define               UNIV_REGOFF_SCYC_CMP    0x17c   /* data to compare with word returned from VME RMW read */
1369+
1370+ /* Special cycle swap data register */
1371+ #define               UNIV_REGOFF_SCYC_SWP    0x180   /* If enabled bits of CMP match, corresponding SWP bits are written back to VME (under control of EN) */
1372+
1373+ /* PCI miscellaneous register */
1374+ #define               UNIV_REGOFF_LMISC       0x184
1375+ # define      UNIV_LMISC_CRT_MASK     (7<<28) /* Univ. I only, not used on II */
1376+ # define      UNIV_LMISC_CRT_INF      (0<<28) /* Coupled Request Timeout */
1377+ # define      UNIV_LMISC_CRT_128_US   (1<<28) /* Coupled Request Timeout */
1378+ # define      UNIV_LMISC_CRT_256_US   (2<<28) /* Coupled Request Timeout */
1379+ # define      UNIV_LMISC_CRT_512_US   (3<<28) /* Coupled Request Timeout */
1380+ # define      UNIV_LMISC_CRT_1024_US  (4<<28) /* Coupled Request Timeout */
1381+ # define      UNIV_LMISC_CRT_2048_US  (5<<28) /* Coupled Request Timeout */
1382+ # define      UNIV_LMISC_CRT_4096_US  (6<<28) /* Coupled Request Timeout */
1383+
1384+ # define      UNIV_LMISC_CWT_MASK     (7<<24) /* coupled window timer */
1385+ # define      UNIV_LMISC_CWT_DISABLE  0       /* disabled (release VME after 1 coupled xaction) */
1386+ # define      UNIV_LMISC_CWT_16       (1<<24) /* 16 PCI clock cycles */
1387+ # define      UNIV_LMISC_CWT_32       (2<<24) /* 32 PCI clock cycles */
1388+ # define      UNIV_LMISC_CWT_64       (3<<24) /* 64 PCI clock cycles */
1389+ # define      UNIV_LMISC_CWT_128      (4<<24) /* 128 PCI clock cycles */
1390+ # define      UNIV_LMISC_CWT_256      (5<<24) /* 256 PCI clock cycles */
1391+ # define      UNIV_LMISC_CWT_512      (6<<24) /* 512 PCI clock cycles */
1392+
1393+ /* PCI Command Error Log Register */
1394+ #define               UNIV_REGOFF_L_CMDERR    0x18c
1395+ # define      UNIV_L_CMDERR_CMDERR(reg) (((reg)>>28)&0xf) /* extract PCI cmd error log */
1396+ # define      UNIV_L_CMDERR_M_ERR     (1<<27) /* multiple errors have occurred */
1397+ # define      UNIV_L_CMDERR_L_STAT    (1<<23) /* PCI error log status valid (write 1 to clear and enable logging) */
1398+
1399+ /* PCI Address Error Log */
1400+ #define               UNIV_REGOFF_LAERR       0x190   /* PCI fault address (if L_CMDERR_L_STAT valid) */
1401+ /* DMA Xfer Control Register */
1402+ #define               UNIV_REGOFF_DCTL        0x200
1403+ # define      UNIV_DCTL_L2V           (1<<31) /* PCI->VME if set */
1404+ # define      UNIV_DCTL_VDW_MSK       (3<<22) /* VME max. width mask 0x00c00000 */
1405+ # define      UNIV_DCTL_VDW_8         (0<<22) /* VME max. width 8 */
1406+ # define      UNIV_DCTL_VDW_16        (1<<22) /* VME max. width 16 */
1407+ # define      UNIV_DCTL_VDW_32        (2<<22) /* VME max. width 32 */
1408+ # define      UNIV_DCTL_VDW_64        (3<<22) /* VME max. width 64 */
1409+ # define      UNIV_DCTL_VAS_MSK       (7<<16) /* VME AS mask 0x00070000 */
1410+ # define      UNIV_DCTL_VAS_A16       (0<<16) /* VME A16 */
1411+ # define      UNIV_DCTL_VAS_A24       (1<<16) /* VME A24 */
1412+ # define      UNIV_DCTL_VAS_A32       (2<<16) /* VME A32 */
1413+ # define      UNIV_DCTL_PGM_MSK       (3<<14) /* VME PGM/DATA mask 0x0000c000 */
1414+ # define      UNIV_DCTL_PGM           (1<<14) /* VME PGM(1)/DATA(0) */
1415+ # define      UNIV_DCTL_SUPER_MSK     (3<<12) /* VME SUPER/USR mask 0x00003000 */
1416+ # define      UNIV_DCTL_SUPER         (1<<12) /* VME SUPER(1)/USR(0) */
1417+ # define      UNIV_DCTL_VCT           (1<<8)  /* VME enable BLT */
1418+ # define      UNIV_DCTL_LD64EN        (1<<7)  /* PCI 64 enable  */
1419+
1420+ /* DMA Xfer byte count register (is updated by DMA) */
1421+ #define               UNIV_REGOFF_DTBC        0x204
1422+ /* DMA Xfer local (PCI) address (direction is  set in DCTL) */
1423+ #define               UNIV_REGOFF_DLA         0x208
1424+ /* DMA Xfer VME address (direction is  set in DCTL)
1425+  * NOTE: (*UNIV_DVA) & ~7 == (*UNIV_DLA) & ~7 MUST HOLD
1426+  */
1427+ #define               UNIV_REGOFF_DVA         0x210
1428+
1429+ /* DMA Xfer VME command packet pointer
1430+  * NOTE: The address stored here MUST be 32-byte aligned
1431+  */
1432+ #define               UNIV_REGOFF_DCPP        0x218
1433+ /* these bits are only used in linked lists */
1434+ # define      UNIV_DCCP_IMG_NULL      (1<<0)  /* last packet in list */
1435+ # define      UNIV_DCCP_IMG_PROCESSED (1<<1)  /* packet processed */
1436+
1437+ /* DMA Xfer General Control/Status register */
1438+ #define               UNIV_REGOFF_DGCS        0x220
1439+ # define      UNIV_DGCS_GO            (1<<31) /* start xfer */
1440+ # define      UNIV_DGCS_STOP_REQ      (1<<30) /* stop xfer (immediate abort) */
1441+ # define      UNIV_DGCS_HALT_REQ      (1<<29) /* halt xfer (abort after current packet) */
1442+ # define      UNIV_DGCS_CHAIN         (1<<27) /* enable linked list mode */
1443+ # define      UNIV_DGCS_VON_MSK       (7<<20) /* VON mask */
1444+ # define      UNIV_DGCS_VON_DONE      (0<<20) /* VON counter disabled (do until done) */
1445+ # define      UNIV_DGCS_VON_256       (1<<20) /* VON yield bus after 256 bytes */
1446+ # define      UNIV_DGCS_VON_512       (2<<20) /* VON yield bus after 512 bytes */
1447+ # define      UNIV_DGCS_VON_1024      (3<<20) /* VON yield bus after 512 bytes */
1448+ # define      UNIV_DGCS_VON_2048      (4<<20) /* VON yield bus after 1024 bytes */
1449+ # define      UNIV_DGCS_VON_4096      (5<<20) /* VON yield bus after 4096 bytes */
1450+ # define      UNIV_DGCS_VON_8192      (6<<20) /* VON yield bus after 8192 bytes */
1451+ # define      UNIV_DGCS_VOFF_MSK      (15<<16) /* VOFF mask */
1452+ # define      UNIV_DGCS_VOFF_0_US     (0<<16) /* re-request VME master after 0 us */
1453+ # define      UNIV_DGCS_VOFF_2_US     (8<<16) /* re-request VME master after 2 us */
1454+ # define      UNIV_DGCS_VOFF_4_US     (9<<16) /* re-request VME master after 4 us */
1455+ # define      UNIV_DGCS_VOFF_8_US     (10<<16)/* re-request VME master after 8 us */
1456+ # define      UNIV_DGCS_VOFF_16_US    (1<<16) /* re-request VME master after 16 us */
1457+ # define      UNIV_DGCS_VOFF_32_US    (2<<16) /* re-request VME master after 32 us */
1458+ # define      UNIV_DGCS_VOFF_64_US    (3<<16) /* re-request VME master after 64 us */
1459+ # define      UNIV_DGCS_VOFF_128_US   (4<<16) /* re-request VME master after 128 us */
1460+ # define      UNIV_DGCS_VOFF_256_US   (5<<16) /* re-request VME master after 256 us */
1461+ # define      UNIV_DGCS_VOFF_512_US   (6<<16) /* re-request VME master after 512 us */
1462+ # define      UNIV_DGCS_VOFF_1024_US  (7<<16) /* re-request VME master after 1024 us */
1463+ /* Status Bits (write 1 to clear) */
1464+ # define      UNIV_DGCS_ACT           (1<<15) /* DMA active */
1465+ # define      UNIV_DGCS_STOP          (1<<14) /* DMA stopped */
1466+ # define      UNIV_DGCS_HALT          (1<<13) /* DMA halted */
1467+ # define      UNIV_DGCS_DONE          (1<<11) /* DMA done (OK) */
1468+ # define      UNIV_DGCS_LERR          (1<<10) /* PCI bus error */
1469+ # define      UNIV_DGCS_VERR          (1<<9)  /* VME bus error */
1470+ # define      UNIV_DGCS_P_ERR         (1<<8)  /* programming protocol error (e.g. PCI master disabled) */
1471+ # define      UNIV_DGCS_STATUS_CLEAR\
1472+       (UNIV_DGCS_ACT|UNIV_DGCS_STOP|UNIV_DGCS_HALT|\
1473+        UNIV_DGCS_DONE|UNIV_DGCS_LERR|UNIV_DGCS_VERR|UNIV_DGCS_P_ERR)
1474+ # define      UNIV_DGCS_P_ERR         (1<<8)  /* programming protocol error (e.g. PCI master disabled) */
1475+ /* Interrupt Mask Bits */
1476+ # define      UNIV_DGCS_INT_STOP      (1<<6)  /* interrupt when stopped */
1477+ # define      UNIV_DGCS_INT_HALT      (1<<5)  /* interrupt when halted */
1478+ # define      UNIV_DGCS_INT_DONE      (1<<3)  /* interrupt when done */
1479+ # define      UNIV_DGCS_INT_LERR      (1<<2)  /* interrupt on LERR */
1480+ # define      UNIV_DGCS_INT_VERR      (1<<1)  /* interrupt on VERR */
1481+ # define      UNIV_DGCS_INT_P_ERR     (1<<0)  /* interrupt on P_ERR */
1482+ # define      UNIV_DGCS_INT_MSK       (0x0000006f) /* interrupt mask */
1483+
1484+ /* DMA Linked List Update Enable Register */
1485+ #define               UNIV_REGOFF_D_LLUE      0x224
1486+ # define      UNIV_D_LLUE_UPDATE      (1<<31)
1487+
1488+
1489+ /* PCI (local) interrupt enable register */
1490+ #define               UNIV_REGOFF_LINT_EN     0x300
1491+ # define      UNIV_LINT_EN_LM3        (1<<23) /* location monitor 3 mask */
1492+ # define      UNIV_LINT_EN_LM2        (1<<22) /* location monitor 2 mask */
1493+ # define      UNIV_LINT_EN_LM1        (1<<21) /* location monitor 1 mask */
1494+ # define      UNIV_LINT_EN_LM0        (1<<20) /* location monitor 0 mask */
1495+ # define      UNIV_LINT_EN_MBOX3      (1<<19) /* mailbox 3 mask */
1496+ # define      UNIV_LINT_EN_MBOX2      (1<<18) /* mailbox 2 mask */
1497+ # define      UNIV_LINT_EN_MBOX1      (1<<17) /* mailbox 1 mask */
1498+ # define      UNIV_LINT_EN_MBOX0      (1<<16) /* mailbox 0 mask */
1499+ # define      UNIV_LINT_EN_ACFAIL     (1<<15) /* ACFAIL irq mask */
1500+ # define      UNIV_LINT_EN_SYSFAIL    (1<<14) /* SYSFAIL irq mask */
1501+ # define      UNIV_LINT_EN_SW_INT     (1<<13) /* PCI (local) software irq */
1502+ # define      UNIV_LINT_EN_SW_IACK    (1<<12) /* VME software IACK mask */
1503+ # define      UNIV_LINT_EN_VERR       (1<<10) /* PCI VERR irq mask */
1504+ # define      UNIV_LINT_EN_LERR       (1<<9)  /* PCI LERR irq mask */
1505+ # define      UNIV_LINT_EN_DMA        (1<<8)  /* PCI DMA irq mask */
1506+ # define      UNIV_LINT_EN_VIRQ7      (1<<7)  /* VIRQ7 mask (universe does IACK automatically) */
1507+ # define      UNIV_LINT_EN_VIRQ6      (1<<6)  /* VIRQ6 mask */
1508+ # define      UNIV_LINT_EN_VIRQ5      (1<<5)  /* VIRQ5 mask */
1509+ # define      UNIV_LINT_EN_VIRQ4      (1<<4)  /* VIRQ4 mask */
1510+ # define      UNIV_LINT_EN_VIRQ3      (1<<3)  /* VIRQ3 mask */
1511+ # define      UNIV_LINT_EN_VIRQ2      (1<<2)  /* VIRQ2 mask */
1512+ # define      UNIV_LINT_EN_VIRQ1      (1<<1)  /* VIRQ1 mask */
1513+ # define      UNIV_LINT_EN_VOWN       (1<<0)  /* VOWN mask */
1514+
1515+ /* PCI (local) interrupt status register */
1516+ #define               UNIV_REGOFF_LINT_STAT   0x304
1517+ # define      UNIV_LINT_STAT_LM3      (1<<23) /* location monitor 3 status */
1518+ # define      UNIV_LINT_STAT_LM2      (1<<22) /* location monitor 2 status */
1519+ # define      UNIV_LINT_STAT_LM1      (1<<21) /* location monitor 1 status */
1520+ # define      UNIV_LINT_STAT_LM0      (1<<20) /* location monitor 0 status */
1521+ # define      UNIV_LINT_STAT_MBOX3    (1<<19) /* mailbox 3 status */
1522+ # define      UNIV_LINT_STAT_MBOX2    (1<<18) /* mailbox 2 status */
1523+ # define      UNIV_LINT_STAT_MBOX1    (1<<17) /* mailbox 1 status */
1524+ # define      UNIV_LINT_STAT_MBOX0    (1<<16) /* mailbox 0 status */
1525+ # define      UNIV_LINT_STAT_ACFAIL   (1<<15) /* ACFAIL irq status */
1526+ # define      UNIV_LINT_STAT_SYSFAIL  (1<<14) /* SYSFAIL irq status */
1527+ # define      UNIV_LINT_STAT_SW_INT   (1<<13) /* PCI (local) software irq */
1528+ # define      UNIV_LINT_STAT_SW_IACK  (1<<12) /* VME software IACK status */
1529+ # define      UNIV_LINT_STAT_VERR             (1<<10) /* PCI VERR irq status */
1530+ # define      UNIV_LINT_STAT_LERR             (1<<9)  /* PCI LERR irq status */
1531+ # define      UNIV_LINT_STAT_DMA              (1<<8)  /* PCI DMA irq status */
1532+ # define      UNIV_LINT_STAT_VIRQ7    (1<<7)  /* VIRQ7 status */
1533+ # define      UNIV_LINT_STAT_VIRQ6    (1<<6)  /* VIRQ6 status */
1534+ # define      UNIV_LINT_STAT_VIRQ5    (1<<5)  /* VIRQ5 status */
1535+ # define      UNIV_LINT_STAT_VIRQ4    (1<<4)  /* VIRQ4 status */
1536+ # define      UNIV_LINT_STAT_VIRQ3    (1<<3)  /* VIRQ3 status */
1537+ # define      UNIV_LINT_STAT_VIRQ2    (1<<2)  /* VIRQ2 status */
1538+ # define      UNIV_LINT_STAT_VIRQ1    (1<<1)  /* VIRQ1 status */
1539+ # define      UNIV_LINT_STAT_VOWN             (1<<0)  /* VOWN status */
1540+ # define      UNIV_LINT_STAT_CLR              (0xfff7ff)/* Clear all status bits */
1541+
1542+ /* PCI (local) interrupt map 0 register */
1543+ #define               UNIV_REGOFF_LINT_MAP0   0x308   /* mapping of VME IRQ sources to PCI irqs */
1544+ # define      UNIV_LINT_MAP0_VIRQ7(lint)      (((lint)&0x7)<<(7*4))
1545+ # define      UNIV_LINT_MAP0_VIRQ6(lint)      (((lint)&0x7)<<(6*4))
1546+ # define      UNIV_LINT_MAP0_VIRQ5(lint)      (((lint)&0x7)<<(5*4))
1547+ # define      UNIV_LINT_MAP0_VIRQ4(lint)      (((lint)&0x7)<<(4*4))
1548+ # define      UNIV_LINT_MAP0_VIRQ3(lint)      (((lint)&0x7)<<(3*4))
1549+ # define      UNIV_LINT_MAP0_VIRQ2(lint)      (((lint)&0x7)<<(2*4))
1550+ # define      UNIV_LINT_MAP0_VIRQ1(lint)      (((lint)&0x7)<<(1*4))
1551+ # define      UNIV_LINT_MAP0_VOWN(lint)       (((lint)&0x7)<<(0*4))
1552+
1553+ #define               UNIV_REGOFF_LINT_MAP1   0x30c   /* mapping of internal / VME IRQ sources to PCI irqs */
1554+ # define      UNIV_LINT_MAP1_ACFAIL(lint)     (((lint)&0x7)<<(7*4))
1555+ # define      UNIV_LINT_MAP1_SYSFAIL(lint)    (((lint)&0x7)<<(6*4))
1556+ # define      UNIV_LINT_MAP1_SW_INT(lint)     (((lint)&0x7)<<(5*4))
1557+ # define      UNIV_LINT_MAP1_SW_IACK(lint)    (((lint)&0x7)<<(4*4))
1558+ # define      UNIV_LINT_MAP1_VERR(lint)       (((lint)&0x7)<<(2*4))
1559+ # define      UNIV_LINT_MAP1_LERR(lint)       (((lint)&0x7)<<(1*4))
1560+ # define      UNIV_LINT_MAP1_DMA(lint)        (((lint)&0x7)<<(0*4))
1561+
1562+ /* enabling of generation of VME bus IRQs, TODO */
1563+ #define               UNIV_REGOFF_VINT_EN             0x310
1564+ # define      UNIV_VINT_EN_DISABLE_ALL    0
1565+
1566+ /* status of generation of VME bus IRQs, TODO */
1567+ #define               UNIV_REGOFF_VINT_STAT   0x314
1568+ # define      UNIV_VINT_STAT_LINT(lint)       (1<<((lint)&7))
1569+ # define      UNIV_VINT_STAT_LINT_MASK        (0xff)
1570+ # define      UNIV_VINT_STAT_CLR                      (0xfe0f17ff)
1571+ #define               UNIV_REGOFF_VINT_MAP0   0x318   /* VME destination of PCI IRQ source, TODO */
1572+ #define               UNIV_REGOFF_VINT_MAP1   0x31c   /* VME destination of PCI IRQ source, TODO */
1573+ #define               UNIV_REGOFF_VINT_STATID 0x320   /* our status/id response to IACK, TODO */
1574+
1575+ #define               UNIV_REGOFF_VIRQ1_STATID 0x324  /* status/id of VME IRQ level 1 */
1576+ #define               UNIV_REGOFF_VIRQ2_STATID 0x328  /* status/id of VME IRQ level 2 */
1577+ #define               UNIV_REGOFF_VIRQ3_STATID 0x32c  /* status/id of VME IRQ level 3 */
1578+ #define               UNIV_REGOFF_VIRQ4_STATID 0x330  /* status/id of VME IRQ level 4 */
1579+ #define               UNIV_REGOFF_VIRQ5_STATID 0x334  /* status/id of VME IRQ level 5 */
1580+ #define               UNIV_REGOFF_VIRQ6_STATID 0x338  /* status/id of VME IRQ level 6 */
1581+ #define               UNIV_REGOFF_VIRQ7_STATID 0x33c  /* status/id of VME IRQ level 7 */
1582+ # define      UNIV_VIRQ_ERR                   (1<<8)  /* set if universe encountered a bus error when doing IACK */
1583+ # define      UNIV_VIRQ_STATID_MASK           (0xff)
1584+
1585+ #define               UNIV_REGOFF_LINT_MAP2   0x340   /* mapping of internal sources to PCI irqs */
1586+ # define      UNIV_LINT_MAP2_LM3(lint)        (((lint)&0x7)<<7*4)     /* location monitor 3 */
1587+ # define      UNIV_LINT_MAP2_LM2(lint)        (((lint)&0x7)<<6*4)     /* location monitor 2 */
1588+ # define      UNIV_LINT_MAP2_LM1(lint)        (((lint)&0x7)<<5*4)     /* location monitor 1 */
1589+ # define      UNIV_LINT_MAP2_LM0(lint)        (((lint)&0x7)<<4*4)     /* location monitor 0 */
1590+ # define      UNIV_LINT_MAP2_MBOX3(lint)      (((lint)&0x7)<<3*4)     /* mailbox 3 */
1591+ # define      UNIV_LINT_MAP2_MBOX2(lint)      (((lint)&0x7)<<2*4)     /* mailbox 2 */
1592+ # define      UNIV_LINT_MAP2_MBOX1(lint)      (((lint)&0x7)<<1*4)     /* mailbox 1 */
1593+ # define      UNIV_LINT_MAP2_MBOX0(lint)      (((lint)&0x7)<<0*4)     /* mailbox 0 */
1594+
1595+ #define               UNIV_REGOFF_VINT_MAP2   0x344   /* mapping of internal sources to VME irqs */
1596+ # define      UNIV_VINT_MAP2_MBOX3(vint)      (((vint)&0x7)<<3*4)     /* mailbox 3 */
1597+ # define      UNIV_VINT_MAP2_MBOX2(vint)      (((vint)&0x7)<<2*4)     /* mailbox 2 */
1598+ # define      UNIV_VINT_MAP2_MBOX1(vint)      (((vint)&0x7)<<1*4)     /* mailbox 1 */
1599+ # define      UNIV_VINT_MAP2_MBOX0(vint)      (((vint)&0x7)<<0*4)     /* mailbox 0 */
1600+
1601+ #define               UNIV_REGOFF_MBOX0       0x348   /* mailbox 0 */
1602+ #define               UNIV_REGOFF_MBOX1       0x34c   /* mailbox 1 */
1603+ #define               UNIV_REGOFF_MBOX2       0x350   /* mailbox 2 */
1604+ #define               UNIV_REGOFF_MBOX3       0x354   /* mailbox 3 */
1605+
1606+ #define               UNIV_REGOFF_SEMA0       0x358   /* semaphore 0 */
1607+ #define               UNIV_REGOFF_SEMA1       0x35c   /* semaphore 0 */
1608+ /* TODO define semaphore register bits */
1609+
1610+ #define               UNIV_REGOFF_MAST_CTL    0x400   /* master control register */
1611+ # define      UNIV_MAST_CTL_MAXRTRY(val)      (((val)&0xf)<<7*4)      /* max # of pci master retries */
1612+ # define      UNIV_MAST_CTL_PWON(val)         (((val)&0xf)<<6*4)      /* posted write xfer count */
1613+ # define      UNIV_MAST_CTL_VRL(val)          (((val)&0x3)<<22)       /* VME bus request level */
1614+ # define      UNIV_MAST_CTL_VRM                       (1<<21) /* bus request mode (demand = 0, fair = 1) */
1615+ # define      UNIV_MAST_CTL_VREL                      (1<<20) /* bus release mode (when done = 0, on request = 1) */
1616+ # define      UNIV_MAST_CTL_VOWN                      (1<<19) /* bus ownership (release = 0, acquire/hold = 1) */
1617+ # define      UNIV_MAST_CTL_VOWN_ACK          (1<<18) /* bus ownership (not owned = 0, acquired/held = 1) */
1618+ # define      UNIV_MAST_CTL_PABS(val)         (((val)&0x3)<<3*4)      /* PCI aligned burst size (32,64,128 byte / 0x3 is reserved) */
1619+ # define      UNIV_MAST_CTL_BUS_NO(val)       (((val)&0xff)<<0*4)     /* PCI bus number */
1620+
1621+ #define               UNIV_REGOFF_MISC_CTL    0x404   /* misc control register */
1622+ # define      UNIV_MISC_CTL_VBTO(val)         (((val)&0x7)<<7*4)      /* VME bus timeout (0=disable, 16*2^(val-1) us) */
1623+ # define      UNIV_MISC_CTL_VARB                      (1<<26) /* VME bus arbitration mode (0=round robin, 1= priority) */
1624+ # define      UNIV_MISC_CTL_VARBTO(val)       (((val)&0x3)<<6*4)      /* arbitration time out: disable, 16us, 256us, reserved */
1625+ # define      UNIV_MISC_CTL_SW_LRST           (1<<23) /* software PCI reset */
1626+ # define      UNIV_MISC_CTL_SW_SYSRST         (1<<22) /* software VME reset */
1627+ # define      UNIV_MISC_CTL_BI                        (1<<20) /* BI mode */
1628+ # define      UNIV_MISC_CTL_ENGBI                     (1<<19) /* enable global BI mode initiator */
1629+ # define      UNIV_MISC_CTL_SYSCON            (1<<17) /* (R/W) 1:universe is system controller */
1630+ # define      UNIV_MISC_CTL_V64AUTO           (1<<16) /* (R/W) 1:initiate VME64 auto id slave participation */
1631+
1632+ /* Location Monitor control register */
1633+ #define               UNIV_REGOFF_LM_CTL              0xf64
1634+ # define      UNIV_LM_CTL_EN                          (1<<31) /* image enable */
1635+ # define      UNIV_LM_CTL_PGM                         (1<<23) /* program AM */
1636+ # define      UNIV_LM_CTL_DATA                        (1<<22) /* data AM */
1637+ # define      UNIV_LM_CTL_SUPER                       (1<<21) /* supervisor AM */
1638+ # define      UNIV_LM_CTL_USER                        (1<<20) /* user AM */
1639+ # define      UNIV_LM_CTL_VAS_A16                     (0<<16) /* A16 */
1640+ # define      UNIV_LM_CTL_VAS_A24                     (1<<16) /* A16 */
1641+ # define      UNIV_LM_CTL_VAS_A32                     (2<<16) /* A16 */
1642+
1643+ /* Location Monitor base address */
1644+ #define               UNIV_REGOFF_LM_BS               0xf68
1645+
1646+ /* VMEbus register access image control register */
1647+ #define               UNIV_REGOFF_VRAI_CTL    0xf70
1648+ # define      UNIV_VRAI_CTL_EN                        (1<<31) /* image enable */
1649+ # define      UNIV_VRAI_CTL_PGM                       (1<<23) /* program AM */
1650+ # define      UNIV_VRAI_CTL_DATA                      (1<<22) /* data AM */
1651+ # define      UNIV_VRAI_CTL_SUPER                     (1<<21) /* supervisor AM */
1652+ # define      UNIV_VRAI_CTL_USER                      (1<<20) /* user AM */
1653+ # define      UNIV_VRAI_CTL_VAS_A16           (0<<16) /* A16 */
1654+ # define      UNIV_VRAI_CTL_VAS_A24           (1<<16) /* A16 */
1655+ # define      UNIV_VRAI_CTL_VAS_A32           (2<<16) /* A16 */
1656+
1657+ /* VMEbus register acces image base address register */
1658+ #define               UNIV_REGOFF_VRAI_BS             0xf74
1659+
1660+ /* VMEbus CSR control register */
1661+ #define               UNIV_REGOFF_VCSR_CTL    0xf80
1662+ # define      UNIV_VCSR_CTL_EN                        (1<<31) /* image enable */
1663+ # define      UNIV_VCSR_CTL_LAS_PCI_MEM       (0<<0)  /* pci mem space */
1664+ # define      UNIV_VCSR_CTL_LAS_PCI_IO        (1<<0)  /* pci IO space */
1665+ # define      UNIV_VCSR_CTL_LAS_PCI_CFG       (2<<0)  /* pci config space */
1666+
1667+ /* VMEbus CSR translation offset */
1668+ #define               UNIV_REGOFF_VCSR_TO             0xf84
1669+
1670+ /* VMEbus AM code error log */
1671+ #define               UNIV_REGOFF_V_AMERR             0xf88
1672+ # define      UNIV_V_AMERR_AMERR(reg)         (((reg)>>26)&0x3f)      /* extract error log code */
1673+ # define      UNIV_V_AMERR_IACK                       (1<<25) /* VMEbus IACK signal */
1674+ # define      UNIV_V_AMERR_M_ERR                      (1<<24) /* multiple errors occurred */
1675+ # define      UNIV_V_AMERR_V_STAT                     (1<<23) /* log status valid (write 1 to clear) */
1676+
1677+ /* VMEbus address error log */
1678+ #define               UNIV_REGOFF_VAERR               0xf8c           /* address of fault address (if MERR_V_STAT valid) */
1679+
1680+ /* VMEbus CSR bit clear register */
1681+ #define               UNIV_REGOFF_VCSR_CLR    0xff4
1682+ # define      UNIV_VCSR_CLR_RESET                     (1<<31) /* read/negate LRST (can only be written from VME bus */
1683+ # define      UNIV_VCSR_CLR_SYSFAIL           (1<<30) /* read/negate SYSFAIL */
1684+ # define      UNIV_VCSR_CLR_FAIL                      (1<<29) /* read: board has failed */
1685+
1686+ /* VMEbus CSR bit set register */
1687+ #define               UNIV_REGOFF_VCSR_SET            (0xff8)
1688+ # define      UNIV_VCSR_SET_RESET                     (1<<31) /* read/assert LRST (can only be written from VME bus */
1689+ # define      UNIV_VCSR_SET_SYSFAIL           (1<<30) /* read/assert SYSFAIL */
1690+ # define      UNIV_VCSR_SET_FAIL                      (1<<29) /* read: board has failed */
1691+
1692+ /* VMEbus CSR base address register */
1693+ #define               UNIV_REGOFF_VCSR_BS             0xffc
1694+ #define               UNIV_VCSR_BS_MASK                       (0xfff80000)
1695+
1696+ #ifdef __cplusplus
1697+ extern "C" {
1698+ #endif
1699+
1700+ /* base address and IRQ line of 1st universe bridge
1701+  * NOTE: vmeUniverseInit() must be called before
1702+  *       these may be used.
1703+  */
1704+ extern volatile LERegister *vmeUniverse0BaseAddr;
1705+ extern int vmeUniverse0PciIrqLine;
1706+
1707+
1708+ /* Initialize the driver */
1709+ int
1710+ vmeUniverseInit(void);
1711+
1712+ /* setup the universe chip, i.e. disable most of its
1713+  * mappings, reset interrupts etc.
1714+  */
1715+ void
1716+ vmeUniverseReset(void);
1717+
1718+ /* avoid pulling stdio.h into this header.
1719+  * Applications that want a declaration of the
1720+  * following routines should
1721+  *  #include <stdio.h>
1722+  *  #define _VME_UNIVERSE_DECLARE_SHOW_ROUTINES
1723+  *  #include <vmeUniverse.h>
1724+  */
1725+ #ifdef _VME_UNIVERSE_DECLARE_SHOW_ROUTINES
1726+ /* print the current configuration of all master ports to
1727+  * f (stderr if NULL)
1728+  */
1729+ void
1730+ vmeUniverseMasterPortsShow(FILE *f);
1731+
1732+ /* print the current configuration of all slave ports to
1733+  * f (stderr if NULL)
1734+  */
1735+ void
1736+ vmeUniverseSlavePortsShow(FILE *f);
1737+ #else
1738+ void
1739+ vmeUniverseMasterPortsShow();
1740+ void
1741+ vmeUniverseSlavePortsShow();
1742+ #endif
1743+
1744+ /* disable all master or slave ports, respectively */
1745+ void
1746+ vmeUniverseDisableAllMasters(void);
1747+
1748+ void
1749+ vmeUniverseDisableAllSlaves(void);
1750+
1751+ /* configure a master port
1752+  *
1753+  *   port:        port number 0..3  (0..7 for a UniverseII)
1754+  *
1755+  *   address_space: vxWorks compliant addressing mode identifier
1756+  *                  (see vme.h). The most important are:
1757+  *                    0x0d - A32, Sup, Data
1758+  *                    0x3d - A24, Sup, Data
1759+  *                    0x2d - A16, Sup, Data
1760+  *                  additionally, the value 0 is accepted; it will
1761+  *                  disable this port.
1762+  *   vme_address:   address on the vme_bus of this port.
1763+  *   local_address: address on the pci_bus of this port.
1764+  *   length:        size of this port.
1765+  *
1766+  *   NOTE: the addresses and length parameters must be aligned on a
1767+  *         2^16 byte (0x10000) boundary, except for port 4 (only available
1768+  *         on a UniverseII), where the alignment can be 4k (4096).
1769+  *
1770+  *   RETURNS: 0 on success, -1 on failure. Error messages printed to stderr.
1771+  */
1772+
1773+ int
1774+ vmeUniverseMasterPortCfg(
1775+       unsigned long   port,
1776+       unsigned long   address_space,
1777+       unsigned long   vme_address,
1778+       unsigned long   local_address,
1779+       unsigned long   length);
1780+
1781+ /* translate an address through the bridge
1782+  *
1783+  * vmeUniverseLocalToBusAdrs() yields a VME a address that reflects
1784+  * a local memory location as seen from the VME bus through the universe
1785+  * VME slave.
1786+  *
1787+  * likewise does vmeUniverseBusToLocalAdrs() translate a VME bus addr
1788+  * (through the VME master) to the PCI side of the bridge.
1789+  *
1790+  * a valid address space modifier must be specified.
1791+  *
1792+  * RETURNS: translated address in *pbusAdrs / *plocalAdrs
1793+  *
1794+  *          0:  success
1795+  *          -1: address/modifier not found in any bridge port
1796+  *          -2: invalid modifier
1797+  */
1798+ int
1799+ vmeUniverseLocalToBusAdrs(unsigned long am, unsigned long localAdrs, unsigned long *pbusAdrs);
1800+
1801+ int
1802+ vmeUniverseBusToLocalAdrs(unsigned long am, unsigned long busAdrs, unsigned long *plocalAdrs);
1803+
1804+
1805+ /* configure a VME slave (PCI master) port */
1806+ int
1807+ vmeUniverseSlavePortCfg(
1808+       unsigned long   port,
1809+       unsigned long   address_space,
1810+       unsigned long   vme_address,
1811+       unsigned long   local_address,
1812+       unsigned long   length);
1813+
1814+ /* start a (direct, not linked) DMA transfer
1815+  *
1816+  * NOTE:  DCTL and DGCS must be set up
1817+  *        prior to calling this routine
1818+  */
1819+ int
1820+ vmeUniverseStartDMA(
1821+       unsigned long local_addr,
1822+       unsigned long vme_addr,
1823+       unsigned long count);
1824+
1825+ /* read a register in PCI memory space
1826+  * (offset being one of the declared constants)
1827+  */
1828+ unsigned long
1829+ vmeUniverseReadReg(unsigned long offset);
1830+
1831+ /* write a register in PCI memory space */
1832+ void
1833+ vmeUniverseWriteReg(unsigned long value, unsigned long offset);
1834+
1835+ /* convert an array of unsigned long values to LE (as needed
1836+  * when the universe reads e.g. DMA descriptors from PCI)
1837+  */
1838+ void
1839+ vmeUniverseCvtToLE(unsigned long *ptr, unsigned long num);
1840+
1841+ /* reset the VME bus */
1842+ static inline void
1843+ vmeUniverseResetBus(void)
1844+ {
1845+       vmeUniverseWriteReg(
1846+               vmeUniverseReadReg(UNIV_REGOFF_MISC_CTL) | UNIV_MISC_CTL_SW_SYSRST,
1847+               UNIV_REGOFF_MISC_CTL);
1848+ }
1849+
1850+ #ifdef __rtems
1851+ /* VME Interrupt Handler functionality */
1852+
1853+ /* we dont use the current RTEMS/BSP interrupt API for the
1854+  * following reasons:
1855+  *
1856+  *    - RTEMS/BSP API does not pass an argument to the ISR :-( :-(
1857+  *    - no separate vector space for VME vectors. Some vectors would
1858+  *      have to overlap with existing PCI/ISA vectors.
1859+  *    - RTEMS/BSP API allocates a structure for every possible vector
1860+  *    - the irq_on(), irq_off() functions add more bloat than helping.
1861+  *      They are (currently) only used by the framework to disable
1862+  *      interrupts at the device level before removing a handler
1863+  *      and to enable interrupts after installing a handler.
1864+  *      These operations may as well be done by the driver itself.
1865+  *
1866+  * Hence, we maintain our own (VME) handler table and hook our PCI
1867+  * handler into the standard RTEMS/BSP environment. Our handler then
1868+  * dispatches VME interrupts.
1869+  */
1870+
1871+ typedef void (*VmeUniverseISR) (void *usrArg, unsigned long vector);
1872+
1873+ /* install a handler for a VME vector
1874+  * RETURNS 0 on success, nonzero on failure.
1875+  */
1876+ int
1877+ vmeUniverseInstallISR(unsigned long vector, VmeUniverseISR handler, void *usrArg);
1878+
1879+ /* remove a handler for a VME vector. The vector and usrArg parameters
1880+  * must match the respective parameters used when installing the handler.
1881+  * RETURNS 0 on success, nonzero on failure.
1882+  */
1883+ int
1884+ vmeUniverseRemoveISR(unsigned long vector, VmeUniverseISR handler, void *usrArg);
1885+
1886+ /* query for the currently installed ISR and usr parameter at a given vector
1887+  * RETURNS: ISR or 0 (vector too big or no ISR installed)
1888+  */
1889+ VmeUniverseISR
1890+ vmeUniverseISRGet(unsigned long vector, void **parg);
1891+
1892+ /* utility routines to enable/disable a VME IRQ level
1893+  *
1894+  * RETURNS 0 on success, nonzero on failure
1895+  */
1896+ int
1897+ vmeUniverseIntEnable(unsigned int level);
1898+ int
1899+ vmeUniverseIntDisable(unsigned int level);
1900+
1901+
1902+ /* use this special vector to connect a handler to the
1903+  * universe specific interrupts (such as "DMA done",
1904+  * VOWN, error irqs etc.)
1905+  * NOTE: The wrapper clears all status LINT bits (except
1906+  * for regular VME irqs). Also note that it is the user's
1907+  * responsibility to enable the necessary interrupts in
1908+  * LINT_EN
1909+  */
1910+ #define UNIV_SPECIAL_IRQ_VECTOR       256
1911+
1912+ /* the universe interrupt handler is capable of routing all sorts of
1913+  * (VME) interrupts to 8 different lines (some of) which may be hooked up
1914+  * in a (board specific) way to a PIC.
1915+  *
1916+  * This driver only supports at most two lines. It routes the 7 VME
1917+  * interrupts to the main line and optionally, it routes the 'special'
1918+  * interrupts generated by the universe itself (DMA done, VOWN etc.)
1919+  * to a second line. If no second line is available, all IRQs are routed
1920+  * to the main line.
1921+  *
1922+  * Because the driver has no way to figure out which lines are actually
1923+  * wired to the PIC, this information has to be provided when installing
1924+  * the manager.
1925+  *
1926+  * Hence the manager sets up routing VME interrupts to 1 or 2 universe
1927+  * OUTPUTS. However, it must also be told to which PIC INPUTS they
1928+  * are wired. The first PIC input line is read from PCI config space
1929+  * but the second must be passed to this routine.
1930+  *
1931+  * PARAMETERS:
1932+  *       vmeIRQunivOut: to which output pin (of the universe) should the 7
1933+  *                                    VME irq levels be routed.
1934+  *   specialIRQunivOut: to which output pin (of the universe) should the
1935+  *                      internally irqs be routed. Use 'vmeIRQunivOut'
1936+  *                      if < 0.
1937+  *   specialIrqPicLine: specifies to which PIC input the 'special' output
1938+  *                      pin is wired. The wiring of the 'vmeIRQunivOut' to
1939+  *                      the PIC is determined by reading PCI config space.
1940+  *
1941+  * RETURNS: 0 on success, -1 on failure.
1942+  *                                           
1943+  */
1944+ int
1945+ vmeUniverseInstallIrqMgr(int vmeIrqUnivOut, int specialIrqUnivOut, int specialIrqPicLine);
1946+
1947+ #endif
1948+
1949+ #ifdef __cplusplus
1950+ }
1951+ #endif
1952+
1953+ #endif