Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:53

0001 /**
0002  *  @file
0003  *
0004  *  @ingroup shared_vmetsi148
0005  *
0006  *  @brief Driver for the Tundra Tsi148 pci-vme bridge
0007  */
0008 
0009 #ifndef VME_TSI148_DRIVER_H
0010 #define VME_TSI148_DRIVER_H
0011 
0012 /*
0013  * Authorship
0014  * ----------
0015  * This software was created by
0016  *     Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
0017  *     Stanford Linear Accelerator Center, Stanford University.
0018  *
0019  * Acknowledgement of sponsorship
0020  * ------------------------------
0021  * This software was produced by
0022  *     the Stanford Linear Accelerator Center, Stanford University,
0023  *     under Contract DE-AC03-76SFO0515 with the Department of Energy.
0024  *
0025  * Government disclaimer of liability
0026  * ----------------------------------
0027  * Neither the United States nor the United States Department of Energy,
0028  * nor any of their employees, makes any warranty, express or implied, or
0029  * assumes any legal liability or responsibility for the accuracy,
0030  * completeness, or usefulness of any data, apparatus, product, or process
0031  * disclosed, or represents that its use would not infringe privately owned
0032  * rights.
0033  *
0034  * Stanford disclaimer of liability
0035  * --------------------------------
0036  * Stanford University makes no representations or warranties, express or
0037  * implied, nor assumes any liability for the use of this software.
0038  *
0039  * Stanford disclaimer of copyright
0040  * --------------------------------
0041  * Stanford University, owner of the copyright, hereby disclaims its
0042  * copyright and all other rights in this software.  Hence, anyone may
0043  * freely use it for any purpose without restriction.
0044  *
0045  * Maintenance of notices
0046  * ----------------------
0047  * In the interest of clarity regarding the origin and status of this
0048  * SLAC software, this and all the preceding Stanford University notices
0049  * are to remain affixed to any copy or derivative of this software made
0050  * or distributed by the recipient and are to be affixed to any copy of
0051  * software made or distributed by the recipient that contains a copy or
0052  * derivative of this software.
0053  *
0054  * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
0055  */
0056 
0057 #include <stdint.h>
0058 #include <bsp/vme_am_defs.h>
0059 
0060 
0061 /**
0062  *  @defgroup shared_vmetsi148 VMETSI148 Support
0063  *
0064  *  @ingroup shared_vmeuniverse
0065  *
0066  *  @brief VMETSI148 Support Package
0067  */
0068 
0069 /* NOTE: A64 currently not implemented */
0070 
0071 /* These can be ored with the AM */
0072 
0073 /* NOTE: unlike the universe, the tsi148 doesn't allow for disabling posted writes ! */
0074 
0075 #define VME_MODE_PREFETCH_ENABLE            VME_AM_IS_MEMORY
0076 #define _LD_VME_MODE_PREFETCHSZ             24
0077 #define VME_MODE_PREFETCH_SIZE(x)           (((x)&3)<<_LD_VME_MODE_PREFETCHSZ)
0078 
0079 /* These bits can be or'ed with the address-modifier when calling
0080  * the 'XlateAddr' routine below to further qualify the
0081  * search criteria.
0082  */
0083 #define VME_MODE_MATCH_MASK                 (3<<30)
0084 #define VME_MODE_EXACT_MATCH                (2<<30) /* all bits must match */
0085 #define VME_MODE_AS_MATCH                   (1<<30) /* only A16/24/32 must match */
0086 
0087 #ifdef __cplusplus
0088 extern "C" {
0089 #endif
0090 
0091 typedef volatile uint32_t BERegister; /* emphasize contents are big endian */
0092 
0093 /*
0094  * Scan the PCI busses for the Nth (N=='instance') Tsi148 VME bridge.
0095  *
0096  * RETURNS:
0097  *    contents of the IRQ_LINE PCI config register on Success,
0098  *    the base address of the Tsi148 register block is stored in
0099  *    *pbase.
0100  *    -1 on error (no Tsi found, error accessing PCI config space).
0101  *
0102  * SIDE_EFFECTS: PCI busmaster and response to memory addresses is enabled.
0103  */
0104 int
0105 vmeTsi148FindPciBase(int instance, BERegister **pbase);
0106 
0107 /* Initialize driver for Nth Tsi148 device found.
0108  * This routine does not change any registers but
0109  * just scans the PCI bus for Tsi bridges and initializes
0110  * a driver slot.
0111  *
0112  * RETURNS: 0 on success, nonzero on error (or if no Tsi148
0113  *          device is found).
0114  */
0115 int
0116 vmeTsi148InitInstance(unsigned instance);
0117 
0118 /* Initialize driver with 1st Tsi148 bridge found
0119  * RETURNS: (see vmeTsi148InitInstance()).
0120  */
0121 int
0122 vmeTsi148Init(void);
0123 
0124 /* Setup the tsi148 chip, i.e. disable most of its
0125  * mappings, reset interrupts etc.
0126  */
0127 void
0128 vmeTsi148ResetXX(BERegister *base);
0129 
0130 /* Setup the tsi148 connected to the first driver slot */
0131 void
0132 vmeTsi148Reset(void);
0133 
0134 /* Pull VME SYSRESET line */
0135 void
0136 vmeTsi148ResetBusXX(BERegister *base);
0137 
0138 /* Pull VME SYSRESET line of the 1st controller */
0139 void
0140 vmeTsi148ResetBus(void);
0141 
0142 /* NOTE: all non-'XX' versions of driver entry points which
0143  *       have an associated 'XX' entry point operate on the
0144  *       device connected to the 1st driver slot.
0145  */
0146 
0147 /* configure a outbound port
0148  *
0149  *   port:      port number 0..7
0150  *
0151  *   address_space: vxWorks compliant addressing mode identifier
0152  *                  (see vme.h). The most important are:
0153  *                    0x0d - A32, Sup, Data
0154  *                    0x3d - A24, Sup, Data
0155  *                    0x2d - A16, Sup, Data
0156  *                  additionally, the value 0 is accepted; it will
0157  *                  disable this port.
0158  *   vme_address:   address on the vme_bus of this port.
0159  *   local_address: address on the pci_bus of this port.
0160  *   length:        size of this port.
0161  *
0162  *   NOTE: the addresses and length parameters must meet certain alignment
0163  *         requirements (see Tsi148 documentation).
0164  *
0165  *   RETURNS: 0 on success, -1 on failure. Error messages printed to stderr.
0166  */
0167 
0168 int
0169 vmeTsi148OutboundPortCfgXX(
0170     BERegister      *base,
0171     unsigned long   port,
0172     unsigned long   address_space,
0173     unsigned long   vme_address,
0174     unsigned long   pci_address,
0175     unsigned long   length);
0176 
0177 int
0178 vmeTsi148OutboundPortCfg(
0179     unsigned long   port,
0180     unsigned long   address_space,
0181     unsigned long   vme_address,
0182     unsigned long   pci_address,
0183     unsigned long   length);
0184 
0185 
0186 /* configure a VME inbound (PCI master) port */
0187 int
0188 vmeTsi148InboundPortCfgXX(
0189     BERegister      *base,
0190     unsigned long   port,
0191     unsigned long   address_space,
0192     unsigned long   vme_address,
0193     unsigned long   pci_address,
0194     unsigned long   length);
0195 
0196 int
0197 vmeTsi148InboundPortCfg(
0198     unsigned long   port,
0199     unsigned long   address_space,
0200     unsigned long   vme_address,
0201     unsigned long   pci_address,
0202     unsigned long   length);
0203 
0204 /* Translate an address through the bridge
0205  *
0206  * vmeTsi248XlateAddr(0,0,as,addr,&result)
0207  * yields a VME a address that reflects
0208  * a local memory location as seen from the VME bus through the
0209  * tsi148 VME inbound port.
0210  *
0211  * Likewise does vmeTsi148XlateAddr(1,0,as,addr,&result)
0212  * translate a VME bus addr (backwards, through the VME outbound
0213  * port) to the PCI side of the bridge.
0214  *
0215  * A valid address space modifier must be specified.
0216  * If VME_MODE_EXACT_MATCH is set, all the mode bits must
0217  * match the requested mode. If VME_MODE_EXACT_MATCH is not
0218  * set in the mode word, only the basic mode (address-space,
0219  * sup/usr and pgm/data) is compared.
0220  *
0221  * The 'reverse' parameter may be used to find a reverse
0222  * mapping, i.e. the pci address in a outbound window can be
0223  * found if the respective vme address is known etc.
0224  *
0225  * RETURNS: translated address in *pbusAdrs / *plocalAdrs
0226  *
0227  *          0:  success
0228  *          -1: address/modifier not found in any bridge port
0229  *          -2: invalid modifier
0230  */
0231 
0232 int
0233 vmeTsi148XlateAddrXX(
0234     BERegister *base,   /* TSI 148 base address */
0235     int outbound,       /* look in the outbound windows */
0236     int reverse,        /* reverse mapping; for outbound ports: map local to VME */
0237     unsigned long as,   /* address space */
0238     unsigned long aIn,  /* address to look up */
0239     unsigned long *paOut/* where to put result */
0240     );
0241 
0242 int
0243 vmeTsi148XlateAddr(
0244     int outbound,       /* look in the outbound windows */
0245     int reverse,        /* reverse mapping; for outbound: map local to VME */
0246     unsigned long as,   /* address space */
0247     unsigned long aIn,  /* address to look up */
0248     unsigned long *paOut/* where to put result */
0249     );
0250 
0251 
0252 /* avoid pulling stdio.h into this header.
0253  * Applications that want a declaration of the
0254  * following routines should
0255  *  #include <stdio.h>
0256  *  #define _VME_TSI148_DECLARE_SHOW_ROUTINES
0257  *  #include <vmeTsi148.h>
0258  */
0259 #ifdef _VME_TSI148_DECLARE_SHOW_ROUTINES
0260 
0261 /* Print the current configuration of all outbound ports to
0262  * f (stdout if NULL)
0263  */
0264 
0265 void
0266 vmeTsi148OutboundPortsShowXX(BERegister *base, FILE *f);
0267 
0268 void
0269 vmeTsi148OutboundPortsShow(FILE *f);
0270 
0271 /* Print the current configuration of all inbound ports to
0272  * f (stdout if NULL)
0273  */
0274 
0275 void
0276 vmeTsi148InboundPortsShowXX(BERegister *base, FILE *f);
0277 
0278 void
0279 vmeTsi148InboundPortsShow(FILE *f);
0280 
0281 #endif
0282 
0283 
0284 /* Disable all in- or out-bound ports, respectively */
0285 void
0286 vmeTsi148DisableAllInboundPortsXX(BERegister *base);
0287 
0288 void
0289 vmeTsi148DisableAllInboundPorts(void);
0290 
0291 void
0292 vmeTsi148DisableAllOutboundPortsXX(BERegister *base);
0293 
0294 void
0295 vmeTsi148DisableAllOutboundPorts(void);
0296 
0297 #   define TSI_VEAT_VES         (1<<31)
0298 #   define TSI_VEAT_VEOF        (1<<30)
0299 #   define TSI_VEAT_VESCL       (1<<29)
0300 #   define TSI_VEAT_2eOT        (1<<21)
0301 #   define TSI_VEAT_2eST        (1<<20)
0302 #   define TSI_VEAT_BERR        (1<<19)
0303 #   define TSI_VEAT_LWORD       (1<<18)
0304 #   define TSI_VEAT_WRITE       (1<<17)
0305 #   define TSI_VEAT_IACK        (1<<16)
0306 #   define TSI_VEAT_DS1         (1<<15)
0307 #   define TSI_VEAT_DS0         (1<<14)
0308 #   define TSI_VEAT_AM(v)       (((v)>>8)&63)
0309 #   define TSI_VEAT_XAM(v)      ((v)&255)
0310 
0311 /* Check and clear the error (AKA 'exception') register.
0312  * Note that the Tsi148 does *not* propagate VME bus errors of any kind to
0313  * the PCI status register and hence this routine (or registering an ISR
0314  * to the TSI_VERR_INT_VEC) is the only means for detecting a bus error.
0315  *
0316  * RETURNS:
0317  *   0 if no error has occurred since this routine was last called.
0318  *     Contents of the 'VEAT' register (bit definitions as above)
0319  *     otherwise.
0320  *   If a non-NULL 'paddr'  argument is provided then the lower 32-bit
0321  *   of the error address is stored in *paddr (only if return value is
0322  *   non-zero).
0323  *
0324  * SIDE EFFECTS: this routine clears the error attribute register, allowing
0325  *               for future errors to be latched.
0326  */
0327 unsigned long
0328 vmeTsi148ClearVMEBusErrorsXX(BERegister *base, uint32_t *paddr);
0329 
0330 unsigned long
0331 vmeTsi148ClearVMEBusErrors(uint32_t *paddr);
0332 
0333 /* Map internal register block to VME.
0334  *
0335  * This routine is intended for BSP implementors. The registers must be
0336  * accessible from VME so that the interrupt handler can flush the
0337  * bridge FIFO (see below).
0338  *
0339  *            vme_base: VME address where the TSI registers (4k) can be mapped.
0340  *                      This VME address must fall into a range covered by
0341  *                      any pre-configured outbound window.
0342  *       address_space: The desired VME address space.
0343  *                      (all of SUP/USR/PGM/DATA are always accepted).
0344  *
0345  * See NOTES [vmeTsi148InstallIrqMgrAlt()] below for further information.
0346  *
0347  * RETURNS: 0 on success, nonzero on error. It is not possible (and results
0348  *          in a non-zero return code) to change the CRG VME address after
0349  *          initializing the interrupt manager as it uses the CRG.
0350  */
0351 int
0352 vmeTsi148MapCRGXX(BERegister *base, uint32_t vme_base, uint32_t address_space);
0353 
0354 int
0355 vmeTsi148MapCRG(uint32_t vme_base, uint32_t address_space);
0356 
0357 
0358 /* VME Interrupt Handler functionality */
0359 
0360 /* we dont use the current RTEMS/BSP interrupt API for the
0361  * following reasons:
0362  *
0363  *    - RTEMS/BSP API does not pass an argument to the ISR :-( :-(
0364  *    - no separate vector space for VME vectors. Some vectors would
0365  *      have to overlap with existing PCI/ISA vectors.
0366  *    - RTEMS/BSP API allocates a structure for every possible vector
0367  *    - the irq_on(), irq_off() functions add more bloat than helping.
0368  *      They are (currently) only used by the framework to disable
0369  *      interrupts at the device level before removing a handler
0370  *      and to enable interrupts after installing a handler.
0371  *      These operations may as well be done by the driver itself.
0372  *
0373  * Hence, we maintain our own (VME) handler table and hook our PCI
0374  * handler into the standard RTEMS/BSP environment. Our handler then
0375  * dispatches VME interrupts.
0376  */
0377 
0378 typedef void (*VmeTsi148ISR) (void *usrArg, unsigned long vector);
0379 
0380 /* install a handler for a VME vector
0381  * RETURNS 0 on success, nonzero on failure.
0382  */
0383 int
0384 vmeTsi148InstallISR(unsigned long vector, VmeTsi148ISR handler, void *usrArg);
0385 
0386 /* remove a handler for a VME vector. The vector and usrArg parameters
0387  * must match the respective parameters used when installing the handler.
0388  * RETURNS 0 on success, nonzero on failure.
0389  */
0390 int
0391 vmeTsi148RemoveISR(unsigned long vector, VmeTsi148ISR handler, void *usrArg);
0392 
0393 /* query for the currently installed ISR and usr parameter at a given vector
0394  * RETURNS: ISR or 0 (vector too big or no ISR installed)
0395  */
0396 VmeTsi148ISR
0397 vmeTsi148ISRGet(unsigned long vector, void **parg);
0398 
0399 /* utility routines to enable/disable a VME IRQ level
0400  *
0401  * To enable/disable the internal interrupt sources (special vectors above)
0402  * pass a vector argument > 255.
0403  *
0404  * RETURNS 0 on success, nonzero on failure
0405  */
0406 int
0407 vmeTsi148IntEnable(unsigned int level);
0408 
0409 int
0410 vmeTsi148IntDisable(unsigned int level);
0411 
0412 /* Check if an interrupt level or internal source is enabled:
0413  *
0414  * 'level': VME level 1..7 or internal special vector > 255
0415  *
0416  * RETURNS: value > 0 if interrupt is currently enabled,
0417  *          zero      if interrupt is currently disabled,
0418  *          -1        on error (invalid argument).
0419  */
0420 
0421 int
0422 vmeTsi148IntIsEnabled(unsigned int level);
0423 
0424 /* Set IACK width (1,2, or 4 bytes) for a given interrupt level.
0425  *
0426  * 'width' arg may be 0,1,2 or 4. If zero, the currently active
0427  * value is returned but not modified.
0428  *
0429  * RETURNS: old width or -1 if invalid argument.
0430  */
0431 
0432 int
0433 vmeTsi148SetIackWidth(int level, int width);
0434 
0435 /* Change the routing of IRQ 'level' to 'pin'.
0436  * If the BSP connects more than one of the four
0437  * physical interrupt lines from the tsi148 to
0438  * the board's PIC then you may change the physical
0439  * line a given 'level' is using. By default,
0440  * all 7 VME levels use the first wire (pin==0) and
0441  * all internal sources use the (optional) second
0442  * wire (pin==1) [The driver doesn't support more than
0443  * four wires].
0444  * This feature is useful if you want to make use of
0445  * different hardware priorities of the PIC. Let's
0446  * say you want to give IRQ level 7 the highest priority.
0447  * You could then give 'pin 0' a higher priority (at the
0448  * PIC) and 'pin 1' a lower priority and issue.
0449  *
0450  *   for ( i=1; i<7; i++ ) vmeTsi148IntRoute(i, 1);
0451  *
0452  * PARAMETERS:
0453  *    'level' : VME interrupt level '1..7' or one of
0454  *              the internal sources. Pass the internal
0455  *              source's vector number (>=256).
0456  *    'pin'   : a value of 0 routes the requested IRQ to
0457  *              the first line registered with the manager,
0458  *              a value of 1 routes it to the second wire
0459  *              etc.
0460  *
0461  * RETURNS: 0 on success, nonzero on error (invalid arguments)
0462  *
0463  * NOTES:   - DONT change the tsi148 'map' registers
0464  *            directly. The driver caches routing internally.
0465  *          - support for the extra wires (beyond wire #0) is
0466  *            board dependent. If the board only provides
0467  *            a single physical wire from the tsi148 to
0468  *            the PIC then the feature might not be available.
0469  */
0470 int
0471 vmeTsi148IntRoute(unsigned int level, unsigned int pin);
0472 
0473 /* Raise a VME Interrupt at 'level' and respond with 'vector' to a
0474  * handler on the VME bus. (The handler could be a different board
0475  * or the tsi148 itself.
0476  *
0477  * Note that you could install a interrupt handler at TSI_VME_SW_IACK_INT_VEC
0478  * to be notified of an IACK cycle having completed.
0479  *
0480  * This routine is mainly FOR TESTING.
0481  *
0482  * NOTES:
0483  *   - the VICR register is modified.
0484  *   - NO MUTUAL EXCLUSION PROTECTION (reads VICR, modifies then writes back).
0485  *     If several users need access to VICR it is their responsibility to serialize access.
0486  *
0487  * Arguments:
0488  *  'level':  interrupt level, 1..7
0489  *  'vector': vector number (0..255) that the tsi148 puts on the bus in response to
0490  *            an IACK cycle.
0491  *
0492  * RETURNS:
0493  *        0:  Success
0494  *       -1:  Invalid argument (level not 1..7, vector >= 256)
0495  *       -2:  Interrupt 'level' already asserted (maybe nobody handles it).
0496  *            You can manually clear it be setting the IRQC bit in
0497  *            VICR. Make sure really nobody responds to avoid spurious
0498  *            interrupts (consult tsi148 docs).
0499  */
0500 
0501 int
0502 vmeTsi148IntRaiseXX(BERegister *base, int level, unsigned vector);
0503 
0504 int
0505 vmeTsi148IntRaise(int level, unsigned vector);
0506 
0507 /* Loopback test of the VME interrupt subsystem.
0508  *  - installs ISRs on 'vector' and on TSI_VME_SW_IACK_INT_VEC
0509  *  - asserts VME interrupt 'level'
0510  *  - waits for both interrupts: 'ordinary' VME interrupt of 'level' and
0511  *    IACK completion interrupt ('special' vector TSI_VME_SW_IACK_INT_VEC).
0512  *
0513  * NOTES:
0514  *  - make sure no other handler responds to 'level'.
0515  *  - make sure no ISR is installed on both vectors yet.
0516  *  - ISRs installed by this routine are removed after completion.
0517  *  - no concurrent access protection of all involved resources
0518  *    (levels, vectors and registers  [see vmeTsi148IntRaise()])
0519  *    is implemented.
0520  *  - this routine is intended for TESTING (when implementing new BSPs etc.).
0521  *  - one RTEMS message queue is temporarily used (created/deleted).
0522  *
0523  * RETURNS:
0524  *                 0: Success.
0525  *                -1: Invalid arguments.
0526  *                 1: Test failed (outstanding interrupts).
0527  * rtems_status_code: Failed RTEMS directive.
0528  */
0529 
0530 int
0531 vmeTsi148IntLoopbackTst(int level, unsigned vector);
0532 
0533 /* use these special vectors to connect a handler to the
0534  * tsi148 specific interrupts (such as "DMA done", SW or
0535  * error irqs etc.)
0536  * NOTE: The wrapper clears all status LINT bits (except
0537  * for regular VME irqs). Also note that it is the user's
0538  * responsibility to enable the necessary interrupts in
0539  * LINT_EN
0540  *
0541  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
0542  * DO NOT CHANGE THE ORDER OF THESE VECTORS - THE DRIVER
0543  * DEPENDS ON IT
0544  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
0545  *
0546  * Deliberately, these vectors match the universe driver's
0547  */
0548 /* 256 no VOWN interrupt */
0549 #define TSI_DMA_INT_VEC         257
0550 #define TSI_LERR_INT_VEC        258
0551 #define TSI_VERR_INT_VEC        259
0552 /* 260 is reserved       */
0553 #define TSI_VME_SW_IACK_INT_VEC 261
0554 /* 262 no PCI SW IRQ     */
0555 #define TSI_SYSFAIL_INT_VEC     263
0556 #define TSI_ACFAIL_INT_VEC      264
0557 #define TSI_MBOX0_INT_VEC       265
0558 #define TSI_MBOX1_INT_VEC       266
0559 #define TSI_MBOX2_INT_VEC       267
0560 #define TSI_MBOX3_INT_VEC       268
0561 #define TSI_LM0_INT_VEC         269
0562 #define TSI_LM1_INT_VEC         270
0563 #define TSI_LM2_INT_VEC         271
0564 #define TSI_LM3_INT_VEC         272
0565 
0566 /* New vectors; only on TSI148 */
0567 #define TSI_VIES_INT_VEC        273
0568 #define TSI_DMA1_INT_VEC        274
0569 
0570 #define TSI_NUM_INT_VECS        275
0571 
0572 #ifdef __INSIDE_RTEMS_BSP__
0573 
0574 #include <stdarg.h>
0575 
0576 /* the tsi148 interrupt handler is capable of routing all sorts of
0577  * (VME) interrupts to 4 different lines (some of) which may be hooked up
0578  * in a (board specific) way to a PIC.
0579  *
0580  * This driver initially supports at most two lines (i.e., if the user
0581  * doesn't re-route anything). By default, it routes the
0582  * 7 VME interrupts to the main line and optionally, it routes the 'special'
0583  * interrupts generated by the tsi148 itself (DMA done, SW irq etc.)
0584  * to a second line. If no second line is available, all IRQs are routed
0585  * to the main line.
0586  *
0587  * The routing of interrupts to the two lines can be modified (using
0588  * the vmeTsi148IntRoute() call - see above - i.e., to make use of
0589  * different hardware priorities and/or more physically available lines.
0590  *
0591  * Because the driver has no way to figure out which lines are actually
0592  * wired to the PIC, this information has to be provided when installing
0593  * the manager.
0594  *
0595  * Hence the manager sets up routing VME interrupts to 1 or 2 tsi148
0596  * OUTPUTS. However, it must also be told to which PIC INPUTS they
0597  * are wired.
0598  * Optionally, the first PIC input line can be read from PCI config space
0599  * but the second must be passed to this routine. Note that the info read
0600  * from PCI config space is wrong for some boards!
0601  *
0602  * PARAMETERS:
0603  *              flags:  VMETSI148_IRQ_MGR_FLAG_SHARED:
0604  *                      use the BSP_install_rtems_shared_irq_handler() instead
0605  *                      of BSP_install_rtems_irq_handler(). Use this if the PIC
0606  *                      line is used by other devices, too.
0607  *                      CAVEAT: shared interrupts need RTEMS workspace, i.e., the
0608  *                      VME interrupt manager can only be installed
0609  *                      *after workspace is initialized* if 'shared' is nonzero
0610  *                      (i.e., *not* from bspstart()).
0611  *
0612  *           tsi_pin_0: to which output pin (of the tsi148) should the 7
0613  *                      VME irq levels be routed.
0614  *
0615  *           pic_pin_0: specifies to which PIC input the 'main' output is
0616  *                      wired on your board. If passed a value < 0, the driver
0617  *                      reads this information from PCI config space ("IRQ line").
0618  *           ...      : up to three additional tsi_pin/pic_pin pairs can be
0619  *                      specified if your board provides more physical wires.
0620  *                      In any case must the varargs list be terminated by '-1'.
0621  *
0622  * RETURNS: 0 on success, -1 on failure.
0623  *
0624  * NOTES: The Tsi148 always does 'posted' writes through a FIFO buffer.
0625  *        This effectively makes VME write operations asynchronous
0626  *        which can have undesired side-effects.
0627  *        In particular, consider the case of an ISR clearing the
0628  *        interrupt condition by writing to a CSR. The write operation
0629  *        doesn't really do anything but goes into the FIFO and
0630  *        the user ISR returns. At this point, the interrupt manager
0631  *        may find the IRQ still pending, trying another IACK
0632  *        cycle. Because it is probable that at this time the FIFO
0633  *        has been flushed and the CSR-write operation been effective,
0634  *        the IACK then times out.
0635  *        Note that this phenomenon becomes more obvious as CPUs
0636  *        become faster.
0637  *
0638  *        To avoid this race condition and many VME drivers having
0639  *        to be re-written, a VME read (having the desired side-effect
0640  *        of flushing the write FIFO) must be issued between the
0641  *        user ISR returning and the interrupt manager checking for
0642  *        more pending interrupts.
0643  *
0644  *        Therefore, the BSP needs to map the Tsi148 register
0645  *        block to VME so that a read over VME can be effectuated.
0646  *        (In addition to being mapped to VME, the mapped address
0647  *        range must be accessible through an outbound window.)
0648  */
0649 
0650 #define VMETSI148_IRQ_MGR_FLAG_SHARED   1
0651 int
0652 vmeTsi148InstallIrqMgrAlt(int shared, int tsi_pin0, int pic_pin0, ...);
0653 
0654 int
0655 vmeTsi148InstallIrqMgrVa(int shared, int tsi_pin0, int pic_pin0, va_list ap);
0656 #endif
0657 
0658 #ifdef __cplusplus
0659 }
0660 #endif
0661 
0662 #endif