File indexing completed on 2025-05-11 08:23:58
0001
0002
0003
0004
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
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
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
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
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
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
0335 return -1;
0336 }
0337
0338 if ( !cb && !curr ) {
0339
0340
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
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
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
0414 err = theOps->install_irq_mgr(
0415 theOps->irq_mgr_flags,
0416 0, -1,
0417 -1
0418 );
0419 #else
0420 BSP_VME_INSTALL_IRQ_MGR(err);
0421 #endif
0422
0423 if ( err )
0424 return err;
0425
0426
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 }