Changeset 784e792 in rtems


Ignore:
Timestamp:
Nov 4, 2005, 8:17:56 AM (14 years ago)
Author:
Till Straumann <strauman@…>
Branches:
4.10, 4.11, 4.8, 4.9, master
Children:
d3b8db7b
Parents:
6d3ff66f
Message:

2005-11-04 Till Straumann <strauman@…>

  • shared/vmeUniverse/vmeTsi148.c, shared/vmeUniverse/vmeTsi148.h, shared/vmeUniverse/vme_am_defs.h: New files.
  • Makefile.am, shared/vmeUniverse/README.universe, shared/vmeUniverse/vmeUniverse.c, shared/vmeUniverse/vmeUniverse.h: Several VME related upgrades and fixes, hopefully addressing PR#835: vmeUniverse driver now supports shared interrupts. vmeUniverse now supports up to four wires between universe and PIC. A new irq mgr installation routine has been added allowing to use the new features. (old version is still present for bwd compatibility). Calls have been added to change interrupt routing (e.g., if wires have different priorities at the PIC this feature can be used to configure priorites). Routine for testing VME interrupts has been added (useful during BSP development). A new header defining standard VME address

modes has been added so that the VME API doesn't have to #include a
particular bridge driver header. For all driver entry points, a 'XX'
variant has been added which allows to pass the chip's base address
[in case a second universe is sitting on a VME card :-)]. Driver now
uses interrupt line as read from PCI config. space (without offset)
BSP needs to use PCI fixup if necessary. Added a driver for the
tundra tsi148 VME bridge.

Location:
c/src/lib/libbsp
Files:
3 added
5 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/ChangeLog

    r6d3ff66f r784e792  
     12005-11-04      Till Straumann <strauman@slac.stanford.edu>
     2
     3        * shared/vmeUniverse/vmeTsi148.c, shared/vmeUniverse/vmeTsi148.h,
     4        shared/vmeUniverse/vme_am_defs.h: New files.
     5        * Makefile.am, shared/vmeUniverse/README.universe,
     6        shared/vmeUniverse/vmeUniverse.c, shared/vmeUniverse/vmeUniverse.h:
     7        Several VME related upgrades and fixes, hopefully addressing PR#835:
     8        vmeUniverse driver now supports shared interrupts. vmeUniverse now
     9        supports up to four wires between universe and PIC. A new irq mgr
     10        installation routine has been added allowing to use the new features.
     11        (old version is still present for bwd compatibility). Calls have been
     12        added to change interrupt routing (e.g., if wires have different
     13        priorities at the PIC this feature can be used to configure
     14        priorites). Routine for testing VME interrupts has been added (useful
     15        during BSP development). A new header defining standard VME address
     16        modes has been added so that the VME API doesn't have to #include a
     17        particular bridge driver header. For all driver entry points, a 'XX'
     18        variant has been added which allows to pass the chip's base address
     19        [in case a second universe is sitting on a VME card :-)]. Driver now
     20        uses interrupt line as read from PCI config. space (without offset)
     21        BSP needs to use PCI fixup if necessary. Added a driver for the
     22        tundra tsi148 VME bridge.
     23
    1242004-02-17      Ralf Corsepius <corsepiu@faw.uni-ulm.de>
    225
  • c/src/lib/libbsp/Makefile.am

    r6d3ff66f r784e792  
    1616    shared/tod.h
    1717EXTRA_DIST += shared/vmeUniverse/vmeUniverse.c \
    18     shared/vmeUniverse/vmeUniverse.h
     18    shared/vmeUniverse/vmeUniverse.h \
     19    shared/vmeUniverse/vmeTsi148.c      \
     20    shared/vmeUniverse/vmeTsi148.h      \
     21    shared/vmeUniverse/vme_am_defs.h \
     22    shared/vmeUniverse/README.porting \
     23    shared/vmeUniverse/README.universe
     24
    1925EXTRA_DIST += shared/include/coverhd.h
    2026EXTRA_DIST += shared/gdbstub/rtems-stub-glue.c
  • c/src/lib/libbsp/shared/vmeUniverse/README.universe

    r6d3ff66f r784e792  
    1 The universe II driver is in a separate subdir
    2 because it is maintained at SSRL outside of the
    3 rtems CVS tree (it supports other OSes as well)
     1The tundra drivers are in a separate subdir
     2because they are maintained at SSRL outside of the
     3rtems CVS tree. The directory is called 'vmeUniverse'
     4for historic reasons. 'tundra' would be better
     5since we now support the tundra tsi148 as well...
    46
    5 Till Straumann <strauman@slac.stanford.edu> 1/2002
     7Till Straumann <strauman@slac.stanford.edu> 1/2002, 2005
    68
    79NOTES:
    8 This driver is maintained _outside_ rtems.
     10These driver are maintained _outside_ rtems.
    911Please forward future modifications to me.
    1012
    11 A BSP that wants to use the vmeUniverse driver
     13A BSP that wants to use these drivers
    1214must implement the following headers / functionality:
    1315 - <bsp/pci.h> offering an API like 'libbsp/powerpc/shared/pci'
     
    1618
    1719The BSP should then use "VPATH magic" (to use Joel's
    18 words :-) to reach the vmeUniverse.* files in the
    19 universe subdir.
     20words :-) to reach the vmeUniverse.* / vmeTsi148.* files
     21in this subdir.
  • c/src/lib/libbsp/shared/vmeUniverse/vmeUniverse.c

    r6d3ff66f r784e792  
    55 *         Nov 2000, Oct 2001, Jan 2002
    66 */
     7
     8#if 0
     9/*
     10 * $Log$
     11 * Revision 1.55  2005/10/25 20:07:18  till
     12 *  - check #if BSP_SHARED_HANDLER_SUPPORT > 0 before using the shared irq API.
     13 *    Bail to use non-shared interrupts if the BSP doesn't support the shared API
     14 *    (giving a warning).
     15 *
     16 * Revision 1.54  2005/10/25 19:52:26  till
     17 *  - Loopback test: ISR check return status of message_queue_send and assumes
     18 *    there's a IRQ storm on error (queue full). The interrupt level is disabled
     19 *    if this occurs.
     20 *
     21 * Revision 1.53  2005/10/21 17:52:08  till
     22 *  - reverted default definition of PCI_MEM_BASE and introduced a short explanation
     23 *
     24 * Revision 1.52  2005/10/21 17:46:37  till
     25 *  - use 0 if PCI_MEM_BASE is undefined
     26 *
     27 * Revision 1.51  2005/10/14 19:04:51  till
     28 *  - removed shared irq handler kludge for mvme5500 bsp -- this *really* doesn't belong here...
     29 *
     30 * Revision 1.50  2005/10/10 21:57:59  till
     31 *  - xxIrqMgrInstalled must be set prior to calling xxIntRoute() because
     32 *    xxIntRoute() now checks the 'installed' flag.
     33 *
     34 * Revision 1.49  2005/10/10 19:45:08  till
     35 *  - enable PCI busmaster and memory access from the 'find' routine
     36 *
     37 * Revision 1.48  2005/10/10 19:35:47  till
     38 *  - added 'Va' version of IrqMgrInstall
     39 *
     40 * Revision 1.47  2005/10/10 18:04:50  till
     41 *  - maintain copy of vme_am_defs.h in driver headers (backwards compat, sigh...)
     42 *
     43 * Revision 1.46  2005/10/10 17:52:58  strauman
     44 *  - separated basic AM definitions into separate file
     45 *
     46 * Revision 1.45  2005/10/10 17:45:58  strauman
     47 *  - added check for initialized 'base' to tsi driver
     48 *
     49 * Revision 1.44  2005/10/10 06:24:15  till
     50 *  - if vector is unknown, the message number (and not the vector number) needs to
     51 *    be printed (IntLoopbackTest()).
     52 *
     53 * Revision 1.43  2005/10/09 00:28:20  till
     54 *  - added vmeUniverseIntRaise() and vmeUniverseIntLoopbackTest() routines
     55 *
     56 * Revision 1.42  2005/10/08 23:48:03  till
     57 *  - 'special' level numbers are now (almost - except for VOWN) aligned
     58 *    with bitmask; removed extra shift for levels >= SW_IACK.
     59 *  - use helper function to convert level -> bitmask. Also used by new feature
     60 *    to let vmeUniverseIntEnable/Disable handle 'special/internal' interrupts
     61 *    as well.
     62 *  - undid bad change. The level sensitive VME interrupts must really be cleared only
     63 *    *after* calling the user handler to prevent the chip to ACK another IRQ at the level
     64 *    currently processed.
     65 *  - added printk() statements in error-branches of ISR (no handler installed or bus error
     66 *    during IACK.
     67 *  - added kludgy weak alias that maps  BSP_install_rtems_shared_irq_handler
     68 *    to BSP_install_rtems_irq_handler -- the mvme5500 bsp doesn't implement the shared handlers...
     69 *  - bugfix: vmeUniverseIntRoute 'pin' argument is actually the slot # in the wire table,
     70 *    so the 'special' pin has to be 1 not universe_wire[1].
     71 *  - added vmeUniverseIntIsEnabled() to check current setting.
     72 *
     73 * Revision 1.41  2005/10/06 21:41:57  till
     74 *  - FIX: protect handler table by switching interrupt off
     75 *  - FIX: skip vector # for nonexistent special IRQ
     76 *  - upgrade: new InstallMgr API allows for requesting shared irqs and more pin/line pairs
     77 *  - only do EOI if BSP defines macro
     78 *  - dont add PCI_LOWEST_OFFSET anymore to irq line info
     79 *
     80 * Revision 1.40  2005/06/04 05:47:00  till
     81 *  - added comment about STAT_ID pecularity
     82 *
     83 * Revision 1.39  2005/05/06 00:03:14  till
     84 *  - added interface to secondary devices (pass base addr of universe)
     85 *  - made the 'ResetBus' routine public
     86 *
     87 * Revision 1.38  2005/04/26 00:02:47  till
     88 *  - fix in inline assembly
     89 *
     90 * Revision 1.37  2004/11/08 22:43:09  till
     91 *  - fix: zero value of specialIrqUnivOut is legal.
     92 *
     93 * Revision 1.36  2003/03/21 20:54:18  till
     94 *  - modified 'printf()' formats to be compliant with the
     95 *    cpukit 'printk()' implementation and use the latter
     96 *    prior to stdio/libc being initialized.
     97 *
     98 * Revision 1.35  2003/03/06 20:52:44  till
     99 *  - fix lazy init bug reported by Kate Feng
     100 *  - rename misspelled dccp/DCCP to dcpp/DCPP ( :-( )
     101 *  - added 'packed' attribute (probably not really necessary)
     102 *
     103 * Revision 1.34  2003/02/10 23:20:05  till
     104 *  - added some macro magic to make porting easier (ppcn_60x BSP in mind)
     105 *  - made mgrInstalled public (vmeUniverseIrqMgrInstalled) so BSPs can
     106 *    supply their own versions of the mgrInstall() routine.
     107 *  - added READMEs to CVS
     108 *
     109 * Revision 1.33.2.1  2003/02/10 23:01:40  till
     110 *  - added some macro magic to make porting easier (ppcn_60x BSP in mind)
     111 *  - made mgrInstalled public (vmeUniverseIrqMgrInstalled) so BSPs can
     112 *    supply their own versions of the mgrInstall() routine.
     113 *
     114 * Revision 1.32  2002/09/05 02:50:41  till
     115 *  - use k_vsprintf(), not vsprintf() during early boot (RTEMS)
     116 *
     117 * Revision 1.31  2002/08/16 23:35:15  strauman
     118 *  - fixed typos
     119 *
     120 * Revision 1.30  2002/08/16 22:53:37  till
     121 *  - made address translation more generic; allow to look for reverse mappings
     122 *    also.
     123 *  - removed vmeUniverseLocalToBus() and vmeUniverseBusToLocal() and made
     124 *    vmeUniverseXlateAddr() public instead.
     125 *
     126 * Revision 1.29  2002/08/16 22:16:25  till
     127 *  - tweak U2SPEC (fix Joerger vtr10012_8 problem) the same
     128 *    way the synergy BSP does (rev 2 chips only)
     129 *
     130 * Revision 1.28  2002/08/15 23:16:01  till
     131 *  - bugfix: vmeUniverseISRGet() dereferenced a possibly NULL pointer
     132 *
     133 * Revision 1.25  2002/07/19 05:18:40  till
     134 *  - CVS log: again a problem. Cannot embed /_* *_/ comments in the log
     135 *    because the log has to be commented as a whole. I had tried
     136 *    #if 0 #endif - doesn't work because cpp expands char constants???
     137 *    WHAT A NUISANCE
     138 *
     139 * Revision 1.24  2002/07/19 02:44:14  till
     140 *  - added a new parameter to the IRQ manager install routine:
     141 *    the main interrupt's line can now also be specified (reading
     142 *    from PCI config does not always work - some boards don't
     143 *    have correct information there - PMC's will have a similar
     144 *    problem, though!)
     145 *
     146 * Revision 1.21  2002/04/11 06:54:48  till
     147 *  - silenced message about 'successfully configured a port'
     148 *
     149 * Revision 1.20  2002/03/27 21:14:50  till
     150 *  - fix: handler table holds pointers, so hdlrTbl[vector]->usrData etc.
     151 *    not hdlrTbl[vector].usrData...
     152 *
     153 * Revision 1.19  2002/03/09 00:14:36  till
     154 *  - added vmeUniverseISRGet() to retrieve the currently installed
     155 *    ISR for a given vector
     156 *  - swapped the argument order for ISRs to (usrarg, vector)
     157 *
     158 * Revision 1.18  2002/02/07 19:53:48  till
     159 *  - reverted back to publish base_addr/irq_line as variables rather than
     160 *    through functions: the irq_line is read by the interrupt dispatcher...
     161 *
     162 * Revision 1.17  2002/01/24 08:28:10  till
     163 *  - initialize driver when reading base address or irq line.
     164 *    however, this requires the pci driver to be working already.
     165 *
     166 * Revision 1.16  2002/01/24 08:21:48  till
     167 *  - replaced public global vars for base address/irq line by routines.
     168 *
     169 * Revision 1.15  2002/01/23 06:15:30  till
     170 *   - changed master port data width to 64 bit.
     171 *        NOTE: reading the CY961 (Echotek ECDR814) with VDW32
     172 *              generated bus errors when reading 32-bit words
     173 *              - very weird, because the registers are 16-bit
     174 *                AFAIK.
     175 *              - 32-bit accesses worked fine on vxWorks which
     176 *                has the port set to 64-bit.
     177 *              ????????
     178 *
     179 * Revision 1.14  2002/01/11 19:30:54  till
     180 *  - added more register defines to header
     181 *  - completed vmeUniverseReset
     182 *
     183 * Revision 1.13  2002/01/11 05:06:18  till
     184 *  - fixed VMEISR failing to check (lint_stat & msk) when determining
     185 *    the highes level...
     186 *  - tested interrupt handling & nesting. Seems to work.
     187 *
     188 * Revision 1.12  2002/01/11 02:25:55  till
     189 *  - added interrupt manager
     190 *
     191 * Revision 1.11  2002/01/08 03:59:52  till
     192 *  - vxworks always defines _LITTLE_ENDIAN, fixed the conditionals
     193 *    so it should work on __vxworks and on __rtems__ now.
     194 *  - rtems uprintf wrapper reverts to printk if stdio is not yet
     195 *    initialized (uses _impure_ptr->__sdidinit)
     196 *  - tested bus address translation utility routines
     197 *
     198 * Revision 1.9  2002/01/05 02:36:32  till
     199 *  - added vmeUniverseBusToLocalAdrs / vmeUniverseLocalToBusAdrs for address
     200 *    space translations.
     201 *  - include bsp.h under rtems to hack around the libcpu/powerpc/shared/io.h
     202 *    #define _IO_BASE & friends problem.
     203 *
     204 * Revision 1.8  2002/01/04 04:12:51  till
     205 *  - changed some rtems/pci related names
     206 *
     207 * Revision 1.7  2002/01/04 03:06:30  till
     208 *  - added further register definitions
     209 *
     210 * Revision 1.6  2001/12/20 04:42:44  till
     211 *  - fixed endianness stuff; theoretically, PPC could be LITTLE_ENDIAN...
     212 *
     213 * Revision 1.4  2001/12/19 01:59:02  till
     214 *  - started adding interrupt stuff
     215 *  - private implementation of PCI scanning if necessary
     216 *
     217 * Revision 1.3  2001/07/27 22:22:51  till
     218 *  - added more DMA support routines and defines to include file
     219 *  - xxxPortsShow can now print to a given file descriptor argument
     220 *
     221 * Revision 1.2  2001/07/26 18:06:13  till
     222 *  - ported to RTEMS
     223 *  - fixed a couple of wrong pointer calculations.
     224 *
     225 * Revision 1.1.1.1  2001/07/12 23:15:19  till
     226 *  - cvs import
     227 */
     228#endif
    7229
    8230#include <stdio.h>
     
    48270#define UNIV_SCTL_AM_MASK       (UNIV_CTL_VAS | UNIV_SCTL_PGM | UNIV_SCTL_DAT | UNIV_SCTL_USER | UNIV_SCTL_SUPER)
    49271
    50 /* we rely on a vxWorks definition here */
    51 #define VX_AM_SUP               4
    52 
    53272#ifdef __rtems__
    54273
    55274#include <stdlib.h>
    56275#include <rtems/bspIo.h>        /* printk */
     276#include <rtems/error.h>
    57277#include <bsp/pci.h>
    58278#include <bsp.h>
     
    60280/* allow the BSP to override the default routines */
    61281#ifndef BSP_PCI_FIND_DEVICE
    62 #define BSP_PCI_FIND_DEVICE     pci_find_device
     282#define BSP_PCI_FIND_DEVICE                     pci_find_device
    63283#endif
    64284#ifndef BSP_PCI_CONFIG_IN_LONG
    65 #define BSP_PCI_CONFIG_IN_LONG  pci_read_config_dword
     285#define BSP_PCI_CONFIG_IN_LONG          pci_read_config_dword
    66286#endif
    67287#ifndef BSP_PCI_CONFIG_IN_BYTE
    68 #define BSP_PCI_CONFIG_IN_BYTE  pci_read_config_byte
    69 #endif
    70 
     288#define BSP_PCI_CONFIG_IN_BYTE          pci_read_config_byte
     289#endif
     290#ifndef BSP_PCI_CONFIG_IN_SHORT
     291#define BSP_PCI_CONFIG_IN_SHORT         pci_read_config_word
     292#endif
     293#ifndef BSP_PCI_CONFIG_OUT_SHORT
     294#define BSP_PCI_CONFIG_OUT_SHORT        pci_write_config_word
     295#endif
     296
     297/* PCI_MEM_BASE is a possible offset between CPU- and PCI addresses.
     298 * Should be defined by the BSP.
     299 */
    71300typedef unsigned int pci_ulong;
    72 #define PCI_TO_LOCAL_ADDR(memaddr) \
    73     ((pci_ulong)(memaddr) + PCI_MEM_BASE)
     301#define PCI_TO_LOCAL_ADDR(memaddr) ((pci_ulong)(memaddr) + PCI_MEM_BASE)
     302
    74303
    75304#elif defined(__vxworks)
     
    89318volatile LERegister *vmeUniverse0BaseAddr=0;
    90319int vmeUniverse0PciIrqLine=-1;
     320
     321#define DFLT_BASE       volatile LERegister *base = vmeUniverse0BaseAddr
     322
     323#define CHECK_DFLT_BASE(base) \
     324        do { \
     325                /* get the universe base address */ \
     326                if (!base) { \
     327                        if (vmeUniverseInit()) { \
     328                                uprintf(stderr,"unable to find the universe in pci config space\n"); \
     329                                return -1; \
     330                        } else { \
     331                                base = vmeUniverse0BaseAddr; \
     332                        } \
     333                } \
     334        } while (0)
    91335
    92336#if 0
     
    132376#endif
    133377
    134 /* registers should be mapped to guarded, non-cached memory; hence
     378/* registers should be mapped to guarded, non-cached memory; hence 
    135379 * subsequent stores are ordered. eieio is only needed to enforce
    136380 * ordering of loads with respect to stores.
     
    175419
    176420#define PORT_UNALIGNED(addr,port) \
    177         ( (port)%4 ? ((addr) & 0xffff) : ((addr) & 4095) )
     421        ( (port)%4 ? ((addr) & 0xffff) : ((addr) & 4095) )
     422
    178423
    179424#define UNIV_REV(base) (READ_LE(base,2*sizeof(LERegister)) & 0xff)
    180 
     425       
    181426#if defined(__rtems__) && 0
    182427static int
     
    198443#endif
    199444
     445
    200446/* private printing wrapper */
    201447static void
     
    212458                 */
    213459                vprintk(fmt,ap);
    214         } else
     460        } else 
    215461#endif
    216462        {
     
    227473{
    228474int bus,dev,fun;
     475unsigned short wrd;
    229476pci_ulong busaddr;
    230477unsigned char irqline;
     
    250497        if (BSP_PCI_CONFIG_IN_BYTE(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline))
    251498                return -1;
    252         else
    253                 vmeUniverse0PciIrqLine = irqline;
    254 
    255         return 0;
     499
     500        /* Enable PCI master and memory access */
     501        BSP_PCI_CONFIG_IN_SHORT(bus, dev, fun, PCI_COMMAND, &wrd);
     502        BSP_PCI_CONFIG_OUT_SHORT(bus, dev, fun, PCI_COMMAND, wrd | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
     503
     504        return irqline;
    256505}
    257506
     
    306555                        return -1;
    307556        }
    308         if (address_space & VX_AM_SUP)
     557        if ( VME_AM_IS_SUP(address_space) )
    309558                mode |= (ismaster ? UNIV_MCTL_SUPER : UNIV_SCTL_SUPER);
    310559        *pmode = mode;
     
    325574static int
    326575cfgUniversePort(
     576        volatile LERegister *base,
    327577        unsigned long   ismaster,
    328578        unsigned long   port,
     
    332582        unsigned long   length)
    333583{
    334 #define base vmeUniverse0BaseAddr
    335584volatile LERegister *preg;
    336585unsigned long   p=port;
    337586unsigned long   mode=0;
     587
     588        CHECK_DFLT_BASE(base);
    338589
    339590        /* check parameters */
     
    439690                if (ismaster)
    440691                        mode |= UNIV_MCTL_EN | UNIV_MCTL_PWEN | UNIV_MCTL_VDW64 | UNIV_MCTL_VCT;
    441                 else
     692                else 
    442693                        mode |= UNIV_SCTL_EN | UNIV_SCTL_PWEN | UNIV_SCTL_PREN;
    443694
     
    464715        }
    465716        return 0;
    466 #undef base
    467717}
    468718
     
    519769                        cntrl&UNIV_MCTL_SUPER ? "Sup" : "Usr");
    520770        } else {
    521                 uprintf(f,"%s %s %s %s",
     771                uprintf(f,"%s %s %s %s", 
    522772                        cntrl&UNIV_SCTL_PGM ?   "Pgm," : "    ",
    523773                        cntrl&UNIV_SCTL_DAT ?   "Dat," : "    ",
     
    598848}
    599849
     850
    600851static int
    601 mapOverAll(int ismaster, int (*func)(int,int,volatile LERegister *,void*), void *arg)
    602 {
    603 #define base    vmeUniverse0BaseAddr
     852mapOverAll(volatile LERegister *base, int ismaster, int (*func)(int,int,volatile LERegister *,void*), void *arg)
     853{
    604854volatile LERegister     *rptr;
    605855unsigned long   port;
    606856int     rval;
    607857
    608         /* get the universe base address */
    609         if (!base && vmeUniverseInit()) {
    610                 uprintf(stderr,"unable to find the universe in pci config space\n");
    611                 return -1;
    612         }
    613         rptr = (base +
     858        CHECK_DFLT_BASE(base);
     859
     860        rptr = (base +
    614861                (ismaster ? UNIV_REGOFF_PCITGT0_CTRL : UNIV_REGOFF_VMESLV0_CTRL)/sizeof(LERegister));
    615862#undef TSILL
     
    626873        if (UNIV_REV(base)<2) return -1;
    627874
    628         rptr = (base +
     875        rptr = (base + 
    629876                (ismaster ? UNIV_REGOFF_PCITGT4_CTRL : UNIV_REGOFF_VMESLV4_CTRL)/sizeof(LERegister));
    630877        for (port=4; port<UNIV_NUM_MPORTS; port++) {
     
    633880        }
    634881        return 0;
    635 #undef base
    636882}
    637883
    638884static void
    639 showUniversePorts(int ismaster, FILE *f)
     885showUniversePorts(volatile LERegister *base, int ismaster, FILE *f)
    640886{
    641887        if (!f) f=stdout;
    642888        uprintf(f,"Universe %s Ports:\n",ismaster ? "Master" : "Slave");
    643889        uprintf(f,"Port  VME-Addr   Size       PCI-Adrs   Mode:\n");
    644         mapOverAll(ismaster,showUniversePort,f);
     890        mapOverAll(base,ismaster,showUniversePort,f);
     891}
     892
     893int
     894vmeUniverseXlateAddrXX(
     895        volatile LERegister *base,      /* Universe base address */
     896        int master,             /* look in the master windows */
     897        int reverse,            /* reverse mapping; for masters: map local to VME */
     898        unsigned long as,       /* address space */
     899        unsigned long aIn,      /* address to look up */
     900        unsigned long *paOut/* where to put result */
     901        )
     902{
     903int     rval;
     904XlatRec l;
     905        l.aspace  = as;
     906        l.address = aIn;
     907        l.reverse = reverse;
     908        /* map result -1/0/1 to -2/-1/0 with 0 on success */
     909        rval = mapOverAll(base,master,xlatePort,(void*)&l) - 1;
     910        *paOut = l.address;
     911        return rval;
    645912}
    646913
     
    654921        )
    655922{
    656 int     rval;
    657 XlatRec l;
    658         l.aspace  = as;
    659         l.address = aIn;
    660         l.reverse = reverse;
    661         /* map result -1/0/1 to -2/-1/0 with 0 on success */
    662         rval = mapOverAll(master,xlatePort,(void*)&l) - 1;
    663         *paOut = l.address;
    664         return rval;
    665 }
     923        DFLT_BASE;
     924        return vmeUniverseXlateAddrXX(base, master, reverse, as, aIn, paOut);
     925}
     926
    666927
    667928void
     
    693954        /* disable VME bus image of VME CSR */
    694955        vmeUniverseWriteReg(0, UNIV_REGOFF_VCSR_CTL);
     956
    695957
    696958        /* I had problems with a Joerger vtr10012_8 card who would
     
    720982
    721983        vmeUniverseDisableAllMasters();
    722 
     984       
    723985        vmeUniverseWriteReg(UNIV_VCSR_CLR_SYSFAIL, UNIV_REGOFF_VCSR_CLR);
    724986
     
    7471009{
    7481010int rval;
    749         if ((rval=vmeUniverseFindPciBase(0,&vmeUniverse0BaseAddr))) {
     1011        if ( (rval=vmeUniverseFindPciBase(0,&vmeUniverse0BaseAddr)) < 0 ) {
    7501012                uprintf(stderr,"unable to find the universe in pci config space\n");
    7511013        } else {
     1014                vmeUniverse0PciIrqLine = rval;
     1015                rval                   = 0;
    7521016                uprintf(stderr,"Universe II PCI-VME bridge detected at 0x%08x, IRQ %d\n",
    7531017                                (unsigned int)vmeUniverse0BaseAddr, vmeUniverse0PciIrqLine);
     
    7571021
    7581022void
     1023vmeUniverseMasterPortsShowXX(volatile LERegister *base, FILE *f)
     1024{
     1025        showUniversePorts(base,1,f);
     1026}
     1027
     1028void
    7591029vmeUniverseMasterPortsShow(FILE *f)
    7601030{
    761         showUniversePorts(1,f);
     1031        DFLT_BASE;
     1032        showUniversePorts(base,1,f);
     1033}
     1034
     1035void
     1036vmeUniverseSlavePortsShowXX(volatile LERegister *base, FILE *f)
     1037{
     1038        showUniversePorts(base,0,f);
    7621039}
    7631040
     
    7651042vmeUniverseSlavePortsShow(FILE *f)
    7661043{
    767         showUniversePorts(0,f);
     1044        DFLT_BASE;
     1045        showUniversePorts(base,0,f);
     1046}
     1047
     1048int
     1049vmeUniverseMasterPortCfgXX(
     1050        volatile LERegister *base,
     1051        unsigned long   port,
     1052        unsigned long   address_space,
     1053        unsigned long   vme_address,
     1054        unsigned long   local_address,
     1055        unsigned long   length)
     1056{
     1057        return cfgUniversePort(base,1,port,address_space,vme_address,local_address,length);
    7681058}
    7691059
     
    7761066        unsigned long   length)
    7771067{
    778         return cfgUniversePort(1,port,address_space,vme_address,local_address,length);
     1068        DFLT_BASE;
     1069        return cfgUniversePort(base,1,port,address_space,vme_address,local_address,length);
     1070}
     1071
     1072int
     1073vmeUniverseSlavePortCfgXX(
     1074        volatile LERegister *base,
     1075        unsigned long   port,
     1076        unsigned long   address_space,
     1077        unsigned long   vme_address,
     1078        unsigned long   local_address,
     1079        unsigned long   length)
     1080{
     1081        return cfgUniversePort(base,0,port,address_space,vme_address,local_address,length);
    7791082}
    7801083
     
    7871090        unsigned long   length)
    7881091{
    789         return cfgUniversePort(0,port,address_space,vme_address,local_address,length);
     1092        DFLT_BASE;
     1093        return cfgUniversePort(base,0,port,address_space,vme_address,local_address,length);
     1094}
     1095
     1096
     1097void
     1098vmeUniverseDisableAllSlavesXX(volatile LERegister *base)
     1099{
     1100        mapOverAll(base,0,disableUniversePort,0);
    7901101}
    7911102
     
    7931104vmeUniverseDisableAllSlaves(void)
    7941105{
    795         mapOverAll(0,disableUniversePort,0);
     1106        DFLT_BASE;
     1107        mapOverAll(base,0,disableUniversePort,0);
     1108}
     1109
     1110void
     1111vmeUniverseDisableAllMastersXX(volatile LERegister *base)
     1112{
     1113        mapOverAll(base,1,disableUniversePort,0);
    7961114}
    7971115
     
    7991117vmeUniverseDisableAllMasters(void)
    8001118{
    801         mapOverAll(1,disableUniversePort,0);
    802 }
    803 
    804 int
    805 vmeUniverseStartDMA(
     1119        DFLT_BASE;
     1120        mapOverAll(base,1,disableUniversePort,0);
     1121}
     1122
     1123int
     1124vmeUniverseStartDMAXX(
     1125        volatile LERegister *base,
    8061126        unsigned long local_addr,
    8071127        unsigned long vme_addr,
    8081128        unsigned long count)
    8091129{
    810 
    811         if (!vmeUniverse0BaseAddr && vmeUniverseInit()) return -1;
    8121130        if ((local_addr & 7) != (vme_addr & 7)) {
    8131131                uprintf(stderr,"vmeUniverseStartDMA: misaligned addresses\n");
     
    8171135        {
    8181136        /* help the compiler allocate registers */
    819         register volatile LERegister *b=vmeUniverse0BaseAddr;
     1137        register volatile LERegister *b=base;;
    8201138        register unsigned long dgcsoff=UNIV_REGOFF_DGCS,dgcs;
    8211139
     
    8411159}
    8421160
     1161int
     1162vmeUniverseStartDMA(
     1163        unsigned long local_addr,
     1164        unsigned long vme_addr,
     1165        unsigned long count)
     1166{
     1167        DFLT_BASE; /* vmeUniverseStartDMAXX doesn't check for a valid base address for efficiency reasons */
     1168        return vmeUniverseStartDMAXX(base, local_addr, vme_addr, count);
     1169}
     1170
     1171unsigned long
     1172vmeUniverseReadRegXX(volatile LERegister *base, unsigned long offset)
     1173{
     1174unsigned long rval;
     1175        rval = READ_LE(base,offset);
     1176        return rval;
     1177}
     1178
     1179
    8431180unsigned long
    8441181vmeUniverseReadReg(unsigned long offset)
     
    8501187
    8511188void
     1189vmeUniverseWriteRegXX(volatile LERegister *base, unsigned long value, unsigned long offset)
     1190{
     1191        WRITE_LE(value, base, offset);
     1192}
     1193
     1194void
    8521195vmeUniverseWriteReg(unsigned long value, unsigned long offset)
    8531196{
    8541197        WRITE_LE(value, vmeUniverse0BaseAddr, offset);
     1198}
     1199
     1200void
     1201vmeUniverseResetBus(void)
     1202{
     1203        vmeUniverseWriteReg(
     1204                vmeUniverseReadReg(UNIV_REGOFF_MISC_CTL) | UNIV_MISC_CTL_SW_SYSRST,
     1205                UNIV_REGOFF_MISC_CTL);
    8551206}
    8561207
     
    8651216                        "lwzu 0, -4(%0)\n"
    8661217                        "stwbrx 0, 0, %0\n"
    867                         : "=r"(p) : "r"(p) : "r0"
     1218                        : "=r"(p) : "0"(p) : "r0"
    8681219                        );
    8691220#elif defined(__rtems__)
     
    8761227}
    8771228
     1229int
     1230vmeUniverseIntRaiseXX(volatile LERegister *base, int level, unsigned vector)
     1231{
     1232unsigned long v;
     1233unsigned long b;
     1234
     1235        CHECK_DFLT_BASE(base);
     1236
     1237        if ( level < 1 || level > 7 || vector > 255 )
     1238                return -1;      /* invalid argument */
     1239
     1240        if ( vector & 1 ) /* SW interrupts always ACK an even vector (pp 2-67) */
     1241                return -1;
     1242
     1243
     1244        /* Check if already asserted */
     1245        if ( vmeUniverseReadRegXX(base, UNIV_REGOFF_VINT_STAT ) & UNIV_VINT_STAT_SWINT(level) ) {
     1246                return -2;  /* already asserted */
     1247        }
     1248
     1249        /* Write Vector */
     1250        vmeUniverseWriteRegXX(base, UNIV_VINT_STATID(vector), UNIV_REGOFF_VINT_STATID );
     1251
     1252        if ( UNIV_REV(base) >= 2 ) {
     1253                /* universe II has individual bits for individual levels */
     1254                b = UNIV_VINT_STAT_SWINT(level);
     1255        } else {
     1256                /* version that is compatible with universe I */
     1257                v  = vmeUniverseReadRegXX(base, UNIV_REGOFF_VINT_MAP1);
     1258                v &= ~UNIV_VINT_MAP1_SWINT(0x7);
     1259                v |=  UNIV_VINT_MAP1_SWINT(level);
     1260                vmeUniverseWriteRegXX(base, v, UNIV_REGOFF_VINT_MAP1);
     1261                b  = UNIV_VINT_EN_SWINT;
     1262        }
     1263        v = vmeUniverseReadRegXX(base, UNIV_REGOFF_VINT_EN);
     1264        /* make sure it is clear, then assert */
     1265        vmeUniverseWriteRegXX(base, v & ~b, UNIV_REGOFF_VINT_EN );
     1266        vmeUniverseWriteRegXX(base, v |  b, UNIV_REGOFF_VINT_EN );
     1267
     1268        return 0;
     1269       
     1270}
     1271
     1272int
     1273vmeUniverseIntRaise(int level, unsigned vector)
     1274{
     1275        return vmeUniverseIntRaiseXX(vmeUniverse0BaseAddr, level, vector);
     1276}
     1277
     1278
    8781279/* RTEMS interrupt subsystem */
    8791280
     
    8901291
    8911292int        vmeUniverseIrqMgrInstalled=0;
    892 static int vmeIrqUnivOut=-1;
    893 static int specialIrqUnivOut=-1;
     1293
     1294/* We support 4 wires between universe + PIC */
     1295
     1296#define UNIV_NUM_WIRES 4
     1297
     1298static volatile unsigned long   wire_mask[UNIV_NUM_WIRES]     = {0};
     1299/* wires are offset by 1 so we can initialize the wire table to all zeros */
     1300static int                                              universe_wire[UNIV_NUM_WIRES] = {0};
     1301
     1302static int
     1303lvl2bit(unsigned int level)
     1304{
     1305int shift = -1;
     1306        if ( level >= UNIV_DMA_INT_VEC && level <= UNIV_LM3_INT_VEC ) {
     1307                shift = 8 + (level-UNIV_DMA_INT_VEC);
     1308        } else if ( UNIV_VOWN_INT_VEC == level ) {
     1309                shift = 0;
     1310        } else if ( 1 <= level && level <=7 ) {
     1311                shift = level;
     1312        } else {
     1313                /* invalid level */
     1314        }
     1315        return shift;
     1316}
     1317
     1318int
     1319vmeUniverseIntRoute(unsigned int level, unsigned int pin)
     1320{
     1321int                             i, shift;
     1322unsigned long   mask, mapreg, flags, wire;
     1323
     1324        if ( pin >= UNIV_NUM_WIRES || ! universe_wire[pin] || !vmeUniverseIrqMgrInstalled )
     1325                return -1;
     1326
     1327        if ( (shift = lvl2bit(level)) < 0 ) {
     1328                return -1; /* invalid level */
     1329        }
     1330
     1331        mask = 1<<shift;
     1332
     1333        /* calculate the mapping register and contents */
     1334        if ( shift < 8 ) {
     1335                mapreg = UNIV_REGOFF_LINT_MAP0;
     1336        } else if ( shift < 16 ) {
     1337                shift -= 8;
     1338                mapreg = UNIV_REGOFF_LINT_MAP1;
     1339        } else if ( shift < 24 ) {
     1340                shift -= 16;
     1341                mapreg = UNIV_REGOFF_LINT_MAP2;
     1342        } else {
     1343                return -1;
     1344        }
     1345
     1346        shift <<=2;
     1347
     1348        /* wires are offset by 1 so we can initialize the wire table to all zeros */
     1349        wire = (universe_wire[pin]-1) << shift;
     1350
     1351rtems_interrupt_disable(flags);
     1352
     1353        for ( i = 0; i<UNIV_NUM_WIRES; i++ ) {
     1354                wire_mask[i] &= ~mask;
     1355        }
     1356        wire_mask[pin] |= mask;
     1357
     1358        mask = vmeUniverseReadReg(mapreg) & ~ (0xf<<shift);
     1359        mask |= wire;
     1360        vmeUniverseWriteReg( mask, mapreg );
     1361
     1362rtems_interrupt_enable(flags);
     1363        return 0;
     1364}
    8941365
    8951366VmeUniverseISR
    8961367vmeUniverseISRGet(unsigned long vector, void **parg)
    8971368{
    898         if (vector>=UNIV_NUM_INT_VECS ||
    899                 ! universeHdlTbl[vector])
     1369unsigned long             flags;
     1370VmeUniverseISR                    rval = 0;
     1371volatile UniverseIRQEntry *pe  = universeHdlTbl + vector;
     1372
     1373        if ( vector>=UNIV_NUM_INT_VECS || ! *pe )
    9001374                return 0;
    901         if (parg)
    902                 *parg=universeHdlTbl[vector]->usrData;
    903         return universeHdlTbl[vector]->isr;
    904 }
     1375
     1376        rtems_interrupt_disable(flags);
     1377                if ( *pe ) {
     1378                        if (parg)
     1379                                *parg=(*pe)->usrData;
     1380                        rval = (*pe)->isr;
     1381                }
     1382        rtems_interrupt_enable(flags);
     1383        return rval;
     1384}
     1385
     1386#define SPECIAL_IRQ_MSK  ( ~((UNIV_LINT_STAT_VIRQ7<<1)-UNIV_LINT_STAT_VIRQ1) )
    9051387
    9061388static void
    907 universeSpecialISR(rtems_irq_hdl_param handle)
     1389universeSpecialISR(unsigned long status)
    9081390{
    9091391register UniverseIRQEntry       ip;
    9101392register unsigned                       vec;
    911 register unsigned long          status;
    912 
    913         status=vmeUniverseReadReg(UNIV_REGOFF_LINT_STAT);
    914 
    915         /* scan all LINT bits except for the 'normal' VME interrupts */
     1393register unsigned long          s;
     1394
     1395        /* handle all LINT bits except for the 'normal' VME interrupts */
     1396
     1397        /* clear all detected special interrupts */
     1398        vmeUniverseWriteReg( (status & SPECIAL_IRQ_MSK), UNIV_REGOFF_LINT_STAT );
    9161399
    9171400        /* do VOWN first */
     
    9261409         * the loop is left early if there are no more bits set.
    9271410         */
    928         for (status>>=8; status; status>>=1) {
     1411        for ( s = status>>8; s; s >>= 1) {
    9291412                vec++;
    930                 if ((status&1) && (ip=universeHdlTbl[vec]))
     1413                if ( (s&1) && (ip=universeHdlTbl[vec]) )
    9311414                        ip->isr(ip->usrData,vec);
    9321415        }
    933         /* clear all special interrupts */
    934         vmeUniverseWriteReg(
    935                                         ~((UNIV_LINT_STAT_VIRQ7<<1)-UNIV_LINT_STAT_VIRQ1),
    936                                         UNIV_REGOFF_LINT_STAT
    937                                         );
    9381416
    9391417/*
     
    9511429 *
    9521430 *
    953  *   VME IRQ ------
    954  *                  & ----- LINT_STAT ----
     1431 *   VME IRQ ------ 
     1432 *                  & ----- LINT_STAT ---- 
    9551433 *                  |                       &  ---------- PCI LINE
    9561434 *                  |                       |
    957  *                  |                       |
    958  *       LINT_EN ---------------------------
    959  *
    960  *  I.e.
     1435 *                  |                       | 
     1436 *       LINT_EN --------------------------- 
     1437 *
     1438 *  I.e. 
    9611439 *   - if LINT_EN is disabled, a VME IRQ will not set LINT_STAT.
    9621440 *   - while LINT_STAT is set, it will pull the PCI line unless
     
    9791457
    9801458static void
    981 universeVMEISR(rtems_irq_hdl_param handle)
    982 {
    983 UniverseIRQEntry ip;
    984 unsigned long lvl,msk,lintstat,linten,status;
     1459universeVMEISR(rtems_irq_hdl_param arg)
     1460{
     1461int                                     pin = (int)arg;
     1462UniverseIRQEntry        ip;
     1463unsigned long           msk,lintstat,status;
     1464int                                     lvl;
     1465#ifdef BSP_PIC_DO_EOI
     1466unsigned long           linten;
     1467#endif
    9851468
    9861469                /* determine the highest priority IRQ source */
    987                 lintstat=vmeUniverseReadReg(UNIV_REGOFF_LINT_STAT);
     1470                lintstat  = vmeUniverseReadReg(UNIV_REGOFF_LINT_STAT);
     1471
     1472                /* only handle interrupts routed to this pin */
     1473                lintstat &= wire_mask[pin];
     1474
     1475#ifdef __PPC__
     1476                asm volatile("cntlzw %0, %1":"=r"(lvl):"r"(lintstat & ~SPECIAL_IRQ_MSK));
     1477                lvl = 31-lvl;
     1478                msk = 1<<lvl;
     1479#else
    9881480                for (msk=UNIV_LINT_STAT_VIRQ7, lvl=7;
    9891481                         lvl>0;
     
    9911483                        if (lintstat & msk) break;
    9921484                }
    993                 if (!lvl) {
     1485#endif
     1486
     1487#ifndef BSP_PIC_DO_EOI /* Software priorities not supported */
     1488
     1489                if ( (status = (lintstat & SPECIAL_IRQ_MSK)) )
     1490                        universeSpecialISR( status );
     1491
     1492                if ( lvl <= 0)
     1493                        return;
     1494
     1495#else
     1496                if ( lvl <= 0 ) {
    9941497                                /* try the special handler */
    995                                 universeSpecialISR(NULL);
    996 
    997                                 /*
     1498                                universeSpecialISR( lintstat & SPECIAL_IRQ_MSK );
     1499
     1500                                /* 
    9981501                                 * let the pic end this cycle
    9991502                                 */
    1000                                 BSP_PIC_DO_EOI;
     1503                                if ( 0 == pin )
     1504                                        BSP_PIC_DO_EOI;
    10011505
    10021506                                return;
     
    10041508                linten = vmeUniverseReadReg(UNIV_REGOFF_LINT_EN);
    10051509
    1006                 /* mask this and all lower levels */
     1510                /* mask this and all lower levels that are routed to the same pin */
    10071511                vmeUniverseWriteReg(
    1008                                                 linten & ~((msk<<1)-UNIV_LINT_STAT_VIRQ1),
     1512                                                linten & ~( ((msk<<1)-UNIV_LINT_STAT_VIRQ1) & wire_mask[pin]),
    10091513                                                UNIV_REGOFF_LINT_EN
    10101514                                                );
     
    10141518                 * caught from now on...
    10151519                 */
    1016                 BSP_PIC_DO_EOI;
     1520                if ( 0 == pin )
     1521                        BSP_PIC_DO_EOI;
     1522#endif
    10171523
    10181524                /* get vector and dispatch handler */
     
    10221528                if (status & UNIV_VIRQ_ERR) {
    10231529                                /* TODO: log error message - RTEMS has no logger :-( */
     1530                        printk("vmeUniverse ISR: error read from STATID register; (level: %i) STATID: 0x%08x\n", lvl, status);
    10241531                } else if (!(ip=universeHdlTbl[status & UNIV_VIRQ_STATID_MASK])) {
    10251532                                /* TODO: log error message - RTEMS has no logger :-( */
     1533                        printk("vmeUniverse ISR: no handler installed for this vector; (level: %i) STATID: 0x%08x\n", lvl, status);
    10261534                } else {
    10271535                                /* dispatch handler, it must clear the IRQ at the device */
     
    10291537                }
    10301538
    1031                 /* clear this interrupt level */
     1539                /* clear this interrupt level; allow the universe to handler further interrupts */
    10321540                vmeUniverseWriteReg(msk, UNIV_REGOFF_LINT_STAT);
     1541
    10331542/*
    10341543 *  this seems not to be necessary; we just leave the
     
    10391548*/
    10401549
     1550#ifdef BSP_PIC_DO_EOI
     1551
    10411552                /* re-enable the previous level */
    10421553                vmeUniverseWriteReg(linten, UNIV_REGOFF_LINT_EN);
    1043 }
     1554#endif
     1555}
     1556
    10441557
    10451558/* STUPID API */
     
    10541567}
    10551568
    1056 int
    1057 vmeUniverseInstallIrqMgr(int vmeOut,
     1569typedef struct {
     1570        int uni_pin, pic_pin;
     1571} IntRoute;
     1572
     1573static void
     1574connectIsr(int shared, rtems_irq_hdl isr, int pic_line, int pic_pin)
     1575{
     1576rtems_irq_connect_data  aarrggh;
     1577        aarrggh.on     = my_no_op; /* at _least_ they could check for a 0 pointer */
     1578        aarrggh.off    = my_no_op;
     1579        aarrggh.isOn   = my_isOn;
     1580        aarrggh.hdl    = isr;
     1581        aarrggh.handle = (rtems_irq_hdl_param)pic_pin;
     1582        aarrggh.name   = pic_line;
     1583
     1584        if ( shared ) {
     1585#if BSP_SHARED_HANDLER_SUPPORT > 0
     1586                if (!BSP_install_rtems_shared_irq_handler(&aarrggh))
     1587                        BSP_panic("unable to install vmeUniverse shared irq handler");
     1588#else
     1589                uprintf(stderr,"vmeUniverse: WARNING: your BSP doesn't support sharing interrupts\n");
     1590                if (!BSP_install_rtems_irq_handler(&aarrggh))
     1591                        BSP_panic("unable to install vmeUniverse irq handler");
     1592#endif
     1593        } else {
     1594                if (!BSP_install_rtems_irq_handler(&aarrggh))
     1595                        BSP_panic("unable to install vmeUniverse irq handler");
     1596        }
     1597}
     1598
     1599int
     1600vmeUniverseInstallIrqMgrAlt(int shared, int uni_pin0, int pic_pin0, ...)
     1601{
     1602int             rval;
     1603va_list ap;
     1604        va_start(ap, pic_pin0);
     1605        rval = vmeUniverseInstallIrqMgrVa(shared, uni_pin0, pic_pin0, ap);
     1606        va_end(ap);
     1607        return rval;
     1608}
     1609
     1610int
     1611vmeUniverseInstallIrqMgrVa(int shared, int uni_pin0, int pic_pin0, va_list ap)
     1612{
     1613int     i,j, specialPin, uni_pin[UNIV_NUM_WIRES+1], pic_pin[UNIV_NUM_WIRES];
     1614
     1615        if (vmeUniverseIrqMgrInstalled)                return -4;
     1616
     1617        /* check parameters */
     1618
     1619        if ( uni_pin0 < 0 || uni_pin0 > 7 )            return -1;
     1620
     1621        uni_pin[0] = uni_pin0;
     1622        pic_pin[0] = pic_pin0 < 0 ? vmeUniverse0PciIrqLine : pic_pin0;
     1623        i = 1;
     1624        while ( (uni_pin[i] = va_arg(ap, int)) >= 0 ) {
     1625               
     1626                if ( i >= UNIV_NUM_WIRES ) {
     1627                                                               return -5;
     1628                }
     1629
     1630                pic_pin[i] = va_arg(ap,int);
     1631
     1632                if ( uni_pin[i] > 7 ) {
     1633                                                   return -2;
     1634                }
     1635                if ( pic_pin[i] < 0 ) {
     1636                                                   return -3;
     1637                }
     1638                i++;
     1639        }
     1640
     1641        /* all routings must be different */
     1642        for ( i=0; uni_pin[i] >= 0; i++ ) {
     1643                for ( j=i+1; uni_pin[j] >= 0; j++ ) {
     1644                        if ( uni_pin[j] == uni_pin[i] )        return -6;
     1645                        if ( pic_pin[j] == pic_pin[i] )        return -7;
     1646                }
     1647        }
     1648
     1649        /* give them a chance to override buggy PCI info */
     1650        if ( pic_pin[0] >= 0 && vmeUniverse0PciIrqLine != pic_pin[0] ) {
     1651                uprintf(stderr,"Overriding main IRQ line PCI info with %d\n",
     1652                                pic_pin[0]);
     1653                vmeUniverse0PciIrqLine=pic_pin[0];
     1654        }
     1655
     1656        for ( i = 0; uni_pin[i] >= 0; i++ ) {
     1657                /* offset wire # by one so we can initialize to 0 == invalid */
     1658                universe_wire[i] = uni_pin[i] + 1;
     1659                connectIsr(shared, universeVMEISR, pic_pin[i], i);
     1660        }
     1661
     1662        specialPin = uni_pin[1] >= 0 ? 1 : 0;
     1663
     1664        /* setup routing */
     1665
     1666        /* IntRoute checks for mgr being installed */
     1667        vmeUniverseIrqMgrInstalled=1;
     1668
     1669        /* route 7 VME irqs to first / 'normal' pin */
     1670        for ( i=1; i<8; i++ )
     1671                vmeUniverseIntRoute( i, 0 );
     1672        for ( i=UNIV_VOWN_INT_VEC; i<=UNIV_LM3_INT_VEC; i++ ) {
     1673                if ( vmeUniverseIntRoute( i, specialPin ) )
     1674                        printk("Routing lvl %i -> wire # %i failed\n", i, specialPin);
     1675        }
     1676
     1677        return 0;
     1678}
     1679
     1680int
     1681vmeUniverseInstallIrqMgr(int vmeIrqUnivOut,
    10581682                                                 int vmeIrqPicLine,
    1059                                                  int specialOut,
     1683                                                 int specialIrqUnivOut,
    10601684                                                 int specialIrqPicLine)
    10611685{
    1062 rtems_irq_connect_data aarrggh;
    1063 
    1064         /* check parameters */
    1065         if ((vmeIrqUnivOut=vmeOut) < 0 || vmeIrqUnivOut > 7) return -1;
    1066         if ((specialIrqUnivOut=specialOut) > 7) return -2;
    1067         if (specialOut >=0 && specialIrqPicLine < 0) return -3;
    1068         /* give them a chance to override buggy PCI info */
    1069         if (vmeIrqPicLine >= 0) {
    1070                 uprintf(stderr,"Overriding main IRQ line PCI info with %d\n",
    1071                                 vmeIrqPicLine);
    1072                 vmeUniverse0PciIrqLine=vmeIrqPicLine;
    1073         }
    1074 
    1075         if (vmeUniverseIrqMgrInstalled) return -4;
    1076 
    1077         aarrggh.on=my_no_op; /* at _least_ they could check for a 0 pointer */
    1078         aarrggh.off=my_no_op;
    1079         aarrggh.isOn=my_isOn;
    1080         aarrggh.hdl=universeVMEISR;
    1081         aarrggh.name=vmeUniverse0PciIrqLine + BSP_PCI_IRQ0;
    1082         if (!BSP_install_rtems_irq_handler(&aarrggh))
    1083                         BSP_panic("unable to install vmeUniverse irq handler");
    1084         if (specialIrqUnivOut > 0) {
    1085                         /* install the special handler to a separate irq */
    1086                         aarrggh.hdl=universeSpecialISR;
    1087                         aarrggh.name=specialIrqPicLine + BSP_PCI_IRQ0;
    1088                         if (!BSP_install_rtems_irq_handler(&aarrggh))
    1089                                 BSP_panic("unable to install vmeUniverse secondary irq handler");
    1090         } else {
    1091                 specialIrqUnivOut = vmeIrqUnivOut;
    1092         }
    1093         /* setup routing */
    1094 
    1095         vmeUniverseWriteReg(
    1096                 (UNIV_LINT_MAP0_VIRQ7(vmeIrqUnivOut) |
    1097                  UNIV_LINT_MAP0_VIRQ6(vmeIrqUnivOut) |
    1098                  UNIV_LINT_MAP0_VIRQ5(vmeIrqUnivOut) |
    1099                  UNIV_LINT_MAP0_VIRQ4(vmeIrqUnivOut) |
    1100                  UNIV_LINT_MAP0_VIRQ3(vmeIrqUnivOut) |
    1101                  UNIV_LINT_MAP0_VIRQ2(vmeIrqUnivOut) |
    1102                  UNIV_LINT_MAP0_VIRQ1(vmeIrqUnivOut) |
    1103                  UNIV_LINT_MAP0_VOWN(specialIrqUnivOut)
    1104                 ),
    1105                 UNIV_REGOFF_LINT_MAP0);
    1106         vmeUniverseWriteReg(
    1107                 (UNIV_LINT_MAP1_ACFAIL(specialIrqUnivOut) |
    1108                  UNIV_LINT_MAP1_SYSFAIL(specialIrqUnivOut) |
    1109                  UNIV_LINT_MAP1_SW_INT(specialIrqUnivOut) |
    1110                  UNIV_LINT_MAP1_SW_IACK(specialIrqUnivOut) |
    1111                  UNIV_LINT_MAP1_VERR(specialIrqUnivOut) |
    1112                  UNIV_LINT_MAP1_LERR(specialIrqUnivOut) |
    1113                  UNIV_LINT_MAP1_DMA(specialIrqUnivOut)
    1114                 ),
    1115                 UNIV_REGOFF_LINT_MAP1);
    1116         vmeUniverseIrqMgrInstalled=1;
    1117         return 0;
     1686        return vmeUniverseInstallIrqMgrAlt(
     1687                                0,      /* bwds compat. */
     1688                                vmeIrqUnivOut, vmeIrqPicLine,
     1689                                specialIrqUnivOut, specialIrqPicLine,
     1690                                -1);
    11181691}
    11191692
     
    11211694vmeUniverseInstallISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
    11221695{
    1123 UniverseIRQEntry ip;
     1696UniverseIRQEntry          ip;
     1697unsigned long             flags;
     1698volatile UniverseIRQEntry *pe;
    11241699
    11251700                if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !vmeUniverseIrqMgrInstalled)
    11261701                                return -1;
    11271702
    1128                 ip=universeHdlTbl[vector];
    1129 
    1130                 if (ip || !(ip=(UniverseIRQEntry)malloc(sizeof(UniverseIRQEntryRec))))
     1703                pe = universeHdlTbl + vector;
     1704
     1705                if (*pe || !(ip=(UniverseIRQEntry)malloc(sizeof(UniverseIRQEntryRec))))
    11311706                                return -1;
     1707
    11321708                ip->isr=hdl;
    11331709                ip->usrData=arg;
    1134                 universeHdlTbl[vector]=ip;
     1710
     1711        rtems_interrupt_disable(flags);
     1712                if ( *pe ) {
     1713                        /* oops; someone intervened */
     1714                        rtems_interrupt_enable(flags);
     1715                        free(ip);
     1716                        return -1;
     1717                }
     1718                *pe = ip;
     1719        rtems_interrupt_enable(flags);
    11351720                return 0;
    11361721}
     
    11391724vmeUniverseRemoveISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
    11401725{
    1141 UniverseIRQEntry ip;
     1726UniverseIRQEntry          ip;
     1727unsigned long             flags;
     1728volatile UniverseIRQEntry *pe;
    11421729
    11431730                if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !vmeUniverseIrqMgrInstalled)
    11441731                                return -1;
    11451732
    1146                 ip=universeHdlTbl[vector];
    1147 
    1148                 if (!ip || ip->isr!=hdl || ip->usrData!=arg)
    1149                                 return -1;
    1150                 universeHdlTbl[vector]=0;
     1733                pe = universeHdlTbl + vector;
     1734
     1735        rtems_interrupt_disable(flags);
     1736                ip = *pe;
     1737                if (!ip || ip->isr!=hdl || ip->usrData!=arg) {
     1738                        rtems_interrupt_enable(flags);
     1739                        return -1;
     1740                }
     1741                *pe = 0;
     1742        rtems_interrupt_enable(flags);
    11511743                free(ip);
    11521744                return 0;
    11531745}
    11541746
     1747static int
     1748intDoEnDis(unsigned int level, int dis)
     1749{
     1750unsigned long   flags, v;
     1751int                             shift;
     1752
     1753        if (  ! vmeUniverseIrqMgrInstalled || (shift = lvl2bit(level)) < 0 )
     1754                return -1;
     1755
     1756        v = 1<<shift;
     1757
     1758        if ( !dis )
     1759                return vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) & v ? 1 : 0;
     1760
     1761        rtems_interrupt_disable(flags);
     1762        if ( dis<0 )
     1763                vmeUniverseWriteReg( vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) & ~v, UNIV_REGOFF_LINT_EN );
     1764        else {
     1765                vmeUniverseWriteReg( vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) |  v, UNIV_REGOFF_LINT_EN  );
     1766        }
     1767        rtems_interrupt_enable(flags);
     1768                return 0;
     1769}
     1770
    11551771int
    11561772vmeUniverseIntEnable(unsigned int level)
    11571773{
    1158                 if (!vmeUniverseIrqMgrInstalled || level<1 || level>7)
    1159                                 return -1;
    1160                 vmeUniverseWriteReg(
    1161                                 (vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) |
    1162                                  (UNIV_LINT_EN_VIRQ1 << (level-1))
    1163                                 ),
    1164                                 UNIV_REGOFF_LINT_EN);
    1165                 return 0;
     1774        return intDoEnDis(level, 1);
    11661775}
    11671776
     
    11691778vmeUniverseIntDisable(unsigned int level)
    11701779{
    1171                 if (!vmeUniverseIrqMgrInstalled || level<1 || level>7)
    1172                                 return -1;
    1173                 vmeUniverseWriteReg(
    1174                                 (vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) &
    1175                                  ~ (UNIV_LINT_EN_VIRQ1 << (level-1))
    1176                                 ),
    1177                                 UNIV_REGOFF_LINT_EN);
    1178                 return 0;
    1179 }
    1180 
    1181 #endif
     1780        return intDoEnDis(level, -1);
     1781}
     1782
     1783int
     1784vmeUniverseIntIsEnabled(unsigned int level)
     1785{
     1786        return intDoEnDis(level, 0);
     1787}
     1788
     1789/* Loopback test of VME/universe interrupts */
     1790
     1791typedef struct {
     1792        rtems_id        q;
     1793        int                     l;
     1794} LoopbackTstArgs;
     1795
     1796static void
     1797loopbackTstIsr(void *arg, unsigned long vector)
     1798{
     1799LoopbackTstArgs *pa = arg;
     1800        if ( RTEMS_SUCCESSFUL != rtems_message_queue_send(pa->q, (void*)&vector, sizeof(vector)) ) {
     1801                /* Overrun ? */
     1802                printk("vmeUniverseIntLoopbackTst: (ISR) message queue full / overrun ? disabling IRQ level %i\n", pa->l);
     1803                vmeUniverseIntDisable(pa->l);
     1804        }
     1805}
     1806
     1807int
     1808vmeUniverseIntLoopbackTst(int level, unsigned vector)
     1809{
     1810DFLT_BASE;
     1811rtems_status_code       sc;
     1812rtems_id                        q = 0;
     1813int                                     installed = 0;
     1814int                                     i, err = 0;
     1815int                                     doDisable = 0;
     1816unsigned32                      size;
     1817unsigned long           msg;
     1818char *                          irqfmt  = "VME IRQ @vector %3i %s";
     1819char *                          iackfmt = "VME IACK            %s";
     1820LoopbackTstArgs         a;
     1821
     1822        CHECK_DFLT_BASE(base);
     1823
     1824        /* arg check */
     1825        if ( level < 1 || level > 7 || vector > 255 )
     1826                return -1;
     1827
     1828        if ( UNIV_REV(base) < 2 && vector != 0 ) {
     1829                fprintf(stderr,
     1830                        "vmeUniverseIntLoopbackTst(): Universe 1 has a bug. IACK in response to\n");
     1831                fprintf(stderr,
     1832                        "self-generated VME interrupt yields always a zero vector. As a workaround,\n");
     1833                fprintf(stderr,
     1834                        "use vector 0, please.\n");
     1835                return -1;
     1836        }
     1837
     1838        /* Create message queue */
     1839        if ( RTEMS_SUCCESSFUL != (sc=rtems_message_queue_create(
     1840                                                                        rtems_build_name('t' ,'U','I','I'),
     1841                                                                        4,
     1842                                                                        sizeof(unsigned long),
     1843                                                                        0,  /* default attributes: fifo, local */
     1844                                                                        &q)) ) {
     1845                rtems_error(sc, "vmeUniverseIntLoopbackTst: Unable to create message queue");
     1846                goto bail;
     1847        }
     1848
     1849        a.q = q;
     1850        a.l = level;
     1851
     1852        /* Install handlers */
     1853        if ( vmeUniverseInstallISR(vector, loopbackTstIsr, (void*)&a) ) {
     1854                fprintf(stderr,"Unable to install VME ISR to vector %i\n",vector);
     1855                goto bail;
     1856        }
     1857        installed++;
     1858        if ( vmeUniverseInstallISR(UNIV_VME_SW_IACK_INT_VEC, loopbackTstIsr, (void*)&a) ) {
     1859                fprintf(stderr,"Unable to install VME ISR to IACK special vector %i\n",UNIV_VME_SW_IACK_INT_VEC);
     1860                goto bail;
     1861        }
     1862        installed++;
     1863
     1864        if ( !vmeUniverseIntIsEnabled(level) && 0==vmeUniverseIntEnable(level) )
     1865                doDisable = 1;
     1866       
     1867        /* make sure there are no pending interrupts */
     1868        vmeUniverseWriteReg( UNIV_LINT_STAT_SW_IACK,  UNIV_REGOFF_LINT_STAT );
     1869
     1870        if ( vmeUniverseIntEnable( UNIV_VME_SW_IACK_INT_VEC ) ) {
     1871                fprintf(stderr,"Unable to enable IACK interrupt\n");
     1872                goto bail;
     1873        }       
     1874
     1875        printf("vmeUniverse VME interrupt loopback test; STARTING...\n");
     1876        printf(" --> asserting VME IRQ level %i\n", level);
     1877        vmeUniverseIntRaise(level, vector);
     1878
     1879        for ( i = 0; i< 3; i++ ) {
     1880        sc = rtems_message_queue_receive(
     1881                            q,
     1882                            &msg,
     1883                            &size,
     1884                            RTEMS_WAIT,
     1885                            20);
     1886                if ( sc ) {
     1887                        if ( RTEMS_TIMEOUT == sc && i>1 ) {
     1888                                /* OK; we dont' expect more to happen */
     1889                                sc = 0;
     1890                        } else {
     1891                                rtems_error(sc,"Error waiting for interrupts");
     1892                        }
     1893                        break;
     1894                }
     1895                if ( msg == vector ) {
     1896                        if ( !irqfmt ) {
     1897                                printf("Excess VME IRQ received ?? -- BAD\n");
     1898                                err = 1;
     1899                        } else {
     1900                                printf(irqfmt, vector, "received -- PASSED\n");
     1901                                irqfmt = 0;
     1902                        }
     1903                } else if ( msg == UNIV_VME_SW_IACK_INT_VEC ) {
     1904                        if ( !iackfmt ) {
     1905                                printf("Excess VME IACK received ?? -- BAD\n");
     1906                                err = 1;
     1907                        } else {
     1908                                printf(iackfmt, "received -- PASSED\n");
     1909                                iackfmt = 0;
     1910                        }
     1911                } else {
     1912                        printf("Unknown IRQ (vector %lu) received -- BAD\n", msg);
     1913                        err = 1;
     1914                }
     1915        }
     1916
     1917
     1918        /* Missing anything ? */
     1919        if ( irqfmt ) {
     1920                printf(irqfmt,vector, "MISSED -- BAD\n");
     1921                err = 1;
     1922        }
     1923        if ( iackfmt ) {
     1924                printf(iackfmt, "MISSED -- BAD\n");
     1925                err = 1;
     1926        }
     1927
     1928        printf("FINISHED.\n");
     1929
     1930bail:
     1931        if ( doDisable )
     1932                vmeUniverseIntDisable(level);
     1933        vmeUniverseIntDisable( UNIV_VME_SW_IACK_INT_VEC );
     1934        if ( installed > 0 )
     1935                vmeUniverseRemoveISR(vector, loopbackTstIsr, (void*)&a);
     1936        if ( installed > 1 )
     1937                vmeUniverseRemoveISR(UNIV_VME_SW_IACK_INT_VEC, loopbackTstIsr, (void*)&a);
     1938        if ( q )
     1939                rtems_message_queue_delete(q);
     1940
     1941        return sc ? sc : err;
     1942}
     1943
     1944#endif
  • c/src/lib/libbsp/shared/vmeUniverse/vmeUniverse.h

    r6d3ff66f r784e792  
    1414#include <vme.h>
    1515#else
     16
    1617/* vxworks compatible addressing modes */
     18
     19#ifndef VME_AM_STD_SUP_ASCENDING
    1720#define VME_AM_STD_SUP_ASCENDING        0x3f
    18 #define VME_AM_STD_SUP_PGM      0x3e
     21#endif
     22#ifndef VME_AM_STD_SUP_PGM
     23#define VME_AM_STD_SUP_PGM                      0x3e
     24#endif
     25#ifndef VME_AM_STD_USR_ASCENDING
    1926#define VME_AM_STD_USR_ASCENDING        0x3b
    20 #define VME_AM_STD_USR_PGM      0x3a
    21 #define VME_AM_STD_SUP_DATA     0x3d
    22 #define VME_AM_STD_USR_DATA     0x39
     27#endif
     28#ifndef VME_AM_STD_USR_PGM
     29#define VME_AM_STD_USR_PGM                      0x3a
     30#endif
     31#ifndef VME_AM_STD_SUP_DATA
     32#define VME_AM_STD_SUP_DATA                     0x3d
     33#endif
     34#ifndef VME_AM_STD_USR_DATA
     35#define VME_AM_STD_USR_DATA                     0x39
     36#endif
     37#ifndef VME_AM_EXT_SUP_ASCENDING
    2338#define VME_AM_EXT_SUP_ASCENDING        0x0f
    24 #define VME_AM_EXT_SUP_PGM      0x0e
     39#endif
     40#ifndef VME_AM_EXT_SUP_PGM
     41#define VME_AM_EXT_SUP_PGM                      0x0e
     42#endif
     43#ifndef VME_AM_EXT_USR_ASCENDING
    2544#define VME_AM_EXT_USR_ASCENDING        0x0b
    26 #define VME_AM_EXT_USR_PGM      0x0a
    27 #define VME_AM_EXT_SUP_DATA     0x0d
    28 #define VME_AM_EXT_USR_DATA     0x09
    29 #define VME_AM_SUP_SHORT_IO     0x2d
    30 #define VME_AM_USR_SHORT_IO     0x29
    31 
    32 #define VME_AM_IS_SHORT(a)      (((a) & 0xf0) == 0x20)
    33 #define VME_AM_IS_STD(a)        (((a) & 0xf0) == 0x30)
    34 #define VME_AM_IS_EXT(a)        (((a) & 0xf0) == 0x00)
    35 
    36 #endif
     45#endif
     46#ifndef VME_AM_EXT_USR_PGM
     47#define VME_AM_EXT_USR_PGM                      0x0a
     48#endif
     49#ifndef VME_AM_EXT_SUP_DATA
     50#define VME_AM_EXT_SUP_DATA                     0x0d
     51#endif
     52#ifndef VME_AM_EXT_USR_DATA
     53#define VME_AM_EXT_USR_DATA                     0x09
     54#endif
     55#ifndef VME_AM_SUP_SHORT_IO
     56#define VME_AM_SUP_SHORT_IO                     0x2d
     57#endif
     58#ifndef VME_AM_USR_SHORT_IO
     59#define VME_AM_USR_SHORT_IO                     0x29
     60#endif
     61#ifndef VME_AM_IS_SHORT
     62#define VME_AM_IS_SHORT(a)                      (((a) & 0xf0) == 0x20)
     63#endif
     64#ifndef VME_AM_IS_STD
     65#define VME_AM_IS_STD(a)                        (((a) & 0xf0) == 0x30)
     66#endif
     67#ifndef VME_AM_IS_EXT
     68#define VME_AM_IS_EXT(a)                        (((a) & 0xf0) == 0x00)
     69#endif
     70#ifndef VME_AM_IS_SUP
     71#define VME_AM_IS_SUP(a)                        ((a)  & 4)
     72#endif
     73#ifndef VME_AM_MASK
     74#define VME_AM_MASK                                     0xff
     75#endif
     76
     77#endif
     78
     79#include <stdarg.h>
    3780
    3881typedef unsigned long LERegister; /* emphasize contents are little endian */
     
    204247# define        UNIV_D_LLUE_UPDATE      (1<<31)
    205248
     249
    206250/* PCI (local) interrupt enable register */
    207251#define         UNIV_REGOFF_LINT_EN     0x300
     
    280324#define         UNIV_REGOFF_VINT_EN             0x310
    281325# define        UNIV_VINT_EN_DISABLE_ALL    0
    282 
    283 /* status of generation of VME bus IRQs, TODO */
     326# define        UNIV_VINT_EN_SWINT                      (1<<12)
     327# define        UNIV_VINT_EN_SWINT_LVL(l)       (1<<(((l)&7)+24))       /* universe II only */
     328
     329
     330/* status of generation of VME bus IRQs */
    284331#define         UNIV_REGOFF_VINT_STAT   0x314
    285332# define        UNIV_VINT_STAT_LINT(lint)       (1<<((lint)&7))
    286333# define        UNIV_VINT_STAT_LINT_MASK        (0xff)
    287334# define        UNIV_VINT_STAT_CLR                      (0xfe0f17ff)
     335# define        UNIV_VINT_STAT_SWINT(l)     (1<<(((l)&7)+24))
     336
    288337#define         UNIV_REGOFF_VINT_MAP0   0x318   /* VME destination of PCI IRQ source, TODO */
     338
    289339#define         UNIV_REGOFF_VINT_MAP1   0x31c   /* VME destination of PCI IRQ source, TODO */
     340# define        UNIV_VINT_MAP1_SWINT(level)     (((level)&0x7)<<16)
     341
     342/* NOTE: The universe seems to always set LSB (which has a special purpose in
     343 *       the STATID register: enable raising a SW_INT on IACK) on the
     344 *               vector it puts out on the bus...
     345 */
    290346#define         UNIV_REGOFF_VINT_STATID 0x320   /* our status/id response to IACK, TODO */
     347# define        UNIV_VINT_STATID(id)        ((id)<<24)
    291348
    292349#define         UNIV_REGOFF_VIRQ1_STATID 0x324  /* status/id of VME IRQ level 1 */
     
    361418/* Location Monitor control register */
    362419#define         UNIV_REGOFF_LM_CTL              0xf64
    363 # define        UNIV_LM_CTL_EN                          (1<<31) /* image enable */
     420# define        UNIV_LM_CTL_EN                          (1<<31) /* image enable */ 
    364421# define        UNIV_LM_CTL_PGM                         (1<<23) /* program AM */
    365422# define        UNIV_LM_CTL_DATA                        (1<<22) /* data AM */
     
    375432/* VMEbus register access image control register */
    376433#define         UNIV_REGOFF_VRAI_CTL    0xf70
    377 # define        UNIV_VRAI_CTL_EN                        (1<<31) /* image enable */
     434# define        UNIV_VRAI_CTL_EN                        (1<<31) /* image enable */ 
    378435# define        UNIV_VRAI_CTL_PGM                       (1<<23) /* program AM */
    379436# define        UNIV_VRAI_CTL_DATA                      (1<<22) /* data AM */
     
    434491extern int vmeUniverse0PciIrqLine;
    435492
     493
    436494/* Initialize the driver */
    437495int
     
    452510 */
    453511#ifdef _VME_UNIVERSE_DECLARE_SHOW_ROUTINES
    454 /* print the current configuration of all master ports to
     512/* print the current configuration of all master ports to 
    455513 * f (stderr if NULL)
    456514 */
     
    509567/* translate an address through the bridge
    510568 *
    511  * vmeUniverseXlateAddr(0,0,addr,as,&result)
     569 * vmeUniverseXlateAddr(0,0,as,addr,&result)
    512570 * yields a VME a address that reflects
    513571 * a local memory location as seen from the VME bus through the universe
    514572 * VME slave.
    515573 *
    516  * likewise does vmeUniverseXlateAddr(1,0,addr,as,&result)
     574 * likewise does vmeUniverseXlateAddr(1,0,as,addr,&result)
    517575 * translate a VME bus addr (through the VME master) to the
    518576 * PCI side of the bridge.
     
    576634
    577635/* reset the VME bus */
    578 static inline void
    579 vmeUniverseResetBus(void)
    580 {
    581         vmeUniverseWriteReg(
    582                 vmeUniverseReadReg(UNIV_REGOFF_MISC_CTL) | UNIV_MISC_CTL_SW_SYSRST,
    583                 UNIV_REGOFF_MISC_CTL);
    584 }
     636void
     637vmeUniverseResetBus(void);
     638
     639/* The ...XX routines take the universe base address as an additional
     640 * argument - this allows for programming secondary devices.
     641 */
     642
     643unsigned long
     644vmeUniverseReadRegXX(volatile LERegister *ubase, unsigned long offset);
     645
     646void
     647vmeUniverseWriteRegXX(volatile LERegister *ubase, unsigned long value, unsigned long offset);
     648
     649int
     650vmeUniverseXlateAddrXX(
     651        volatile LERegister *ubase,
     652        int master,
     653        int reverse,
     654        unsigned long as,
     655        unsigned long addr,
     656        unsigned long *paOut
     657        );
     658
     659int
     660vmeUniverseMasterPortCfgXX(
     661        volatile LERegister *ubase,
     662        unsigned long   port,
     663        unsigned long   address_space,
     664        unsigned long   vme_address,
     665        unsigned long   local_address,
     666        unsigned long   length);
     667
     668int
     669vmeUniverseSlavePortCfgXX(
     670        volatile LERegister *ubase,
     671        unsigned long   port,
     672        unsigned long   address_space,
     673        unsigned long   vme_address,
     674        unsigned long   local_address,
     675        unsigned long   length);
     676
     677void
     678vmeUniverseDisableAllMastersXX(volatile LERegister *ubase);
     679
     680void
     681vmeUniverseDisableAllSlavesXX(volatile LERegister *ubase);
     682
     683#ifdef _VME_UNIVERSE_DECLARE_SHOW_ROUTINES
     684/* print the current configuration of all master ports to
     685 * f (stderr if NULL)
     686 */
     687void
     688vmeUniverseMasterPortsShowXX(
     689        volatile LERegister *ubase,FILE *f);
     690
     691/* print the current configuration of all slave ports to
     692 * f (stderr if NULL)
     693 */
     694void
     695vmeUniverseSlavePortsShowXX(
     696        volatile LERegister *ubase,FILE *f);
     697#else
     698void
     699vmeUniverseMasterPortsShowXX();
     700void
     701vmeUniverseSlavePortsShowXX();
     702#endif
     703
     704int
     705vmeUniverseStartDMAXX(
     706        volatile LERegister *ubase,
     707        unsigned long local_addr,
     708        unsigned long vme_addr,
     709        unsigned long count);
     710
     711/* Raise a VME Interrupt at 'level' and respond with 'vector' to a
     712 * handler on the VME bus. (The handler could be a different board
     713 * or the universe itself - [only works with universe II]).
     714 *
     715 * Note that you could install a interrupt handler at UNIV_VME_SW_IACK_INT_VEC
     716 * to be notified of an IACK cycle having completed.
     717 *
     718 * This routine is mainly FOR TESTING.
     719 *
     720 * NOTES:
     721 *   - several registers are modified: the vector is written to VINT_STATID
     722 *     and (universe 1 chip only) the level is written to the SW_INT bits
     723 *     int VINT_MAP1
     724 *   - NO MUTUAL EXCLUSION PROTECTION (reads VINT_EN, modifies then writes back).
     725 *     If several users need access to VINT_EN and/or VINT_STATID (and VINT_MAP1
     726 *     on the universe 1) it is their responsibility to serialize access.
     727 *
     728 * Arguments:
     729 *  'level':  interrupt level, 1..7
     730 *  'vector': vector number (0..254) that the universe puts on the bus in response to
     731 *            an IACK cycle. NOTE: the vector number *must be even* (hardware restriction
     732 *            of the universe -- it always clears the LSB when the interrupter is
     733 *            a software interrupt).
     734 *
     735 * RETURNS:
     736 *        0:  Success
     737 *       -1:  Invalid argument (level not 1..7, vector odd or >= 256)
     738 *       -2:  Interrupt 'level' already asserted (maybe nobody handles it).
     739 *            You can manually clear it be writing the respective bit in
     740 *            VINT_STAT. Make sure really nobody responds to avoid spurious
     741 *            interrupts (consult universe docs).
     742 */
     743
     744int
     745vmeUniverseIntRaiseXX(volatile LERegister *base, int level, unsigned vector);
     746
     747int
     748vmeUniverseIntRaise(int level, unsigned vector);
    585749
    586750#ifdef __rtems__
     
    626790vmeUniverseISRGet(unsigned long vector, void **parg);
    627791
    628 /* utility routines to enable/disable a VME IRQ level
     792/* utility routines to enable/disable a VME IRQ level.
     793 *
     794 * To enable/disable the internal interrupt sources (special vectors above)
     795 * pass a vector argument > 255.
    629796 *
    630797 * RETURNS 0 on success, nonzero on failure
     
    635802vmeUniverseIntDisable(unsigned int level);
    636803
     804/* Check if an interrupt level or internal source is enabled:
     805 *
     806 * 'level': VME level 1..7 or internal special vector > 255
     807 *
     808 * RETURNS: value > 0 if interrupt is currently enabled,
     809 *          zero      if interrupt is currently disabled,
     810 *          -1        on error (invalid argument).
     811 */
     812int
     813vmeUniverseIntIsEnabled(unsigned int level);
     814
     815
     816/* Change the routing of IRQ 'level' to 'pin'.
     817 * If the BSP connects more than one of the eight
     818 * physical interrupt lines from the universe to
     819 * the board's PIC then you may change the physical
     820 * line a given 'level' is using. By default,
     821 * all 7 VME levels use the first wire (pin==0) and
     822 * all internal sources use the (optional) second
     823 * wire (pin==1) [The driver doesn't support more than
     824 * to wires].
     825 * This feature is useful if you want to make use of
     826 * different hardware priorities of the PIC. Let's
     827 * say you want to give IRQ level 7 the highest priority.
     828 * You could then give 'pin 0' a higher priority (at the
     829 * PIC) and 'pin 1' a lower priority and issue.
     830 *
     831 *   for ( i=1; i<7; i++ ) vmeUniverseIntRoute(i, 1);
     832 *
     833 * PARAMETERS:
     834 *    'level' : VME interrupt level '1..7' or one of
     835 *              the internal sources. Pass the internal
     836 *              source's vector number (>=256).
     837 *    'pin'   : a value of 0 routes the requested IRQ to
     838 *              the first line registered with the manager
     839 *              (vmeIrqUnivOut parameter), a value of 1
     840 *              routes it to the alternate wire
     841 *              (specialIrqUnivOut)
     842 * RETURNS: 0 on success, nonzero on error (invalid arguments)
     843 *
     844 * NOTES:       - DONT change the universe 'map' registers
     845 *            directly. The driver caches routing internally.
     846 *          - support for the 'specialIrqUnivOut' wire is
     847 *            board dependent. If the board only provides
     848 *            a single physical wire from the universe to
     849 *            the PIC then the feature might not be available.
     850 */
     851int
     852vmeUniverseIntRoute(unsigned int level, unsigned int pin);
     853
    637854/* use these special vectors to connect a handler to the
    638  * universe specific interrupts (such as "DMA done",
     855 * universe specific interrupts (such as "DMA done", 
    639856 * VOWN, error irqs etc.)
    640857 * NOTE: The wrapper clears all status LINT bits (except
     
    647864 * DEPENDS ON IT
    648865 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    649  *
     866 * 
    650867 */
    651868#define UNIV_VOWN_INT_VEC                       256
     
    653870#define UNIV_LERR_INT_VEC                       258
    654871#define UNIV_VERR_INT_VEC                       259
    655 #define UNIV_VME_SW_IACK_INT_VEC        260
    656 #define UNIV_PCI_SW_INT_VEC                     261
    657 #define UNIV_SYSFAIL_INT_VEC            262
    658 #define UNIV_ACFAIL_INT_VEC                     263
    659 #define UNIV_MBOX0_INT_VEC                      264
    660 #define UNIV_MBOX1_INT_VEC                      265
    661 #define UNIV_MBOX2_INT_VEC                      266
    662 #define UNIV_MBOX3_INT_VEC                      267
    663 #define UNIV_LM0_INT_VEC                        268
    664 #define UNIV_LM1_INT_VEC                        269
    665 #define UNIV_LM2_INT_VEC                        270
    666 #define UNIV_LM3_INT_VEC                        271
    667 
    668 #define UNIV_NUM_INT_VECS                       272
     872/* 260 is reserved */
     873#define UNIV_VME_SW_IACK_INT_VEC        261
     874#define UNIV_PCI_SW_INT_VEC                     262
     875#define UNIV_SYSFAIL_INT_VEC            263
     876#define UNIV_ACFAIL_INT_VEC                     264
     877#define UNIV_MBOX0_INT_VEC                      265
     878#define UNIV_MBOX1_INT_VEC                      266
     879#define UNIV_MBOX2_INT_VEC                      267
     880#define UNIV_MBOX3_INT_VEC                      268
     881#define UNIV_LM0_INT_VEC                        269
     882#define UNIV_LM1_INT_VEC                        270
     883#define UNIV_LM2_INT_VEC                        271
     884#define UNIV_LM3_INT_VEC                        272
     885
     886#define UNIV_NUM_INT_VECS                       273
    669887
    670888/* the universe interrupt handler is capable of routing all sorts of
     
    672890 * in a (board specific) way to a PIC.
    673891 *
    674  * This driver only supports at most two lines. It routes the 7 VME
    675  * interrupts to the main line and optionally, it routes the 'special'
     892 * This driver only supports at most two lines. By default, it routes the
     893 * 7 VME interrupts to the main line and optionally, it routes the 'special'
    676894 * interrupts generated by the universe itself (DMA done, VOWN etc.)
    677895 * to a second line. If no second line is available, all IRQs are routed
    678896 * to the main line.
     897 *
     898 * The routing of interrupts to the two lines can be modified (using
     899 * the vmeUniverseIntRoute() call - see above - i.e., to make use of
     900 * different hardware priorities of the two pins.
    679901 *
    680902 * Because the driver has no way to figure out which lines are actually
     
    687909 * Optionally, the first PIC input line can be read from PCI config space
    688910 * but the second must be passed to this routine. Note that the info read
    689  * from PCI config space is wrong for many boards!
     911 * from PCI config space is wrong for many boards! 
    690912 *
    691913 * PARAMETERS:
     
    703925 *
    704926 * RETURNS: 0 on success, -1 on failure.
    705  *
     927 *                                             
    706928 */
    707929int
     
    711933                                                 int specialIrqPicLine);
    712934
     935/* up to 4 universe outputs are now supported by this alternate
     936 * entry point.
     937 * Terminate the vararg list (uni_pin/pic_pin pairs) with a
     938 * '-1' uni_pin.
     939 * E.g., the old interface is now just a wrapper to
     940 *   vmeUniverseInstallIrqMgrAlt(0, vmeUnivOut, vmePicLint, specUnivOut, specPicLine, -1);
     941 *
     942 * The 'shared' argument uses the BSP_install_rtems_shared_irq_handler()
     943 * API. CAVEAT: shared interrupts need RTEMS workspace, i.e., the
     944 * VME interrupt manager can only be installed *after workspace is initialized*
     945 * if 'shared' is nonzero (i.e., *not* from bspstart()).
     946 */
     947int
     948vmeUniverseInstallIrqMgrAlt(int shared, int uni_pin0, int pic_pin0, ...);
     949
     950int
     951vmeUniverseInstallIrqMgrVa(int shared, int uni_pin0, int pic_pin0, va_list ap);
     952
     953/* Loopback test of the VME interrupt subsystem.
     954 *  - installs ISRs on 'vector' and on UNIV_VME_SW_IACK_INT_VEC
     955 *  - asserts VME interrupt 'level'
     956 *  - waits for both interrupts: 'ordinary' VME interrupt of 'level' and
     957 *    IACK completion interrupt ('special' vector UNIV_VME_SW_IACK_INT_VEC).
     958 *
     959 * NOTES:
     960 *  - make sure no other handler responds to 'level'.
     961 *  - make sure no ISR is installed on both vectors yet.
     962 *  - ISRs installed by this routine are removed after completion.
     963 *  - no concurrent access protection of all involved resources
     964 *    (levels, vectors and registers  [see vmeUniverseIntRaise()])
     965 *    is implemented.
     966 *  - this routine is intended for TESTING (when implementing new BSPs etc.).
     967 *  - one RTEMS message queue is temporarily used (created/deleted).
     968 *  - the universe 1 always yields a zero vector (VIRQx_STATID) in response
     969 *    to a self-generated VME interrupt. As a workaround, the routine
     970 *    only accepts a zero vector when running on a universe 1.
     971 *
     972 * RETURNS:
     973 *                 0: Success.
     974 *                -1: Invalid arguments.
     975 *                 1: Test failed (outstanding interrupts).
     976 * rtems_status_code: Failed RTEMS directive.
     977 */
     978int
     979vmeUniverseIntLoopbackTst(int level, unsigned vector);
     980
    713981#endif
    714982
Note: See TracChangeset for help on using the changeset viewer.