Back to home page

LXR

 
 

    


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

0001 /* Implementation of the VME.h and VMEDMA.h APIs for the BSP using the
0002  * vmeUniverse/vmeTsi148 drivers
0003  *
0004  * This file is named vme_universe.c for historic reasons.
0005  */
0006 
0007 
0008 #include <rtems.h>
0009 #include <bsp.h>
0010 #include <bsp/VME.h>
0011 #include <bsp/VMEDMA.h>
0012 #include <bsp/VMEConfig.h>
0013 #include <bsp/irq.h>
0014 #include <stdio.h>
0015 
0016 #define __INSIDE_RTEMS_BSP__
0017 
0018 #if !defined(_VME_DRIVER_TSI148) && !defined(_VME_DRIVER_UNIVERSE)
0019 #define _VME_DRIVER_UNIVERSE
0020 #endif
0021 
0022 #if defined(_VME_DRIVER_TSI148)
0023 #define _VME_TSI148_DECLARE_SHOW_ROUTINES
0024 #include <bsp/vmeTsi148.h>
0025 #include <bsp/vmeTsi148DMA.h>
0026 #endif
0027 
0028 #if defined(_VME_DRIVER_UNIVERSE)
0029 #define _VME_UNIVERSE_DECLARE_SHOW_ROUTINES
0030 #include <bsp/vmeUniverse.h>
0031 #include <bsp/vmeUniverseDMA.h>
0032 #if     !defined(BSP_VME_INSTALL_IRQ_MGR) && defined(BSP_VME_UNIVERSE_INSTALL_IRQ_MGR)
0033 #define BSP_VME_INSTALL_IRQ_MGR BSP_VME_UNIVERSE_INSTALL_IRQ_MGR
0034 #endif
0035 #endif
0036 
0037 #include <bsp/bspVmeDmaList.h>
0038 
0039 /* Wrap BSP VME calls around driver calls - we do this so EPICS doesn't have to
0040  * include bridge-specific headers. This file provides the necessary glue
0041  * to make VME.h and vmeconfig.c independent of the bridge chip.
0042  *
0043  * This file is named 'vme_universe.c' for historical reasons.
0044  */
0045 
0046 /*
0047  * Authorship
0048  * ----------
0049  * This software was created by
0050  *     Till Straumann <strauman@slac.stanford.edu>, 9/2005,
0051  *     Stanford Linear Accelerator Center, Stanford University.
0052  *
0053  * Acknowledgement of sponsorship
0054  * ------------------------------
0055  * This software was produced by
0056  *     the Stanford Linear Accelerator Center, Stanford University,
0057  *     under Contract DE-AC03-76SFO0515 with the Department of Energy.
0058  *
0059  * Government disclaimer of liability
0060  * ----------------------------------
0061  * Neither the United States nor the United States Department of Energy,
0062  * nor any of their employees, makes any warranty, express or implied, or
0063  * assumes any legal liability or responsibility for the accuracy,
0064  * completeness, or usefulness of any data, apparatus, product, or process
0065  * disclosed, or represents that its use would not infringe privately owned
0066  * rights.
0067  *
0068  * Stanford disclaimer of liability
0069  * --------------------------------
0070  * Stanford University makes no representations or warranties, express or
0071  * implied, nor assumes any liability for the use of this software.
0072  *
0073  * Stanford disclaimer of copyright
0074  * --------------------------------
0075  * Stanford University, owner of the copyright, hereby disclaims its
0076  * copyright and all other rights in this software.  Hence, anyone may
0077  * freely use it for any purpose without restriction.
0078  *
0079  * Maintenance of notices
0080  * ----------------------
0081  * In the interest of clarity regarding the origin and status of this
0082  * SLAC software, this and all the preceding Stanford University notices
0083  * are to remain affixed to any copy or derivative of this software made
0084  * or distributed by the recipient and are to be affixed to any copy of
0085  * software made or distributed by the recipient that contains a copy or
0086  * derivative of this software.
0087  *
0088  * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
0089  */
0090 typedef struct {
0091     int             (*xlate_adrs)(int, int, unsigned long, unsigned long, unsigned long *);
0092     int             (*install_isr)(unsigned long, BSP_VME_ISR_t, void *);
0093     int             (*remove_isr)(unsigned long, BSP_VME_ISR_t, void *);
0094     BSP_VME_ISR_t   (*get_isr)(unsigned long vector, void **);
0095     int             (*enable_int_lvl)(unsigned int);
0096     int             (*disable_int_lvl)(unsigned int);
0097     int             (*outbound_p_cfg)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
0098     int             (*inbound_p_cfg) (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
0099     void            (*outbound_p_show)(FILE*);
0100     void            (*inbound_p_show) (FILE*);
0101     void            (*reset_bus)(void);
0102     int             (*install_irq_mgr)(int, int, int, ...);
0103     int             irq_mgr_flags;
0104 } VMEOpsRec, *VMEOps;
0105 
0106 /* two separate 'ops' structs for historic reasons */
0107 typedef struct DmaOpsRec_ {
0108     int             (*setup)(int, uint32_t, uint32_t, void *);
0109     int             (*start)(int, uint32_t, uint32_t, uint32_t);
0110     uint32_t        (*status)(int);
0111     VMEDmaListClass listClass;
0112     int             nChannels;
0113     int             *vectors;
0114 } DmaOpsRec, *DmaOps;
0115 
0116 #ifdef _VME_DRIVER_UNIVERSE
0117 static VMEOpsRec uniOpsRec = {
0118     xlate_adrs:         vmeUniverseXlateAddr,
0119     install_isr:        vmeUniverseInstallISR,
0120     remove_isr:         vmeUniverseRemoveISR,
0121     get_isr:            vmeUniverseISRGet,
0122     enable_int_lvl:     vmeUniverseIntEnable,
0123     disable_int_lvl:    vmeUniverseIntDisable,
0124     outbound_p_cfg:     vmeUniverseMasterPortCfg,
0125     inbound_p_cfg:      vmeUniverseSlavePortCfg,
0126     outbound_p_show:    vmeUniverseMasterPortsShow,
0127     inbound_p_show:     vmeUniverseSlavePortsShow,
0128     reset_bus:          vmeUniverseResetBus,
0129     install_irq_mgr:    vmeUniverseInstallIrqMgrAlt,
0130     irq_mgr_flags:      VMEUNIVERSE_IRQ_MGR_FLAG_SHARED |
0131                         VMEUNIVERSE_IRQ_MGR_FLAG_PW_WORKAROUND,
0132 };
0133 
0134 static int uniVecs[] = { UNIV_DMA_INT_VEC };
0135 
0136 static DmaOpsRec uniDmaOpsRec = {
0137     setup:              vmeUniverseDmaSetup,
0138     start:              vmeUniverseDmaStart,
0139     status:             vmeUniverseDmaStatus,
0140     listClass:          &vmeUniverseDmaListClass,
0141     nChannels:          1,
0142     vectors:            uniVecs,
0143 };
0144 #endif
0145 
0146 #ifdef _VME_DRIVER_TSI148
0147 static VMEOpsRec tsiOpsRec = {
0148     xlate_adrs:         vmeTsi148XlateAddr,
0149     install_isr:        vmeTsi148InstallISR,
0150     remove_isr:         vmeTsi148RemoveISR,
0151     get_isr:            vmeTsi148ISRGet,
0152     enable_int_lvl:     vmeTsi148IntEnable,
0153     disable_int_lvl:    vmeTsi148IntDisable,
0154     outbound_p_cfg:     vmeTsi148OutboundPortCfg,
0155     inbound_p_cfg:      vmeTsi148InboundPortCfg,
0156     outbound_p_show:    vmeTsi148OutboundPortsShow,
0157     inbound_p_show:     vmeTsi148InboundPortsShow,
0158     reset_bus:          vmeTsi148ResetBus,
0159     install_irq_mgr:    vmeTsi148InstallIrqMgrAlt,
0160     irq_mgr_flags:      VMETSI148_IRQ_MGR_FLAG_SHARED,
0161 };
0162 
0163 static int tsiVecs[] = {
0164     TSI_DMA_INT_VEC,
0165     TSI_DMA1_INT_VEC,
0166 };
0167 
0168 static DmaOpsRec tsiDmaOpsRec = {
0169     setup:              vmeTsi148DmaSetup,
0170     start:              vmeTsi148DmaStart,
0171     status:             vmeTsi148DmaStatus,
0172     listClass:          &vmeTsi148DmaListClass,
0173     nChannels:          2,
0174     vectors:            tsiVecs,
0175 };
0176 #endif
0177 
0178 static VMEOps theOps    = 0;
0179 static DmaOps theDmaOps = 0;
0180 
0181 int
0182 BSP_vme2local_adrs(unsigned long am, unsigned long vmeaddr, unsigned long *plocaladdr)
0183 {
0184 int rval=theOps->xlate_adrs(1,0,am,vmeaddr,plocaladdr);
0185     *plocaladdr+=PCI_MEM_BASE;
0186     return rval;
0187 }
0188 
0189 int
0190 BSP_local2vme_adrs(unsigned long am, unsigned long localaddr, unsigned long *pvmeaddr)
0191 {
0192     return theOps->xlate_adrs(0, 0, am,localaddr+PCI_DRAM_OFFSET,pvmeaddr);
0193 }
0194 
0195 int
0196 BSP_installVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *arg)
0197 {
0198     return theOps->install_isr(vector, handler, arg);
0199 }
0200 
0201 int
0202 BSP_removeVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *arg)
0203 {
0204     return theOps->remove_isr(vector, handler, arg);
0205 }
0206 
0207 /* retrieve the currently installed ISR for a given vector */
0208 BSP_VME_ISR_t
0209 BSP_getVME_isr(unsigned long vector, void **parg)
0210 {
0211     return theOps->get_isr(vector, parg);
0212 }
0213 
0214 int
0215 BSP_enableVME_int_lvl(unsigned int level)
0216 {
0217     return theOps->enable_int_lvl(level);
0218 }
0219 
0220 int
0221 BSP_disableVME_int_lvl(unsigned int level)
0222 {
0223     return theOps->disable_int_lvl(level);
0224 }
0225 
0226 int
0227 BSP_VMEOutboundPortCfg(
0228     unsigned long port,
0229     unsigned long address_space,
0230     unsigned long vme_address,
0231     unsigned long pci_address,
0232     unsigned long size)
0233 {
0234     return theOps->outbound_p_cfg(port, address_space, vme_address, pci_address, size);
0235 }
0236 
0237 int
0238 BSP_VMEInboundPortCfg(
0239     unsigned long port,
0240     unsigned long address_space,
0241     unsigned long vme_address,
0242     unsigned long pci_address,
0243     unsigned long size)
0244 {
0245     return theOps->inbound_p_cfg(port, address_space, vme_address, pci_address, size);
0246 }
0247 
0248 void
0249 BSP_VMEOutboundPortsShow(FILE *f)
0250 {
0251     theOps->outbound_p_show(f);
0252 }
0253 
0254 void
0255 BSP_VMEInboundPortsShow(FILE *f)
0256 {
0257     theOps->inbound_p_show(f);
0258 }
0259 
0260 void
0261 BSP_VMEResetBus(void)
0262 {
0263     theOps->reset_bus();
0264 }
0265 
0266 int
0267 BSP_VMEDmaSetup(int channel, uint32_t bus_mode, uint32_t xfer_mode, void *custom_setup)
0268 {
0269     return theDmaOps->setup(channel, bus_mode, xfer_mode, custom_setup);
0270 }
0271 
0272 int
0273 BSP_VMEDmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes)
0274 {
0275     return theDmaOps->start(channel, pci_addr, vme_addr, n_bytes);
0276 }
0277 
0278 uint32_t
0279 BSP_VMEDmaStatus(int channel)
0280 {
0281     return theDmaOps->status(channel);
0282 }
0283 
0284 BSP_VMEDmaListDescriptor
0285 BSP_VMEDmaListDescriptorSetup(
0286         BSP_VMEDmaListDescriptor d,
0287         uint32_t                 attr_mask,
0288         uint32_t                 xfer_mode,
0289         uint32_t                 pci_addr,
0290         uint32_t                 vme_addr,
0291         uint32_t                 n_bytes)
0292 {
0293 VMEDmaListClass pc;
0294 
0295     if ( !d ) {
0296 
0297         pc = theDmaOps->listClass;
0298 
0299         return BSP_VMEDmaListDescriptorNewTool(
0300                     pc,
0301                     attr_mask,
0302                     xfer_mode,
0303                     pci_addr,
0304                     vme_addr,
0305                     n_bytes);
0306 
0307     }
0308 
0309     return BSP_VMEDmaListDescriptorSetupTool(d, attr_mask, xfer_mode, pci_addr, vme_addr, n_bytes);
0310 }
0311 
0312 int
0313 BSP_VMEDmaListStart(int channel, BSP_VMEDmaListDescriptor list)
0314 {
0315     return BSP_VMEDmaListDescriptorStartTool(0, channel, list);
0316 }
0317 
0318 /* NOT thread safe! */
0319 int
0320 BSP_VMEDmaInstallISR(int channel, BSP_VMEDmaIRQCallback cb, void *usr_arg)
0321 {
0322 int vec;
0323 BSP_VME_ISR_t curr;
0324 void          *carg;
0325 
0326     if ( channel < 0 || channel >= theDmaOps->nChannels )
0327         return -1;
0328 
0329     vec = theDmaOps->vectors[channel];
0330 
0331     curr = BSP_getVME_isr(vec, &carg);
0332 
0333     if ( cb && curr ) {
0334         /* IRQ currently in use */
0335         return -1;
0336     }
0337 
0338     if ( !cb && !curr ) {
0339         /* Allow uninstall if no handler is currently installed;
0340          * just make sure IRQ is disabled
0341          */
0342         BSP_disableVME_int_lvl(vec);
0343         return 0;
0344     }
0345 
0346     if ( cb ) {
0347         if ( BSP_installVME_isr(vec, (BSP_VME_ISR_t)cb, usr_arg) )
0348             return -4;
0349         BSP_enableVME_int_lvl(vec);
0350     } else {
0351         BSP_disableVME_int_lvl(vec);
0352         if ( BSP_removeVME_isr(vec, curr, carg) )
0353             return -4;
0354     }
0355     return 0;
0356 }
0357 
0358 #if defined(_VME_DRIVER_TSI148) && !defined(VME_CLEAR_BRIDGE_ERRORS)
0359 static unsigned short
0360 tsi_clear_errors(int quiet)
0361 {
0362 unsigned long   v;
0363 unsigned short  rval;
0364     v = vmeTsi148ClearVMEBusErrors(0);
0365 
0366     /* return bits 8..23 of VEAT; set bit 15 to make sure rval is nonzero on error */
0367     rval =  v ? ((v>>8) & 0xffff) | (1<<15) : 0;
0368     return rval;
0369 }
0370 
0371 #define VME_CLEAR_BRIDGE_ERRORS tsi_clear_errors
0372 #endif
0373 
0374 extern unsigned short (*_BSP_clear_vmebridge_errors)(int);
0375 
0376 int BSP_VMEInit(void)
0377 {
0378 #if defined(_VME_DRIVER_UNIVERSE)
0379   if ( 0 == vmeUniverseInit() ) {
0380     theOps    = &uniOpsRec;
0381     theDmaOps = &uniDmaOpsRec;
0382     vmeUniverseReset();
0383   }
0384 #endif
0385 #if defined(_VME_DRIVER_UNIVERSE) && defined(_VME_DRIVER_TSI148)
0386     else
0387 #endif
0388 #if defined(_VME_DRIVER_TSI148)
0389   if ( 0 == vmeTsi148Init() ) {
0390     theOps    = &tsiOpsRec;
0391     theDmaOps = &tsiDmaOpsRec;
0392     vmeTsi148Reset();
0393 #ifdef VME_CLEAR_BRIDGE_ERRORS
0394     {
0395 
0396       _BSP_clear_vmebridge_errors = VME_CLEAR_BRIDGE_ERRORS;
0397 
0398     }
0399 #endif
0400   }
0401 #endif
0402     else
0403       /*  maybe no VME at all - or no universe/tsi148 ... */
0404       return -1;
0405 
0406   return 0;
0407 }
0408 
0409 int BSP_VMEIrqMgrInstall(void)
0410 {
0411 int err;
0412 #ifndef BSP_VME_INSTALL_IRQ_MGR
0413   /* No map; use first line only and obtain PIC wire from PCI config */
0414   err = theOps->install_irq_mgr(
0415     theOps->irq_mgr_flags, /* use shared IRQs */
0416     0, -1,  /* Universe/Tsi148 pin0 -> PIC line from config space */
0417     -1      /* terminate list  */
0418   );
0419 #else
0420   BSP_VME_INSTALL_IRQ_MGR(err);
0421 #endif
0422 
0423   if ( err )
0424     return err;
0425 
0426 /* This feature is only supported by the Universe driver (not Tsi148) */
0427 #if defined(BSP_PCI_VME_DRIVER_DOES_EOI) && defined(BSP_PIC_DO_EOI)
0428 #ifdef  _VME_DRIVER_TSI148
0429 #error  "BSP_PCI_VME_DRIVER_DOES_EOI/BSP_PIC_DO_EOI feature can only be used with vmeUniverse"
0430 #endif
0431   if ( vmeUniverse0PciIrqLine < 0 )
0432     rtems_panic("Unable to get universe interrupt line info from PCI config");
0433   _BSP_vme_bridge_irq = vmeUniverse0PciIrqLine;
0434 #endif
0435   return 0;
0436 }