Back to home page

LXR

 
 

    


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

0001 /* Driver for the Tundra Tsi148 pci-vme bridge */
0002 
0003 /*
0004  * Authorship
0005  * ----------
0006  * This software was created by
0007  *     Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
0008  *     Stanford Linear Accelerator Center, Stanford University.
0009  *
0010  * Acknowledgement of sponsorship
0011  * ------------------------------
0012  * This software was produced by
0013  *     the Stanford Linear Accelerator Center, Stanford University,
0014  *     under Contract DE-AC03-76SFO0515 with the Department of Energy.
0015  *
0016  * Government disclaimer of liability
0017  * ----------------------------------
0018  * Neither the United States nor the United States Department of Energy,
0019  * nor any of their employees, makes any warranty, express or implied, or
0020  * assumes any legal liability or responsibility for the accuracy,
0021  * completeness, or usefulness of any data, apparatus, product, or process
0022  * disclosed, or represents that its use would not infringe privately owned
0023  * rights.
0024  *
0025  * Stanford disclaimer of liability
0026  * --------------------------------
0027  * Stanford University makes no representations or warranties, express or
0028  * implied, nor assumes any liability for the use of this software.
0029  *
0030  * Stanford disclaimer of copyright
0031  * --------------------------------
0032  * Stanford University, owner of the copyright, hereby disclaims its
0033  * copyright and all other rights in this software.  Hence, anyone may
0034  * freely use it for any purpose without restriction.
0035  *
0036  * Maintenance of notices
0037  * ----------------------
0038  * In the interest of clarity regarding the origin and status of this
0039  * SLAC software, this and all the preceding Stanford University notices
0040  * are to remain affixed to any copy or derivative of this software made
0041  * or distributed by the recipient and are to be affixed to any copy of
0042  * software made or distributed by the recipient that contains a copy or
0043  * derivative of this software.
0044  *
0045  * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
0046  */
0047 
0048 #include <rtems.h>
0049 #include <inttypes.h>
0050 #include <stdio.h>
0051 #include <stdarg.h>
0052 #include <bsp/irq.h>
0053 #include <stdlib.h>
0054 #include <rtems/bspIo.h>    /* printk */
0055 #include <rtems/error.h>    /* printk */
0056 #include <rtems/irq.h>
0057 #include <rtems/pci.h>
0058 #include <rtems/score/sysstate.h>
0059 #include <bsp.h>
0060 #include <libcpu/byteorder.h>
0061 #include <libcpu/io.h>
0062 
0063 #define __INSIDE_RTEMS_BSP__
0064 #define _VME_TSI148_DECLARE_SHOW_ROUTINES
0065 
0066 #include <bsp/vmeTsi148.h>
0067 #include <bsp/VMEDMA.h>
0068 #include <bsp/vmeTsi148DMA.h>
0069 #include "bspVmeDmaListP.h"
0070 
0071 
0072 #define DEBUG
0073 
0074 #ifdef DEBUG
0075 #define STATIC
0076 #else
0077 #define STATIC static
0078 #endif
0079 
0080 /* The tsi has 4 'local' wires that can be hooked to a PIC */
0081 
0082 #define TSI_NUM_WIRES           4
0083 
0084 #define TSI148_NUM_OPORTS       8 /* number of outbound ports */
0085 #define TSI148_NUM_IPORTS       8 /* number of inbound  ports */
0086 
0087 #define NUM_TSI_DEVS            2 /* number of instances supported */
0088 
0089 #define PCI_VENDOR_TUNDRA   0x10e3
0090 #define PCI_DEVICE_TSI148   0x0148
0091 
0092 #define TSI_OTSAU_SPACING   0x020
0093 
0094 #define TSI_OTSAU0_REG      0x100
0095 #define TSI_OTSAL0_REG      0x104
0096 #define TSI_OTEAU0_REG      0x108
0097 #define TSI_OTEAL0_REG      0x10c
0098 #define TSI_OTOFU0_REG      0x110
0099 #define TSI_OTOFL0_REG      0x114
0100 #define TSI_OTBS0_REG       0x118   /* 2eSST broadcast select */
0101 #define TSI_OTAT0_REG       0x11c
0102 #define TSI_OTSAU_REG(port) (TSI_OTSAU0_REG + ((port)<<5))
0103 #define TSI_OTSAL_REG(port) (TSI_OTSAL0_REG + ((port)<<5))
0104 #define TSI_OTEAU_REG(port) (TSI_OTEAU0_REG + ((port)<<5))
0105 #define TSI_OTEAL_REG(port) (TSI_OTEAL0_REG + ((port)<<5))
0106 #define TSI_OTOFU_REG(port) (TSI_OTOFU0_REG + ((port)<<5))
0107 #define TSI_OTOFL_REG(port) (TSI_OTOFL0_REG + ((port)<<5))
0108 #define TSI_OTBS_REG(port)  (TSI_OTBS0_REG + ((port)<<5))
0109 #define TSI_OTAT_REG(port)  (TSI_OTAT0_REG + ((port)<<5))
0110 #   define TSI_OTAT_EN          (1<<31)
0111 #   define TSI_OTAT_MRPFD       (1<<18)
0112 #   define TSI_OTAT_PFS(x)      (((x)&3)<<16)
0113 #   define TSI_OTAT_2eSSTM(x)   (((x)&7)<<11)
0114 #   define TSI_OTAT_2eSSTM_160  TSI_OTAT_2eSSTM(0)
0115 #   define TSI_OTAT_2eSSTM_267  TSI_OTAT_2eSSTM(1)
0116 #   define TSI_OTAT_2eSSTM_320  TSI_OTAT_2eSSTM(2)
0117 #   define TSI_OTAT_TM(x)       (((x)&7)<<8)
0118 #       define TSI_TM_SCT_IDX       0
0119 #       define TSI_TM_BLT_IDX       1
0120 #       define TSI_TM_MBLT_IDX      2
0121 #       define TSI_TM_2eVME_IDX     3
0122 #       define TSI_TM_2eSST_IDX     4
0123 #       define TSI_TM_2eSSTB_IDX    5
0124 #   define TSI_OTAT_DBW(x)      (((x)&3)<<6)
0125 #   define TSI_OTAT_SUP         (1<<5)
0126 #   define TSI_OTAT_PGM         (1<<4)
0127 #   define TSI_OTAT_ADMODE(x)   (((x)&0xf))
0128 #   define TSI_OTAT_ADMODE_A16  0
0129 #   define TSI_OTAT_ADMODE_A24  1
0130 #   define TSI_OTAT_ADMODE_A32  2
0131 #   define TSI_OTAT_ADMODE_A64  4
0132 #   define TSI_OTAT_ADMODE_CSR  5
0133 #   define TSI_OTAT_ADMODE_USR1 8
0134 #   define TSI_OTAT_ADMODE_USR2 9
0135 #   define TSI_OTAT_ADMODE_USR3 0xa
0136 #   define TSI_OTAT_ADMODE_USR4 0xb
0137 
0138 #define TSI_VIACK_1_REG     0x204
0139 
0140 #define TSI_VMCTRL_REG      0x234
0141 #   define TSI_VMCTRL_VSA       (1<<27)
0142 #   define TSI_VMCTRL_VS        (1<<26)
0143 #   define TSI_VMCTRL_DHB       (1<<25)
0144 #   define TSI_VMCTRL_DWB       (1<<24)
0145 #   define TSI_VMCTRL_RMWEN     (1<<20)
0146 #   define TSI_VMCTRL_A64DS     (1<<16)
0147 #   define TSI_VMCTRL_VTOFF_MSK (7<<12)
0148 #   define TSI_VMCTRL_VTOFF_0us (0<<12)
0149 #   define TSI_VMCTRL_VTOFF_1us (1<<12)
0150 #   define TSI_VMCTRL_VTOFF_2us (2<<12)
0151 #   define TSI_VMCTRL_VTOFF_4us (3<<12)
0152 #   define TSI_VMCTRL_VTOFF_8us (4<<12)
0153 #   define TSI_VMCTRL_VTOFF_16us    (5<<12)
0154 #   define TSI_VMCTRL_VTOFF_32us    (6<<12)
0155 #   define TSI_VMCTRL_VTOFF_64us    (7<<12)
0156 #   define TSI_VMCTRL_VTON_MSK  (7<< 8)
0157 #   define TSI_VMCTRL_VTON_4us  (0<< 8)
0158 #   define TSI_VMCTRL_VTON_8us  (1<< 8)
0159 #   define TSI_VMCTRL_VTON_16us (2<< 8)
0160 #   define TSI_VMCTRL_VTON_32us (3<< 8)
0161 #   define TSI_VMCTRL_VTON_64us (4<< 8)
0162 #   define TSI_VMCTRL_VTON_128us    (5<< 8)
0163 #   define TSI_VMCTRL_VTON_256us    (6<< 8)
0164 #   define TSI_VMCTRL_VTON_512us    (7<< 8)
0165 #   define TSI_VMCTRL_VREL_MSK      (3<< 3)
0166 #   define TSI_VMCTRL_VREL_TON_or_DONE          (0<< 3)
0167 #   define TSI_VMCTRL_VREL_TONandREQ_or_DONE    (1<< 3)
0168 #   define TSI_VMCTRL_VREL_TONandBCLR_or_DONE   (2<< 3)
0169 #   define TSI_VMCTRL_VREL_TONorDONE_and_REQ    (3<< 3)
0170 #   define TSI_VMCTRL_VFAIR     (1<< 2)
0171 #   define TSI_VMCTRL_VREQL_MSK (3<< 0)
0172 #   define TSI_VMCTRL_VREQL(x)  ((x)&3)
0173 
0174 #define TSI_VCTRL_REG       0x238
0175 #define TSI_VCTRL_DLT_MSK       (0xf<<24)
0176 #define TSI_VCTRL_NELBB         (1<<20)
0177 #define TSI_VCTRL_SRESET        (1<<17)
0178 #define TSI_VCTRL_LRESET        (1<<16)
0179 #define TSI_VCTRL_SFAILAI       (1<<15)
0180 #define TSI_VCTRL_BID_MSK       (0x1f<<8)
0181 #define TSI_VCTRL_ATOEN         (1<< 7)
0182 #define TSI_VCTRL_ROBIN         (1<< 6)
0183 #define TSI_VCTRL_GTO_MSK       (7<< 0)
0184 
0185 
0186 #define TSI_VSTAT_REG       0x23c
0187 #   define TSI_VSTAT_CPURST     (1<<15) /* clear power-up reset bit */
0188 #   define TSI_VSTAT_BDFAIL     (1<<14)
0189 #   define TSI_VSTAT_PURSTS     (1<<12)
0190 #   define TSI_VSTAT_BDFAILS    (1<<11)
0191 #   define TSI_VSTAT_SYSFLS     (1<<10)
0192 #   define TSI_VSTAT_ACFAILS    (1<< 9)
0193 #   define TSI_VSTAT_SCONS      (1<< 8)
0194 #   define TSI_VSTAT_GAP        (1<< 5)
0195 #   define TSI_VSTAT_GA_MSK     (0x1f)
0196 
0197 #define TSI_VEAU_REG        0x260
0198 #define TSI_VEAL_REG        0x264
0199 #define TSI_VEAT_REG        0x268
0200 
0201 #define TSI_ITSAU_SPACING   0x020
0202 
0203 #define TSI_ITSAU0_REG      0x300
0204 #define TSI_ITSAL0_REG      0x304
0205 #define TSI_ITEAU0_REG      0x308
0206 #define TSI_ITEAL0_REG      0x30c
0207 #define TSI_ITOFU0_REG      0x310
0208 #define TSI_ITOFL0_REG      0x314
0209 #define TSI_ITAT0_REG       0x318
0210 #define TSI_ITSAU_REG(port) (TSI_ITSAU0_REG + ((port)<<5))
0211 #define TSI_ITSAL_REG(port) (TSI_ITSAL0_REG + ((port)<<5))
0212 #define TSI_ITEAU_REG(port) (TSI_ITEAU0_REG + ((port)<<5))
0213 #define TSI_ITEAL_REG(port) (TSI_ITEAL0_REG + ((port)<<5))
0214 #define TSI_ITOFU_REG(port) (TSI_ITOFU0_REG + ((port)<<5))
0215 #define TSI_ITOFL_REG(port) (TSI_ITOFL0_REG + ((port)<<5))
0216 #define TSI_ITAT_REG(port)  (TSI_ITAT0_REG + ((port)<<5))
0217 
0218 #   define TSI_ITAT_EN          (1<<31)
0219 #   define TSI_ITAT_TH          (1<<18)
0220 #   define TSI_ITAT_VFS(x)      (((x)&3)<<16)
0221 #   define TSI_ITAT_2eSSTM(x)   (((x)&7)<<12)
0222 #   define TSI_ITAT_2eSSTM_160  TSI_ITAT_2eSSTM(0)
0223 #   define TSI_ITAT_2eSSTM_267  TSI_ITAT_2eSSTM(1)
0224 #   define TSI_ITAT_2eSSTM_320  TSI_ITAT_2eSSTM(2)
0225 #   define TSI_ITAT_2eSSTB      (1<<11)
0226 #   define TSI_ITAT_2eSST       (1<<10)
0227 #   define TSI_ITAT_2eVME       (1<<9)
0228 #   define TSI_ITAT_MBLT        (1<<8)
0229 #   define TSI_ITAT_BLT         (1<<7)
0230 #   define TSI_ITAT_AS(x)       (((x)&7)<<4)
0231 #   define TSI_ITAT_ADMODE_A16  (0<<4)
0232 #   define TSI_ITAT_ADMODE_A24  (1<<4)
0233 #   define TSI_ITAT_ADMODE_A32  (2<<4)
0234 #   define TSI_ITAT_ADMODE_A64  (4<<4)
0235 #   define TSI_ITAT_SUP         (1<<3)
0236 #   define TSI_ITAT_USR         (1<<2)
0237 #   define TSI_ITAT_PGM         (1<<1)
0238 #   define TSI_ITAT_DATA        (1<<0)
0239 
0240 #define TSI_CBAU_REG        0x40c
0241 #define TSI_CBAL_REG        0x410
0242 #define TSI_CRGAT_REG       0x414
0243 #   define TSI_CRGAT_EN     (1<<7)
0244 #   define TSI_CRGAT_AS_MSK (7<<4)
0245 #   define TSI_CRGAT_A16    (0<<4)
0246 #   define TSI_CRGAT_A24    (1<<4)
0247 #   define TSI_CRGAT_A32    (2<<4)
0248 #   define TSI_CRGAT_A64    (4<<4)
0249 #   define TSI_CRGAT_SUP    (1<<3)
0250 #   define TSI_CRGAT_USR    (1<<2)
0251 #   define TSI_CRGAT_PGM    (1<<1)
0252 #   define TSI_CRGAT_DATA   (1<<0)
0253 
0254 #define TSI_VICR_REG        0x440
0255 #   define TSI_VICR_CNTS(v)     (((v)&3)<<30)
0256 #   define TSI_VICR_CNTS_DIS    (0<<30)
0257 #   define TSI_VICR_CNTS_IRQ1   (1<<30)
0258 #   define TSI_VICR_CNTS_IRQ2   (2<<30)
0259 #   define TSI_VICR_EDGIS(v)    (((v)&3)<<28)
0260 #   define TSI_VICR_EDGIS_DIS   (0<<28)
0261 #   define TSI_VICR_EDGIS_IRQ1  (1<<28)
0262 #   define TSI_VICR_EDGIS_IRQ2  (2<<28)
0263 #   define TSI_VICR_IRQ1F(v)    (((v)&3)<<26)
0264 #   define TSI_VICR_IRQ1F_NORML (0<<26)
0265 #   define TSI_VICR_IRQ1F_PULSE (1<<26)
0266 #   define TSI_VICR_IRQ1F_CLOCK (2<<26)
0267 #   define TSI_VICR_IRQ1F_1MHZ  (3<<26)
0268 #   define TSI_VICR_IRQ2F(v)    (((v)&3)<<24)
0269 #   define TSI_VICR_IRQ2F_NORML (0<<24)
0270 #   define TSI_VICR_IRQ2F_PULSE (1<<24)
0271 #   define TSI_VICR_IRQ2F_CLOCK (2<<24)
0272 #   define TSI_VICR_IRQ2F_1MHZ  (3<<24)
0273 #   define TSI_VICR_BIP         (1<<23)
0274 #   define TSI_VICR_BIPS        (1<<22)
0275 #   define TSI_VICR_IRQC        (1<<15)
0276 #   define TSI_VICR_IRQLS(v)    (((v)&7)<<12)
0277 #   define TSI_VICR_IRQS        (1<<11)
0278 #   define TSI_VICR_IRQL(v)     (((v)&7)<<8)
0279 #   define TSI_VICR_STID(v)     ((v)&0xff)
0280 #define TSI_INTEN_REG       0x448
0281 #define TSI_INTEO_REG       0x44c
0282 #define TSI_INTS_REG        0x450
0283 #   define TSI_INTS_IRQ1S   (1<<1)
0284 #   define TSI_INTS_IRQ2S   (1<<2)
0285 #   define TSI_INTS_IRQ3S   (1<<3)
0286 #   define TSI_INTS_IRQ4S   (1<<4)
0287 #   define TSI_INTS_IRQ5S   (1<<5)
0288 #   define TSI_INTS_IRQ6S   (1<<6)
0289 #   define TSI_INTS_IRQ7S   (1<<7)
0290 #   define TSI_INTS_ACFLS   (1<<8)
0291 #   define TSI_INTS_SYSFLS  (1<<9)
0292 #   define TSI_INTS_IACKS   (1<<10)
0293 #   define TSI_INTS_VIES    (1<<11)
0294 #   define TSI_INTS_VERRS   (1<<12)
0295 #   define TSI_INTS_PERRS   (1<<13)
0296 #   define TSI_INTS_MB0S    (1<<16)
0297 #   define TSI_INTS_MB1S    (1<<17)
0298 #   define TSI_INTS_MB2S    (1<<18)
0299 #   define TSI_INTS_MB3S    (1<<19)
0300 #   define TSI_INTS_LM0S    (1<<20)
0301 #   define TSI_INTS_LM1S    (1<<21)
0302 #   define TSI_INTS_LM2S    (1<<22)
0303 #   define TSI_INTS_LM3S    (1<<23)
0304 #   define TSI_INTS_DMA0S   (1<<24)
0305 #   define TSI_INTS_DMA1S   (1<<25)
0306 #define TSI_INTC_REG        0x454
0307 #   define TSI_INTC_ACFLC   (1<<8)
0308 #   define TSI_INTC_SYSFLC  (1<<9)
0309 #   define TSI_INTC_IACKC   (1<<10)
0310 #   define TSI_INTC_VIEC    (1<<11)
0311 #   define TSI_INTC_VERRC   (1<<12)
0312 #   define TSI_INTC_PERRC   (1<<13)
0313 #   define TSI_INTC_MB0C    (1<<16)
0314 #   define TSI_INTC_MB1C    (1<<17)
0315 #   define TSI_INTC_MB2C    (1<<18)
0316 #   define TSI_INTC_MB3C    (1<<19)
0317 #   define TSI_INTC_LM0C    (1<<20)
0318 #   define TSI_INTC_LM1C    (1<<21)
0319 #   define TSI_INTC_LM2C    (1<<22)
0320 #   define TSI_INTC_LM3C    (1<<23)
0321 #   define TSI_INTC_DMA0C   (1<<24)
0322 #   define TSI_INTC_DMA1C   (1<<25)
0323 #define TSI_INTM1_REG       0x458
0324 #define TSI_INTM2_REG       0x45c
0325 
0326 #define TSI_CBAR_REG        0xffc
0327 
0328 #define TSI_CSR_OFFSET      0x7f000
0329 
0330 #define TSI_CRG_SIZE        (1<<12)     /* 4k */
0331 
0332 
0333 #define TSI_RD(base, reg)               in_be32((volatile uint32_t *)((base) + (reg)/sizeof(*base)))
0334 #define TSI_RD16(base, reg)             in_be16((volatile uint16_t *)(base) + (reg)/sizeof(uint16_t))
0335 #define TSI_LE_RD16(base, reg)          in_le16((volatile uint16_t *)(base) + (reg)/sizeof(uint16_t))
0336 #define TSI_LE_RD32(base, reg)          in_le32((volatile uint32_t *)(base) + (reg)/sizeof(*base))
0337 #define TSI_RD8(base, reg)              in_8((volatile uint8_t *)(base) + (reg))
0338 #define TSI_WR(base, reg, val)          out_be32((volatile uint32_t *)((base) + (reg)/sizeof(*base)), val)
0339 
0340 #define UNIV_SCTL_AM_MASK   (UNIV_CTL_VAS | UNIV_SCTL_PGM | UNIV_SCTL_DAT | UNIV_SCTL_USER | UNIV_SCTL_SUPER)
0341 
0342 
0343 /* allow the BSP to override the default routines */
0344 #ifndef BSP_PCI_FIND_DEVICE
0345 #define BSP_PCI_FIND_DEVICE     pci_find_device
0346 #endif
0347 #ifndef BSP_PCI_CONFIG_IN_LONG
0348 #define BSP_PCI_CONFIG_IN_LONG  pci_read_config_dword
0349 #endif
0350 #ifndef BSP_PCI_CONFIG_IN_SHORT
0351 #define BSP_PCI_CONFIG_IN_SHORT pci_read_config_word
0352 #endif
0353 #ifndef BSP_PCI_CONFIG_OUT_SHORT
0354 #define BSP_PCI_CONFIG_OUT_SHORT pci_write_config_word
0355 #endif
0356 #ifndef BSP_PCI_CONFIG_IN_BYTE
0357 #define BSP_PCI_CONFIG_IN_BYTE  pci_read_config_byte
0358 #endif
0359 
0360 typedef uint32_t pci_ulong;
0361 
0362 #ifdef __BIG_ENDIAN__
0363     static inline void st_be32( uint32_t *a, uint32_t v)
0364     {
0365         *a = v;
0366     }
0367     static inline uint32_t ld_be32( uint32_t *a )
0368     {
0369         return *a;
0370     }
0371 #elif defined(__LITTLE_ENDIAN__)
0372 #error "You need to implement st_be32/ld_be32"
0373 #else
0374 #error "Undefined endianness??"
0375 #endif
0376 
0377 #ifndef BSP_LOCAL2PCI_ADDR
0378 /* try legacy PCI_DRAM_OFFSET */
0379 #ifndef PCI_DRAM_OFFSET
0380 #define PCI_DRAM_OFFSET 0
0381 #endif
0382 #define BSP_LOCAL2PCI_ADDR(l)   (((uint32_t)l)+PCI_DRAM_OFFSET)
0383 #endif
0384 
0385 /* PCI_MEM_BASE is a possible offset between CPU- and PCI addresses.
0386  * Should be defined by the BSP.
0387  */
0388 #ifndef BSP_PCI2LOCAL_ADDR
0389 #ifndef PCI_MEM_BASE
0390 #define PCI_MEM_BASE 0
0391 #endif
0392 #define BSP_PCI2LOCAL_ADDR(memaddr) ((unsigned long)(memaddr) + PCI_MEM_BASE)
0393 #endif
0394 
0395 typedef uint32_t BEValue;
0396 
0397 typedef struct {
0398     BERegister *base;
0399     int         irqLine;
0400     int         pic_pin[TSI_NUM_WIRES];
0401 } Tsi148Dev;
0402 
0403 static Tsi148Dev devs[NUM_TSI_DEVS] = {{0}};
0404 
0405 #define THEBASE (devs[0].base)
0406 
0407 /* forward decl */
0408 extern int vmeTsi148RegPort;
0409 extern int vmeTsi148RegCSR;
0410 
0411 /* registers should be mapped to guarded, non-cached memory; hence
0412  * subsequent stores are ordered. eieio is only needed to enforce
0413  * ordering of loads with respect to stores.
0414  */
0415 
0416 /* private printing wrapper */
0417 static void
0418 uprintf(FILE *f, char *fmt, ...)
0419 {
0420 va_list ap;
0421     va_start(ap, fmt);
0422     if (!f || !_System_state_Is_up(_System_state_Get())) {
0423         /* Might be called at an early stage when
0424          * to a buffer.
0425          */
0426         vprintk(fmt,ap);
0427     } else
0428     {
0429         vfprintf(f,fmt,ap);
0430     }
0431     va_end(ap);
0432 }
0433 
0434 #define CHECK_BASE(base,quiet,rval) \
0435     do {                            \
0436         if ( !base ) {              \
0437             if ( !quiet ) {         \
0438                 uprintf(stderr,"Tsi148: Driver not initialized\n"); \
0439             }                       \
0440             return rval;            \
0441         }                           \
0442     } while (0)
0443 
0444 int
0445 vmeTsi148FindPciBase(
0446     int instance,
0447     BERegister **pbase
0448     )
0449 {
0450 int                 bus,dev,fun;
0451 pci_ulong           busaddr;
0452 unsigned char       irqline;
0453 unsigned short      wrd;
0454 
0455     if (BSP_PCI_FIND_DEVICE(
0456             PCI_VENDOR_TUNDRA,
0457             PCI_DEVICE_TSI148,
0458             instance,
0459             &bus,
0460             &dev,
0461             &fun))
0462         return -1;
0463     if (BSP_PCI_CONFIG_IN_LONG(bus,dev,fun,PCI_BASE_ADDRESS_0,&busaddr))
0464         return -1;
0465     /* Assume upper BAR is zero */
0466 
0467     *pbase=(BERegister*)(((pci_ulong)BSP_PCI2LOCAL_ADDR(busaddr)) & ~0xff);
0468 
0469     if (BSP_PCI_CONFIG_IN_BYTE(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline))
0470         return -1;
0471 
0472     /* Enable PCI master and memory access */
0473     BSP_PCI_CONFIG_IN_SHORT(bus, dev, fun, PCI_COMMAND, &wrd);
0474     BSP_PCI_CONFIG_OUT_SHORT(bus, dev, fun, PCI_COMMAND, wrd | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
0475 
0476     return irqline;
0477 }
0478 
0479 int
0480 vmeTsi148InitInstance(unsigned instance)
0481 {
0482 int                 irq;
0483 BERegister *base;
0484 
0485     if ( instance >= NUM_TSI_DEVS )
0486         return  -1;
0487     if ( devs[instance].base )
0488         return  -1;
0489 
0490     if ((irq=vmeTsi148FindPciBase(instance,&base)) < 0) {
0491         uprintf(stderr,"unable to find a Tsi148 in pci config space\n");
0492     } else {
0493         uprintf(stderr,"Tundra Tsi148 PCI-VME bridge detected at 0x%08x, IRQ %d\n",
0494                 (unsigned int)base, irq);
0495     }
0496     devs[0].base    = base;
0497     devs[0].irqLine = irq;
0498 
0499     return irq < 0 ? -1 : 0;
0500 }
0501 
0502 int
0503 vmeTsi148Init(void)
0504 {
0505     return vmeTsi148InitInstance(0);
0506 }
0507 
0508 
0509 void
0510 vmeTsi148ResetXX(BERegister *base)
0511 {
0512 int port;
0513 uint32_t v;
0514 
0515     CHECK_BASE(base,0, );
0516 
0517     vmeTsi148DisableAllOutboundPortsXX(base);
0518     for ( port=0; port < TSI148_NUM_OPORTS; port++ )
0519         TSI_WR(base, TSI_OTBS_REG(port), 0);
0520     TSI_WR(base, TSI_INTEO_REG, 0);
0521     TSI_WR(base, TSI_INTEN_REG, 0);
0522     TSI_WR(base, TSI_INTC_REG, 0xffffffff);
0523     TSI_WR(base, TSI_INTM1_REG, 0);
0524     TSI_WR(base, TSI_INTM2_REG, 0);
0525     TSI_WR(base, TSI_VICR_REG, 0);
0526     TSI_WR(base, TSI_VEAT_REG, TSI_VEAT_VESCL);
0527     /* Clear BDFAIL / (--> SYSFAIL) */
0528 #   define TSI_VSTAT_BDFAIL     (1<<14)
0529     TSI_WR(base, TSI_VSTAT_REG, TSI_RD(base, TSI_VSTAT_REG) & ~TSI_VSTAT_BDFAIL);
0530     /* Set (long) bus master timeout; the timeout actually overrides
0531      * the DMA block size so that the DMA settings would effectively
0532      * not be used.
0533      * Also, we enable 'release on request' mode so that we normally
0534      * don't have to rearbitrate the bus for every transfer.
0535      */
0536     v = TSI_RD(base, TSI_VMCTRL_REG);
0537     v &= ~( TSI_VMCTRL_VTON_MSK | TSI_VMCTRL_VREL_MSK );
0538     v |= (TSI_VMCTRL_VTON_512us | TSI_VMCTRL_VREL_TONorDONE_and_REQ );
0539     TSI_WR(base, TSI_VMCTRL_REG, v);
0540 }
0541 
0542 void
0543 vmeTsi148Reset(void)
0544 {
0545     vmeTsi148ResetXX(THEBASE);
0546 }
0547 
0548 RTEMS_INTERRUPT_LOCK_DEFINE( static, vmeTsi148_lock, "vmeTsi148_lock" )
0549 void
0550 vmeTsi148ResetBusXX(BERegister *base)
0551 {
0552 uint32_t      v;
0553 rtems_interrupt_lock_context lock_context;
0554 
0555     rtems_interrupt_lock_acquire( &vmeTsi148_lock, &lock_context );
0556     v = TSI_RD(base, TSI_VCTRL_REG);
0557     TSI_WR(base, TSI_VCTRL_REG, v | TSI_VCTRL_SRESET);
0558     rtems_interrupt_lock_release( &vmeTsi148_lock, &lock_context );
0559 }
0560 
0561 void
0562 vmeTsi148ResetBus(void)
0563 {
0564     vmeTsi148ResetBusXX(THEBASE);
0565 }
0566 
0567 
0568 /* convert an address space selector to a corresponding
0569  * Tsi148 control mode word
0570  */
0571 
0572 static unsigned long ck2esst(unsigned long am)
0573 {
0574     if ( VME_AM_IS_2eSST(am) ) {
0575         /* make sure 2eVME is selected */
0576         am &= ~VME_AM_MASK;
0577         am |= VME_AM_2eVME_6U;
0578     }
0579     return am;
0580 }
0581 
0582 static int
0583 am2omode(unsigned long address_space, unsigned long *pmode)
0584 {
0585 unsigned long mode = 0;
0586 unsigned long tm   = TSI_TM_SCT_IDX;
0587 
0588     switch ( VME_MODE_DBW_MSK & address_space ) {
0589         case VME_MODE_DBW8:
0590             return -1;  /* unsupported */
0591 
0592         case VME_MODE_DBW16:
0593             break;
0594 
0595         default:
0596         case VME_MODE_DBW32:
0597             mode |= TSI_OTAT_DBW(1);
0598             break;
0599     }
0600 
0601     if ( ! (VME_MODE_PREFETCH_ENABLE & address_space) )
0602         mode |= TSI_OTAT_MRPFD;
0603     else {
0604         mode |= TSI_OTAT_PFS(address_space>>_LD_VME_MODE_PREFETCHSZ);
0605     }
0606 
0607     address_space = ck2esst(address_space);
0608 
0609     switch (address_space & VME_AM_MASK) {
0610         case VME_AM_STD_SUP_PGM:
0611         case VME_AM_STD_USR_PGM:
0612 
0613             mode |= TSI_OTAT_PGM;
0614 
0615             /* fall thru */
0616         case VME_AM_STD_SUP_BLT:
0617         case VME_AM_STD_SUP_MBLT:
0618 
0619         case VME_AM_STD_USR_BLT:
0620         case VME_AM_STD_USR_MBLT:
0621             switch ( address_space & 3 ) {
0622                 case 0: tm = TSI_TM_MBLT_IDX; break;
0623                 case 3: tm = TSI_TM_BLT_IDX; break;
0624                 default: break;
0625             }
0626 
0627         case VME_AM_STD_SUP_DATA:
0628         case VME_AM_STD_USR_DATA:
0629 
0630             mode |= TSI_OTAT_ADMODE_A24;
0631             break;
0632 
0633         case VME_AM_EXT_SUP_PGM:
0634         case VME_AM_EXT_USR_PGM:
0635             mode |= TSI_OTAT_PGM;
0636 
0637             /* fall thru */
0638         case VME_AM_EXT_SUP_BLT:
0639         case VME_AM_EXT_SUP_MBLT:
0640 
0641         case VME_AM_EXT_USR_BLT:
0642         case VME_AM_EXT_USR_MBLT:
0643             switch ( address_space & 3 ) {
0644                 case 0: tm = TSI_TM_MBLT_IDX; break;
0645                 case 3: tm = TSI_TM_BLT_IDX; break;
0646                 default: break;
0647             }
0648 
0649         case VME_AM_EXT_SUP_DATA:
0650         case VME_AM_EXT_USR_DATA:
0651 
0652             mode |= TSI_OTAT_ADMODE_A32;
0653             break;
0654 
0655         case VME_AM_SUP_SHORT_IO:
0656         case VME_AM_USR_SHORT_IO:
0657             mode |= TSI_OTAT_ADMODE_A16;
0658             break;
0659 
0660         case VME_AM_CSR:
0661             mode |= TSI_OTAT_ADMODE_CSR;
0662             break;
0663 
0664         case VME_AM_2eVME_6U:
0665         case VME_AM_2eVME_3U:
0666             mode |= TSI_OTAT_ADMODE_A32;
0667             if ( VME_AM_IS_2eSST(address_space) ) {
0668                 tm = ( VME_AM_2eSST_BCST & address_space ) ?
0669                         TSI_TM_2eSSTB_IDX : TSI_TM_2eSST_IDX;
0670                 switch ( VME_AM_IS_2eSST(address_space) ) {
0671                     default:
0672                     case VME_AM_2eSST_LO:  mode |= TSI_OTAT_2eSSTM_160; break;
0673                     case VME_AM_2eSST_MID: mode |= TSI_OTAT_2eSSTM_267; break;
0674                     case VME_AM_2eSST_HI:  mode |= TSI_OTAT_2eSSTM_320; break;
0675                 }
0676             } else {
0677                 tm    = TSI_TM_2eVME_IDX;
0678             }
0679         break;
0680 
0681         case 0: /* disable the port alltogether */
0682             break;
0683 
0684         default:
0685             return -1;
0686     }
0687 
0688     mode |= TSI_OTAT_TM(tm);
0689 
0690     if ( VME_AM_IS_SUP(address_space) )
0691         mode |= TSI_OTAT_SUP;
0692     *pmode = mode;
0693     return 0;
0694 }
0695 
0696 static int
0697 am2imode(unsigned long address_space, unsigned long *pmode)
0698 {
0699 unsigned long mode=0;
0700 unsigned long pgm = 0;
0701 
0702     mode |= TSI_ITAT_VFS(address_space>>_LD_VME_MODE_PREFETCHSZ);
0703 
0704     if ( VME_AM_IS_2eSST(address_space) ) {
0705             mode |= TSI_ITAT_2eSST;
0706         if ( VME_AM_2eSST_BCST & address_space )
0707             mode |= TSI_ITAT_2eSSTB;
0708         switch ( VME_AM_IS_2eSST(address_space) ) {
0709             default:
0710             case VME_AM_2eSST_LO:  mode |= TSI_ITAT_2eSSTM_160; break;
0711             case VME_AM_2eSST_MID: mode |= TSI_ITAT_2eSSTM_267; break;
0712             case VME_AM_2eSST_HI:  mode |= TSI_ITAT_2eSSTM_320; break;
0713         }
0714         address_space = ck2esst(address_space);
0715     }
0716 
0717     mode |= TSI_ITAT_BLT;
0718     mode |= TSI_ITAT_MBLT;
0719 
0720     mode |= TSI_ITAT_PGM; /* always allow PGM access */
0721     mode |= TSI_ITAT_USR; /* always allow USR access */
0722 
0723     switch (address_space & VME_AM_MASK) {
0724         case VME_AM_STD_SUP_PGM:
0725         case VME_AM_STD_USR_PGM:
0726 
0727             pgm = 1;
0728 
0729             /* fall thru */
0730         case VME_AM_STD_SUP_BLT:
0731         case VME_AM_STD_SUP_MBLT:
0732         case VME_AM_STD_USR_BLT:
0733         case VME_AM_STD_USR_MBLT:
0734         case VME_AM_STD_SUP_DATA:
0735         case VME_AM_STD_USR_DATA:
0736 
0737             mode |= TSI_ITAT_ADMODE_A24;
0738             break;
0739 
0740         case VME_AM_EXT_SUP_PGM:
0741         case VME_AM_EXT_USR_PGM:
0742             pgm = 1;
0743 
0744             /* fall thru */
0745         case VME_AM_2eVME_6U:
0746         case VME_AM_2eVME_3U:
0747         case VME_AM_EXT_SUP_BLT:
0748         case VME_AM_EXT_SUP_MBLT:
0749         case VME_AM_EXT_USR_BLT:
0750         case VME_AM_EXT_USR_MBLT:
0751         case VME_AM_EXT_SUP_DATA:
0752         case VME_AM_EXT_USR_DATA:
0753             mode |= TSI_ITAT_ADMODE_A32;
0754             break;
0755 
0756         case VME_AM_SUP_SHORT_IO:
0757         case VME_AM_USR_SHORT_IO:
0758             mode |= TSI_ITAT_ADMODE_A16;
0759             break;
0760 
0761         case 0: /* disable the port alltogether */
0762             *pmode = 0;
0763             return 0;
0764 
0765         default:
0766             return -1;
0767     }
0768 
0769     if ( VME_AM_IS_SUP(address_space) )
0770         mode |= TSI_ITAT_SUP;
0771 
0772     if ( !pgm )
0773         mode |= TSI_ITAT_DATA;
0774 
0775     *pmode = mode;
0776     return 0;
0777 }
0778 
0779 static void
0780 readTriple(
0781     BERegister *base,
0782     unsigned reg,
0783     unsigned long long *ps,
0784     unsigned long long *pl,
0785     unsigned long long *po)
0786 {
0787     *ps = TSI_RD(base, reg);
0788     *ps = (*ps<<32) | (TSI_RD(base, (reg+4)) & 0xffff0000);
0789     *pl = TSI_RD(base, (reg+8));
0790     *pl = (*pl<<32) | (TSI_RD(base, (reg+0xc)) & 0xffff0000);
0791     *po = TSI_RD(base, (reg+0x10));
0792     *po = (*po<<32) | (TSI_RD(base, (reg+0x14)) & 0xffff0000);
0793 }
0794 
0795 
0796 static unsigned long
0797 inboundGranularity(unsigned long itat)
0798 {
0799     switch ( itat & TSI_ITAT_AS(-1) ) {
0800         case TSI_ITAT_ADMODE_A16:   return 0xf;
0801         case TSI_ITAT_ADMODE_A24:   return 0xfff;
0802         default:
0803         break;
0804     }
0805     return 0xffff;
0806 }
0807 
0808 static int
0809 configTsiPort(
0810     BERegister      *base,
0811     int             isout,
0812     unsigned long   port,
0813     unsigned long   address_space,
0814     unsigned long   vme_address,
0815     unsigned long   pci_address,
0816     unsigned long   length)
0817 {
0818 unsigned long long  start, limit, offst;
0819 unsigned long       mode, mask, tat_reg, tsau_reg;
0820 char                *name = (isout ? "Outbound" : "Inbound");
0821 int                 i,s,l;
0822 
0823     CHECK_BASE(base,0,-1);
0824 
0825     mode = 0; /* silence warning */
0826 
0827     if ( port >= (isout ? TSI148_NUM_OPORTS : TSI148_NUM_IPORTS) ) {
0828         uprintf(stderr,"Tsi148 %s Port Cfg: invalid port\n", name);
0829         return -1;
0830     }
0831 
0832     if ( base == THEBASE && isout && vmeTsi148RegPort == port ) {
0833         uprintf(stderr,"Tsi148 %s Port Cfg: invalid port; reserved by the interrupt manager for CRG\n", name);
0834         return -1;
0835     }
0836 
0837     if ( length && (isout ? am2omode(address_space, &mode) : am2imode(address_space, &mode)) ) {
0838         uprintf(stderr,"Tsi148 %s Port Cfg: invalid address space / mode flags\n",name);
0839         return -1;
0840     }
0841 
0842 
0843     if ( isout ) {
0844         start     = pci_address;
0845         offst     = (unsigned long long)vme_address - start;
0846         mask      = 0xffff;
0847         tat_reg   = TSI_OTAT_REG(port);
0848         tsau_reg  = TSI_OTSAU_REG(port);
0849         mode     |= TSI_OTAT_EN;
0850 
0851         /* check for overlap */
0852         for ( i = 0; i < TSI148_NUM_OPORTS; i++ ) {
0853             /* ignore 'this' port */
0854             if ( i == port || ! (TSI_OTAT_EN & TSI_RD(base, TSI_OTAT_REG(i))) )
0855                 continue;
0856 
0857             /* check requested PCI range against current port 'i' config */
0858             s = TSI_RD(base, TSI_OTSAU_REG(i) + 0x04); /* start */
0859             l = TSI_RD(base, TSI_OTSAU_REG(i) + 0x0c); /* limit */
0860             if ( ! ( start + length <= s || start > s + l ) ) {
0861                 uprintf(stderr,"Tsi148 Outbound Port Cfg: PCI address range overlaps with port %i (0x%08x..0x%08x)\n", i, s, l);
0862                 return -1;
0863             }
0864         }
0865     } else {
0866         start     = vme_address;
0867         offst     = (unsigned long long)pci_address - start;
0868         mask      = inboundGranularity(mode);
0869         tat_reg   = TSI_ITAT_REG(port);
0870         tsau_reg  = TSI_ITSAU_REG(port);
0871         mode     |= TSI_ITAT_EN;
0872 
0873         /* check for overlap */
0874         for ( i = 0; i < TSI148_NUM_IPORTS; i++ ) {
0875             /* ignore 'this' port */
0876             if ( i == port || ! (TSI_ITAT_EN & (s=TSI_RD(base, TSI_ITAT_REG(i)))) )
0877                 continue;
0878 
0879             if ( (TSI_ITAT_AS(-1) & s) != (TSI_ITAT_AS(-1) & mode) ) {
0880                 /* different address space */
0881                 continue;
0882             }
0883 
0884             if ( ! (mode & s & (TSI_ITAT_SUP | TSI_ITAT_USR | TSI_ITAT_PGM | TSI_ITAT_DATA)) ) {
0885                 /* orthogonal privileges */
0886                 continue;
0887             }
0888 
0889             /* check requested VME range against current port 'i' config */
0890             s = TSI_RD(base, TSI_ITSAU_REG(i) + 0x04); /* start */
0891             l = TSI_RD(base, TSI_ITSAU_REG(i) + 0x0c); /* limit */
0892             if ( ! ( start + length <= s || start > s + l ) ) {
0893                 uprintf(stderr,"Tsi148 Inbound Port Cfg: VME address range overlaps with port %i (0x%08x..0x%08x)\n", i, s, l);
0894                 return -1;
0895             }
0896         }
0897     }
0898 
0899     /* If they pass 'length==0' just disable */
0900     if ( 0 == length ) {
0901         TSI_WR(base, tat_reg, TSI_RD(base, tat_reg) & ~(isout ? TSI_OTAT_EN : TSI_ITAT_EN));
0902         return 0;
0903     }
0904 
0905 
0906     if (   (vme_address & mask)
0907         || (pci_address & mask)
0908         || (length      & mask) ) {
0909         uprintf(stderr,"Tsi148 %s Port Cfg: invalid address/length; must be multiple of 0x%x\n",
0910                 name,
0911                 mask+1);
0912         return -1;
0913     }
0914 
0915     limit  = start + length - 1;
0916 
0917     if ( limit >= (unsigned long long)1<<32 ) {
0918         uprintf(stderr,"Tsi148 %s Port Cfg: invalid address/length; must be < 1<<32\n", name);
0919         return -1;
0920     }
0921 
0922     /* Disable port */
0923     TSI_WR(base, tat_reg, 0);
0924 
0925     /* Force to 32-bits */
0926     TSI_WR(base, tsau_reg       , 0);
0927     TSI_WR(base, tsau_reg + 0x04, (uint32_t)start);
0928     TSI_WR(base, tsau_reg + 0x08, 0);
0929     TSI_WR(base, tsau_reg + 0x0c, (uint32_t)limit);
0930     TSI_WR(base, tsau_reg + 0x10, (uint32_t)(offst>>32));
0931     TSI_WR(base, tsau_reg + 0x14, (uint32_t)offst);
0932 
0933     /* (outbound only:) leave 2eSST broadcast register alone for user to program */
0934 
0935     /* Set mode and enable */
0936     TSI_WR(base, tat_reg, mode);
0937     return 0;
0938 }
0939 
0940 static int
0941 disableTsiPort(
0942     BERegister      *base,
0943     int             isout,
0944     unsigned long   port)
0945 {
0946     return configTsiPort(base, isout, port, 0, 0, 0, 0);
0947 }
0948 
0949 int
0950 vmeTsi148InboundPortCfgXX(
0951     BERegister      *base,
0952     unsigned long   port,
0953     unsigned long   address_space,
0954     unsigned long   vme_address,
0955     unsigned long   pci_address,
0956     unsigned long   length)
0957 {
0958     return configTsiPort(base, 0, port, address_space, vme_address, pci_address, length);
0959 }
0960 
0961 int
0962 vmeTsi148InboundPortCfg(
0963     unsigned long   port,
0964     unsigned long   address_space,
0965     unsigned long   vme_address,
0966     unsigned long   pci_address,
0967     unsigned long   length)
0968 {
0969     return configTsiPort(THEBASE, 0, port, address_space, vme_address, pci_address, length);
0970 }
0971 
0972 
0973 int
0974 vmeTsi148OutboundPortCfgXX(
0975     BERegister      *base,
0976     unsigned long   port,
0977     unsigned long   address_space,
0978     unsigned long   vme_address,
0979     unsigned long   pci_address,
0980     unsigned long   length)
0981 {
0982     return configTsiPort(base, 1, port, address_space, vme_address, pci_address, length);
0983 }
0984 
0985 int
0986 vmeTsi148OutboundPortCfg(
0987     unsigned long   port,
0988     unsigned long   address_space,
0989     unsigned long   vme_address,
0990     unsigned long   pci_address,
0991     unsigned long   length)
0992 {
0993     return configTsiPort(THEBASE, 1, port, address_space, vme_address, pci_address, length);
0994 }
0995 
0996 
0997 static int
0998 xlateFindPort(
0999     BERegister *base,   /* TSI 148 base address */
1000     int outbound,       /* look in the outbound windows */
1001     int reverse,        /* reverse mapping; for outbound ports: map local to VME */
1002     unsigned long as,   /* address space */
1003     unsigned long aIn,  /* address to look up */
1004     unsigned long *paOut/* where to put result */
1005     )
1006 {
1007 unsigned long       mode, mode_msk;
1008 int                 port;
1009 unsigned long long  start, limit, offst, a;
1010 unsigned long       tsau_reg, tat_reg, gran, skip;
1011 
1012     CHECK_BASE(base,0,-1);
1013 
1014     mode = 0; /* silence warning */
1015 
1016     switch ( as & VME_MODE_MATCH_MASK ) {
1017         case VME_MODE_EXACT_MATCH:
1018             mode_msk = ~0;
1019         break;
1020 
1021         case VME_MODE_AS_MATCH:
1022             if ( outbound )
1023                 mode_msk = TSI_OTAT_ADMODE(-1) | TSI_OTAT_EN;
1024             else
1025                 mode_msk = TSI_ITAT_AS(-1) | TSI_ITAT_EN;
1026         break;
1027 
1028         default:
1029             if ( outbound )
1030                 mode_msk = TSI_OTAT_PGM | TSI_OTAT_SUP | TSI_OTAT_ADMODE(-1) | TSI_OTAT_EN;
1031             else
1032                 mode_msk = TSI_ITAT_PGM | TSI_ITAT_DATA | TSI_ITAT_SUP | TSI_ITAT_USR | TSI_ITAT_AS(-1) | TSI_ITAT_EN;
1033         break;
1034     }
1035 
1036     as &= ~VME_MODE_MATCH_MASK;
1037 
1038     if ( outbound ? am2omode(as,&mode) : am2imode(as,&mode) ) {
1039         uprintf(stderr, "vmeTsi148XlateAddr: invalid address space/mode argument");
1040         return -2;
1041     }
1042 
1043     if (outbound ) {
1044         tsau_reg = TSI_OTSAU_REG(0);
1045         tat_reg  = TSI_OTAT_REG(0);
1046         skip     = TSI_OTSAU_SPACING;
1047         mode    |= TSI_OTAT_EN;
1048         gran     = 0x10000;
1049     } else {
1050         tsau_reg = TSI_ITSAU_REG(0);
1051         tat_reg  = TSI_ITAT_REG(0);
1052         skip     = TSI_ITSAU_SPACING;
1053         mode    |= TSI_ITAT_EN;
1054         gran     = inboundGranularity(mode) + 1;
1055     }
1056 
1057     for ( port = 0; port < TSI148_NUM_OPORTS; port++, tsau_reg += skip, tat_reg += skip ) {
1058 
1059         if ( (mode & mode_msk) == (TSI_RD(base, tat_reg) & mode_msk) ) {
1060 
1061             /* found a window with of the right mode; now check the range */
1062             readTriple(base, tsau_reg, &start, &limit, &offst);
1063             limit += gran;
1064 
1065             if ( !reverse ) {
1066                 start += offst;
1067                 limit += offst;
1068                 offst  = -offst;
1069             }
1070             a = aIn;
1071             if ( aIn >= start && aIn <= limit ) {
1072                 /* found it */
1073                 *paOut = (unsigned long)(a + offst);
1074                 return port;
1075             }
1076         }
1077     }
1078 
1079     uprintf(stderr, "vmeTsi148XlateAddr: no matching mapping found\n");
1080     return -1;
1081 }
1082 
1083 int
1084 vmeTsi148XlateAddrXX(
1085     BERegister *base,   /* TSI 148 base address */
1086     int outbound,       /* look in the outbound windows */
1087     int reverse,        /* reverse mapping; for outbound ports: map local to VME */
1088     unsigned long as,   /* address space */
1089     unsigned long aIn,  /* address to look up */
1090     unsigned long *paOut/* where to put result */
1091     )
1092 {
1093 int port = xlateFindPort( base, outbound, reverse, as, aIn, paOut );
1094     return port < 0 ? -1 : 0;
1095 }
1096 
1097 int
1098 vmeTsi148XlateAddr(
1099     int outbound,       /* look in the outbound windows */
1100     int reverse,        /* reverse mapping; for outbound ports: map local to VME */
1101     unsigned long as,   /* address space */
1102     unsigned long aIn,  /* address to look up */
1103     unsigned long *paOut/* where to put result */
1104     )
1105 {
1106     return vmeTsi148XlateAddrXX(THEBASE, outbound, reverse, as, aIn, paOut);
1107 }
1108 
1109 
1110 static void uprintfllx(FILE *f, unsigned long long v)
1111 {
1112     uprintf(f,"0x%08llx ", v);
1113 }
1114 
1115 void
1116 vmeTsi148OutboundPortsShowXX(BERegister *base, FILE *f)
1117 {
1118 int             port;
1119 unsigned long   mode;
1120 char            tit = 0;
1121 
1122 unsigned long long  start, limit, offst;
1123 
1124     CHECK_BASE(base,0, );
1125 
1126     if (!f) f=stdout;
1127     uprintf(f,"Tsi148 Outbound Ports:\n");
1128 
1129     for ( port = 0; port < TSI148_NUM_OPORTS; port++ ) {
1130         mode = TSI_RD(base, TSI_OTAT_REG(port));
1131         if ( ! (TSI_OTAT_EN & mode) )
1132             continue; /* skip disabled ports */
1133 
1134         readTriple(base, TSI_OTSAU_REG(port), &start, &limit, &offst);
1135 
1136         /* convert limit to size */
1137         limit = limit-start+0x10000;
1138         if ( !tit ) {
1139             uprintf(f,"Port  VME-Addr   Size       PCI-Adrs   Mode:\n");
1140             tit = 1;
1141         }
1142         uprintf(f,"%d:    ", port);
1143         uprintfllx(f,start+offst);
1144         uprintfllx(f,limit);
1145         uprintfllx(f,start);
1146         switch( mode & TSI_OTAT_ADMODE(-1) ) {
1147             case TSI_OTAT_ADMODE_A16: uprintf(f,"A16"); break;
1148             case TSI_OTAT_ADMODE_A24: uprintf(f,"A24"); break;
1149             case TSI_OTAT_ADMODE_A32: uprintf(f,"A32"); break;
1150             case TSI_OTAT_ADMODE_A64: uprintf(f,"A64"); break;
1151             case TSI_OTAT_ADMODE_CSR: uprintf(f,"CSR"); break;
1152             default:                  uprintf(f,"A??"); break;
1153         }
1154 
1155         if ( mode & TSI_OTAT_PGM ) uprintf(f,", PGM");
1156         if ( mode & TSI_OTAT_SUP ) uprintf(f,", SUP");
1157         if ( ! (TSI_OTAT_MRPFD & mode) ) uprintf(f,", PREFETCH");
1158 
1159         switch ( mode & TSI_OTAT_DBW(-1) ) {
1160             case TSI_OTAT_DBW(0):   uprintf(f,", D16"); break;
1161             case TSI_OTAT_DBW(1):   uprintf(f,", D32"); break;
1162             default:                uprintf(f,", D??"); break;
1163         }
1164 
1165         switch( mode & TSI_OTAT_TM(-1) ) {
1166             case TSI_OTAT_TM(0):    uprintf(f,", SCT");         break;
1167             case TSI_OTAT_TM(1):    uprintf(f,", BLT");         break;
1168             case TSI_OTAT_TM(2):    uprintf(f,", MBLT");        break;
1169             case TSI_OTAT_TM(3):    uprintf(f,", 2eVME");       break;
1170             case TSI_OTAT_TM(4):    uprintf(f,", 2eSST");       break;
1171             case TSI_OTAT_TM(5):    uprintf(f,", 2eSST_BCST");  break;
1172             default:                uprintf(f," TM??");     break;
1173         }
1174 
1175         uprintf(f,"\n");
1176     }
1177 }
1178 
1179 void
1180 vmeTsi148OutboundPortsShow(FILE *f)
1181 {
1182     vmeTsi148OutboundPortsShowXX(THEBASE, f);
1183 }
1184 
1185 void
1186 vmeTsi148InboundPortsShowXX(BERegister *base, FILE *f)
1187 {
1188 int             port;
1189 unsigned long   mode;
1190 char            tit = 0;
1191 
1192 unsigned long long  start, limit, offst;
1193 
1194     CHECK_BASE(base,0, );
1195 
1196     if (!f) f=stdout;
1197     uprintf(f,"Tsi148 Inbound Ports:\n");
1198 
1199     for ( port = 0; port < TSI148_NUM_IPORTS; port++ ) {
1200         mode = TSI_RD(base, TSI_ITAT_REG(port));
1201         if ( ! (TSI_ITAT_EN & mode) )
1202             continue; /* skip disabled ports */
1203 
1204         readTriple(base, TSI_ITSAU_REG(port), &start, &limit, &offst);
1205 
1206         /* convert limit to size */
1207         limit = limit - start + inboundGranularity(mode) + 1;
1208         if ( !tit ) {
1209             uprintf(f,"Port  VME-Addr   Size       PCI-Adrs   Mode:\n");
1210             tit = 1;
1211         }
1212         uprintf(f,"%d:    ", port);
1213         uprintfllx(f,start);
1214         uprintfllx(f,limit);
1215         uprintfllx(f,start+offst);
1216         switch( mode & TSI_ITAT_AS(-1) ) {
1217             case TSI_ITAT_ADMODE_A16: uprintf(f,"A16"); break;
1218             case TSI_ITAT_ADMODE_A24: uprintf(f,"A24"); break;
1219             case TSI_ITAT_ADMODE_A32: uprintf(f,"A32"); break;
1220             case TSI_ITAT_ADMODE_A64: uprintf(f,"A64"); break;
1221             default:                  uprintf(f,"A??"); break;
1222         }
1223 
1224         if ( mode & TSI_ITAT_PGM )  uprintf(f,", PGM");
1225         if ( mode & TSI_ITAT_DATA ) uprintf(f,", DAT");
1226         if ( mode & TSI_ITAT_SUP )  uprintf(f,", SUP");
1227         if ( mode & TSI_ITAT_USR )  uprintf(f,", USR");
1228 
1229         if ( mode & TSI_ITAT_2eSSTB )  uprintf(f,", 2eSSTB");
1230         if ( mode & TSI_ITAT_2eSST  )  uprintf(f,", 2eSST");
1231         if ( mode & TSI_ITAT_2eVME  )  uprintf(f,", 2eVME");
1232         if ( mode & TSI_ITAT_MBLT   )  uprintf(f,", MBLT");
1233         if ( mode & TSI_ITAT_BLT    )  uprintf(f,", BLT");
1234 
1235         uprintf(f,"\n");
1236     }
1237 }
1238 
1239 void
1240 vmeTsi148InboundPortsShow(FILE *f)
1241 {
1242     vmeTsi148InboundPortsShowXX(THEBASE, f);
1243 }
1244 
1245 
1246 void
1247 vmeTsi148DisableAllInboundPortsXX(BERegister *base)
1248 {
1249 int port;
1250 
1251     for ( port = 0; port < TSI148_NUM_IPORTS; port++ )
1252         if ( disableTsiPort(base, 0, port) )
1253             break;
1254 }
1255 
1256 void
1257 vmeTsi148DisableAllInboundPorts(void)
1258 {
1259     vmeTsi148DisableAllInboundPortsXX(THEBASE);
1260 }
1261 
1262 void
1263 vmeTsi148DisableAllOutboundPortsXX(BERegister *base)
1264 {
1265 int port;
1266 
1267     for ( port = 0; port < TSI148_NUM_IPORTS; port++ )
1268         if ( disableTsiPort(base, 1, port) )
1269             break;
1270 }
1271 
1272 void
1273 vmeTsi148DisableAllOutboundPorts(void)
1274 {
1275     vmeTsi148DisableAllOutboundPortsXX(THEBASE);
1276 }
1277 
1278 
1279 /* Map internal register block to VME */
1280 
1281 int
1282 vmeTsi148MapCRGXX(BERegister *b, uint32_t vme_base, uint32_t as )
1283 {
1284 uint32_t mode;
1285 
1286     CHECK_BASE( b, 0, -1 );
1287 
1288     if ( vmeTsi148RegPort > -1 && ! vmeTsi148RegCSR ) {
1289         uprintf(stderr,"vmeTsi148: CRG already mapped and in use by interrupt manager\n");
1290         return -1;
1291     }
1292 
1293     /* enable all, SUP/USR/PGM/DATA accesses */
1294     mode = TSI_CRGAT_EN | TSI_CRGAT_SUP | TSI_CRGAT_USR | TSI_CRGAT_PGM |  TSI_CRGAT_DATA;
1295 
1296     if ( VME_AM_IS_SHORT(as) ) {
1297         mode |= TSI_CRGAT_A16;
1298     } else
1299     if ( VME_AM_IS_STD(as) ) {
1300         mode |= TSI_CRGAT_A24;
1301     } else
1302     if ( VME_AM_IS_EXT(as) ) {
1303         mode |= TSI_CRGAT_A32;
1304     } else {
1305         return -2;
1306     }
1307 
1308     /* map CRG to VME bus */
1309     TSI_WR( b, TSI_CBAL_REG, (vme_base & ~(TSI_CRG_SIZE-1)));
1310     TSI_WR( b, TSI_CRGAT_REG, mode );
1311 
1312     return 0;
1313 }
1314 
1315 int
1316 vmeTsi148MapCRG(uint32_t vme_base, uint32_t as )
1317 {
1318     return vmeTsi148MapCRGXX( THEBASE, vme_base, as );
1319 }
1320 
1321 /* Interrupt Subsystem */
1322 
1323 typedef struct
1324 IRQEntryRec_ {
1325         VmeTsi148ISR    isr;
1326         void            *usrData;
1327 } IRQEntryRec, *IRQEntry;
1328 
1329 static IRQEntry irqHdlTbl[TSI_NUM_INT_VECS]={0};
1330 
1331 int        vmeTsi148IrqMgrInstalled = 0;
1332 int        vmeTsi148RegPort         = -1;
1333 int        vmeTsi148RegCSR          = 0;
1334 BERegister *vmeTsi148RegBase        = 0;
1335 
1336 static volatile unsigned long   wire_mask[TSI_NUM_WIRES]     = {0};
1337 /* wires are offset by 1 so we can initialize the wire table to all zeros */
1338 static int                      tsi_wire[TSI_NUM_WIRES] = {0};
1339 
1340 /* how should we iack a given level, 1,2,4 bytes? */
1341 static unsigned char tsi_iack_width[7] = {
1342     1,1,1,1,1,1,1
1343 };
1344 
1345 /* map universe compatible vector # to Tsi slot (which maps to bit layout in stat/enable/... regs) */
1346 static int uni2tsi_vec_map[TSI_NUM_INT_VECS-256] = {
1347     /* 256 no VOWN interrupt */         -1,
1348     /* TSI_DMA_INT_VEC          257 */  256 + 24 - 8,
1349     /* TSI_LERR_INT_VEC         258 */  256 + 13 - 8,
1350     /* TSI_VERR_INT_VEC         259 */  256 + 12 - 8,
1351     /* 260 is reserved       */         -1,
1352     /* TSI_VME_SW_IACK_INT_VEC  261 */  256 + 10 - 8,
1353     /* 262 no PCI SW IRQ     */         -1,
1354     /* TSI_SYSFAIL_INT_VEC      263 */  256 +  9 - 8,
1355     /* TSI_ACFAIL_INT_VEC       264 */  256 +  8 - 8,
1356     /* TSI_MBOX0_INT_VEC        265 */  256 + 16 - 8,
1357     /* TSI_MBOX1_INT_VEC        266 */  256 + 17 - 8,
1358     /* TSI_MBOX2_INT_VEC        267 */  256 + 18 - 8,
1359     /* TSI_MBOX3_INT_VEC        268 */  256 + 19 - 8,
1360     /* TSI_LM0_INT_VEC          269 */  256 + 20 - 8,
1361     /* TSI_LM1_INT_VEC          270 */  256 + 21 - 8,
1362     /* TSI_LM2_INT_VEC          271 */  256 + 22 - 8,
1363     /* TSI_LM3_INT_VEC          272 */  256 + 23 - 8,
1364 /* New vectors; only on TSI148 */
1365     /* TSI_VIES_INT_VEC         273 */  256 + 11 - 8,
1366     /* TSI_DMA1_INT_VEC         274 */  256 + 25 - 8,
1367 };
1368 
1369 /* and the reverse; map tsi bit number to universe compatible 'special' vector number */
1370 static int tsi2uni_vec_map[TSI_NUM_INT_VECS - 256] = {
1371     TSI_ACFAIL_INT_VEC,
1372     TSI_SYSFAIL_INT_VEC,
1373     TSI_VME_SW_IACK_INT_VEC,
1374     TSI_VIES_INT_VEC,
1375     TSI_VERR_INT_VEC,
1376     TSI_LERR_INT_VEC,
1377     -1,
1378     -1,
1379     TSI_MBOX0_INT_VEC,
1380     TSI_MBOX1_INT_VEC,
1381     TSI_MBOX2_INT_VEC,
1382     TSI_MBOX3_INT_VEC,
1383     TSI_LM0_INT_VEC,
1384     TSI_LM1_INT_VEC,
1385     TSI_LM2_INT_VEC,
1386     TSI_LM3_INT_VEC,
1387     TSI_DMA_INT_VEC,
1388     TSI_DMA1_INT_VEC,
1389     -1,
1390 };
1391 
1392 static inline int
1393 uni2tsivec(int v)
1394 {
1395     if ( v < 0 || v >= TSI_NUM_INT_VECS )
1396         return -1;
1397     return v < 256 ? v : uni2tsi_vec_map[v-256];
1398 }
1399 
1400 static int
1401 lvl2bitno(unsigned int level)
1402 {
1403     if ( level >= 256 )
1404         return uni2tsivec(level) + 8 - 256;
1405     else if ( level < 8 && level > 0 )
1406         return level;
1407     return -1;
1408 }
1409 
1410 int
1411 vmeTsi148IntRoute(unsigned int level, unsigned int pin)
1412 {
1413 int             i;
1414 unsigned long   mask, shift, mapreg, wire;
1415 rtems_interrupt_lock_context lock_context;
1416 
1417     if ( pin >= TSI_NUM_WIRES || ! tsi_wire[pin] || !vmeTsi148IrqMgrInstalled )
1418         return -1;
1419 
1420     if ( level >= 256 ) {
1421         if ( (i = uni2tsivec(level)) < 0 )
1422             return -1;
1423         shift = 8 + (i-256);
1424     } else if ( 1 <= level && level <=7 ) {
1425         shift = level;
1426     } else {
1427         return -1;  /* invalid level */
1428     }
1429 
1430     mask = 1<<shift;
1431 
1432     /* calculate the mapping register and contents */
1433     if ( shift < 16 ) {
1434         mapreg = TSI_INTM2_REG;
1435     } else if ( shift < 32 ) {
1436         shift -= 16;
1437         mapreg = TSI_INTM1_REG;
1438     } else {
1439         return -1;
1440     }
1441 
1442     shift <<=1;
1443 
1444     /* wires are offset by 1 so we can initialize the wire table to all zeros */
1445     wire = (tsi_wire[pin]-1) << shift;
1446 
1447     rtems_interrupt_lock_acquire( &vmeTsi148_lock, &lock_context );
1448     for ( i = 0; i<TSI_NUM_WIRES; i++ ) {
1449         wire_mask[i] &= ~mask;
1450     }
1451     wire_mask[pin] |= mask;
1452 
1453     mask = TSI_RD(THEBASE, mapreg) & ~ (0x3<<shift);
1454     mask |= wire;
1455     TSI_WR( THEBASE, mapreg, mask );
1456 
1457     rtems_interrupt_lock_release( &vmeTsi148_lock, &lock_context );
1458     return 0;
1459 }
1460 
1461 VmeTsi148ISR
1462 vmeTsi148ISRGet(unsigned long vector, void **parg)
1463 {
1464 VmeTsi148ISR      rval = 0;
1465 volatile IRQEntry *p;
1466 int               v = uni2tsivec(vector);
1467 rtems_interrupt_lock_context lock_context;
1468 
1469 
1470     if ( v < 0 )
1471         return rval;
1472 
1473     p = irqHdlTbl + v;
1474 
1475     rtems_interrupt_lock_acquire( &vmeTsi148_lock, &lock_context );
1476         if ( *p ) {
1477             if ( parg )
1478                 *parg = (*p)->usrData;
1479             rval = (*p)->isr;
1480         }
1481     rtems_interrupt_lock_release( &vmeTsi148_lock, &lock_context );
1482 
1483     return rval;
1484 }
1485 
1486 static void
1487 tsiVMEISR(rtems_irq_hdl_param arg)
1488 {
1489 int                 pin = (int)arg;
1490 BERegister          *b  = THEBASE;
1491 IRQEntry            ip;
1492 unsigned long       msk,lintstat,vector, vecarg;
1493 int                 lvl;
1494 
1495     /* only handle interrupts routed to this pin */
1496 
1497     /* NOTE: we read the status register over VME, thus flushing the FIFO
1498      *       where the user ISR possibly left write commands to clear
1499      *       the interrupt condition at the device.
1500      *       This is very important - otherwise, the IRQ level may still be
1501      *       asserted and we would detect an interrupt here but the subsequent
1502      *       IACK would fail since the write operation was flushed to the
1503      *       device in the mean time.
1504      */
1505     while ( (lintstat  = (TSI_RD(vmeTsi148RegBase, TSI_INTS_REG) & wire_mask[pin])) ) {
1506 
1507         /* bit 0 is never set since it is never set in wire_mask */
1508 
1509         do {
1510             /* simplicity is king; just handle them in MSB to LSB order; reserved bits read as 0 */
1511 #ifdef __PPC__
1512             asm volatile("cntlzw %0, %1":"=r"(lvl):"r"(lintstat));
1513             lvl = 31-lvl;
1514             msk = 1<<lvl;
1515 #else
1516             { static unsigned long m[] = {
1517                                              0xffff0000, 0xff00ff00, 0xf0f0f0f0, 0xcccccccc, 0xaaaaaaaa
1518                                          };
1519             int      i;
1520             unsigned tmp;
1521 
1522             /* lintstat has already been checked...
1523             if ( !lintstat ) {
1524                lvl = -1; msk = 0;
1525             } else
1526              */
1527             for ( i=0, lvl=0, msk = lintstat; i<5; i++ ) {
1528                 lvl <<= 1;
1529                 if ( (tmp = msk & m[i]) ) {
1530                     lvl++;
1531                     msk = tmp;
1532                 } else
1533                     msk = msk & ~m[i];
1534             }
1535             }
1536 #endif
1537 
1538             if ( lvl > 7 ) {
1539                 /* clear this interrupt level */
1540                 TSI_WR(b, TSI_INTC_REG, msk);
1541                 vector = 256 + lvl - 8;
1542                 vecarg = tsi2uni_vec_map[lvl-8];
1543             } else {
1544                 /* need to do get the vector for this level */
1545                 switch ( tsi_iack_width[lvl-1] ) {
1546                     default:
1547                     case  1:
1548                         vector = TSI_RD8(b, TSI_VIACK_1_REG - 4 + (lvl<<2) + 3);
1549                         break;
1550 
1551                     case  2:
1552                         vector = TSI_RD16(b, TSI_VIACK_1_REG - 4 + (lvl<<2) + 2);
1553                         break;
1554 
1555                     case  4:
1556                         vector = TSI_RD(b, TSI_VIACK_1_REG - 4 + (lvl<<2));
1557                         break;
1558                 }
1559                 vecarg = vector;
1560             }
1561 
1562             if ( !(ip=irqHdlTbl[vector])) {
1563                 /* TODO: log error message - RTEMS has no logger :-( */
1564                 vmeTsi148IntDisable(lvl);
1565                 printk("vmeTsi148 ISR: ERROR: no handler registered (level %i) IACK 0x%08lx -- DISABLING level %i\n",
1566                         lvl, vector, lvl);
1567             } else {
1568                 /* dispatch handler, it must clear the IRQ at the device */
1569                 ip->isr(ip->usrData, vecarg);
1570                 /* convenience for disobedient users who don't use in_xxx/out_xxx; make
1571                  * sure we order the subsequent read from the status register after
1572                  * their business.
1573                  */
1574                 iobarrier_rw();
1575             }
1576         } while ( (lintstat &= ~msk) );
1577         /* check if a new irq is pending already */
1578     }
1579 }
1580 
1581 
1582 static void
1583 my_no_op(const rtems_irq_connect_data * arg)
1584 {}
1585 
1586 static int
1587 my_isOn(const rtems_irq_connect_data *arg)
1588 {
1589         return (int)(TSI_RD(THEBASE, TSI_INTEO_REG) & TSI_RD(THEBASE, TSI_INTEN_REG));
1590 }
1591 
1592 static void
1593 connectIsr(int shared, rtems_irq_hdl isr, int pic_line, int slot)
1594 {
1595 rtems_irq_connect_data  xx;
1596     xx.on     = my_no_op; /* at _least_ they could check for a 0 pointer */
1597     xx.off    = my_no_op;
1598     xx.isOn   = my_isOn;
1599     xx.hdl    = isr;
1600     xx.handle = (rtems_irq_hdl_param)slot;
1601     xx.name   = pic_line;
1602 
1603     if ( shared ) {
1604 #if BSP_SHARED_HANDLER_SUPPORT > 0
1605         if (!BSP_install_rtems_shared_irq_handler(&xx))
1606             rtems_panic("unable to install vmeTsi148 shared irq handler");
1607 #else
1608         uprintf(stderr,"vmeTsi148: WARNING: your BSP doesn't support sharing interrupts\n");
1609         if (!BSP_install_rtems_irq_handler(&xx))
1610             rtems_panic("unable to install vmeTsi148 irq handler");
1611 #endif
1612     } else {
1613         if (!BSP_install_rtems_irq_handler(&xx))
1614             rtems_panic("unable to install vmeTsi148 irq handler");
1615     }
1616 }
1617 
1618 int
1619 vmeTsi148InstallIrqMgrAlt(int shared, int tsi_pin0, int pic_pin0, ...)
1620 {
1621 int     rval;
1622 va_list ap;
1623     va_start(ap, pic_pin0);
1624     rval = vmeTsi148InstallIrqMgrVa(shared, tsi_pin0, pic_pin0, ap);
1625     va_end(ap);
1626     return rval;
1627 }
1628 
1629 #ifndef BSP_EARLY_PROBE_VME
1630 #define BSP_EARLY_PROBE_VME(addr)   \
1631     (                                                                                                   \
1632         vmeTsi148ClearVMEBusErrorsXX( THEBASE, 0 ),                                             \
1633         ( ((PCI_DEVICE_TSI148 << 16) | PCI_VENDOR_TUNDRA ) == TSI_LE_RD32( ((BERegister*)(addr)), 0 )   \
1634          && 0 == vmeTsi148ClearVMEBusErrorsXX( THEBASE, 0 ) )                                       \
1635     )
1636 #endif
1637 
1638 /* Check if there is a vme address/as is mapped in any of the outbound windows
1639  * and look for the PCI vendordevice ID there.
1640  * RETURNS: -1 on error (no mapping or probe failure), outbound window # (0..7)
1641  *          on success. Address translated into CPU address is returned in *pcpu_addr.
1642  */
1643 static int
1644 mappedAndProbed(unsigned long vme_addr, unsigned as, unsigned long *pcpu_addr)
1645 {
1646 int j;
1647 char *regtype = (as & VME_AM_MASK) == VME_AM_CSR ? "CSR" : "CRG";
1648 
1649     /* try to find mapping */
1650     if ( 0 > (j = xlateFindPort(
1651                 THEBASE,
1652                 1, 0,
1653                 as | VME_MODE_AS_MATCH,
1654                 vme_addr,
1655                 pcpu_addr ) ) ) {
1656             uprintf(stderr,"vmeTsi148 - Unable to find mapping for %s VME base (0x%08x)\n", regtype, vme_addr);
1657             uprintf(stderr,"            in outbound windows.\n");
1658     }
1659     else {
1660             /* found a slot number; probe it */
1661             *pcpu_addr = BSP_PCI2LOCAL_ADDR( *pcpu_addr );
1662             if ( BSP_EARLY_PROBE_VME(*pcpu_addr) ) {
1663                 uprintf(stderr,"vmeTsi148 - IRQ manager using VME %s to flush FIFO\n", regtype);
1664                 return j;
1665             } else {
1666                 uprintf(stderr,"vmeTsi148 - Found slot info but detection of tsi148 in VME %s space failed\n", regtype);
1667             }
1668     }
1669     return -1;
1670 }
1671 
1672 int
1673 vmeTsi148InstallIrqMgrVa(int shared, int tsi_pin0, int pic_pin0, va_list ap)
1674 {
1675 int i,j, specialPin, tsi_pin[TSI_NUM_WIRES+1], pic_pin[TSI_NUM_WIRES];
1676 unsigned long cpu_base, vme_reg_base;
1677 
1678     if (vmeTsi148IrqMgrInstalled)                  return -4;
1679 
1680     /* check parameters */
1681 
1682     if ( tsi_pin0 < 0 || tsi_pin0 > 3 )            return -1;
1683 
1684     tsi_pin[0] = tsi_pin0;
1685     pic_pin[0] = pic_pin0 < 0 ? devs[0].irqLine : pic_pin0;
1686     i = 1;
1687     while ( (tsi_pin[i] = va_arg(ap, int)) >= 0 ) {
1688 
1689         if ( i >= TSI_NUM_WIRES ) {
1690                                                    return -5;
1691         }
1692 
1693         pic_pin[i] = va_arg(ap,int);
1694 
1695         if ( tsi_pin[i] > 3 )                      return -2;
1696         if ( pic_pin[i] < 0 )                      return -3;
1697         i++;
1698     }
1699 
1700     /* all routings must be different */
1701     for ( i=0; tsi_pin[i] >= 0; i++ ) {
1702         for ( j=i+1; tsi_pin[j] >= 0; j++ ) {
1703             if ( tsi_pin[j] == tsi_pin[i] )        return -6;
1704             if ( pic_pin[j] == pic_pin[i] )        return -7;
1705         }
1706     }
1707 
1708     i        = -1;
1709 
1710     /* first try VME CSR space; do we have a base address set ? */
1711 
1712     uprintf(stderr,"vmeTsi148 IRQ manager: looking for registers on VME...\n");
1713 
1714     if ( ( i = ((TSI_RD( THEBASE, TSI_CBAR_REG ) & 0xff) >> 3) ) > 0 ) {
1715         uprintf(stderr,"Trying to find CSR on VME...\n");
1716         vme_reg_base = i*0x80000 + TSI_CSR_OFFSET;
1717         i = mappedAndProbed( vme_reg_base, VME_AM_CSR , &cpu_base);
1718         if ( i >= 0 )
1719             vmeTsi148RegCSR = 1;
1720     } else {
1721         i = -1;
1722     }
1723 
1724     if ( -1 == i ) {
1725 
1726         uprintf(stderr,"Trying to find CRG on VME...\n");
1727 
1728         /* Next we see if the CRG block is mapped to VME */
1729 
1730         if ( (TSI_CRGAT_EN & (j = TSI_RD( THEBASE, TSI_CRGAT_REG ))) ) {
1731             switch ( j & TSI_CRGAT_AS_MSK ) {
1732                 case TSI_CRGAT_A16 : i = VME_AM_SUP_SHORT_IO; break;
1733                 case TSI_CRGAT_A24 : i = VME_AM_STD_SUP_DATA; break;
1734                 case TSI_CRGAT_A32 : i = VME_AM_EXT_SUP_DATA; break;
1735                 default:
1736                 break;
1737             }
1738             vme_reg_base = TSI_RD( THEBASE, TSI_CBAL_REG ) & ~ (TSI_CRG_SIZE - 1);
1739         }
1740 
1741         if ( -1 == i ) {
1742         } else {
1743             i = mappedAndProbed( vme_reg_base, (i & VME_AM_MASK), &cpu_base );
1744         }
1745     }
1746 
1747     if ( i < 0 ) {
1748             uprintf(stderr,"vmeTsi148 IRQ manager - BSP configuration error: registers not found on VME\n");
1749             uprintf(stderr,"(should open outbound window to CSR space or map CRG [vmeTsi148MapCRG()])\n");
1750             uprintf(stderr,"Falling back to PCI but you might experience spurious VME interrupts; read a register\n");
1751             uprintf(stderr,"back from user ISR to flush posted-write FIFO as a work-around\n");
1752             cpu_base = (unsigned long)THEBASE;
1753             i        = -1;
1754     }
1755 
1756     vmeTsi148RegBase = (BERegister*)cpu_base;
1757     vmeTsi148RegPort = i;
1758 
1759     /* give them a chance to override buggy PCI info */
1760     if ( pic_pin[0] >= 0 && devs[0].irqLine != pic_pin[0] ) {
1761         uprintf(stderr,"Overriding main IRQ line PCI info with %d\n",
1762                 pic_pin[0]);
1763         devs[0].irqLine = pic_pin[0];
1764     }
1765 
1766     for ( i = 0; tsi_pin[i] >= 0; i++ ) {
1767         /* offset wire # by one so we can initialize to 0 == invalid */
1768         tsi_wire[i] = tsi_pin[i] + 1;
1769         connectIsr(shared, tsiVMEISR, pic_pin[i], i);
1770     }
1771 
1772     specialPin = tsi_pin[1] >= 0 ? 1 : 0;
1773 
1774     /* setup routing */
1775 
1776     /* IntRoute checks for mgr being installed */
1777     vmeTsi148IrqMgrInstalled=1;
1778 
1779     /* route 7 VME irqs to first / 'normal' pin */
1780     for ( i=1; i<8; i++ )
1781         vmeTsi148IntRoute( i, 0 );
1782     for ( i=TSI_DMA_INT_VEC; i<TSI_NUM_INT_VECS; i++ )
1783         vmeTsi148IntRoute( i, specialPin );
1784 
1785     for ( i = 0; i<TSI_NUM_WIRES; i++ ) {
1786         /* remember (for unloading the driver) */
1787         devs[0].pic_pin[i] = ( ( tsi_pin[i] >=0 ) ? pic_pin[i] : -1 );
1788     }
1789 
1790     return 0;
1791 }
1792 
1793 int
1794 vmeTsi148InstallISR(unsigned long vector, VmeTsi148ISR hdl, void *arg)
1795 {
1796 IRQEntry          ip;
1797 int               v;
1798 volatile IRQEntry *p;
1799 rtems_interrupt_lock_context lock_context;
1800 
1801         if ( !vmeTsi148IrqMgrInstalled || (v = uni2tsivec(vector)) < 0 )
1802             return -1;
1803 
1804         p = irqHdlTbl + v;
1805 
1806         if (*p || !(ip=(IRQEntry)malloc(sizeof(IRQEntryRec))))
1807                 return -1;
1808 
1809         ip->isr=hdl;
1810         ip->usrData=arg;
1811 
1812         rtems_interrupt_lock_acquire( &vmeTsi148_lock, &lock_context );
1813         if (*p) {
1814             rtems_interrupt_lock_release( &vmeTsi148_lock, &lock_context );
1815             free(ip);
1816             return -1;
1817         }
1818         *p = ip;
1819         rtems_interrupt_lock_release( &vmeTsi148_lock, &lock_context );
1820         return 0;
1821 }
1822 
1823 int
1824 vmeTsi148RemoveISR(unsigned long vector, VmeTsi148ISR hdl, void *arg)
1825 {
1826 int               v;
1827 IRQEntry          ip;
1828 volatile IRQEntry *p;
1829 rtems_interrupt_lock_context lock_context;
1830 
1831         if ( !vmeTsi148IrqMgrInstalled || (v = uni2tsivec(vector)) < 0 )
1832             return -1;
1833 
1834         p = irqHdlTbl + v;
1835 
1836         rtems_interrupt_lock_acquire( &vmeTsi148_lock, &lock_context );
1837         ip = *p;
1838         if ( !ip || ip->isr!=hdl || ip->usrData!=arg ) {
1839                 rtems_interrupt_lock_release( &vmeTsi148_lock, &lock_context );
1840                 return -1;
1841         }
1842         *p = 0;
1843         rtems_interrupt_lock_release( &vmeTsi148_lock, &lock_context );
1844 
1845         free(ip);
1846         return 0;
1847 }
1848 
1849 static int
1850 intDoEnDis(unsigned int level, int dis)
1851 {
1852 BERegister      *b = THEBASE;
1853 unsigned long        v;
1854 int             shift;
1855 rtems_interrupt_lock_context lock_context;
1856 
1857     if (  ! vmeTsi148IrqMgrInstalled || (shift = lvl2bitno(level)) < 0 )
1858         return -1;
1859 
1860     v = 1<<shift;
1861 
1862     if ( !dis )
1863         return (int)(v & TSI_RD(b, TSI_INTEO_REG) & TSI_RD(b, TSI_INTEN_REG)) ? 1 : 0;
1864 
1865     rtems_interrupt_lock_acquire( &vmeTsi148_lock, &lock_context );
1866     if ( dis<0 ) {
1867         TSI_WR(b, TSI_INTEN_REG, TSI_RD(b, TSI_INTEN_REG) & ~v);
1868         TSI_WR(b, TSI_INTEO_REG, TSI_RD(b, TSI_INTEO_REG) & ~v);
1869     } else {
1870         TSI_WR(b, TSI_INTEN_REG, TSI_RD(b, TSI_INTEN_REG) |  v);
1871         TSI_WR(b, TSI_INTEO_REG, TSI_RD(b, TSI_INTEO_REG) |  v);
1872     }
1873     rtems_interrupt_lock_release( &vmeTsi148_lock, &lock_context );
1874     return 0;
1875 }
1876 
1877 int
1878 vmeTsi148IntEnable(unsigned int level)
1879 {
1880     return intDoEnDis(level, 1);
1881 }
1882 
1883 int
1884 vmeTsi148IntDisable(unsigned int level)
1885 {
1886     return intDoEnDis(level, -1);
1887 }
1888 
1889 int
1890 vmeTsi148IntIsEnabled(unsigned int level)
1891 {
1892     return intDoEnDis(level, 0);
1893 }
1894 
1895 /* Set IACK width (1,2, or 4 bytes) for a given interrupt level.
1896  *
1897  * 'width' arg may be 0,1,2 or 4. If zero, the currently active
1898  * value is returned but not modified.
1899  *
1900  * RETURNS: old width or -1 if invalid argument.
1901  */
1902 
1903 int
1904 vmeTsi148SetIackWidth(int level, int width)
1905 {
1906 int rval;
1907     if ( level < 1 || level > 7 || !vmeTsi148IrqMgrInstalled )
1908         return -1;
1909 
1910     switch ( width ) {
1911         default: return -1;
1912         case 0:
1913         case 1:
1914         case 2:
1915         case 4:
1916         break;
1917     }
1918 
1919     rval = tsi_iack_width[level-1];
1920     if ( width )
1921         tsi_iack_width[level-1] = width;
1922     return rval;
1923 }
1924 
1925 int
1926 vmeTsi148IntRaiseXX(BERegister *base, int level, unsigned vector)
1927 {
1928 unsigned long v;
1929 
1930     CHECK_BASE(base,0,-1);
1931 
1932     if ( level < 1 || level > 7 || vector > 255 )
1933         return -1;  /* invalid argument */
1934 
1935     /* Check if already asserted */
1936     if ( (v = TSI_RD(base, TSI_VICR_REG)) & TSI_VICR_IRQS ) {
1937         return -2;  /* already asserted */
1938     }
1939 
1940     v &= ~255;
1941 
1942     v |= TSI_VICR_IRQL(level) | TSI_VICR_STID(vector);
1943 
1944     /* Write Vector */
1945     TSI_WR(base, TSI_VICR_REG, v);
1946 
1947     return 0;
1948 
1949 }
1950 
1951 int
1952 vmeTsi148IntRaise(int level, unsigned vector)
1953 {
1954     return vmeTsi148IntRaiseXX(THEBASE, level, vector);
1955 }
1956 
1957 /* Loopback test of VME/Tsi148 internal interrupts */
1958 
1959 typedef struct {
1960     rtems_id    q;
1961     int         l;
1962 } LoopbackTstArgs;
1963 
1964 static void
1965 loopbackTstIsr(void *arg, unsigned long vector)
1966 {
1967 LoopbackTstArgs *pa = arg;
1968     if ( RTEMS_SUCCESSFUL != rtems_message_queue_send(pa->q, (void*)&vector, sizeof(vector)) ) {
1969         /* Overrun ? */
1970         printk("vmeTsi148IntLoopbackTst: (ISR) message queue full / overrun ? disabling IRQ level %i\n", pa->l);
1971         vmeTsi148IntDisable(pa->l);
1972     }
1973 }
1974 
1975 int
1976 vmeTsi148IntLoopbackTst(int level, unsigned vector)
1977 {
1978 BERegister          *b = THEBASE;
1979 rtems_status_code   sc;
1980 rtems_id            q = 0;
1981 int                 installed = 0;
1982 int                 i, err = 0;
1983 int                 doDisable = 0;
1984 size_t              size;
1985 unsigned long       msg;
1986 char *              irqfmt  = "VME IRQ @vector %3i %s";
1987 char *              iackfmt = "VME IACK            %s";
1988 LoopbackTstArgs     a;
1989 
1990     CHECK_BASE(b,0,-1);
1991 
1992     /* arg check */
1993     if ( level < 1 || level > 7 || vector > 255 )
1994         return -1;
1995 
1996     /* Create message queue */
1997     if ( RTEMS_SUCCESSFUL != (sc=rtems_message_queue_create(
1998                                         rtems_build_name('t' ,'U','I','I'),
1999                                         4,
2000                                         sizeof(unsigned long),
2001                                         0,  /* default attributes: fifo, local */
2002                                         &q)) ) {
2003         rtems_error(sc, "vmeTsi148IntLoopbackTst: Unable to create message queue");
2004         goto bail;
2005     }
2006 
2007     a.q = q;
2008     a.l = level;
2009 
2010     /* Install handlers */
2011     if ( vmeTsi148InstallISR(vector, loopbackTstIsr, (void*)&a) ) {
2012         uprintf(stderr,"Unable to install VME ISR to vector %i\n",vector);
2013         goto bail;
2014     }
2015     installed++;
2016     if ( vmeTsi148InstallISR(TSI_VME_SW_IACK_INT_VEC, loopbackTstIsr, (void*)&a) ) {
2017         uprintf(stderr,"Unable to install VME ISR to IACK special vector %i\n",TSI_VME_SW_IACK_INT_VEC);
2018         goto bail;
2019     }
2020     installed++;
2021 
2022     if ( !vmeTsi148IntIsEnabled(level) && 0==vmeTsi148IntEnable(level) )
2023         doDisable = 1;
2024 
2025     /* make sure there are no pending interrupts */
2026     TSI_WR(b, TSI_INTC_REG, TSI_INTC_IACKC);
2027 
2028     if ( vmeTsi148IntEnable( TSI_VME_SW_IACK_INT_VEC ) ) {
2029         uprintf(stderr,"Unable to enable IACK interrupt\n");
2030         goto bail;
2031     }
2032 
2033     printf("vmeTsi148 VME interrupt loopback test; STARTING...\n");
2034     printf(" --> asserting VME IRQ level %i\n", level);
2035     vmeTsi148IntRaise(level, vector);
2036 
2037     for ( i = 0; i< 3; i++ ) {
2038         sc = rtems_message_queue_receive(
2039                     q,
2040                     &msg,
2041                     &size,
2042                     RTEMS_WAIT,
2043                     20);
2044         if ( sc ) {
2045             if ( RTEMS_TIMEOUT == sc && i>1 ) {
2046                 /* OK; we dont' expect more to happen */
2047                 sc = 0;
2048             } else {
2049                 rtems_error(sc,"Error waiting for interrupts");
2050             }
2051             break;
2052         }
2053         if ( msg == vector ) {
2054             if ( !irqfmt ) {
2055                 printf("Excess VME IRQ received ?? -- BAD\n");
2056                 err = 1;
2057             } else {
2058                 printf(irqfmt, vector, "received -- PASSED\n");
2059                 irqfmt = 0;
2060             }
2061         } else if ( msg == TSI_VME_SW_IACK_INT_VEC ) {
2062             if ( !iackfmt ) {
2063                 printf("Excess VME IACK received ?? -- BAD\n");
2064                 err = 1;
2065             } else {
2066                 printf(iackfmt, "received -- PASSED\n");
2067                 iackfmt = 0;
2068             }
2069         } else {
2070             printf("Unknown IRQ (vector %lu) received -- BAD\n", msg);
2071             err = 1;
2072         }
2073     }
2074 
2075 
2076     /* Missing anything ? */
2077     if ( irqfmt ) {
2078         printf(irqfmt,vector, "MISSED -- BAD\n");
2079         err = 1;
2080     }
2081     if ( iackfmt ) {
2082         printf(iackfmt, "MISSED -- BAD\n");
2083         err = 1;
2084     }
2085 
2086     printf("FINISHED.\n");
2087 
2088 bail:
2089     if ( doDisable )
2090         vmeTsi148IntDisable(level);
2091     vmeTsi148IntDisable( TSI_VME_SW_IACK_INT_VEC );
2092     if ( installed > 0 )
2093         vmeTsi148RemoveISR(vector, loopbackTstIsr, (void*)&a);
2094     if ( installed > 1 )
2095         vmeTsi148RemoveISR(TSI_VME_SW_IACK_INT_VEC, loopbackTstIsr, (void*)&a);
2096     if ( q )
2097         rtems_message_queue_delete(q);
2098 
2099     return sc ? sc : err;
2100 }
2101 
2102 unsigned long
2103 vmeTsi148ClearVMEBusErrorsXX(BERegister *base, uint32_t *paddr)
2104 {
2105 unsigned long rval;
2106 
2107     CHECK_BASE(base,1,-1);
2108 
2109     rval = TSI_RD(base, TSI_VEAT_REG);
2110     if ( rval & TSI_VEAT_VES ) {
2111         if ( paddr ) {
2112 #if 0 /* no 64-bit support yet */
2113             *paddr  = ((unsigned long long)TSI_RD(base, TSI_VEAU_REG))<<32;
2114             *paddr |= TSI_RD(base, TSI_VEAL_REG);
2115 #else
2116             *paddr = TSI_RD(base, TSI_VEAL_REG);
2117 #endif
2118         }
2119         /* clear errors */
2120         TSI_WR(base, TSI_VEAT_REG, TSI_VEAT_VESCL);
2121     } else {
2122         rval = 0;
2123     }
2124     return rval;
2125 }
2126 
2127 unsigned long
2128 vmeTsi148ClearVMEBusErrors(uint32_t *paddr)
2129 {
2130     return vmeTsi148ClearVMEBusErrorsXX(THEBASE, paddr);
2131 }
2132 
2133 /** DMA Support **/
2134 
2135 /* descriptor must be 8-byte aligned */
2136 typedef struct VmeTsi148DmaListDescriptorRec_ {
2137     BEValue                     dsau,  dsal;
2138     BEValue                     ddau,  ddal;
2139     BEValue                     dsat,  ddat;
2140     BEValue                     dnlau, dnlal;
2141     BEValue                     dcnt,  ddbs;
2142 } VmeTsi148DmaListDescriptorRec;
2143 
2144 static void     tsi_desc_init  (DmaDescriptor);
2145 static int      tsi_desc_setup (DmaDescriptor, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
2146 static void     tsi_desc_setnxt(DmaDescriptor, DmaDescriptor);
2147 static void     tsi_desc_dump  (DmaDescriptor);
2148 static int      tsi_desc_start (volatile void *controller_addr, int channel, DmaDescriptor p);
2149 
2150 VMEDmaListClassRec  vmeTsi148DmaListClass = {
2151     desc_size:  sizeof(VmeTsi148DmaListDescriptorRec),
2152     desc_align: 8,
2153     freeList:   0,
2154     desc_alloc: 0,
2155     desc_free:  0,
2156     desc_init:  tsi_desc_init,
2157     desc_setnxt:tsi_desc_setnxt,
2158     desc_setup: tsi_desc_setup,
2159     desc_start: tsi_desc_start,
2160     desc_refr:  0,
2161     desc_dump:  tsi_desc_dump,
2162 };
2163 
2164 /* DMA Control */
2165 #define TSI_DMA_REG(off,i)  ((off)+(((i)&1)<<7))
2166 
2167 #define TSI_DCTL_REG(i)     TSI_DMA_REG(0x500,i)
2168 #define TSI_DCTL0_REG       0x500
2169 #define TSI_DCTL1_REG       0x580
2170 #   define TSI_DCTL_ABT     (1<<27) /* abort */
2171 #   define TSI_DCTL_PAU     (1<<26) /* pause */
2172 #   define TSI_DCTL_DGO     (1<<25) /* GO    */
2173 #   define TSI_DCTL_MOD     (1<<23) /* linked list: 0, direct: 1 */
2174 #   define TSI_DCTL_VFAR    (1<<17) /* flush FIFO on VME error: 1 (discard: 0) */
2175 #   define TSI_DCTL_PFAR    (1<<16) /* flush FIFO on PCI error: 1 (discard: 0) */
2176 
2177 #   define TSI_DCTL_VBKS(i) (((i)&7)<<12) /* VME block size */
2178 #   define TSI_DCTL_VBKS_32 TSI_DCTL_VBKS(0)
2179 #   define TSI_DCTL_VBKS_64 TSI_DCTL_VBKS(1)
2180 #   define TSI_DCTL_VBKS_128    TSI_DCTL_VBKS(2)
2181 #   define TSI_DCTL_VBKS_256    TSI_DCTL_VBKS(3)
2182 #   define TSI_DCTL_VBKS_512    TSI_DCTL_VBKS(4)
2183 #   define TSI_DCTL_VBKS_1024   TSI_DCTL_VBKS(5)
2184 #   define TSI_DCTL_VBKS_2048   TSI_DCTL_VBKS(6)
2185 #   define TSI_DCTL_VBKS_4096   TSI_DCTL_VBKS(7)
2186 
2187 #   define TSI_DCTL_VBOT(i) (((i)&7)<< 8) /* VME back-off time */
2188 #   define TSI_DCTL_VBOT_0us    TSI_DCTL_VBOT(0)
2189 #   define TSI_DCTL_VBOT_1us    TSI_DCTL_VBOT(1)
2190 #   define TSI_DCTL_VBOT_2us    TSI_DCTL_VBOT(2)
2191 #   define TSI_DCTL_VBOT_4us    TSI_DCTL_VBOT(3)
2192 #   define TSI_DCTL_VBOT_8us    TSI_DCTL_VBOT(4)
2193 #   define TSI_DCTL_VBOT_16us   TSI_DCTL_VBOT(5)
2194 #   define TSI_DCTL_VBOT_32us   TSI_DCTL_VBOT(6)
2195 #   define TSI_DCTL_VBOT_64us   TSI_DCTL_VBOT(7)
2196 
2197 #   define TSI_DCTL_PBKS(i) (((i)&7)<< 4) /* PCI block size */
2198 #   define TSI_DCTL_PBKS_32 TSI_DCTL_PBKS(0)
2199 #   define TSI_DCTL_PBKS_64 TSI_DCTL_PBKS(1)
2200 #   define TSI_DCTL_PBKS_128    TSI_DCTL_PBKS(2)
2201 #   define TSI_DCTL_PBKS_256    TSI_DCTL_PBKS(3)
2202 #   define TSI_DCTL_PBKS_512    TSI_DCTL_PBKS(4)
2203 #   define TSI_DCTL_PBKS_1024   TSI_DCTL_PBKS(5)
2204 #   define TSI_DCTL_PBKS_2048   TSI_DCTL_PBKS(6)
2205 #   define TSI_DCTL_PBKS_4096   TSI_DCTL_PBKS(7)
2206 
2207 #   define TSI_DCTL_PBOT(i) (((i)&7)<< 0) /* PCI back-off time */
2208 #   define TSI_DCTL_PBOT_0us    TSI_DCTL_PBOT(0)
2209 #   define TSI_DCTL_PBOT_1us    TSI_DCTL_PBOT(1)
2210 #   define TSI_DCTL_PBOT_2us    TSI_DCTL_PBOT(2)
2211 #   define TSI_DCTL_PBOT_4us    TSI_DCTL_PBOT(3)
2212 #   define TSI_DCTL_PBOT_8us    TSI_DCTL_PBOT(4)
2213 #   define TSI_DCTL_PBOT_16us   TSI_DCTL_PBOT(5)
2214 #   define TSI_DCTL_PBOT_32us   TSI_DCTL_PBOT(6)
2215 #   define TSI_DCTL_PBOT_64us   TSI_DCTL_PBOT(7)
2216 
2217 /* DMA Status */
2218 #define TSI_DSTA_REG(i)     TSI_DMA_REG(0x504,i)
2219 #define TSI_DSTA0_REG       0x504
2220 #define TSI_DSTA1_REG       0x584
2221 #   define TSI_DSTA_ERR     (1<<28)
2222 #   define TSI_DSTA_ABT     (1<<27)
2223 #   define TSI_DSTA_PAU     (1<<26)
2224 #   define TSI_DSTA_DON     (1<<25)
2225 #   define TSI_DSTA_BSY     (1<<24)
2226 #   define TSI_DSTA_ERRS    (1<<20) /* Error source; PCI:1, VME:0 */
2227 #   define TSI_DSTA_ERT_MSK (3<<16) /* Error type                 */
2228 #   define TSI_DSTA_ERT_BERR_E  (0<<16) /* 2eVME even or other bus error */
2229 #   define TSI_DSTA_ERT_BERR_O  (1<<16) /* 2eVME odd bus error        */
2230 #   define TSI_DSTA_ERT_SLVE_E  (2<<16) /* 2eVME even or other slave termination */
2231 #   define TSI_DSTA_ERT_SLVE_O  (3<<16) /* 2eVME odd slave termination; 2eSST read last word invalid */
2232 
2233 /* DMA Current source address upper */
2234 #define TSI_DCSAU_REG(i)    TSI_DMA_REG(0x508,i)
2235 #define TSI_DCSAU0_REG      0x508
2236 #define TSI_DCSAU1_REG      0x588
2237 
2238 /* DMA Current source address lower */
2239 #define TSI_DCSAL_REG(i)    TSI_DMA_REG(0x50c,i)
2240 #define TSI_DCSAL0_REG      0x50c
2241 #define TSI_DCSAL1_REG      0x58c
2242 
2243 /* DMA Current destination address upper */
2244 #define TSI_DCDAU_REG(i)    TSI_DMA_REG(0x510,i)
2245 #define TSI_DCDAU0_REG      0x510
2246 #define TSI_DCDAU1_REG      0x590
2247 
2248 /* DMA Current destination address lower */
2249 #define TSI_DCDAL_REG(i)    TSI_DMA_REG(0x514,i)
2250 #define TSI_DCDAL0_REG      0x514
2251 #define TSI_DCDAL1_REG      0x594
2252 
2253 /* DMA Current link address upper */
2254 #define TSI_DCLAU_REG(i)    TSI_DMA_REG(0x518,i)
2255 #define TSI_DCLAU0_REG      0x518
2256 #define TSI_DCLAU1_REG      0x598
2257 
2258 /* DMA Current link address lower */
2259 #define TSI_DCLAL_REG(i)    TSI_DMA_REG(0x51c,i)
2260 #define TSI_DCLAL0_REG      0x51c
2261 #define TSI_DCLAL1_REG      0x59c
2262 
2263 /* DMA Source address upper */
2264 #define TSI_DSAU_REG(i)     TSI_DMA_REG(0x520,i)
2265 #define TSI_DSAU0_REG       0x520
2266 #define TSI_DSAU1_REG       0x5a0
2267 
2268 /* DMA Source address lower */
2269 #define TSI_DSAL_REG(i)     TSI_DMA_REG(0x524,i)
2270 #define TSI_DSAL0_REG       0x524
2271 #define TSI_DSAL1_REG       0x5a4
2272 
2273 /* DMA Destination address upper */
2274 #define TSI_DDAU_REG(i)     TSI_DMA_REG(0x528,i)
2275 #define TSI_DDAU0_REG       0x528
2276 #define TSI_DDAU1_REG       0x5a8
2277 
2278 /* DMA Destination address lower */
2279 #define TSI_DDAL_REG(i)     TSI_DMA_REG(0x52c,i)
2280 #define TSI_DDAL0_REG       0x52c
2281 #define TSI_DDAL1_REG       0x5ac
2282 
2283 /* DMA Source Attribute */
2284 #define TSI_DSAT_REG(i)     TSI_DMA_REG(0x530,i)
2285 #define TSI_DSAT0_REG       0x530
2286 #define TSI_DSAT1_REG       0x5b0
2287 
2288 /* DMA Destination Attribute */
2289 #define TSI_DDAT_REG(i)     TSI_DMA_REG(0x534,i)
2290 #define TSI_DDAT0_REG       0x534
2291 #define TSI_DDAT1_REG       0x5b4
2292 
2293 #   define TSI_DXAT_TYP(i)  (((i)&3)<<28)   /* Xfer type */
2294 #   define TSI_DXAT_TYP_PCI TSI_DXAT_TYP(0)
2295 #   define TSI_DXAT_TYP_VME TSI_DXAT_TYP(1)
2296 #   define TSI_DSAT_TYP_PAT TSI_DXAT_TYP(2) /* pattern */
2297 
2298 #   define TSI_DSAT_PSZ     (1<<25) /* pattern size 32-bit: 0, 8-bit: 1 */
2299 #   define TSI_DSAT_NIN     (1<<24) /* no-increment */
2300 
2301 #   define TSI_DXAT_OTAT_MSK    ((1<<13)-1) /* get bits compatible with OTAT */
2302 
2303 #   define TSI_DXAT_SSTM(i) (((i)&3)<<11)   /* 2eSST Xfer rate (MB/s) */
2304 #   define TSI_DXAT_SSTM_116    TSI_DXAT_SSTM(0)
2305 #   define TSI_DXAT_SSTM_267    TSI_DXAT_SSTM(1)
2306 #   define TSI_DXAT_SSTM_320    TSI_DXAT_SSTM(2)
2307 
2308 #   define TSI_DXAT_TM(i)   (((i)&7)<< 8) /* VME Xfer mode */
2309 #   define TSI_DXAT_TM_SCT  TSI_DXAT_TM(0)
2310 #   define TSI_DXAT_TM_BLT  TSI_DXAT_TM(1)
2311 #   define TSI_DXAT_TM_MBLT TSI_DXAT_TM(2)
2312 #   define TSI_DXAT_TM_2eVME    TSI_DXAT_TM(3)
2313 #   define TSI_DXAT_TM_2eSST    TSI_DXAT_TM(4)
2314 #   define TSI_DSAT_TM_2eSST_B  TSI_DXAT_TM(5)  /* 2eSST broadcast */
2315 
2316 #   define TSI_DXAT_DBW(i)  (((i)&3)<< 6)   /* VME Data width */
2317 #   define TSI_DXAT_DBW_16  TSI_DXAT_DBW(0)
2318 #   define TSI_DXAT_DBW_32  TSI_DXAT_DBW(1)
2319 
2320 #   define TSI_DXAT_SUP     (1<<5)  /* supervisor access */
2321 #   define TSI_DXAT_PGM     (1<<4)  /* program access    */
2322 
2323 #   define TSI_DXAT_AM(i)   (((i)&15)<<0)   /* VME Address mode */
2324 #   define TSI_DXAT_AM_A16  TSI_DXAT_AM(0)
2325 #   define TSI_DXAT_AM_A24  TSI_DXAT_AM(1)
2326 #   define TSI_DXAT_AM_A32  TSI_DXAT_AM(2)
2327 #   define TSI_DXAT_AM_A64  TSI_DXAT_AM(4)
2328 #   define TSI_DXAT_AM_CSR  TSI_DXAT_AM(5)
2329 
2330 /* DMA Next link address upper */
2331 #define TSI_DNLAU_REG(i)    TSI_DMA_REG(0x538,i)
2332 #define TSI_DNLAU0_REG      0x538
2333 #define TSI_DNLAU1_REG      0x5b8
2334 
2335 /* DMA Next link address lower */
2336 #define TSI_DNLAL_REG(i)    TSI_DMA_REG(0x53c,i)
2337 #define TSI_DNLAL0_REG      0x53c
2338 #define TSI_DNLAL1_REG      0x5bc
2339 
2340 #   define TSI_DNLAL_LLA    1   /* last element in chain */
2341 
2342 /* DMA Byte Count */
2343 #define TSI_DCNT_REG(i)     TSI_DMA_REG(0x540,i)
2344 #define TSI_DCNT0_REG       0x540
2345 #define TSI_DCNT1_REG       0x54c
2346 
2347 /* DMA 2eSST destination broadcast select */
2348 #define TSI_DDBS_REG(i)     TSI_DMA_REG(0x544,i)
2349 #define TSI_DDBS0_REG       0x544
2350 #define TSI_DDBS1_REG       0x5c4
2351 
2352 /* Convert canonical xfer_mode into Tsi148 bits; return -1 if invalid */
2353 static uint32_t
2354 vme_attr(uint32_t xfer_mode)
2355 {
2356 uint32_t vme_mode;
2357 unsigned long ul;
2358     if ( am2omode(xfer_mode, &ul) )
2359         return BSP_VMEDMA_STATUS_UNSUP;
2360     vme_mode = (uint32_t) ul;
2361 
2362     /* am2omode may set prefetch and other bits */
2363     vme_mode &= TSI_DXAT_OTAT_MSK;
2364     vme_mode |= TSI_DXAT_TYP_VME;
2365 
2366     if ( BSP_VMEDMA_MODE_NOINC_VME & xfer_mode )  {
2367         /* no-incr. only supported on source address */
2368         if ( (BSP_VMEDMA_MODE_PCI2VME & xfer_mode) )
2369             return BSP_VMEDMA_STATUS_UNSUP;
2370         vme_mode |= TSI_DSAT_NIN;
2371     }
2372 
2373     return vme_mode;
2374 }
2375 
2376 static uint32_t
2377 pci_attr(uint32_t xfer_mode)
2378 {
2379 uint32_t pci_mode = 0;
2380     if ( BSP_VMEDMA_MODE_NOINC_PCI & xfer_mode )  {
2381         /* no-incr. only supported on source address */
2382         if ( ! (BSP_VMEDMA_MODE_PCI2VME & xfer_mode) )
2383             return BSP_VMEDMA_STATUS_UNSUP;
2384         pci_mode |= TSI_DSAT_NIN;
2385     }
2386     return pci_mode;
2387 }
2388 
2389 static void tsi_desc_init(DmaDescriptor p)
2390 {
2391 VmeTsi148DmaListDescriptor d = p;
2392     st_be32( &d->dnlau, 0 );
2393     st_be32( &d->dnlal, TSI_DNLAL_LLA );
2394     st_be32( &d->ddbs, (1<<22)-1 ); /* SSTB broadcast not yet fully supported */
2395 }
2396 
2397 static void
2398 tsi_desc_setnxt(DmaDescriptor p, DmaDescriptor n)
2399 {
2400 VmeTsi148DmaListDescriptor d = p;
2401     if ( 0 == n ) {
2402         st_be32( &d->dnlal, TSI_DNLAL_LLA );
2403     } else {
2404         st_be32( &d->dnlal, BSP_LOCAL2PCI_ADDR((uint32_t)n) );
2405     }
2406 }
2407 
2408 static void
2409 tsi_desc_dump(DmaDescriptor p)
2410 {
2411 VmeTsi148DmaListDescriptor d = p;
2412         printf("   DSA: 0x%08" PRIx32 "%08" PRIx32 "\n", ld_be32(&d->dsau),  ld_be32(&d->dsal));
2413         printf("   DDA: 0x%08" PRIx32 "%08" PRIx32 "\n", ld_be32(&d->ddau),  ld_be32(&d->ddal));
2414         printf("   NLA: 0x%08" PRIx32 "%08" PRIx32 "\n", ld_be32(&d->dnlau), ld_be32(&d->dnlal));
2415         printf("   SAT: 0x%08" PRIx32 "              DAT: 0x%08" PRIx32 "\n", ld_be32(&d->dsat), ld_be32(&d->ddat));
2416         printf("   CNT: 0x%08" PRIx32 "\n",      ld_be32(&d->dcnt));
2417 }
2418 
2419 
2420 int
2421 vmeTsi148DmaSetupXX(BERegister *base, int channel, uint32_t mode, uint32_t xfer_mode, void *custom)
2422 {
2423 uint32_t ctl = 0;
2424 uint32_t vmeatt, pciatt, sat, dat;
2425 
2426     if ( channel < 0 || channel > 1 )
2427         return BSP_VMEDMA_STATUS_UNSUP;
2428 
2429     /* Check bus mode */
2430     if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == (vmeatt = vme_attr(xfer_mode)) )
2431         return -2;
2432 
2433     /* Check PCI bus mode */
2434     if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == (pciatt = pci_attr(xfer_mode)) )
2435         return -3;
2436 
2437     /* Compute control word; bottleneck is VME; */
2438     ctl |= TSI_DCTL_PBKS_32;
2439     ctl |= (BSP_VMEDMA_OPT_THROUGHPUT == mode ? TSI_DCTL_PBOT_0us : TSI_DCTL_PBOT_1us);
2440 
2441     switch ( mode ) {
2442         case BSP_VMEDMA_OPT_THROUGHPUT:
2443             ctl |= TSI_DCTL_VBKS_1024;
2444             ctl |= TSI_DCTL_VBOT_0us;
2445         break;
2446 
2447         case BSP_VMEDMA_OPT_LOWLATENCY:
2448             ctl |= TSI_DCTL_VBKS_32;
2449             ctl |= TSI_DCTL_VBOT_0us;
2450         break;
2451 
2452         case BSP_VMEDMA_OPT_SHAREDBUS:
2453             ctl |= TSI_DCTL_VBKS_128;
2454             ctl |= TSI_DCTL_VBOT_64us;
2455         break;
2456 
2457         case BSP_VMEDMA_OPT_CUSTOM:
2458             ctl = *(uint32_t*)custom;
2459         break;
2460 
2461         default:
2462         case BSP_VMEDMA_OPT_DEFAULT:
2463             ctl = 0;
2464         break;
2465     }
2466     TSI_WR(base, TSI_DCTL_REG(channel), ctl);
2467     if ( BSP_VMEDMA_MODE_PCI2VME & xfer_mode ) {
2468         dat = vmeatt; sat = pciatt;
2469     } else {
2470         sat = vmeatt; dat = pciatt;
2471     }
2472     TSI_WR(base, TSI_DSAT_REG(channel), sat);
2473     TSI_WR(base, TSI_DDAT_REG(channel), dat);
2474     return 0;
2475 }
2476 
2477 int
2478 vmeTsi148DmaSetup(int channel, uint32_t mode, uint32_t xfer_mode, void *custom)
2479 {
2480 BERegister *base = THEBASE;
2481     return vmeTsi148DmaSetupXX(base, channel, mode, xfer_mode, custom);
2482 }
2483 
2484 
2485 int
2486 vmeTsi148DmaListStartXX(BERegister *base, int channel, VmeTsi148DmaListDescriptor d)
2487 {
2488 uint32_t ctl;
2489 
2490     if ( d ) {
2491         /* Set list pointer and start */
2492         if ( channel < 0 || channel > 1 )
2493             return BSP_VMEDMA_STATUS_UNSUP;
2494 
2495         if ( TSI_DSTA_BSY & TSI_RD(base, TSI_DSTA_REG(channel)) )
2496             return BSP_VMEDMA_STATUS_BUSY;  /* channel busy */
2497 
2498         TSI_WR(base, TSI_DNLAL_REG(channel), (uint32_t)BSP_LOCAL2PCI_ADDR(d));
2499 
2500         asm volatile("":::"memory");
2501 
2502         /* Start transfer */
2503         ctl  = TSI_RD(base, TSI_DCTL_REG(channel)) | TSI_DCTL_DGO;
2504         ctl &= ~TSI_DCTL_MOD;
2505         TSI_WR(base, TSI_DCTL_REG(channel), ctl);
2506     }
2507     /* else: list vs. direct mode is set by the respective start commands */
2508     return 0;
2509 }
2510 
2511 int
2512 vmeTsi148DmaListStart(int channel, VmeTsi148DmaListDescriptor d)
2513 {
2514 BERegister *base = THEBASE;
2515     return vmeTsi148DmaListStartXX(base, channel, d);
2516 }
2517 
2518 int
2519 vmeTsi148DmaStartXX(BERegister *base, int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes)
2520 {
2521 uint32_t src, dst, ctl;
2522 
2523     if ( channel < 0 || channel > 1 )
2524         return BSP_VMEDMA_STATUS_UNSUP;
2525 
2526     if ( TSI_DSTA_BSY & TSI_RD(base, TSI_DSTA_REG(channel)) )
2527         return BSP_VMEDMA_STATUS_BUSY;  /* channel busy */
2528 
2529     /* retrieve direction from dst attribute */
2530     if ( TSI_DXAT_TYP_VME & TSI_RD(base, TSI_DDAT_REG(channel)) ) {
2531         dst = vme_addr;
2532         src = pci_addr;
2533     } else {
2534         src = vme_addr;
2535         dst = pci_addr;
2536     }
2537     /* FIXME: we leave the 'upper' registers (topmost 32bits) alone.
2538      *        Probably, we should reset them at init...
2539      */
2540     TSI_WR(base, TSI_DSAL_REG(channel), src);
2541     TSI_WR(base, TSI_DDAL_REG(channel), dst);
2542     TSI_WR(base, TSI_DCNT_REG(channel), n_bytes);
2543 
2544     asm volatile("":::"memory");
2545 
2546     /* Start transfer */
2547     ctl  = TSI_RD(base, TSI_DCTL_REG(channel)) | TSI_DCTL_DGO | TSI_DCTL_MOD;
2548     TSI_WR(base, TSI_DCTL_REG(channel), ctl);
2549 
2550     return 0;
2551 }
2552 
2553 int
2554 vmeTsi148DmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes)
2555 {
2556 BERegister *base = THEBASE;
2557     return vmeTsi148DmaStartXX(base, channel, pci_addr, vme_addr, n_bytes);
2558 }
2559 
2560 uint32_t
2561 vmeTsi148DmaStatusXX(BERegister *base, int channel)
2562 {
2563 uint32_t    st = TSI_RD(base, TSI_DSTA_REG(channel));
2564 
2565     if ( channel < 0 || channel > 1 )
2566         return BSP_VMEDMA_STATUS_UNSUP;
2567 
2568     st = TSI_RD(base, TSI_DSTA_REG(channel));
2569 
2570     /* Status can be zero if an empty list (all counts == 0) is executed */
2571     if ( (TSI_DSTA_DON & st) || 0 == st )
2572         return BSP_VMEDMA_STATUS_OK;
2573 
2574     if ( TSI_DSTA_BSY & st )
2575         return BSP_VMEDMA_STATUS_BUSY;  /* channel busy */
2576 
2577     if ( TSI_DSTA_ERR & st ) {
2578         if ( TSI_DSTA_ERRS & st )
2579             return BSP_VMEDMA_STATUS_BERR_PCI;
2580         if ( ! (TSI_DSTA_ERT_SLVE_E & st) )
2581             return BSP_VMEDMA_STATUS_BERR_VME;
2582     }
2583 
2584     return BSP_VMEDMA_STATUS_OERR;
2585 }
2586 
2587 uint32_t
2588 vmeTsi148DmaStatus(int channel)
2589 {
2590 BERegister *base = THEBASE;
2591     return vmeTsi148DmaStatusXX(base, channel);
2592 }
2593 
2594 #define ALL_BITS_NEEDED (BSP_VMEDMA_MSK_ATTR | BSP_VMEDMA_MSK_PCIA | BSP_VMEDMA_MSK_VMEA)
2595 
2596 static int
2597 tsi_desc_setup (
2598         DmaDescriptor p,
2599         uint32_t    attr_mask,
2600         uint32_t    xfer_mode,
2601         uint32_t    pci_addr,
2602         uint32_t    vme_addr,
2603         uint32_t    n_bytes)
2604 {
2605 VmeTsi148DmaListDescriptor  d = p;
2606 uint32_t    vmeatt = 0, pciatt = 0, tmp, src, dst, dat, sat;
2607 
2608     /* argument check */
2609 
2610     /* since we must vme/pci into src/dst we need the direction
2611      * bit. Reject requests that have only part of the mask
2612      * bits set. It would be possible to be more sophisticated
2613      * by caching more information but we try to be simple here...
2614      */
2615     tmp = attr_mask & ALL_BITS_NEEDED;
2616     if ( tmp != 0 && tmp != ALL_BITS_NEEDED )
2617         return -1;
2618 
2619     if ( BSP_VMEDMA_MSK_ATTR & attr_mask ) {
2620         /* Check VME bus mode */
2621         vmeatt = vme_attr(xfer_mode);
2622         if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == vmeatt  )
2623             return -1;
2624 
2625         /* Check PCI bus mode */
2626         pciatt = pci_attr(xfer_mode);
2627         if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == pciatt  )
2628             return -1;
2629     }
2630 
2631     if ( BSP_VMEDMA_MSK_ATTR & attr_mask ) {
2632         if ( BSP_VMEDMA_MODE_PCI2VME & xfer_mode ) {
2633             dat = vmeatt;   sat = pciatt;
2634             dst = vme_addr; src = pci_addr;
2635         } else {
2636             sat = vmeatt;   dat = pciatt;
2637             src = vme_addr; dst = pci_addr;
2638         }
2639         st_be32( &d->dsau, 0 );   st_be32( &d->dsal, src );
2640         st_be32( &d->ddau, 0 );   st_be32( &d->ddal, dst );
2641         st_be32( &d->dsat, sat ); st_be32( &d->ddat, dat );
2642     }
2643 
2644     if ( BSP_VMEDMA_MSK_BCNT & attr_mask )
2645         st_be32( &d->dcnt, n_bytes);
2646 
2647     return 0;
2648 }
2649 
2650 static int
2651 tsi_desc_start (volatile void *controller_addr, int channel, DmaDescriptor p)
2652 {
2653 VmeTsi148DmaListDescriptor d = p;
2654     if ( !controller_addr )
2655         controller_addr = THEBASE;
2656     return vmeTsi148DmaListStartXX((BERegister*)controller_addr, channel, d);
2657 }
2658 
2659 #ifdef DEBUG_MODULAR
2660 void
2661 _cexpModuleInitialize(void* unused)
2662 {
2663     vmeTsi148Init();
2664     vmeTsi148Reset();
2665 }
2666 
2667 int
2668 _cexpModuleFinalize(void *unused)
2669 {
2670 int     i;
2671 int     rval = 1;
2672 void    (*isrs[TSI_NUM_WIRES])() = {
2673     isr_pin0,
2674     isr_pin1,
2675     isr_pin2,
2676     isr_pin3,
2677 };
2678 
2679 rtems_irq_connect_data  xx;
2680     xx.on   = my_no_op; /* at _least_ they could check for a 0 pointer */
2681     xx.off  = my_no_op;
2682     xx.isOn = my_isOn;
2683 
2684     TSI_WR(THEBASE, TSI_INTEO_REG, 0);
2685 
2686     for ( i=0; i<TSI_NUM_INT_VECS; i++) {
2687         /* Dont even bother to uninstall handlers */
2688     }
2689     if ( vmeTsi148IrqMgrInstalled ) {
2690         for ( i=0; i<TSI_NUM_WIRES; i++ ) {
2691             if ( (int)(xx.name = devs[0].pic_pin[i]) >=0 ) {
2692                 xx.hdl  = isrs[i];
2693                 rval    = rval && BSP_remove_rtems_irq_handler(&xx);
2694             }
2695         }
2696     }
2697     return !rval;
2698 }
2699 #endif