File indexing completed on 2025-05-11 08:23:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 #include <stdio.h>
0049 #include <inttypes.h>
0050
0051 #if defined(__rtems__)
0052 #ifndef __INSIDE_RTEMS_BSP__
0053 #define __INSIDE_RTEMS_BSP__
0054 #endif
0055 #endif
0056
0057 #include <bsp/vmeUniverse.h>
0058 #include <bsp/vmeUniverseDMA.h>
0059
0060 #define UNIV_NUM_MPORTS 8
0061 #define UNIV_NUM_SPORTS 8
0062
0063 #define PCI_VENDOR_TUNDRA 0x10e3
0064 #define PCI_DEVICE_UNIVERSEII 0
0065 #define PCI_UNIVERSE_BASE0 0x10
0066 #define PCI_UNIVERSE_BASE1 0x14
0067
0068 #define UNIV_REGOFF_PCITGT0_CTRL 0x100
0069 #define UNIV_REGOFF_PCITGT4_CTRL 0x1a0
0070 #define UNIV_REGOFF_VMESLV0_CTRL 0xf00
0071 #define UNIV_REGOFF_VMESLV4_CTRL 0xf90
0072
0073 #define UNIV_CTL_VAS16 (0x00000000)
0074 #define UNIV_CTL_VAS24 (0x00010000)
0075 #define UNIV_CTL_VAS32 (0x00020000)
0076 #define UNIV_MCTL_VASCSR (0x00050000)
0077 #define UNIV_CTL_VAS (0x00070000)
0078
0079 #define UNIV_MCTL_EN (0x80000000)
0080 #define UNIV_MCTL_PWEN (0x40000000)
0081 #define UNIV_MCTL_PGM (0x00004000)
0082 #define UNIV_MCTL_VCT (0x00000100)
0083 #define UNIV_MCTL_SUPER (0x00001000)
0084 #define UNIV_MCTL_VDW16 (0x00400000)
0085 #define UNIV_MCTL_VDW32 (0x00800000)
0086 #define UNIV_MCTL_VDW64 (0x00c00000)
0087
0088 #define UNIV_MCTL_AM_MASK (UNIV_CTL_VAS | UNIV_MCTL_PGM | UNIV_MCTL_SUPER)
0089
0090 #define UNIV_SCTL_EN (0x80000000)
0091 #define UNIV_SCTL_PWEN (0x40000000)
0092 #define UNIV_SCTL_PREN (0x20000000)
0093 #define UNIV_SCTL_PGM (0x00800000)
0094 #define UNIV_SCTL_DAT (0x00400000)
0095 #define UNIV_SCTL_SUPER (0x00200000)
0096 #define UNIV_SCTL_USER (0x00100000)
0097
0098 #define UNIV_SCTL_AM_MASK (UNIV_CTL_VAS | UNIV_SCTL_PGM | UNIV_SCTL_DAT | UNIV_SCTL_USER | UNIV_SCTL_SUPER)
0099
0100 #ifdef __rtems__
0101
0102 #include <stdlib.h>
0103 #include <rtems/bspIo.h> /* printk */
0104 #include <rtems/error.h>
0105 #include <rtems/pci.h>
0106 #include <rtems/score/sysstate.h>
0107 #include <bsp.h>
0108 #include <libcpu/byteorder.h>
0109
0110
0111 #ifndef BSP_PCI_FIND_DEVICE
0112 #define BSP_PCI_FIND_DEVICE pci_find_device
0113 #endif
0114 #ifndef BSP_PCI_CONFIG_IN_LONG
0115 #define BSP_PCI_CONFIG_IN_LONG pci_read_config_dword
0116 #endif
0117 #ifndef BSP_PCI_CONFIG_IN_BYTE
0118 #define BSP_PCI_CONFIG_IN_BYTE pci_read_config_byte
0119 #endif
0120 #ifndef BSP_PCI_CONFIG_IN_SHORT
0121 #define BSP_PCI_CONFIG_IN_SHORT pci_read_config_word
0122 #endif
0123 #ifndef BSP_PCI_CONFIG_OUT_SHORT
0124 #define BSP_PCI_CONFIG_OUT_SHORT pci_write_config_word
0125 #endif
0126
0127
0128
0129
0130 typedef uint32_t pci_ulong;
0131
0132 #ifndef BSP_PCI2LOCAL_ADDR
0133 #ifndef PCI_MEM_BASE
0134 #define PCI_MEM_BASE 0
0135 #endif
0136 #define BSP_PCI2LOCAL_ADDR(memaddr) ((pci_ulong)(memaddr) + PCI_MEM_BASE)
0137 #endif
0138
0139 #ifndef BSP_LOCAL2PCI_ADDR
0140 #ifndef PCI_DRAM_OFFSET
0141 #define PCI_DRAM_OFFSET 0
0142 #endif
0143 #define BSP_LOCAL2PCI_ADDR(pciaddr) ((uint32_t)(pciaddr) + PCI_DRAM_OFFSET)
0144 #endif
0145
0146
0147 #elif defined(__vxworks)
0148 typedef unsigned long pci_ulong;
0149 #define BSP_PCI2LOCAL_ADDR(memaddr) (memaddr)
0150 #define BSP_PCI_FIND_DEVICE pciFindDevice
0151 #define BSP_PCI_CONFIG_IN_LONG pciConfigInLong
0152 #define BSP_PCI_CONFIG_IN_BYTE pciConfigInByte
0153 #else
0154 #error "vmeUniverse not ported to this architecture yet"
0155 #endif
0156
0157 #ifndef PCI_INTERRUPT_LINE
0158 #define PCI_INTERRUPT_LINE 0x3c
0159 #endif
0160
0161 volatile LERegister *vmeUniverse0BaseAddr=0;
0162 int vmeUniverse0PciIrqLine=-1;
0163
0164 #ifdef __rtems__
0165 int vmeUniverseRegPort = -1;
0166 int vmeUniverseRegCSR = 0;
0167 #endif
0168
0169 #define DFLT_BASE volatile LERegister *base = vmeUniverse0BaseAddr
0170
0171 #define CHECK_DFLT_BASE(base) \
0172 do { \
0173 \
0174 if (!base) { \
0175 if (vmeUniverseInit()) { \
0176 uprintf(stderr,"unable to find the universe in pci config space\n"); \
0177 return -1; \
0178 } else { \
0179 base = vmeUniverse0BaseAddr; \
0180 } \
0181 } \
0182 } while (0)
0183
0184 #if 0
0185
0186 volatile LERegister *
0187 vmeUniverseBaseAddr(void)
0188 {
0189 if (!vmeUniverse0BaseAddr) vmeUniverseInit();
0190 return vmeUniverse0BaseAddr;
0191 }
0192
0193 int
0194 vmeUniversePciIrqLine(void)
0195 {
0196 if (vmeUniverse0PciIrqLine<0) vmeUniverseInit();
0197 return vmeUniverse0PciIrqLine;
0198 }
0199 #endif
0200
0201 static inline void
0202 WRITE_LE(
0203 unsigned long val,
0204 volatile LERegister *adrs,
0205 unsigned long off)
0206 {
0207 #if (__LITTLE_ENDIAN__ == 1)
0208 *(volatile unsigned long*)(((unsigned long)adrs)+off)=val;
0209 #elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
0210
0211 __asm__ __volatile__("stwbrx %1, %0, %2" :: "b"(off),"r"(val),"r"(adrs));
0212 #elif defined(__rtems__)
0213 st_le32((volatile uint32_t *)(((uint32_t)adrs)+off), val);
0214 #else
0215 #error "little endian register writing not implemented"
0216 #endif
0217 }
0218
0219 #if defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)
0220 #define SYNC __asm__ __volatile__("sync")
0221 #else
0222 #define SYNC
0223 #warning "SYNC instruction unknown for this architecture"
0224 #endif
0225
0226
0227
0228
0229
0230 #define EIEIO_REG
0231
0232 static inline unsigned long
0233 READ_LE0(volatile LERegister *adrs)
0234 {
0235 #if (__LITTLE_ENDIAN__ == 1)
0236 return *(volatile unsigned long *)adrs;
0237 #elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
0238 register unsigned long rval;
0239 __asm__ __volatile__("lwbrx %0, 0, %1":"=r"(rval):"r"(adrs));
0240 return rval;
0241 #elif defined(__rtems__)
0242 return ld_le32((volatile uint32_t*)adrs);
0243 #else
0244 #error "little endian register reading not implemented"
0245 #endif
0246 }
0247
0248 static inline unsigned long
0249 READ_LE(volatile LERegister *adrs, unsigned long off)
0250 {
0251 #if (__LITTLE_ENDIAN__ == 1)
0252 return *((volatile LERegister *)(((unsigned long)adrs)+off));
0253 #elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
0254 register unsigned long rval;
0255
0256 __asm__ __volatile__("lwbrx %0, %2, %1"
0257 : "=r"(rval)
0258 : "r"(adrs), "b"(off));
0259 #if 0
0260 __asm__ __volatile__("eieio");
0261 #endif
0262 return rval;
0263 #else
0264 return READ_LE0((volatile LERegister *)(((unsigned long)adrs)+off));
0265 #endif
0266 }
0267
0268 #define PORT_UNALIGNED(addr,port) \
0269 ( (port)%4 ? ((addr) & 0xffff) : ((addr) & 4095) )
0270
0271
0272 #define UNIV_REV(base) (READ_LE(base,2*sizeof(LERegister)) & 0xff)
0273
0274 #if defined(__rtems__) && 0
0275 static int
0276 uprintk(char *fmt, va_list ap)
0277 {
0278 int rval;
0279 extern int k_vsprintf(char *, char *, va_list);
0280
0281
0282
0283
0284 char buf[200];
0285 rval = k_vsprintf(buf,fmt,ap);
0286 if (rval > sizeof(buf))
0287 rtems_panic("vmeUniverse/uprintk: buffer overrun");
0288 printk(buf);
0289 return rval;
0290 }
0291 #endif
0292
0293
0294
0295 static void
0296 uprintf(FILE *f, char *fmt, ...)
0297 {
0298 va_list ap;
0299 va_start(ap, fmt);
0300 #ifdef __rtems__
0301 if (!f || !_System_state_Is_up(_System_state_Get())) {
0302
0303
0304
0305
0306
0307 vprintk(fmt,ap);
0308 } else
0309 #endif
0310 {
0311 vfprintf(f,fmt,ap);
0312 }
0313 va_end(ap);
0314 }
0315
0316 static int
0317 vmeUniverseFindPciBase(
0318 int instance,
0319 volatile LERegister **pbase
0320 )
0321 {
0322 int bus,dev,fun;
0323 unsigned short wrd;
0324 pci_ulong busaddr;
0325 unsigned char irqline;
0326
0327 if (BSP_PCI_FIND_DEVICE(
0328 PCI_VENDOR_TUNDRA,
0329 PCI_DEVICE_UNIVERSEII,
0330 instance,
0331 &bus,
0332 &dev,
0333 &fun))
0334 return -1;
0335 if (BSP_PCI_CONFIG_IN_LONG(bus,dev,fun,PCI_UNIVERSE_BASE0,&busaddr))
0336 return -1;
0337 if ((unsigned long)(busaddr) & 1) {
0338
0339 if (BSP_PCI_CONFIG_IN_LONG(bus,dev,fun,PCI_UNIVERSE_BASE1,&busaddr)
0340 || ((unsigned long)(busaddr) & 1))
0341 return -1;
0342 }
0343 *pbase=(volatile LERegister*)BSP_PCI2LOCAL_ADDR(busaddr);
0344
0345 if (BSP_PCI_CONFIG_IN_BYTE(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline))
0346 return -1;
0347
0348
0349 BSP_PCI_CONFIG_IN_SHORT(bus, dev, fun, PCI_COMMAND, &wrd);
0350 BSP_PCI_CONFIG_OUT_SHORT(bus, dev, fun, PCI_COMMAND, wrd | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
0351
0352 return irqline;
0353 }
0354
0355
0356
0357
0358
0359 static int
0360 am2mode(int ismaster, unsigned long address_space, unsigned long *pmode)
0361 {
0362 unsigned long mode=0;
0363 unsigned long vdw =0;
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374 address_space &= ~VME_MODE_MATCH_MASK;
0375
0376 if (!ismaster) {
0377 mode |= UNIV_SCTL_DAT | UNIV_SCTL_PGM;
0378 mode |= UNIV_SCTL_USER;
0379 if ( VME_AM_IS_MEMORY & address_space )
0380 mode |= UNIV_SCTL_PWEN | UNIV_SCTL_PREN;
0381 mode |= UNIV_SCTL_EN;
0382 } else {
0383 switch ( VME_MODE_DBW_MSK & address_space ) {
0384 default:
0385 vdw = UNIV_MCTL_VDW64;
0386 break;
0387
0388 case VME_MODE_DBW8:
0389 break;
0390
0391 case VME_MODE_DBW16:
0392 vdw = UNIV_MCTL_VDW16;
0393 break;
0394
0395 case VME_MODE_DBW32:
0396 vdw = UNIV_MCTL_VDW32;
0397 break;
0398 }
0399 if ( VME_AM_IS_MEMORY & address_space )
0400 mode |= UNIV_MCTL_PWEN;
0401 mode |= UNIV_MCTL_EN;
0402 }
0403
0404 address_space &= ~VME_AM_IS_MEMORY;
0405
0406 switch (address_space & VME_AM_MASK) {
0407 case VME_AM_STD_SUP_PGM:
0408 case VME_AM_STD_USR_PGM:
0409 if (ismaster)
0410 mode |= UNIV_MCTL_PGM ;
0411 else {
0412 mode &= ~UNIV_SCTL_DAT;
0413 }
0414
0415
0416
0417 case VME_AM_STD_SUP_DATA:
0418 case VME_AM_STD_USR_DATA:
0419 case VME_AM_STD_SUP_BLT:
0420 case VME_AM_STD_SUP_MBLT:
0421 case VME_AM_STD_USR_BLT:
0422 case VME_AM_STD_USR_MBLT:
0423
0424 if ( ismaster ) {
0425 switch ( address_space & 3 ) {
0426 case 0:
0427 if ( UNIV_MCTL_VDW64 != vdw )
0428 return -1;
0429 break;
0430
0431 case 3:
0432 mode |= UNIV_MCTL_VCT;
0433
0434
0435
0436 vdw = UNIV_MCTL_VDW32;
0437 }
0438 }
0439
0440 mode |= UNIV_CTL_VAS24;
0441 break;
0442
0443
0444 case VME_AM_EXT_SUP_PGM:
0445 case VME_AM_EXT_USR_PGM:
0446 if (ismaster)
0447 mode |= UNIV_MCTL_PGM ;
0448 else {
0449 mode &= ~UNIV_SCTL_DAT;
0450 }
0451
0452
0453 case VME_AM_EXT_SUP_DATA:
0454 case VME_AM_EXT_USR_DATA:
0455 case VME_AM_EXT_SUP_BLT:
0456 case VME_AM_EXT_SUP_MBLT:
0457 case VME_AM_EXT_USR_BLT:
0458 case VME_AM_EXT_USR_MBLT:
0459
0460 if ( ismaster ) {
0461 switch ( address_space & 3 ) {
0462 case 0:
0463 if ( UNIV_MCTL_VDW64 != vdw )
0464 return -1;
0465 break;
0466
0467 case 3:
0468 mode |= UNIV_MCTL_VCT;
0469
0470
0471
0472 vdw = UNIV_MCTL_VDW32;
0473 }
0474 }
0475
0476 mode |= UNIV_CTL_VAS32;
0477
0478 break;
0479
0480 case VME_AM_SUP_SHORT_IO:
0481 case VME_AM_USR_SHORT_IO:
0482 mode |= UNIV_CTL_VAS16;
0483 break;
0484
0485 case VME_AM_CSR:
0486 if ( !ismaster )
0487 return -1;
0488 mode |= UNIV_MCTL_VASCSR;
0489 break;
0490
0491 case 0:
0492 break;
0493
0494 default:
0495 return -1;
0496 }
0497 if ( VME_AM_IS_SUP(address_space) )
0498 mode |= (ismaster ? UNIV_MCTL_SUPER : UNIV_SCTL_SUPER);
0499
0500 mode |= vdw;
0501 *pmode = mode;
0502 return 0;
0503 }
0504
0505 static int
0506 disableUniversePort(int ismaster, int portno, volatile unsigned long *preg, void *param)
0507 {
0508 unsigned long cntrl;
0509 cntrl=READ_LE0(preg);
0510 cntrl &= ~(ismaster ? UNIV_MCTL_EN : UNIV_SCTL_EN);
0511 WRITE_LE(cntrl,preg,0);
0512 SYNC;
0513 return 0;
0514 }
0515
0516 static int
0517 cfgUniversePort(
0518 volatile LERegister *base,
0519 unsigned long ismaster,
0520 unsigned long port,
0521 unsigned long address_space,
0522 unsigned long vme_address,
0523 unsigned long local_address,
0524 unsigned long length)
0525 {
0526 volatile LERegister *preg;
0527 unsigned long p=port;
0528 unsigned long mode=0;
0529
0530 CHECK_DFLT_BASE(base);
0531
0532
0533 if (port >= (ismaster ? UNIV_NUM_MPORTS : UNIV_NUM_SPORTS)) {
0534 uprintf(stderr,"invalid port\n");
0535 return -1;
0536 }
0537
0538
0539
0540 if ( PORT_UNALIGNED(local_address,port) ) {
0541 uprintf(stderr,"local address misaligned\n");
0542 return -1;
0543 }
0544 if ( PORT_UNALIGNED(vme_address,port) ) {
0545 uprintf(stderr,"vme address misaligned\n");
0546 return -1;
0547 }
0548 if ( PORT_UNALIGNED(length,port) ) {
0549 uprintf(stderr,"length misaligned\n");
0550 return -1;
0551 }
0552
0553
0554 if (am2mode(ismaster,address_space,&mode)) {
0555 uprintf(stderr,"invalid address space\n");
0556 return -1;
0557 }
0558
0559
0560 if (!base && vmeUniverseInit()) {
0561 return -1;
0562 }
0563
0564 preg=base;
0565
0566
0567 if ( UNIV_REV(base) < 2 ) {
0568 if (port>3) {
0569 uprintf(stderr,"Universe rev. < 2 has only 4 ports\n");
0570 return -1;
0571 }
0572 }
0573
0574
0575
0576
0577 if (port<4) {
0578 preg += (ismaster ? UNIV_REGOFF_PCITGT0_CTRL : UNIV_REGOFF_VMESLV0_CTRL)/sizeof(LERegister);
0579 } else {
0580 preg += (ismaster ? UNIV_REGOFF_PCITGT4_CTRL : UNIV_REGOFF_VMESLV4_CTRL)/sizeof(LERegister);
0581 p-=4;
0582 }
0583 preg += 5 * p;
0584
0585
0586 disableUniversePort(ismaster,port,preg,0);
0587
0588
0589 if (address_space != 0) {
0590 unsigned long start,offst;
0591
0592
0593
0594
0595 if (ismaster) {
0596 start=local_address;
0597
0598 offst=vme_address-local_address;
0599 } else {
0600 start=vme_address;
0601
0602 offst=local_address-vme_address;
0603 }
0604 #undef TSILL
0605 #ifdef TSILL
0606 uprintf(stderr,"writing 0x%08x to 0x%08x + 4\n",start,preg);
0607 #else
0608 WRITE_LE(start,preg,4);
0609 #endif
0610
0611 length+=start;
0612 #ifdef TSILL
0613 uprintf(stderr,"writing 0x%08x to 0x%08x + 8\n",length,preg);
0614 #else
0615 WRITE_LE(length,preg,8);
0616 #endif
0617
0618 #ifdef TSILL
0619 uprintf(stderr,"writing 0x%08x to 0x%08x + 12\n",offst,preg);
0620 #else
0621 WRITE_LE(offst,preg,12);
0622 #endif
0623
0624 #ifdef TSILL
0625 uprintf(stderr,"writing 0x%08x to 0x%08x + 0\n",mode,preg);
0626 #else
0627 EIEIO_REG;
0628 WRITE_LE(mode,preg,0);
0629 SYNC;
0630 #endif
0631
0632 #ifdef TSILL
0633 uprintf(stderr,
0634 "universe %s port %lu successfully configured\n",
0635 ismaster ? "master" : "slave",
0636 port);
0637 #endif
0638
0639 #ifdef __vxworks
0640 if (ismaster)
0641 uprintf(stderr,
0642 "WARNING: on the synergy, sysMasterPortsShow() may show incorrect settings (it uses cached values)\n");
0643 #endif
0644 }
0645 return 0;
0646 }
0647
0648 static int
0649 showUniversePort(
0650 int ismaster,
0651 int portno,
0652 volatile LERegister *preg,
0653 void *parm)
0654 {
0655 FILE *f=parm ? (FILE *)parm : stdout;
0656 unsigned long cntrl, start, bound, offst, mask;
0657
0658 cntrl = READ_LE0(preg++);
0659 #undef TSILL
0660 #ifdef TSILL
0661 uprintf(stderr,"showUniversePort: *(0x%08x): 0x%08x\n",preg-1,cntrl);
0662 #endif
0663 #undef TSILL
0664
0665
0666 if (!(cntrl & (ismaster ? UNIV_MCTL_EN : UNIV_SCTL_EN)))
0667 return 0;
0668
0669
0670
0671
0672 mask = ~PORT_UNALIGNED(0xffffffff,portno);
0673
0674 start = READ_LE0(preg++)&mask;
0675 bound = READ_LE0(preg++)&mask;
0676 offst = READ_LE0(preg++)&mask;
0677
0678 offst+=start;
0679
0680 if (ismaster) {
0681 uprintf(f,"%d: 0x%08lx 0x%08lx 0x%08lx ",
0682 portno,offst,bound-start,start);
0683 } else {
0684 uprintf(f,"%d: 0x%08lx 0x%08lx 0x%08lx ",
0685 portno,start,bound-start,offst);
0686 }
0687
0688 switch (cntrl & UNIV_CTL_VAS) {
0689 case UNIV_CTL_VAS16: uprintf(f,"A16, "); break;
0690 case UNIV_CTL_VAS24: uprintf(f,"A24, "); break;
0691 case UNIV_CTL_VAS32: uprintf(f,"A32, "); break;
0692 case UNIV_MCTL_VASCSR: if ( ismaster ) { uprintf(f,"CSR, "); break; }
0693
0694 default: uprintf(f,"A??, "); break;
0695 }
0696
0697 if (ismaster) {
0698 unsigned vdw;
0699 switch ( cntrl & UNIV_MCTL_VDW64 ) {
0700 case UNIV_MCTL_VDW64:
0701 vdw = 64;
0702 break;
0703
0704 case UNIV_MCTL_VDW32:
0705 vdw = 32;
0706 break;
0707
0708 case UNIV_MCTL_VDW16:
0709 vdw = 16;
0710 break;
0711
0712 default:
0713 vdw = 8;
0714 break;
0715 }
0716
0717 if ( 64 == vdw ) {
0718 switch ( UNIV_CTL_VAS & cntrl ) {
0719 case UNIV_CTL_VAS24:
0720 case UNIV_CTL_VAS32:
0721 uprintf(f,"D64 [MBLT], ");
0722 break;
0723
0724 default:
0725 uprintf(f,"D64, ");
0726 break;
0727 }
0728 } else {
0729 uprintf(f, "D%u%s, ", vdw, (cntrl & UNIV_MCTL_VCT) ? " [BLT]" : "");
0730 }
0731
0732 uprintf(f,"%s, %s",
0733 cntrl&UNIV_MCTL_PGM ? "Pgm" : "Dat",
0734 cntrl&UNIV_MCTL_SUPER ? "Sup" : "Usr");
0735 if ( cntrl & UNIV_MCTL_PWEN )
0736 uprintf(f,", PWEN");
0737 } else {
0738 uprintf(f,"%s %s %s %s",
0739 cntrl&UNIV_SCTL_PGM ? "Pgm," : " ",
0740 cntrl&UNIV_SCTL_DAT ? "Dat," : " ",
0741 cntrl&UNIV_SCTL_SUPER ? "Sup," : " ",
0742 cntrl&UNIV_SCTL_USER ? "Usr" : "");
0743 if ( cntrl & UNIV_SCTL_PWEN )
0744 uprintf(f,", PWEN");
0745 if ( cntrl & UNIV_SCTL_PREN )
0746 uprintf(f,", PREN");
0747 }
0748 uprintf(f,"\n");
0749 return 0;
0750 }
0751
0752 typedef struct XlatRec_ {
0753 unsigned long address;
0754 unsigned long aspace;
0755 unsigned reverse;
0756 } XlatRec, *Xlat;
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768 static int
0769 xlatePort(int ismaster, int port, volatile LERegister *preg, void *parm)
0770 {
0771 Xlat l=(Xlat)parm;
0772 unsigned long cntrl, start, bound, offst, mask, x;
0773
0774 cntrl = READ_LE0(preg++);
0775
0776
0777 if (!(cntrl & (ismaster ? UNIV_MCTL_EN : UNIV_SCTL_EN)))
0778 return 0;
0779
0780
0781 if ( am2mode(ismaster,l->aspace,&offst) ) {
0782 uprintf(stderr,"vmeUniverse WARNING: invalid adressing mode 0x%x\n",
0783 l->aspace);
0784 return -1;
0785 }
0786
0787
0788 switch (VME_MODE_MATCH_MASK & l->aspace) {
0789 case VME_MODE_EXACT_MATCH:
0790 mask = -1 & ~VME_MODE_MATCH_MASK;
0791 break;
0792
0793 case VME_MODE_AS_MATCH:
0794 mask = UNIV_CTL_VAS;
0795 break;
0796
0797 default:
0798 mask = (ismaster ? UNIV_MCTL_AM_MASK : UNIV_SCTL_AM_MASK);
0799 break;
0800 }
0801
0802 cntrl &= mask;
0803 offst &= mask;
0804
0805 if ( cntrl != offst )
0806 return 0;
0807
0808
0809 mask = ~PORT_UNALIGNED(0xffffffff,port);
0810
0811
0812
0813
0814 start = READ_LE0(preg++) & mask;
0815 bound = READ_LE0(preg++) & mask;
0816 offst = READ_LE0(preg++) & mask;
0817
0818
0819 if (l->reverse) {
0820
0821
0822
0823 if (l->address >= start && l->address < bound) {
0824 l->address+=offst;
0825 return 1 + port;
0826 }
0827 } else {
0828 x = l->address - offst;
0829
0830 if (x >= start && x < bound) {
0831
0832 l->address = x;
0833 return 1 + port;
0834 }
0835 }
0836 return 0;
0837 }
0838
0839
0840 static int
0841 hasPWENWindow(
0842 int ismaster,
0843 int portno,
0844 volatile LERegister *preg,
0845 void *parm)
0846 {
0847 unsigned long cntrl = READ_LE0(preg);
0848 unsigned long mask = ismaster ? (UNIV_MCTL_EN|UNIV_MCTL_PWEN) : (UNIV_SCTL_EN|UNIV_SCTL_PWEN);
0849 return (cntrl & mask) == mask ? -1 : 0;
0850 }
0851
0852 static int
0853 mapOverAll(volatile LERegister *base, int ismaster, int (*func)(int,int,volatile LERegister *,void*), void *arg)
0854 {
0855 volatile LERegister *rptr;
0856 unsigned long port;
0857 int rval;
0858
0859 CHECK_DFLT_BASE(base);
0860
0861 rptr = (base +
0862 (ismaster ? UNIV_REGOFF_PCITGT0_CTRL : UNIV_REGOFF_VMESLV0_CTRL)/sizeof(LERegister));
0863 #undef TSILL
0864 #ifdef TSILL
0865 uprintf(stderr,"mapoverall: base is 0x%08x, rptr 0x%08x\n",base,rptr);
0866 #endif
0867 #undef TSILL
0868 for (port=0; port<4; port++) {
0869 if ((rval=func(ismaster,port,rptr,arg))) return rval;
0870 rptr+=5;
0871 }
0872
0873
0874 if (UNIV_REV(base)<2) return -1;
0875
0876 rptr = (base +
0877 (ismaster ? UNIV_REGOFF_PCITGT4_CTRL : UNIV_REGOFF_VMESLV4_CTRL)/sizeof(LERegister));
0878 for (port=4; port<UNIV_NUM_MPORTS; port++) {
0879 if ((rval=func(ismaster,port,rptr,arg))) return rval;
0880 rptr+=5;
0881 }
0882 return 0;
0883 }
0884
0885 static void
0886 showUniversePorts(volatile LERegister *base, int ismaster, FILE *f)
0887 {
0888 if (!f) f=stdout;
0889 uprintf(f,"Universe %s Ports:\n",ismaster ? "Master" : "Slave");
0890 uprintf(f,"Port VME-Addr Size PCI-Adrs Mode:\n");
0891 mapOverAll(base,ismaster,showUniversePort,f);
0892 }
0893
0894 static int
0895 xlateFindPort(
0896 volatile LERegister *base,
0897 int master,
0898 int reverse,
0899 unsigned long as,
0900 unsigned long aIn,
0901 unsigned long *paOut
0902 )
0903 {
0904 int rval;
0905 XlatRec l;
0906 l.aspace = as;
0907 l.address = aIn;
0908 l.reverse = reverse;
0909
0910 rval = mapOverAll(base,master,xlatePort,(void*)&l) - 1;
0911 *paOut = l.address;
0912 return rval;
0913 }
0914
0915 int
0916 vmeUniverseXlateAddrXX(
0917 volatile LERegister *base,
0918 int master,
0919 int reverse,
0920 unsigned long as,
0921 unsigned long aIn,
0922 unsigned long *paOut
0923 )
0924 {
0925 return xlateFindPort(base, master, reverse, as, aIn, paOut) >= 0 ? 0 : -1;
0926 }
0927
0928 int
0929 vmeUniverseXlateAddr(
0930 int master,
0931 int reverse,
0932 unsigned long as,
0933 unsigned long aIn,
0934 unsigned long *paOut
0935 )
0936 {
0937 DFLT_BASE;
0938 return vmeUniverseXlateAddrXX(base, master, reverse, as, aIn, paOut);
0939 }
0940
0941
0942 void
0943 vmeUniverseReset(void)
0944 {
0945
0946 vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_CTL);
0947 vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_ADDR);
0948 vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_EN);
0949
0950
0951
0952
0953 vmeUniverseWriteReg(UNIV_LMISC_CRT_128_US, UNIV_REGOFF_LMISC);
0954
0955
0956 vmeUniverseWriteReg(0, UNIV_REGOFF_DCTL);
0957 vmeUniverseWriteReg(0, UNIV_REGOFF_DTBC);
0958 vmeUniverseWriteReg(0, UNIV_REGOFF_DLA);
0959 vmeUniverseWriteReg(0, UNIV_REGOFF_DVA);
0960 vmeUniverseWriteReg(0, UNIV_REGOFF_DCPP);
0961
0962
0963 vmeUniverseWriteReg(0, UNIV_REGOFF_LM_CTL);
0964
0965
0966 vmeUniverseWriteReg(0, UNIV_REGOFF_VRAI_CTL);
0967
0968 #if 0
0969
0970 vmeUniverseWriteReg(0, UNIV_REGOFF_VCSR_CTL);
0971 #endif
0972
0973
0974
0975
0976
0977
0978
0979
0980 if (2==UNIV_REV(vmeUniverse0BaseAddr))
0981 vmeUniverseWriteReg(UNIV_U2SPEC_DTKFLTR |
0982 UNIV_U2SPEC_MASt11 |
0983 UNIV_U2SPEC_READt27_NODELAY |
0984 UNIV_U2SPEC_POSt28_FAST |
0985 UNIV_U2SPEC_PREt28_FAST,
0986 UNIV_REGOFF_U2SPEC);
0987
0988
0989 vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_EN);
0990 vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP0);
0991 vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP1);
0992
0993 vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_EN);
0994 vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_MAP0);
0995 vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_MAP1);
0996
0997 vmeUniverseDisableAllSlaves();
0998
0999 vmeUniverseDisableAllMasters();
1000
1001 vmeUniverseWriteReg(UNIV_VCSR_CLR_SYSFAIL, UNIV_REGOFF_VCSR_CLR);
1002
1003
1004 vmeUniverseWriteReg(UNIV_LINT_STAT_CLR, UNIV_REGOFF_LINT_STAT);
1005 vmeUniverseWriteReg(UNIV_VINT_STAT_CLR, UNIV_REGOFF_VINT_STAT);
1006
1007 vmeUniverseWriteReg(UNIV_V_AMERR_V_STAT, UNIV_REGOFF_V_AMERR);
1008
1009 vmeUniverseWriteReg(
1010 vmeUniverseReadReg(UNIV_REGOFF_PCI_CSR) |
1011 UNIV_PCI_CSR_D_PE | UNIV_PCI_CSR_S_SERR | UNIV_PCI_CSR_R_MA |
1012 UNIV_PCI_CSR_R_TA | UNIV_PCI_CSR_S_TA,
1013 UNIV_REGOFF_PCI_CSR);
1014
1015 vmeUniverseWriteReg(UNIV_L_CMDERR_L_STAT, UNIV_REGOFF_L_CMDERR);
1016
1017 vmeUniverseWriteReg(
1018 UNIV_DGCS_STOP | UNIV_DGCS_HALT | UNIV_DGCS_DONE |
1019 UNIV_DGCS_LERR | UNIV_DGCS_VERR | UNIV_DGCS_P_ERR,
1020 UNIV_REGOFF_DGCS);
1021 }
1022
1023 int
1024 vmeUniverseInit(void)
1025 {
1026 int rval;
1027 if ( (rval=vmeUniverseFindPciBase(0,&vmeUniverse0BaseAddr)) < 0 ) {
1028 uprintf(stderr,"unable to find the universe in pci config space\n");
1029 } else {
1030 vmeUniverse0PciIrqLine = rval;
1031 rval = 0;
1032 uprintf(stderr,"Universe II PCI-VME bridge detected at 0x%08x, IRQ %d\n",
1033 (unsigned int)vmeUniverse0BaseAddr, vmeUniverse0PciIrqLine);
1034 }
1035 return rval;
1036 }
1037
1038 void
1039 vmeUniverseMasterPortsShowXX(volatile LERegister *base, FILE *f)
1040 {
1041 showUniversePorts(base,1,f);
1042 }
1043
1044 void
1045 vmeUniverseMasterPortsShow(FILE *f)
1046 {
1047 DFLT_BASE;
1048 showUniversePorts(base,1,f);
1049 }
1050
1051 void
1052 vmeUniverseSlavePortsShowXX(volatile LERegister *base, FILE *f)
1053 {
1054 showUniversePorts(base,0,f);
1055 }
1056
1057 void
1058 vmeUniverseSlavePortsShow(FILE *f)
1059 {
1060 DFLT_BASE;
1061 showUniversePorts(base,0,f);
1062 }
1063
1064 int
1065 vmeUniverseMasterPortCfgXX(
1066 volatile LERegister *base,
1067 unsigned long port,
1068 unsigned long address_space,
1069 unsigned long vme_address,
1070 unsigned long local_address,
1071 unsigned long length)
1072 {
1073 return cfgUniversePort(base,1,port,address_space,vme_address,local_address,length);
1074 }
1075
1076 int
1077 vmeUniverseMasterPortCfg(
1078 unsigned long port,
1079 unsigned long address_space,
1080 unsigned long vme_address,
1081 unsigned long local_address,
1082 unsigned long length)
1083 {
1084 DFLT_BASE;
1085 return cfgUniversePort(base,1,port,address_space,vme_address,local_address,length);
1086 }
1087
1088 int
1089 vmeUniverseSlavePortCfgXX(
1090 volatile LERegister *base,
1091 unsigned long port,
1092 unsigned long address_space,
1093 unsigned long vme_address,
1094 unsigned long local_address,
1095 unsigned long length)
1096 {
1097 return cfgUniversePort(base,0,port,address_space,vme_address,local_address,length);
1098 }
1099
1100 int
1101 vmeUniverseSlavePortCfg(
1102 unsigned long port,
1103 unsigned long address_space,
1104 unsigned long vme_address,
1105 unsigned long local_address,
1106 unsigned long length)
1107 {
1108 DFLT_BASE;
1109 return cfgUniversePort(base,0,port,address_space,vme_address,local_address,length);
1110 }
1111
1112
1113 void
1114 vmeUniverseDisableAllSlavesXX(volatile LERegister *base)
1115 {
1116 mapOverAll(base,0,disableUniversePort,0);
1117 }
1118
1119 void
1120 vmeUniverseDisableAllSlaves(void)
1121 {
1122 DFLT_BASE;
1123 mapOverAll(base,0,disableUniversePort,0);
1124 }
1125
1126 void
1127 vmeUniverseDisableAllMastersXX(volatile LERegister *base)
1128 {
1129 mapOverAll(base,1,disableUniversePort,0);
1130 }
1131
1132 void
1133 vmeUniverseDisableAllMasters(void)
1134 {
1135 DFLT_BASE;
1136 mapOverAll(base,1,disableUniversePort,0);
1137 }
1138
1139 unsigned long
1140 vmeUniverseReadRegXX(volatile LERegister *base, unsigned long offset)
1141 {
1142 unsigned long rval;
1143 rval = READ_LE(base,offset);
1144 return rval;
1145 }
1146
1147
1148 unsigned long
1149 vmeUniverseReadReg(unsigned long offset)
1150 {
1151 unsigned long rval;
1152 rval = READ_LE(vmeUniverse0BaseAddr,offset);
1153 return rval;
1154 }
1155
1156 void
1157 vmeUniverseWriteRegXX(volatile LERegister *base, unsigned long value, unsigned long offset)
1158 {
1159 WRITE_LE(value, base, offset);
1160 }
1161
1162 void
1163 vmeUniverseWriteReg(unsigned long value, unsigned long offset)
1164 {
1165 WRITE_LE(value, vmeUniverse0BaseAddr, offset);
1166 }
1167
1168 void
1169 vmeUniverseResetBus(void)
1170 {
1171 vmeUniverseWriteReg(
1172 vmeUniverseReadReg(UNIV_REGOFF_MISC_CTL) | UNIV_MISC_CTL_SW_SYSRST,
1173 UNIV_REGOFF_MISC_CTL);
1174 }
1175
1176 void
1177 vmeUniverseCvtToLE(unsigned long *ptr, unsigned long num)
1178 {
1179 #if !defined(__LITTLE_ENDIAN__) || (__LITTLE_ENDIAN__ != 1)
1180 register unsigned long *p=ptr+num;
1181 while (p > ptr) {
1182 #if (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
1183 __asm__ __volatile__(
1184 "lwzu 0, -4(%0)\n"
1185 "stwbrx 0, 0, %0\n"
1186 : "=r"(p) : "0"(p) : "r0"
1187 );
1188 #elif defined(__rtems__)
1189 p--; st_le32(p, *p);
1190 #else
1191 #error "vmeUniverse: endian conversion not implemented for this architecture"
1192 #endif
1193 }
1194 #endif
1195 }
1196
1197 int
1198 vmeUniverseIntRaiseXX(volatile LERegister *base, int level, unsigned vector)
1199 {
1200 unsigned long v;
1201 unsigned long b;
1202
1203 CHECK_DFLT_BASE(base);
1204
1205 if ( level < 1 || level > 7 || vector > 255 )
1206 return -1;
1207
1208 if ( vector & 1 )
1209 return -1;
1210
1211
1212
1213 if ( vmeUniverseReadRegXX(base, UNIV_REGOFF_VINT_STAT ) & UNIV_VINT_STAT_SWINT(level) ) {
1214 return -2;
1215 }
1216
1217
1218 vmeUniverseWriteRegXX(base, UNIV_VINT_STATID(vector), UNIV_REGOFF_VINT_STATID );
1219
1220 if ( UNIV_REV(base) >= 2 ) {
1221
1222 b = UNIV_VINT_STAT_SWINT(level);
1223 } else {
1224
1225 v = vmeUniverseReadRegXX(base, UNIV_REGOFF_VINT_MAP1);
1226 v &= ~UNIV_VINT_MAP1_SWINT(0x7);
1227 v |= UNIV_VINT_MAP1_SWINT(level);
1228 vmeUniverseWriteRegXX(base, v, UNIV_REGOFF_VINT_MAP1);
1229 b = UNIV_VINT_EN_SWINT;
1230 }
1231 v = vmeUniverseReadRegXX(base, UNIV_REGOFF_VINT_EN);
1232
1233 vmeUniverseWriteRegXX(base, v & ~b, UNIV_REGOFF_VINT_EN );
1234 vmeUniverseWriteRegXX(base, v | b, UNIV_REGOFF_VINT_EN );
1235
1236 return 0;
1237
1238 }
1239
1240 int
1241 vmeUniverseIntRaise(int level, unsigned vector)
1242 {
1243 return vmeUniverseIntRaiseXX(vmeUniverse0BaseAddr, level, vector);
1244 }
1245
1246
1247
1248 #define UNIV_CRG_SIZE (1<<12)
1249
1250 int
1251 vmeUniverseMapCRGXX(volatile LERegister *base, unsigned long vme_base, unsigned long as )
1252 {
1253 uint32_t mode;
1254
1255 CHECK_DFLT_BASE(base);
1256
1257 #ifdef __rtems__
1258 if ( vmeUniverseRegPort > -1 && ! vmeUniverseRegCSR ) {
1259 uprintf(stderr,"vmeUniverse: CRG already mapped and in use by interrupt manager\n");
1260 return -1;
1261 }
1262 #endif
1263
1264
1265 mode = UNIV_VRAI_CTL_EN | UNIV_VRAI_CTL_PGM | UNIV_VRAI_CTL_DATA | UNIV_VRAI_CTL_SUPER | UNIV_VRAI_CTL_USER;
1266
1267 if ( VME_AM_IS_SHORT(as) ) {
1268 mode |= UNIV_VRAI_CTL_VAS_A16;
1269 } else
1270 if ( VME_AM_IS_STD(as) ) {
1271 mode |= UNIV_VRAI_CTL_VAS_A24;
1272 } else
1273 if ( VME_AM_IS_EXT(as) ) {
1274 mode |= UNIV_VRAI_CTL_VAS_A32;
1275 } else {
1276 return -2;
1277 }
1278
1279
1280 WRITE_LE( (vme_base & ~(UNIV_CRG_SIZE-1)), base, UNIV_REGOFF_VRAI_BS );
1281 WRITE_LE( mode, base, UNIV_REGOFF_VRAI_CTL );
1282
1283 return 0;
1284 }
1285
1286 int
1287 vmeUniverseMapCRG(unsigned long vme_base, unsigned long as )
1288 {
1289 return vmeUniverseMapCRGXX( vmeUniverse0BaseAddr, vme_base, as );
1290 }
1291
1292 #ifdef __rtems__
1293
1294 #include "bspVmeDmaListP.h"
1295 #include <bsp/vmeUniverseDMA.h>
1296
1297
1298 #define DCTL_MODE_MASK \
1299 ( UNIV_DCTL_VDW_MSK | UNIV_DCTL_VAS_MSK | UNIV_DCTL_PGM | UNIV_DCTL_SUPER | UNIV_DCTL_VCT )
1300
1301 static uint32_t
1302 xfer_mode2dctl(uint32_t xfer_mode)
1303 {
1304 uint32_t dctl;
1305 unsigned long ul;
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315 if ( xfer_mode & BSP_VMEDMA_MODE_NOINC_PCI )
1316 return BSP_VMEDMA_STATUS_UNSUP;
1317
1318
1319 xfer_mode &= ~VME_AM_IS_MEMORY;
1320
1321 if ( VME_AM_IS_2eSST(xfer_mode) )
1322 return BSP_VMEDMA_STATUS_UNSUP;
1323
1324 if ( ! VME_AM_IS_SHORT(xfer_mode) && ! VME_AM_IS_STD(xfer_mode) && ! VME_AM_IS_EXT(xfer_mode) )
1325 return BSP_VMEDMA_STATUS_UNSUP;
1326
1327
1328 if ( am2mode( 1, xfer_mode, &ul ) )
1329 return BSP_VMEDMA_STATUS_UNSUP;
1330 dctl = (uint32_t) ul;
1331
1332
1333
1334
1335
1336
1337
1338
1339 switch ( UNIV_DCTL_VAS_MSK & dctl ) {
1340 case UNIV_DCTL_VAS_A24:
1341 case UNIV_DCTL_VAS_A32:
1342
1343
1344
1345
1346 if ( (xfer_mode & 0xb) != 8
1347 && ( UNIV_DCTL_VDW_64 == (dctl & UNIV_DCTL_VDW_MSK) ) ) {
1348 dctl &= ~UNIV_DCTL_VDW_MSK;
1349 dctl |= UNIV_DCTL_VDW_32;
1350 }
1351 break;
1352
1353 case UNIV_DCTL_VAS_A16:
1354 break;
1355
1356 default:
1357 return BSP_VMEDMA_STATUS_UNSUP;
1358 }
1359
1360
1361 dctl &= DCTL_MODE_MASK;
1362
1363 if ( xfer_mode & BSP_VMEDMA_MODE_NOINC_VME ) {
1364
1365
1366
1367 dctl &= ~UNIV_DCTL_VCT;
1368 dctl |= UNIV_DCTL_NO_VINC;
1369
1370 if ( UNIV_DCTL_VDW_64 == (dctl & UNIV_DCTL_VDW_MSK) ) {
1371 dctl &= ~UNIV_DCTL_VDW_MSK;
1372 dctl |= UNIV_DCTL_VDW_32;
1373 }
1374 }
1375
1376
1377
1378 if ( BSP_VMEDMA_MODE_PCI2VME & xfer_mode )
1379 dctl |= UNIV_DCTL_L2V;
1380
1381 return dctl;
1382 }
1383
1384
1385
1386
1387 int
1388 vmeUniverseDmaSetupXX(volatile LERegister *base, int channel, uint32_t mode, uint32_t xfer_mode, void *custom)
1389 {
1390 uint32_t dctl, dgcs;
1391
1392 if ( channel != 0 )
1393 return BSP_VMEDMA_STATUS_UNSUP;
1394
1395 dctl = xfer_mode2dctl(xfer_mode);
1396
1397 if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == dctl )
1398 return BSP_VMEDMA_STATUS_UNSUP;
1399
1400
1401 dgcs = UNIV_DGCS_INT_MSK;
1402
1403 switch ( mode ) {
1404 case BSP_VMEDMA_OPT_THROUGHPUT:
1405 dgcs |= UNIV_DGCS_VON_1024 | UNIV_DGCS_VOFF_0_US;
1406
1407 dgcs |= ( xfer_mode & BSP_VMEDMA_MODE_NOINC_VME ) ?
1408 UNIV_DGCS_VON_2048 : UNIV_DGCS_VON_1024;
1409 break;
1410
1411 case BSP_VMEDMA_OPT_LOWLATENCY:
1412 dgcs |= UNIV_DGCS_VOFF_0_US;
1413
1414 dgcs |= ( xfer_mode & BSP_VMEDMA_MODE_NOINC_VME ) ?
1415 UNIV_DGCS_VON_512 : UNIV_DGCS_VON_256;
1416 break;
1417
1418 case BSP_VMEDMA_OPT_SHAREDBUS:
1419 dgcs |= UNIV_DGCS_VOFF_512_US;
1420
1421 dgcs |= ( xfer_mode & BSP_VMEDMA_MODE_NOINC_VME ) ?
1422 UNIV_DGCS_VON_512 : UNIV_DGCS_VON_256;
1423 break;
1424
1425 case BSP_VMEDMA_OPT_CUSTOM:
1426 dctl = ((uint32_t*)custom)[0];
1427 dgcs = ((uint32_t*)custom)[1];
1428 break;
1429
1430 default:
1431 case BSP_VMEDMA_OPT_DEFAULT:
1432 break;
1433 }
1434
1435
1436 dgcs |= UNIV_DGCS_STATUS_CLEAR;
1437
1438 vmeUniverseWriteRegXX(base, dctl, UNIV_REGOFF_DCTL);
1439 vmeUniverseWriteRegXX(base, dgcs, UNIV_REGOFF_DGCS);
1440
1441 return BSP_VMEDMA_STATUS_OK;
1442 }
1443
1444 int
1445 vmeUniverseDmaSetup(int channel, uint32_t mode, uint32_t xfer_mode, void *custom)
1446 {
1447 DFLT_BASE;
1448 return vmeUniverseDmaSetupXX(base, channel, mode, xfer_mode, custom);
1449 }
1450
1451 int
1452 vmeUniverseDmaStartXX(volatile LERegister *base, int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes)
1453 {
1454 if ( channel != 0 )
1455 return BSP_VMEDMA_STATUS_UNSUP;
1456
1457 if ((pci_addr & 7) != (vme_addr & 7)) {
1458 uprintf(stderr,"vmeUniverseDmaStartXX: misaligned addresses\n");
1459 return -1;
1460 }
1461
1462 {
1463
1464 register volatile LERegister *b=base;
1465 register unsigned long dgcsoff=UNIV_REGOFF_DGCS,dgcs;
1466
1467 dgcs=READ_LE(b, dgcsoff);
1468
1469
1470 dgcs &= ~UNIV_DGCS_CHAIN;
1471 WRITE_LE(dgcs,
1472 b, dgcsoff);
1473 WRITE_LE(pci_addr,
1474 b, UNIV_REGOFF_DLA);
1475 WRITE_LE(vme_addr,
1476 b, UNIV_REGOFF_DVA);
1477 WRITE_LE(n_bytes,
1478 b, UNIV_REGOFF_DTBC);
1479 dgcs |= UNIV_DGCS_GO;
1480 EIEIO_REG;
1481 WRITE_LE(dgcs,
1482 b, dgcsoff);
1483 }
1484 SYNC;
1485 return 0;
1486 }
1487
1488
1489 int
1490 vmeUniverseStartDMAXX(
1491 volatile LERegister *base,
1492 unsigned long local_addr,
1493 unsigned long vme_addr,
1494 unsigned long count)
1495 {
1496 return vmeUniverseDmaStartXX(base, 0, local_addr, vme_addr, count);
1497 }
1498
1499 int
1500 vmeUniverseDmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes)
1501 {
1502 DFLT_BASE;
1503 return vmeUniverseDmaStartXX(base, channel, pci_addr, vme_addr, n_bytes);
1504 }
1505
1506
1507 int
1508 vmeUniverseStartDMA(
1509 unsigned long local_addr,
1510 unsigned long vme_addr,
1511 unsigned long count)
1512 {
1513 DFLT_BASE;
1514 return vmeUniverseDmaStartXX(base, 0, local_addr, vme_addr, count);
1515 }
1516
1517 uint32_t
1518 vmeUniverseDmaStatusXX(volatile LERegister *base, int channel)
1519 {
1520 uint32_t dgcs;
1521 if ( channel != 0 )
1522 return BSP_VMEDMA_STATUS_UNSUP;
1523
1524 dgcs = vmeUniverseReadRegXX(base, UNIV_REGOFF_DGCS);
1525
1526 dgcs &= UNIV_DGCS_STATUS_CLEAR;
1527
1528 if ( 0 == dgcs || UNIV_DGCS_DONE == dgcs )
1529 return BSP_VMEDMA_STATUS_OK;
1530
1531 if ( UNIV_DGCS_ACT & dgcs )
1532 return BSP_VMEDMA_STATUS_BUSY;
1533
1534 if ( UNIV_DGCS_LERR & dgcs )
1535 return BSP_VMEDMA_STATUS_BERR_PCI;
1536
1537 if ( UNIV_DGCS_VERR & dgcs )
1538 return BSP_VMEDMA_STATUS_BERR_VME;
1539
1540 return BSP_VMEDMA_STATUS_OERR;
1541 }
1542
1543 uint32_t
1544 vmeUniverseDmaStatus(int channel)
1545 {
1546 DFLT_BASE;
1547 return vmeUniverseDmaStatusXX(base, channel);
1548 }
1549
1550
1551
1552
1553
1554
1555
1556 typedef volatile uint32_t LERegister1;
1557
1558 typedef struct VmeUniverseDmaListDescRec_ {
1559 LERegister1 dctl;
1560 LERegister1 dtbc;
1561 LERegister1 dla;
1562 LERegister1 dummy1;
1563 LERegister1 dva;
1564 LERegister1 dummy2;
1565 LERegister1 dcpp;
1566 LERegister1 dummy3;
1567 } __attribute__((aligned(32), __may_alias__))
1568 VmeUniverseDmaListDescRec;
1569
1570 typedef VmeUniverseDmaListDescRec *VmeUniverseDmaListDesc;
1571
1572 static void uni_desc_init (DmaDescriptor);
1573 static int uni_desc_setup (DmaDescriptor, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
1574 static void uni_desc_setnxt(DmaDescriptor, DmaDescriptor);
1575 static void uni_desc_dump (DmaDescriptor);
1576 static int uni_desc_start (volatile void *controller_addr, int channel, DmaDescriptor p);
1577
1578 VMEDmaListClassRec vmeUniverseDmaListClass = {
1579 desc_size: sizeof(VmeUniverseDMAPacketRec),
1580 desc_align: 32,
1581 freeList: 0,
1582 desc_alloc: 0,
1583 desc_free: 0,
1584 desc_init: uni_desc_init,
1585 desc_setnxt:uni_desc_setnxt,
1586 desc_setup: uni_desc_setup,
1587 desc_start: uni_desc_start,
1588 desc_refr: 0,
1589 desc_dump: uni_desc_dump,
1590 };
1591
1592 static void uni_desc_init (DmaDescriptor p)
1593 {
1594 VmeUniverseDmaListDesc d = p;
1595 st_le32( &d->dcpp, UNIV_DCPP_IMG_NULL );
1596 }
1597
1598 static void uni_desc_setnxt(DmaDescriptor p, DmaDescriptor n)
1599 {
1600 VmeUniverseDmaListDesc d = p;
1601 if ( 0 == n ) {
1602 st_le32( &d->dcpp, UNIV_DCPP_IMG_NULL );
1603 } else {
1604 st_le32( &d->dcpp, BSP_LOCAL2PCI_ADDR( (uint32_t)n));
1605 }
1606 }
1607
1608 static int
1609 uni_desc_setup (
1610 DmaDescriptor p,
1611 uint32_t attr_mask,
1612 uint32_t xfer_mode,
1613 uint32_t pci_addr,
1614 uint32_t vme_addr,
1615 uint32_t n_bytes)
1616 {
1617 VmeUniverseDmaListDesc d = p;
1618 LERegister1 dctl;
1619
1620 if ( BSP_VMEDMA_MSK_ATTR & attr_mask ) {
1621 dctl = xfer_mode2dctl(xfer_mode);
1622
1623 if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == dctl )
1624 return -1;
1625
1626 st_le32( &d->dctl, dctl );
1627 }
1628
1629
1630
1631
1632
1633 if ( BSP_VMEDMA_MSK_PCIA & attr_mask ) {
1634 if ( pci_addr & 0x7 )
1635 return -1;
1636
1637 st_le32( &d->dla, pci_addr );
1638 }
1639
1640 if ( BSP_VMEDMA_MSK_VMEA & attr_mask ) {
1641 if ( vme_addr & 0x7 )
1642 return -1;
1643
1644 st_le32( &d->dva, vme_addr );
1645 }
1646
1647 if ( BSP_VMEDMA_MSK_BCNT & attr_mask ) {
1648 st_le32( &d->dtbc, n_bytes );
1649 }
1650
1651 return 0;
1652 }
1653
1654 static int uni_desc_start
1655 (volatile void *controller_addr, int channel, DmaDescriptor p)
1656 {
1657 volatile LERegister *base = controller_addr;
1658 uint32_t dgcs;
1659
1660 if ( !base )
1661 base = vmeUniverse0BaseAddr;
1662
1663 dgcs = vmeUniverseReadRegXX( base, UNIV_REGOFF_DGCS );
1664
1665 if ( UNIV_DGCS_ACT & dgcs )
1666 return BSP_VMEDMA_STATUS_BUSY;
1667
1668 if ( !p ) {
1669
1670
1671
1672 dgcs &= ~UNIV_DGCS_CHAIN;
1673 vmeUniverseWriteRegXX( base, UNIV_REGOFF_DGCS, dgcs);
1674 return 0;
1675 }
1676
1677
1678 dgcs |= UNIV_DGCS_CHAIN;
1679
1680 vmeUniverseWriteRegXX( base, UNIV_REGOFF_DGCS, dgcs);
1681
1682
1683 vmeUniverseWriteRegXX( base, 0x0, UNIV_REGOFF_DTBC);
1684
1685
1686 vmeUniverseWriteRegXX( base, BSP_LOCAL2PCI_ADDR((uint32_t)p), UNIV_REGOFF_DCPP);
1687
1688
1689 dgcs |= UNIV_DGCS_GO;
1690 vmeUniverseWriteReg(dgcs, UNIV_REGOFF_DGCS);
1691
1692 return 0;
1693 }
1694
1695 static void
1696 uni_desc_dump(DmaDescriptor p)
1697 {
1698 VmeUniverseDmaListDesc d = p;
1699 LERegister1 dcpp = ld_le32(&d->dcpp);
1700
1701 printf(" DLA: 0x%08x\n", ld_le32(&d->dla));
1702 printf(" DVA: 0x%08x\n", ld_le32(&d->dva));
1703 printf(" DCPP: 0x%08"PRIx32"%s\n", dcpp, (dcpp & UNIV_DCPP_IMG_NULL) ? " (LAST)" : "");
1704 printf(" CTL: 0x%08x\n", ld_le32(&d->dctl));
1705 printf(" TBC: 0x%08x\n", ld_le32(&d->dtbc));
1706 }
1707
1708
1709
1710 #include <bsp/irq.h>
1711 #include <rtems/irq.h>
1712
1713 typedef struct
1714 UniverseIRQEntryRec_ {
1715 VmeUniverseISR isr;
1716 void *usrData;
1717 } UniverseIRQEntryRec, *UniverseIRQEntry;
1718
1719 static UniverseIRQEntry universeHdlTbl[UNIV_NUM_INT_VECS]={0};
1720
1721 int vmeUniverseIrqMgrInstalled = 0;
1722
1723 volatile LERegister *vmeUniverseRegBase = 0;
1724
1725
1726
1727 #define UNIV_NUM_WIRES 4
1728
1729 static volatile unsigned long wire_mask[UNIV_NUM_WIRES] = {0};
1730
1731 static int universe_wire[UNIV_NUM_WIRES] = {0};
1732
1733 static int
1734 lvl2bit(unsigned int level)
1735 {
1736 int shift = -1;
1737 if ( level >= UNIV_DMA_INT_VEC && level <= UNIV_LM3_INT_VEC ) {
1738 shift = 8 + (level-UNIV_DMA_INT_VEC);
1739 } else if ( UNIV_VOWN_INT_VEC == level ) {
1740 shift = 0;
1741 } else if ( 1 <= level && level <=7 ) {
1742 shift = level;
1743 } else {
1744
1745 }
1746 return shift;
1747 }
1748
1749 RTEMS_INTERRUPT_LOCK_DEFINE( static, vmeUniverse_lock, "vmeUniverse_lock" )
1750
1751 int
1752 vmeUniverseIntRoute(unsigned int level, unsigned int pin)
1753 {
1754 int i, shift;
1755 unsigned long mask, mapreg, wire;
1756 rtems_interrupt_lock_context lock_context;
1757
1758 if ( pin >= UNIV_NUM_WIRES || ! universe_wire[pin] || !vmeUniverseIrqMgrInstalled )
1759 return -1;
1760
1761 if ( (shift = lvl2bit(level)) < 0 ) {
1762 return -1;
1763 }
1764
1765 mask = 1<<shift;
1766
1767
1768 if ( shift < 8 ) {
1769 mapreg = UNIV_REGOFF_LINT_MAP0;
1770 } else if ( shift < 16 ) {
1771 shift -= 8;
1772 mapreg = UNIV_REGOFF_LINT_MAP1;
1773 } else if ( shift < 24 ) {
1774 shift -= 16;
1775 mapreg = UNIV_REGOFF_LINT_MAP2;
1776 } else {
1777 return -1;
1778 }
1779
1780 shift <<=2;
1781
1782
1783 wire = (universe_wire[pin]-1) << shift;
1784
1785 rtems_interrupt_lock_acquire( &vmeUniverse_lock, &lock_context );
1786
1787 for ( i = 0; i<UNIV_NUM_WIRES; i++ ) {
1788 wire_mask[i] &= ~mask;
1789 }
1790 wire_mask[pin] |= mask;
1791
1792 mask = vmeUniverseReadReg(mapreg) & ~ (0xf<<shift);
1793 mask |= wire;
1794 vmeUniverseWriteReg( mask, mapreg );
1795
1796 rtems_interrupt_lock_release( &vmeUniverse_lock, &lock_context );
1797 return 0;
1798 }
1799
1800 VmeUniverseISR
1801 vmeUniverseISRGet(unsigned long vector, void **parg)
1802 {
1803 VmeUniverseISR rval = 0;
1804 volatile UniverseIRQEntry *pe = universeHdlTbl + vector;
1805 rtems_interrupt_lock_context lock_context;
1806
1807 if ( vector>=UNIV_NUM_INT_VECS || ! *pe )
1808 return 0;
1809
1810 rtems_interrupt_lock_acquire( &vmeUniverse_lock, &lock_context );
1811 if ( *pe ) {
1812 if (parg)
1813 *parg=(*pe)->usrData;
1814 rval = (*pe)->isr;
1815 }
1816 rtems_interrupt_lock_release( &vmeUniverse_lock, &lock_context );
1817 return rval;
1818 }
1819
1820 #define SPECIAL_IRQ_MSK ( ~((UNIV_LINT_STAT_VIRQ7<<1)-UNIV_LINT_STAT_VIRQ1) )
1821
1822 static void
1823 universeSpecialISR(unsigned long status)
1824 {
1825 register UniverseIRQEntry ip;
1826 register unsigned vec;
1827 register unsigned long s;
1828
1829
1830
1831
1832 vmeUniverseWriteReg( (status & SPECIAL_IRQ_MSK), UNIV_REGOFF_LINT_STAT );
1833
1834
1835 vec=UNIV_VOWN_INT_VEC;
1836 if ( (status & UNIV_LINT_STAT_VOWN) && (ip=universeHdlTbl[vec]))
1837 ip->isr(ip->usrData,vec);
1838
1839
1840
1841
1842
1843
1844
1845 for ( s = status>>8; s; s >>= 1) {
1846 vec++;
1847 if ( (s&1) && (ip=universeHdlTbl[vec]) )
1848 ip->isr(ip->usrData,vec);
1849 }
1850
1851
1852
1853
1854
1855
1856
1857
1858 }
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892 static void
1893 universeVMEISR(rtems_irq_hdl_param arg)
1894 {
1895 int pin = (int)arg;
1896 UniverseIRQEntry ip;
1897 unsigned long msk,lintstat,status;
1898 int lvl;
1899 #if defined(BSP_PIC_DO_EOI)
1900 unsigned long linten;
1901 #endif
1902
1903
1904 lintstat = vmeUniverseReadReg(UNIV_REGOFF_LINT_STAT);
1905
1906
1907 lintstat &= wire_mask[pin];
1908
1909 #ifdef __PPC__
1910 asm volatile("cntlzw %0, %1":"=r"(lvl):"r"(lintstat & ~SPECIAL_IRQ_MSK));
1911 lvl = 31-lvl;
1912 msk = 1<<lvl;
1913 #else
1914 for (msk=UNIV_LINT_STAT_VIRQ7, lvl=7;
1915 lvl>0;
1916 lvl--, msk>>=1) {
1917 if (lintstat & msk) break;
1918 }
1919 #endif
1920
1921 #ifndef BSP_PIC_DO_EOI
1922
1923 if ( (status = (lintstat & SPECIAL_IRQ_MSK)) )
1924 universeSpecialISR( status );
1925
1926 if ( lvl <= 0)
1927 return;
1928
1929 #else
1930 if ( lvl <= 0 ) {
1931
1932 universeSpecialISR( lintstat & SPECIAL_IRQ_MSK );
1933
1934
1935
1936
1937 if ( 0 == pin )
1938 BSP_PIC_DO_EOI;
1939
1940 return;
1941 }
1942 linten = vmeUniverseReadReg(UNIV_REGOFF_LINT_EN);
1943
1944
1945 vmeUniverseWriteReg(
1946 linten & ~( ((msk<<1)-UNIV_LINT_STAT_VIRQ1) & wire_mask[pin]),
1947 UNIV_REGOFF_LINT_EN
1948 );
1949
1950
1951
1952
1953
1954 if ( 0 == pin )
1955 BSP_PIC_DO_EOI;
1956 #endif
1957
1958
1959 status = vmeUniverseReadReg(UNIV_REGOFF_VIRQ1_STATID - 4 + (lvl<<2));
1960
1961
1962 if (status & UNIV_VIRQ_ERR) {
1963
1964 #ifdef BSP_PIC_DO_EOI
1965 linten &= ~msk;
1966 #else
1967 vmeUniverseIntDisable(lvl);
1968 #endif
1969 printk("vmeUniverse ISR: error read from STATID register; (level: %i) STATID: 0x%08lx -- DISABLING\n", lvl, status);
1970 } else if (!(ip=universeHdlTbl[status & UNIV_VIRQ_STATID_MASK])) {
1971 #ifdef BSP_PIC_DO_EOI
1972 linten &= ~msk;
1973 #else
1974 vmeUniverseIntDisable(lvl);
1975 #endif
1976
1977 printk("vmeUniverse ISR: no handler installed for this vector; (level: %i) STATID: 0x%08lx -- DISABLING\n", lvl, status);
1978 } else {
1979
1980 ip->isr(ip->usrData, status&UNIV_VIRQ_STATID_MASK);
1981
1982
1983 #ifdef __PPC__
1984
1985 asm volatile("eieio");
1986 #endif
1987 READ_LE0(vmeUniverseRegBase);
1988 #ifdef __PPC__
1989
1990 asm volatile("eieio");
1991 #endif
1992 }
1993
1994
1995 vmeUniverseWriteReg(msk, UNIV_REGOFF_LINT_STAT);
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005 #ifdef BSP_PIC_DO_EOI
2006
2007
2008 vmeUniverseWriteReg(linten, UNIV_REGOFF_LINT_EN);
2009 #endif
2010 }
2011
2012
2013
2014 static void
2015 my_no_op(const rtems_irq_connect_data * arg)
2016 {}
2017
2018 static int
2019 my_isOn(const rtems_irq_connect_data *arg)
2020 {
2021 return (int)vmeUniverseReadReg(UNIV_REGOFF_LINT_EN);
2022 }
2023
2024 typedef struct {
2025 int uni_pin, pic_pin;
2026 } IntRoute;
2027
2028 static void
2029 connectIsr(int shared, rtems_irq_hdl isr, int pic_line, int pic_pin)
2030 {
2031 rtems_irq_connect_data aarrggh;
2032 aarrggh.on = my_no_op;
2033 aarrggh.off = my_no_op;
2034 aarrggh.isOn = my_isOn;
2035 aarrggh.hdl = isr;
2036 aarrggh.handle = (rtems_irq_hdl_param)pic_pin;
2037 aarrggh.name = pic_line;
2038
2039 if ( shared ) {
2040 #if BSP_SHARED_HANDLER_SUPPORT > 0
2041 if (!BSP_install_rtems_shared_irq_handler(&aarrggh))
2042 rtems_panic("unable to install vmeUniverse shared irq handler");
2043 #else
2044 uprintf(stderr,"vmeUniverse: WARNING: your BSP doesn't support sharing interrupts\n");
2045 if (!BSP_install_rtems_irq_handler(&aarrggh))
2046 rtems_panic("unable to install vmeUniverse irq handler");
2047 #endif
2048 } else {
2049 if (!BSP_install_rtems_irq_handler(&aarrggh))
2050 rtems_panic("unable to install vmeUniverse irq handler");
2051 }
2052 }
2053
2054 #ifndef BSP_EARLY_PROBE_VME
2055 #define BSP_EARLY_PROBE_VME(addr) \
2056 ( \
2057 ((PCI_DEVICE_UNIVERSEII << 16) | PCI_VENDOR_TUNDRA ) == READ_LE( ((volatile LERegister*)(addr)), 0 ) \
2058 )
2059 #endif
2060
2061
2062
2063
2064
2065
2066 static int
2067 mappedAndProbed(unsigned long vme_addr, unsigned as, unsigned long *pcpu_addr)
2068 {
2069 int j;
2070 char *regtype = (as & VME_AM_MASK) == VME_AM_CSR ? "CSR" : "CRG";
2071
2072
2073 if ( 0 > (j = xlateFindPort(
2074 vmeUniverse0BaseAddr,
2075 1, 0,
2076 as | VME_MODE_AS_MATCH,
2077 vme_addr,
2078 pcpu_addr ) ) ) {
2079 uprintf(stderr,"vmeUniverse - Unable to find mapping for %s VME base (0x%08x)\n", regtype, vme_addr);
2080 uprintf(stderr," in outbound windows.\n");
2081 } else {
2082
2083 *pcpu_addr = BSP_PCI2LOCAL_ADDR( *pcpu_addr );
2084 if ( BSP_EARLY_PROBE_VME(*pcpu_addr) ) {
2085 uprintf(stderr,"vmeUniverse - IRQ manager using VME %s to flush FIFO\n", regtype);
2086 return j;
2087 } else {
2088 uprintf(stderr,"vmeUniverse - Found slot info but detection of universe in VME %s space failed\n", regtype);
2089 }
2090 }
2091 return -1;
2092 }
2093
2094
2095 int
2096 vmeUniverseInstallIrqMgrAlt(int flags, int uni_pin0, int pic_pin0, ...)
2097 {
2098 int rval;
2099 va_list ap;
2100 va_start(ap, pic_pin0);
2101 rval = vmeUniverseInstallIrqMgrVa(flags, uni_pin0, pic_pin0, ap);
2102 va_end(ap);
2103 return rval;
2104 }
2105
2106 int
2107 vmeUniverseInstallIrqMgrVa(int flags, int uni_pin0, int pic_pin0, va_list ap)
2108 {
2109 int i,j, specialPin, uni_pin[UNIV_NUM_WIRES+1], pic_pin[UNIV_NUM_WIRES];
2110 unsigned long cpu_base, vme_reg_base;
2111
2112 if (vmeUniverseIrqMgrInstalled) return -4;
2113
2114
2115
2116 if ( uni_pin0 < 0 || uni_pin0 > 7 ) return -1;
2117
2118 uni_pin[0] = uni_pin0;
2119 pic_pin[0] = pic_pin0 < 0 ? vmeUniverse0PciIrqLine : pic_pin0;
2120 i = 1;
2121 while ( (uni_pin[i] = va_arg(ap, int)) >= 0 ) {
2122
2123 if ( i >= UNIV_NUM_WIRES ) {
2124 return -5;
2125 }
2126
2127 pic_pin[i] = va_arg(ap,int);
2128
2129 if ( uni_pin[i] > 7 ) {
2130 return -2;
2131 }
2132 if ( pic_pin[i] < 0 ) {
2133 return -3;
2134 }
2135 i++;
2136 }
2137
2138
2139 for ( i=0; uni_pin[i] >= 0; i++ ) {
2140 for ( j=i+1; uni_pin[j] >= 0; j++ ) {
2141 if ( uni_pin[j] == uni_pin[i] ) return -6;
2142 if ( pic_pin[j] == pic_pin[i] ) return -7;
2143 }
2144 }
2145
2146 if ( flags & VMEUNIVERSE_IRQ_MGR_FLAG_PW_WORKAROUND ) {
2147
2148
2149 uprintf(stderr,"vmeUniverse IRQ manager: looking for registers on VME...\n");
2150
2151
2152
2153
2154
2155 if ( ( i = ((READ_LE( vmeUniverse0BaseAddr, UNIV_REGOFF_VCSR_BS ) >> 27) & 0x1f ) ) > 0 ) {
2156 uprintf(stderr,"Trying to find CSR on VME...\n");
2157 vme_reg_base = i*0x80000 + UNIV_CSR_OFFSET;
2158 i = mappedAndProbed( vme_reg_base, VME_AM_CSR , &cpu_base);
2159 if ( i >= 0 )
2160 vmeUniverseRegCSR = 1;
2161 } else {
2162 i = -1;
2163 }
2164
2165 if ( -1 == i ) {
2166
2167 uprintf(stderr,"Trying to find CRG on VME...\n");
2168
2169
2170
2171 if ( UNIV_VRAI_CTL_EN & (j = READ_LE( vmeUniverse0BaseAddr, UNIV_REGOFF_VRAI_CTL )) ) {
2172 switch ( j & UNIV_VRAI_CTL_VAS_MSK ) {
2173 case UNIV_VRAI_CTL_VAS_A16 : i = VME_AM_SUP_SHORT_IO; break;
2174 case UNIV_VRAI_CTL_VAS_A24 : i = VME_AM_STD_SUP_DATA; break;
2175 case UNIV_VRAI_CTL_VAS_A32 : i = VME_AM_EXT_SUP_DATA; break;
2176 default:
2177 break;
2178 }
2179 vme_reg_base = READ_LE( vmeUniverse0BaseAddr, UNIV_REGOFF_VRAI_BS ) & ~(UNIV_CRG_SIZE - 1);
2180 }
2181
2182 if ( -1 == i ) {
2183 } else {
2184 i = mappedAndProbed( vme_reg_base, (i & VME_AM_MASK), &cpu_base );
2185 }
2186 }
2187
2188 if ( i < 0 ) {
2189 if ( mapOverAll( vmeUniverse0BaseAddr, 1, hasPWENWindow, 0 ) ) {
2190 uprintf(stderr,"vmeUniverse IRQ manager - BSP configuration error: registers not found on VME\n");
2191 uprintf(stderr,"(should open outbound window to CSR space or map CRG [vmeUniverseMapCRG()])\n");
2192 uprintf(stderr,"Falling back to PCI but you might experience spurious VME interrupts; read a register\n");
2193 uprintf(stderr,"back from user ISR to flush universe FIFO as a work-around or\n");
2194 uprintf(stderr,"make sure ISR accesses device using a window with posted-writes disabled\n");
2195 } else {
2196 uprintf(stderr,"vmeUniverse IRQ manager - registers not found on VME; falling back to PCI\n");
2197 }
2198 vmeUniverseRegBase = vmeUniverse0BaseAddr;
2199 vmeUniverseRegPort = -1;
2200 } else {
2201 vmeUniverseRegBase = (volatile LERegister*)cpu_base;
2202 vmeUniverseRegPort = i;
2203 }
2204 } else {
2205 vmeUniverseRegBase = vmeUniverse0BaseAddr;
2206 vmeUniverseRegPort = -1;
2207 }
2208
2209
2210 if ( pic_pin[0] >= 0 && vmeUniverse0PciIrqLine != pic_pin[0] ) {
2211 uprintf(stderr,"Overriding main IRQ line PCI info with %d\n",
2212 pic_pin[0]);
2213 vmeUniverse0PciIrqLine=pic_pin[0];
2214 }
2215
2216 for ( i = 0; uni_pin[i] >= 0; i++ ) {
2217
2218 universe_wire[i] = uni_pin[i] + 1;
2219 connectIsr((flags & VMEUNIVERSE_IRQ_MGR_FLAG_SHARED), universeVMEISR, pic_pin[i], i);
2220 }
2221
2222 specialPin = uni_pin[1] >= 0 ? 1 : 0;
2223
2224
2225
2226
2227 vmeUniverseIrqMgrInstalled=1;
2228
2229
2230 for ( i=1; i<8; i++ )
2231 vmeUniverseIntRoute( i, 0 );
2232 for ( i=UNIV_VOWN_INT_VEC; i<=UNIV_LM3_INT_VEC; i++ ) {
2233 if ( vmeUniverseIntRoute( i, specialPin ) )
2234 printk("Routing lvl %i -> wire # %i failed\n", i, specialPin);
2235 }
2236
2237 return 0;
2238 }
2239
2240 int
2241 vmeUniverseInstallIrqMgr(int vmeIrqUnivOut,
2242 int vmeIrqPicLine,
2243 int specialIrqUnivOut,
2244 int specialIrqPicLine)
2245 {
2246 return vmeUniverseInstallIrqMgrAlt(
2247 0,
2248 vmeIrqUnivOut, vmeIrqPicLine,
2249 specialIrqUnivOut, specialIrqPicLine,
2250 -1);
2251 }
2252
2253 int
2254 vmeUniverseInstallISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
2255 {
2256 UniverseIRQEntry ip;
2257 volatile UniverseIRQEntry *pe;
2258 rtems_interrupt_lock_context lock_context;
2259
2260 if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !vmeUniverseIrqMgrInstalled)
2261 return -1;
2262
2263 pe = universeHdlTbl + vector;
2264
2265 if (*pe || !(ip=(UniverseIRQEntry)malloc(sizeof(UniverseIRQEntryRec))))
2266 return -1;
2267
2268 ip->isr=hdl;
2269 ip->usrData=arg;
2270
2271 rtems_interrupt_lock_acquire( &vmeUniverse_lock, &lock_context );
2272 if ( *pe ) {
2273
2274 rtems_interrupt_lock_release( &vmeUniverse_lock, &lock_context );
2275 free(ip);
2276 return -1;
2277 }
2278 *pe = ip;
2279 rtems_interrupt_lock_release( &vmeUniverse_lock, &lock_context );
2280 return 0;
2281 }
2282
2283 int
2284 vmeUniverseRemoveISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
2285 {
2286 UniverseIRQEntry ip;
2287 volatile UniverseIRQEntry *pe;
2288 rtems_interrupt_lock_context lock_context;
2289
2290 if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !vmeUniverseIrqMgrInstalled)
2291 return -1;
2292
2293 pe = universeHdlTbl + vector;
2294
2295 rtems_interrupt_lock_acquire( &vmeUniverse_lock, &lock_context );
2296 ip = *pe;
2297 if (!ip || ip->isr!=hdl || ip->usrData!=arg) {
2298 rtems_interrupt_lock_release( &vmeUniverse_lock, &lock_context );
2299 return -1;
2300 }
2301 *pe = 0;
2302 rtems_interrupt_lock_release( &vmeUniverse_lock, &lock_context );
2303 free(ip);
2304 return 0;
2305 }
2306
2307 static int
2308 intDoEnDis(unsigned int level, int dis)
2309 {
2310 unsigned long v;
2311 int shift;
2312 rtems_interrupt_lock_context lock_context;
2313
2314 if ( ! vmeUniverseIrqMgrInstalled || (shift = lvl2bit(level)) < 0 )
2315 return -1;
2316
2317 v = 1<<shift;
2318
2319 if ( !dis )
2320 return vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) & v ? 1 : 0;
2321
2322 rtems_interrupt_lock_acquire( &vmeUniverse_lock, &lock_context );
2323 if ( dis<0 )
2324 vmeUniverseWriteReg( vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) & ~v, UNIV_REGOFF_LINT_EN );
2325 else {
2326 vmeUniverseWriteReg( vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) | v, UNIV_REGOFF_LINT_EN );
2327 }
2328 rtems_interrupt_lock_release( &vmeUniverse_lock, &lock_context );
2329 return 0;
2330 }
2331
2332 int
2333 vmeUniverseIntEnable(unsigned int level)
2334 {
2335 return intDoEnDis(level, 1);
2336 }
2337
2338 int
2339 vmeUniverseIntDisable(unsigned int level)
2340 {
2341 return intDoEnDis(level, -1);
2342 }
2343
2344 int
2345 vmeUniverseIntIsEnabled(unsigned int level)
2346 {
2347 return intDoEnDis(level, 0);
2348 }
2349
2350
2351
2352 typedef struct {
2353 rtems_id q;
2354 int l;
2355 } LoopbackTstArgs;
2356
2357 static void
2358 loopbackTstIsr(void *arg, unsigned long vector)
2359 {
2360 LoopbackTstArgs *pa = arg;
2361 if ( RTEMS_SUCCESSFUL != rtems_message_queue_send(pa->q, (void*)&vector, sizeof(vector)) ) {
2362
2363 printk("vmeUniverseIntLoopbackTst: (ISR) message queue full / overrun ? disabling IRQ level %i\n", pa->l);
2364 vmeUniverseIntDisable(pa->l);
2365 }
2366 }
2367
2368 int
2369 vmeUniverseIntLoopbackTst(int level, unsigned vector)
2370 {
2371 DFLT_BASE;
2372 rtems_status_code sc;
2373 rtems_id q = 0;
2374 int installed = 0;
2375 int i, err = 0;
2376 int doDisable = 0;
2377 size_t size;
2378 unsigned long msg;
2379 char * irqfmt = "VME IRQ @vector %3i %s";
2380 char * iackfmt = "VME IACK %s";
2381 LoopbackTstArgs a;
2382
2383 CHECK_DFLT_BASE(base);
2384
2385
2386 if ( level < 1 || level > 7 || vector > 255 ) {
2387 fprintf(stderr,"Invalid level or vector argument\n");
2388 return -1;
2389 }
2390
2391 if ( (vector & 1) ) {
2392 fprintf(stderr,"Software interrupts can only use even-numbered vectors, sorry.\n");
2393 return -1;
2394 }
2395
2396 if ( UNIV_REV(base) < 2 && vector != 0 ) {
2397 fprintf(stderr,
2398 "vmeUniverseIntLoopbackTst(): Universe 1 has a bug. IACK in response to\n");
2399 fprintf(stderr,
2400 "self-generated VME interrupt yields always a zero vector. As a workaround,\n");
2401 fprintf(stderr,
2402 "use vector 0, please.\n");
2403 return -1;
2404 }
2405
2406
2407 if ( RTEMS_SUCCESSFUL != (sc=rtems_message_queue_create(
2408 rtems_build_name('t' ,'U','I','I'),
2409 4,
2410 sizeof(unsigned long),
2411 0,
2412 &q)) ) {
2413 rtems_error(sc, "vmeUniverseIntLoopbackTst: Unable to create message queue");
2414 goto bail;
2415 }
2416
2417 a.q = q;
2418 a.l = level;
2419
2420
2421 if ( vmeUniverseInstallISR(vector, loopbackTstIsr, (void*)&a) ) {
2422 fprintf(stderr,"Unable to install VME ISR to vector %i\n",vector);
2423 goto bail;
2424 }
2425 installed++;
2426 if ( vmeUniverseInstallISR(UNIV_VME_SW_IACK_INT_VEC, loopbackTstIsr, (void*)&a) ) {
2427 fprintf(stderr,"Unable to install VME ISR to IACK special vector %i\n",UNIV_VME_SW_IACK_INT_VEC);
2428 goto bail;
2429 }
2430 installed++;
2431
2432 if ( !vmeUniverseIntIsEnabled(level) && 0==vmeUniverseIntEnable(level) )
2433 doDisable = 1;
2434
2435
2436 vmeUniverseWriteReg( UNIV_LINT_STAT_SW_IACK, UNIV_REGOFF_LINT_STAT );
2437
2438 if ( vmeUniverseIntEnable( UNIV_VME_SW_IACK_INT_VEC ) ) {
2439 fprintf(stderr,"Unable to enable IACK interrupt\n");
2440 goto bail;
2441 }
2442
2443 printf("vmeUniverse VME interrupt loopback test; STARTING...\n");
2444 printf(" --> asserting VME IRQ level %i\n", level);
2445 vmeUniverseIntRaise(level, vector);
2446
2447 for ( i = 0; i< 3; i++ ) {
2448 sc = rtems_message_queue_receive(
2449 q,
2450 &msg,
2451 &size,
2452 RTEMS_WAIT,
2453 20);
2454 if ( sc ) {
2455 if ( RTEMS_TIMEOUT == sc && i>1 ) {
2456
2457 sc = 0;
2458 } else {
2459 rtems_error(sc,"Error waiting for interrupts");
2460 }
2461 break;
2462 }
2463 if ( msg == vector ) {
2464 if ( !irqfmt ) {
2465 printf("Excess VME IRQ received ?? -- BAD\n");
2466 err = 1;
2467 } else {
2468 printf(irqfmt, vector, "received -- PASSED\n");
2469 irqfmt = 0;
2470 }
2471 } else if ( msg == UNIV_VME_SW_IACK_INT_VEC ) {
2472 if ( !iackfmt ) {
2473 printf("Excess VME IACK received ?? -- BAD\n");
2474 err = 1;
2475 } else {
2476 printf(iackfmt, "received -- PASSED\n");
2477 iackfmt = 0;
2478 }
2479 } else {
2480 printf("Unknown IRQ (vector %lu) received -- BAD\n", msg);
2481 err = 1;
2482 }
2483 }
2484
2485
2486
2487 if ( irqfmt ) {
2488 printf(irqfmt,vector, "MISSED -- BAD\n");
2489 err = 1;
2490 }
2491 if ( iackfmt ) {
2492 printf(iackfmt, "MISSED -- BAD\n");
2493 err = 1;
2494 }
2495
2496 printf("FINISHED.\n");
2497
2498 bail:
2499 if ( doDisable )
2500 vmeUniverseIntDisable(level);
2501 vmeUniverseIntDisable( UNIV_VME_SW_IACK_INT_VEC );
2502 if ( installed > 0 )
2503 vmeUniverseRemoveISR(vector, loopbackTstIsr, (void*)&a);
2504 if ( installed > 1 )
2505 vmeUniverseRemoveISR(UNIV_VME_SW_IACK_INT_VEC, loopbackTstIsr, (void*)&a);
2506 if ( q )
2507 rtems_message_queue_delete(q);
2508
2509 return sc ? sc : err;
2510 }
2511
2512 #endif