source: rtems/bsps/powerpc/shared/vme/vmeTsi148.c @ 814eccb4

5
Last change on this file since 814eccb4 was 814eccb4, checked in by Sebastian Huber <sebastian.huber@…>, on 04/03/18 at 14:41:16

bsps: Move VME support to bsps

The VME support is only used by powerpc BSPs.

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 69.8 KB
Line 
1/* Driver for the Tundra Tsi148 pci-vme bridge */
2
3/*
4 * Authorship
5 * ----------
6 * This software was created by
7 *     Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
8 *         Stanford Linear Accelerator Center, Stanford University.
9 *
10 * Acknowledgement of sponsorship
11 * ------------------------------
12 * This software was produced by
13 *     the Stanford Linear Accelerator Center, Stanford University,
14 *         under Contract DE-AC03-76SFO0515 with the Department of Energy.
15 *
16 * Government disclaimer of liability
17 * ----------------------------------
18 * Neither the United States nor the United States Department of Energy,
19 * nor any of their employees, makes any warranty, express or implied, or
20 * assumes any legal liability or responsibility for the accuracy,
21 * completeness, or usefulness of any data, apparatus, product, or process
22 * disclosed, or represents that its use would not infringe privately owned
23 * rights.
24 *
25 * Stanford disclaimer of liability
26 * --------------------------------
27 * Stanford University makes no representations or warranties, express or
28 * implied, nor assumes any liability for the use of this software.
29 *
30 * Stanford disclaimer of copyright
31 * --------------------------------
32 * Stanford University, owner of the copyright, hereby disclaims its
33 * copyright and all other rights in this software.  Hence, anyone may
34 * freely use it for any purpose without restriction.
35 *
36 * Maintenance of notices
37 * ----------------------
38 * In the interest of clarity regarding the origin and status of this
39 * SLAC software, this and all the preceding Stanford University notices
40 * are to remain affixed to any copy or derivative of this software made
41 * or distributed by the recipient and are to be affixed to any copy of
42 * software made or distributed by the recipient that contains a copy or
43 * derivative of this software.
44 *
45 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
46 */
47
48#include <rtems.h>
49#include <stdio.h>
50#include <stdarg.h>
51#include <bsp/irq.h>
52#include <stdlib.h>
53#include <rtems/bspIo.h>        /* printk */
54#include <rtems/error.h>        /* printk */
55#include <rtems/pci.h>
56#include <bsp.h>
57#include <libcpu/byteorder.h>
58
59#define __INSIDE_RTEMS_BSP__
60#define _VME_TSI148_DECLARE_SHOW_ROUTINES
61
62#include <bsp/vmeTsi148.h>
63#include <bsp/VMEDMA.h>
64#include <bsp/vmeTsi148DMA.h>
65#include "bspVmeDmaListP.h"
66
67
68#define DEBUG
69
70#ifdef DEBUG
71#define STATIC
72#else
73#define STATIC static
74#endif
75
76/* The tsi has 4 'local' wires that can be hooked to a PIC */
77
78#define TSI_NUM_WIRES                   4
79
80#define TSI148_NUM_OPORTS               8 /* number of outbound ports */
81#define TSI148_NUM_IPORTS               8 /* number of inbound  ports */
82
83#define NUM_TSI_DEVS                    2 /* number of instances supported */
84
85#define PCI_VENDOR_TUNDRA       0x10e3
86#define PCI_DEVICE_TSI148       0x0148
87
88#define TSI_OTSAU_SPACING       0x020
89
90#define TSI_OTSAU0_REG          0x100
91#define TSI_OTSAL0_REG          0x104
92#define TSI_OTEAU0_REG          0x108
93#define TSI_OTEAL0_REG          0x10c
94#define TSI_OTOFU0_REG          0x110
95#define TSI_OTOFL0_REG          0x114
96#define TSI_OTBS0_REG           0x118   /* 2eSST broadcast select */
97#define TSI_OTAT0_REG           0x11c
98#define TSI_OTSAU_REG(port)     (TSI_OTSAU0_REG + ((port)<<5))
99#define TSI_OTSAL_REG(port)     (TSI_OTSAL0_REG + ((port)<<5))
100#define TSI_OTEAU_REG(port)     (TSI_OTEAU0_REG + ((port)<<5))
101#define TSI_OTEAL_REG(port)     (TSI_OTEAL0_REG + ((port)<<5))
102#define TSI_OTOFU_REG(port)     (TSI_OTOFU0_REG + ((port)<<5))
103#define TSI_OTOFL_REG(port)     (TSI_OTOFL0_REG + ((port)<<5))
104#define TSI_OTBS_REG(port)      (TSI_OTBS0_REG + ((port)<<5))
105#define TSI_OTAT_REG(port)      (TSI_OTAT0_REG + ((port)<<5))
106#       define TSI_OTAT_EN                      (1<<31)
107#       define TSI_OTAT_MRPFD           (1<<18)
108#       define TSI_OTAT_PFS(x)          (((x)&3)<<16)
109#       define TSI_OTAT_2eSSTM(x)       (((x)&7)<<11)
110#       define TSI_OTAT_2eSSTM_160      TSI_OTAT_2eSSTM(0)
111#       define TSI_OTAT_2eSSTM_267      TSI_OTAT_2eSSTM(1)
112#       define TSI_OTAT_2eSSTM_320      TSI_OTAT_2eSSTM(2)
113#       define TSI_OTAT_TM(x)           (((x)&7)<<8)
114#               define TSI_TM_SCT_IDX           0
115#               define TSI_TM_BLT_IDX           1
116#               define TSI_TM_MBLT_IDX          2
117#               define TSI_TM_2eVME_IDX         3
118#               define TSI_TM_2eSST_IDX         4
119#               define TSI_TM_2eSSTB_IDX        5
120#       define TSI_OTAT_DBW(x)          (((x)&3)<<6)
121#       define TSI_OTAT_SUP                     (1<<5)
122#       define TSI_OTAT_PGM                     (1<<4)
123#       define TSI_OTAT_ADMODE(x)       (((x)&0xf))
124#       define TSI_OTAT_ADMODE_A16      0
125#       define TSI_OTAT_ADMODE_A24      1
126#       define TSI_OTAT_ADMODE_A32      2
127#       define TSI_OTAT_ADMODE_A64      4
128#       define TSI_OTAT_ADMODE_CSR      5
129#       define TSI_OTAT_ADMODE_USR1     8
130#       define TSI_OTAT_ADMODE_USR2     9
131#       define TSI_OTAT_ADMODE_USR3     0xa
132#       define TSI_OTAT_ADMODE_USR4     0xb
133
134#define TSI_VIACK_1_REG         0x204
135
136#define TSI_VMCTRL_REG          0x234
137#       define TSI_VMCTRL_VSA           (1<<27)
138#       define TSI_VMCTRL_VS            (1<<26)
139#       define TSI_VMCTRL_DHB           (1<<25)
140#       define TSI_VMCTRL_DWB           (1<<24)
141#       define TSI_VMCTRL_RMWEN         (1<<20)
142#       define TSI_VMCTRL_A64DS         (1<<16)
143#       define TSI_VMCTRL_VTOFF_MSK     (7<<12)
144#       define TSI_VMCTRL_VTOFF_0us     (0<<12)
145#       define TSI_VMCTRL_VTOFF_1us     (1<<12)
146#       define TSI_VMCTRL_VTOFF_2us     (2<<12)
147#       define TSI_VMCTRL_VTOFF_4us     (3<<12)
148#       define TSI_VMCTRL_VTOFF_8us     (4<<12)
149#       define TSI_VMCTRL_VTOFF_16us    (5<<12)
150#       define TSI_VMCTRL_VTOFF_32us    (6<<12)
151#       define TSI_VMCTRL_VTOFF_64us    (7<<12)
152#       define TSI_VMCTRL_VTON_MSK      (7<< 8)
153#       define TSI_VMCTRL_VTON_4us      (0<< 8)
154#       define TSI_VMCTRL_VTON_8us      (1<< 8)
155#       define TSI_VMCTRL_VTON_16us     (2<< 8)
156#       define TSI_VMCTRL_VTON_32us     (3<< 8)
157#       define TSI_VMCTRL_VTON_64us     (4<< 8)
158#       define TSI_VMCTRL_VTON_128us    (5<< 8)
159#       define TSI_VMCTRL_VTON_256us    (6<< 8)
160#       define TSI_VMCTRL_VTON_512us    (7<< 8)
161#       define TSI_VMCTRL_VREL_MSK              (3<< 3)
162#       define TSI_VMCTRL_VREL_TON_or_DONE                      (0<< 3)
163#       define TSI_VMCTRL_VREL_TONandREQ_or_DONE        (1<< 3)
164#       define TSI_VMCTRL_VREL_TONandBCLR_or_DONE       (2<< 3)
165#       define TSI_VMCTRL_VREL_TONorDONE_and_REQ        (3<< 3)
166#       define TSI_VMCTRL_VFAIR         (1<< 2)
167#       define TSI_VMCTRL_VREQL_MSK     (3<< 0)
168#       define TSI_VMCTRL_VREQL(x)      ((x)&3)
169
170#define TSI_VCTRL_REG           0x238
171#define TSI_VCTRL_DLT_MSK               (0xf<<24)
172#define TSI_VCTRL_NELBB                 (1<<20)
173#define TSI_VCTRL_SRESET                (1<<17)
174#define TSI_VCTRL_LRESET                (1<<16)
175#define TSI_VCTRL_SFAILAI               (1<<15)
176#define TSI_VCTRL_BID_MSK               (0x1f<<8)
177#define TSI_VCTRL_ATOEN                 (1<< 7)
178#define TSI_VCTRL_ROBIN                 (1<< 6)
179#define TSI_VCTRL_GTO_MSK               (7<< 0)
180
181
182#define TSI_VSTAT_REG           0x23c
183#       define TSI_VSTAT_CPURST         (1<<15) /* clear power-up reset bit */
184#       define TSI_VSTAT_BDFAIL         (1<<14)
185#       define TSI_VSTAT_PURSTS         (1<<12)
186#       define TSI_VSTAT_BDFAILS        (1<<11)
187#       define TSI_VSTAT_SYSFLS         (1<<10)
188#       define TSI_VSTAT_ACFAILS        (1<< 9)
189#       define TSI_VSTAT_SCONS          (1<< 8)
190#       define TSI_VSTAT_GAP            (1<< 5)
191#       define TSI_VSTAT_GA_MSK         (0x1f)
192
193#define TSI_VEAU_REG            0x260
194#define TSI_VEAL_REG            0x264
195#define TSI_VEAT_REG            0x268
196
197#define TSI_ITSAU_SPACING       0x020
198
199#define TSI_ITSAU0_REG          0x300
200#define TSI_ITSAL0_REG          0x304
201#define TSI_ITEAU0_REG          0x308
202#define TSI_ITEAL0_REG          0x30c
203#define TSI_ITOFU0_REG          0x310
204#define TSI_ITOFL0_REG          0x314
205#define TSI_ITAT0_REG           0x318
206#define TSI_ITSAU_REG(port)     (TSI_ITSAU0_REG + ((port)<<5))
207#define TSI_ITSAL_REG(port)     (TSI_ITSAL0_REG + ((port)<<5))
208#define TSI_ITEAU_REG(port)     (TSI_ITEAU0_REG + ((port)<<5))
209#define TSI_ITEAL_REG(port)     (TSI_ITEAL0_REG + ((port)<<5))
210#define TSI_ITOFU_REG(port)     (TSI_ITOFU0_REG + ((port)<<5))
211#define TSI_ITOFL_REG(port)     (TSI_ITOFL0_REG + ((port)<<5))
212#define TSI_ITAT_REG(port)      (TSI_ITAT0_REG + ((port)<<5))
213
214#       define TSI_ITAT_EN                      (1<<31)
215#       define TSI_ITAT_TH                      (1<<18)
216#       define TSI_ITAT_VFS(x)          (((x)&3)<<16)
217#       define TSI_ITAT_2eSSTM(x)       (((x)&7)<<12)
218#       define TSI_ITAT_2eSSTM_160      TSI_ITAT_2eSSTM(0)
219#       define TSI_ITAT_2eSSTM_267      TSI_ITAT_2eSSTM(1)
220#       define TSI_ITAT_2eSSTM_320      TSI_ITAT_2eSSTM(2)
221#       define TSI_ITAT_2eSSTB          (1<<11)
222#       define TSI_ITAT_2eSST           (1<<10)
223#       define TSI_ITAT_2eVME           (1<<9)
224#       define TSI_ITAT_MBLT            (1<<8)
225#       define TSI_ITAT_BLT                     (1<<7)
226#       define TSI_ITAT_AS(x)           (((x)&7)<<4)
227#       define TSI_ITAT_ADMODE_A16      (0<<4)
228#       define TSI_ITAT_ADMODE_A24      (1<<4)
229#       define TSI_ITAT_ADMODE_A32      (2<<4)
230#       define TSI_ITAT_ADMODE_A64      (4<<4)
231#       define TSI_ITAT_SUP                     (1<<3)
232#       define TSI_ITAT_USR                     (1<<2)
233#       define TSI_ITAT_PGM                     (1<<1)
234#       define TSI_ITAT_DATA            (1<<0)
235
236#define TSI_CBAU_REG            0x40c
237#define TSI_CBAL_REG            0x410
238#define TSI_CRGAT_REG           0x414
239#   define TSI_CRGAT_EN         (1<<7)
240#       define TSI_CRGAT_AS_MSK (7<<4)
241#       define TSI_CRGAT_A16    (0<<4)
242#       define TSI_CRGAT_A24    (1<<4)
243#       define TSI_CRGAT_A32    (2<<4)
244#       define TSI_CRGAT_A64    (4<<4)
245#   define TSI_CRGAT_SUP        (1<<3)
246#   define TSI_CRGAT_USR        (1<<2)
247#   define TSI_CRGAT_PGM        (1<<1)
248#   define TSI_CRGAT_DATA       (1<<0)
249
250#define TSI_VICR_REG            0x440
251#   define TSI_VICR_CNTS(v)             (((v)&3)<<30)
252#   define TSI_VICR_CNTS_DIS    (0<<30)
253#   define TSI_VICR_CNTS_IRQ1   (1<<30)
254#   define TSI_VICR_CNTS_IRQ2   (2<<30)
255#   define TSI_VICR_EDGIS(v)    (((v)&3)<<28)
256#   define TSI_VICR_EDGIS_DIS   (0<<28)
257#   define TSI_VICR_EDGIS_IRQ1  (1<<28)
258#   define TSI_VICR_EDGIS_IRQ2  (2<<28)
259#   define TSI_VICR_IRQ1F(v)    (((v)&3)<<26)
260#   define TSI_VICR_IRQ1F_NORML (0<<26)
261#   define TSI_VICR_IRQ1F_PULSE (1<<26)
262#   define TSI_VICR_IRQ1F_CLOCK (2<<26)
263#   define TSI_VICR_IRQ1F_1MHZ  (3<<26)
264#   define TSI_VICR_IRQ2F(v)    (((v)&3)<<24)
265#   define TSI_VICR_IRQ2F_NORML (0<<24)
266#   define TSI_VICR_IRQ2F_PULSE (1<<24)
267#   define TSI_VICR_IRQ2F_CLOCK (2<<24)
268#   define TSI_VICR_IRQ2F_1MHZ  (3<<24)
269#   define TSI_VICR_BIP                 (1<<23)
270#   define TSI_VICR_BIPS                (1<<22)
271#   define TSI_VICR_IRQC                (1<<15)
272#   define TSI_VICR_IRQLS(v)    (((v)&7)<<12)
273#   define TSI_VICR_IRQS                (1<<11)
274#   define TSI_VICR_IRQL(v)             (((v)&7)<<8)
275#   define TSI_VICR_STID(v)             ((v)&0xff)
276#define TSI_INTEN_REG           0x448
277#define TSI_INTEO_REG           0x44c
278#define TSI_INTS_REG            0x450
279#   define TSI_INTS_IRQ1S       (1<<1)
280#   define TSI_INTS_IRQ2S       (1<<2)
281#   define TSI_INTS_IRQ3S       (1<<3)
282#   define TSI_INTS_IRQ4S       (1<<4)
283#   define TSI_INTS_IRQ5S       (1<<5)
284#   define TSI_INTS_IRQ6S       (1<<6)
285#   define TSI_INTS_IRQ7S       (1<<7)
286#   define TSI_INTS_ACFLS       (1<<8)
287#   define TSI_INTS_SYSFLS      (1<<9)
288#   define TSI_INTS_IACKS       (1<<10)
289#   define TSI_INTS_VIES        (1<<11)
290#   define TSI_INTS_VERRS       (1<<12)
291#   define TSI_INTS_PERRS       (1<<13)
292#   define TSI_INTS_MB0S        (1<<16)
293#   define TSI_INTS_MB1S        (1<<17)
294#   define TSI_INTS_MB2S        (1<<18)
295#   define TSI_INTS_MB3S        (1<<19)
296#   define TSI_INTS_LM0S        (1<<20)
297#   define TSI_INTS_LM1S        (1<<21)
298#   define TSI_INTS_LM2S        (1<<22)
299#   define TSI_INTS_LM3S        (1<<23)
300#   define TSI_INTS_DMA0S       (1<<24)
301#   define TSI_INTS_DMA1S       (1<<25)
302#define TSI_INTC_REG            0x454
303#   define TSI_INTC_ACFLC       (1<<8)
304#   define TSI_INTC_SYSFLC      (1<<9)
305#   define TSI_INTC_IACKC       (1<<10)
306#   define TSI_INTC_VIEC        (1<<11)
307#   define TSI_INTC_VERRC       (1<<12)
308#   define TSI_INTC_PERRC       (1<<13)
309#   define TSI_INTC_MB0C        (1<<16)
310#   define TSI_INTC_MB1C        (1<<17)
311#   define TSI_INTC_MB2C        (1<<18)
312#   define TSI_INTC_MB3C        (1<<19)
313#   define TSI_INTC_LM0C        (1<<20)
314#   define TSI_INTC_LM1C        (1<<21)
315#   define TSI_INTC_LM2C        (1<<22)
316#   define TSI_INTC_LM3C        (1<<23)
317#   define TSI_INTC_DMA0C       (1<<24)
318#   define TSI_INTC_DMA1C       (1<<25)
319#define TSI_INTM1_REG           0x458
320#define TSI_INTM2_REG           0x45c
321
322#define TSI_CBAR_REG            0xffc
323
324#define TSI_CSR_OFFSET          0x7f000
325
326#define TSI_CRG_SIZE            (1<<12)         /* 4k */
327
328
329#define TSI_RD(base, reg)                               in_be32((volatile uint32_t *)((base) + (reg)/sizeof(*base)))
330#define TSI_RD16(base, reg)                             in_be16((volatile uint16_t *)(base) + (reg)/sizeof(uint16_t))
331#define TSI_LE_RD16(base, reg)                  in_le16((volatile uint16_t *)(base) + (reg)/sizeof(uint16_t))
332#define TSI_LE_RD32(base, reg)                  in_le32((volatile uint32_t *)(base) + (reg)/sizeof(*base))
333#define TSI_RD8(base, reg)                              in_8((volatile uint8_t *)(base) + (reg))
334#define TSI_WR(base, reg, val)                  out_be32((volatile uint32_t *)((base) + (reg)/sizeof(*base)), val)
335
336#define UNIV_SCTL_AM_MASK       (UNIV_CTL_VAS | UNIV_SCTL_PGM | UNIV_SCTL_DAT | UNIV_SCTL_USER | UNIV_SCTL_SUPER)
337
338
339/* allow the BSP to override the default routines */
340#ifndef BSP_PCI_FIND_DEVICE
341#define BSP_PCI_FIND_DEVICE             pci_find_device
342#endif
343#ifndef BSP_PCI_CONFIG_IN_LONG
344#define BSP_PCI_CONFIG_IN_LONG  pci_read_config_dword
345#endif
346#ifndef BSP_PCI_CONFIG_IN_SHORT
347#define BSP_PCI_CONFIG_IN_SHORT pci_read_config_word
348#endif
349#ifndef BSP_PCI_CONFIG_OUT_SHORT
350#define BSP_PCI_CONFIG_OUT_SHORT pci_write_config_word
351#endif
352#ifndef BSP_PCI_CONFIG_IN_BYTE
353#define BSP_PCI_CONFIG_IN_BYTE  pci_read_config_byte
354#endif
355
356typedef uint32_t pci_ulong;
357
358#ifdef __BIG_ENDIAN__
359        static inline void st_be32( uint32_t *a, uint32_t v)
360        {
361                *a = v;
362        }
363        static inline uint32_t ld_be32( uint32_t *a )
364        {
365                return *a;
366        }
367#elif defined(__LITTLE_ENDIAN__)
368#error "You need to implement st_be32/ld_be32"
369#else
370#error "Undefined endianness??"
371#endif
372
373#ifndef BSP_LOCAL2PCI_ADDR
374/* try legacy PCI_DRAM_OFFSET */
375#ifndef PCI_DRAM_OFFSET
376#define PCI_DRAM_OFFSET 0
377#endif
378#define BSP_LOCAL2PCI_ADDR(l)   (((uint32_t)l)+PCI_DRAM_OFFSET)
379#endif
380
381/* PCI_MEM_BASE is a possible offset between CPU- and PCI addresses.
382 * Should be defined by the BSP.
383 */
384#ifndef BSP_PCI2LOCAL_ADDR
385#ifndef PCI_MEM_BASE
386#define PCI_MEM_BASE 0
387#endif
388#define BSP_PCI2LOCAL_ADDR(memaddr) ((unsigned long)(memaddr) + PCI_MEM_BASE)
389#endif
390
391typedef uint32_t BEValue;
392
393typedef struct {
394        BERegister *base;
395        int                     irqLine;
396        int                     pic_pin[TSI_NUM_WIRES];
397} Tsi148Dev;
398
399static Tsi148Dev devs[NUM_TSI_DEVS] = {{0}};
400
401#define THEBASE (devs[0].base)
402
403/* forward decl */
404extern int vmeTsi148RegPort;
405extern int vmeTsi148RegCSR;
406
407/* registers should be mapped to guarded, non-cached memory; hence
408 * subsequent stores are ordered. eieio is only needed to enforce
409 * ordering of loads with respect to stores.
410 */
411
412/* private printing wrapper */
413static void
414uprintf(FILE *f, char *fmt, ...)
415{
416va_list ap;
417        va_start(ap, fmt);
418        if (!f || !_impure_ptr->__sdidinit) {
419                /* Might be called at an early stage when
420                 * to a buffer.
421                 */
422                vprintk(fmt,ap);
423        } else
424        {
425                vfprintf(f,fmt,ap);
426        }
427        va_end(ap);
428}
429
430#define CHECK_BASE(base,quiet,rval)     \
431        do {                                                    \
432                if ( !base ) {                          \
433                        if ( !quiet ) {                 \
434                                uprintf(stderr,"Tsi148: Driver not initialized\n");     \
435                        }                                               \
436                        return rval;                    \
437                }                                                       \
438        } while (0)
439
440int
441vmeTsi148FindPciBase(
442        int instance,
443        BERegister **pbase
444        )
445{
446int                                     bus,dev,fun;
447pci_ulong                       busaddr;
448unsigned char           irqline;
449unsigned short          wrd;
450
451        if (BSP_PCI_FIND_DEVICE(
452                        PCI_VENDOR_TUNDRA,
453                        PCI_DEVICE_TSI148,
454                        instance,
455                        &bus,
456                        &dev,
457                        &fun))
458                return -1;
459        if (BSP_PCI_CONFIG_IN_LONG(bus,dev,fun,PCI_BASE_ADDRESS_0,&busaddr))
460                return -1;
461        /* Assume upper BAR is zero */
462
463        *pbase=(BERegister*)(((pci_ulong)BSP_PCI2LOCAL_ADDR(busaddr)) & ~0xff);
464
465        if (BSP_PCI_CONFIG_IN_BYTE(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline))
466                return -1;
467
468        /* Enable PCI master and memory access */
469        BSP_PCI_CONFIG_IN_SHORT(bus, dev, fun, PCI_COMMAND, &wrd);
470        BSP_PCI_CONFIG_OUT_SHORT(bus, dev, fun, PCI_COMMAND, wrd | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
471
472        return irqline;
473}
474
475int
476vmeTsi148InitInstance(unsigned instance)
477{
478int                                     irq;
479BERegister *base;
480
481        if ( instance >= NUM_TSI_DEVS )
482                return  -1;
483        if ( devs[instance].base )
484                return  -1;
485
486        if ((irq=vmeTsi148FindPciBase(instance,&base)) < 0) {
487                uprintf(stderr,"unable to find a Tsi148 in pci config space\n");
488        } else {
489                uprintf(stderr,"Tundra Tsi148 PCI-VME bridge detected at 0x%08x, IRQ %d\n",
490                                (unsigned int)base, irq);
491        }
492        devs[0].base    = base;
493        devs[0].irqLine = irq;
494
495        return irq < 0 ? -1 : 0;
496}
497
498int
499vmeTsi148Init(void)
500{
501        return vmeTsi148InitInstance(0);
502}
503
504
505void
506vmeTsi148ResetXX(BERegister *base)
507{
508int port;
509uint32_t v;
510
511        CHECK_BASE(base,0, );
512
513        vmeTsi148DisableAllOutboundPortsXX(base);
514        for ( port=0; port < TSI148_NUM_OPORTS; port++ )
515                TSI_WR(base, TSI_OTBS_REG(port), 0);
516        TSI_WR(base, TSI_INTEO_REG, 0);
517        TSI_WR(base, TSI_INTEN_REG, 0);
518        TSI_WR(base, TSI_INTC_REG, 0xffffffff);
519        TSI_WR(base, TSI_INTM1_REG, 0);
520        TSI_WR(base, TSI_INTM2_REG, 0);
521        TSI_WR(base, TSI_VICR_REG, 0);
522        TSI_WR(base, TSI_VEAT_REG, TSI_VEAT_VESCL);
523        /* Clear BDFAIL / (--> SYSFAIL) */
524#       define TSI_VSTAT_BDFAIL         (1<<14)
525        TSI_WR(base, TSI_VSTAT_REG, TSI_RD(base, TSI_VSTAT_REG) & ~TSI_VSTAT_BDFAIL);
526        /* Set (long) bus master timeout; the timeout actually overrides
527         * the DMA block size so that the DMA settings would effectively
528         * not be used.
529         * Also, we enable 'release on request' mode so that we normally
530         * don't have to rearbitrate the bus for every transfer.
531         */
532        v = TSI_RD(base, TSI_VMCTRL_REG);
533        v &= ~( TSI_VMCTRL_VTON_MSK | TSI_VMCTRL_VREL_MSK );
534        v |= (TSI_VMCTRL_VTON_512us | TSI_VMCTRL_VREL_TONorDONE_and_REQ );
535        TSI_WR(base, TSI_VMCTRL_REG, v);
536}
537
538void
539vmeTsi148Reset(void)
540{
541        vmeTsi148ResetXX(THEBASE);
542}
543
544void
545vmeTsi148ResetBusXX(BERegister *base)
546{
547unsigned long flags;
548uint32_t      v;
549
550        rtems_interrupt_disable(flags);
551        v = TSI_RD(base, TSI_VCTRL_REG);
552        TSI_WR(base, TSI_VCTRL_REG, v | TSI_VCTRL_SRESET);
553        rtems_interrupt_enable(flags);
554}
555
556void
557vmeTsi148ResetBus(void)
558{
559        vmeTsi148ResetBusXX(THEBASE);
560}
561
562
563/* convert an address space selector to a corresponding
564 * Tsi148 control mode word
565 */
566
567static unsigned long ck2esst(unsigned long am)
568{
569        if ( VME_AM_IS_2eSST(am) ) {
570                /* make sure 2eVME is selected */
571                am &= ~VME_AM_MASK;
572                am |= VME_AM_2eVME_6U;
573        }
574        return am;
575}
576
577static int
578am2omode(unsigned long address_space, unsigned long *pmode)
579{
580unsigned long mode = 0;
581unsigned long tm   = TSI_TM_SCT_IDX;
582
583        switch ( VME_MODE_DBW_MSK & address_space ) {
584                case VME_MODE_DBW8:
585                        return -1;      /* unsupported */
586
587                case VME_MODE_DBW16:
588                        break;
589
590                default:
591                case VME_MODE_DBW32:
592                        mode |= TSI_OTAT_DBW(1);
593                        break;
594        }
595
596        if ( ! (VME_MODE_PREFETCH_ENABLE & address_space) )
597                mode |= TSI_OTAT_MRPFD;
598        else {
599                mode |= TSI_OTAT_PFS(address_space>>_LD_VME_MODE_PREFETCHSZ);
600        }
601
602        address_space = ck2esst(address_space);
603
604        switch (address_space & VME_AM_MASK) {
605                case VME_AM_STD_SUP_PGM:
606                case VME_AM_STD_USR_PGM:
607
608                        mode |= TSI_OTAT_PGM;
609
610                        /* fall thru */
611                case VME_AM_STD_SUP_BLT:
612                case VME_AM_STD_SUP_MBLT:
613
614                case VME_AM_STD_USR_BLT:
615                case VME_AM_STD_USR_MBLT:
616                        switch ( address_space & 3 ) {
617                                case 0: tm = TSI_TM_MBLT_IDX; break;
618                                case 3: tm = TSI_TM_BLT_IDX; break;
619                                default: break;
620                        }
621
622                case VME_AM_STD_SUP_DATA:
623                case VME_AM_STD_USR_DATA:
624
625                        mode |= TSI_OTAT_ADMODE_A24;
626                        break;
627
628                case VME_AM_EXT_SUP_PGM:
629                case VME_AM_EXT_USR_PGM:
630                        mode |= TSI_OTAT_PGM;
631
632                        /* fall thru */
633                case VME_AM_EXT_SUP_BLT:
634                case VME_AM_EXT_SUP_MBLT:
635
636                case VME_AM_EXT_USR_BLT:
637                case VME_AM_EXT_USR_MBLT:
638                        switch ( address_space & 3 ) {
639                                case 0: tm = TSI_TM_MBLT_IDX; break;
640                                case 3: tm = TSI_TM_BLT_IDX; break;
641                                default: break;
642                        }
643
644                case VME_AM_EXT_SUP_DATA:
645                case VME_AM_EXT_USR_DATA:
646
647                        mode |= TSI_OTAT_ADMODE_A32;
648                        break;
649
650                case VME_AM_SUP_SHORT_IO:
651                case VME_AM_USR_SHORT_IO:
652                        mode |= TSI_OTAT_ADMODE_A16;
653                        break;
654
655                case VME_AM_CSR:
656                        mode |= TSI_OTAT_ADMODE_CSR;
657                        break;
658
659                case VME_AM_2eVME_6U:
660                case VME_AM_2eVME_3U:
661                        mode |= TSI_OTAT_ADMODE_A32;
662                        if ( VME_AM_IS_2eSST(address_space) ) {
663                                tm = ( VME_AM_2eSST_BCST & address_space ) ?
664                                                TSI_TM_2eSSTB_IDX : TSI_TM_2eSST_IDX;
665                                switch ( VME_AM_IS_2eSST(address_space) ) {
666                                        default:
667                                        case VME_AM_2eSST_LO:  mode |= TSI_OTAT_2eSSTM_160; break;
668                                        case VME_AM_2eSST_MID: mode |= TSI_OTAT_2eSSTM_267; break;
669                                        case VME_AM_2eSST_HI:  mode |= TSI_OTAT_2eSSTM_320; break;
670                                }
671                        } else {
672                                tm    = TSI_TM_2eVME_IDX;
673                        }
674                break;
675
676                case 0: /* disable the port alltogether */
677                        break;
678
679                default:
680                        return -1;
681        }
682
683        mode |= TSI_OTAT_TM(tm);
684
685        if ( VME_AM_IS_SUP(address_space) )
686                mode |= TSI_OTAT_SUP;
687        *pmode = mode;
688        return 0;
689}
690
691static int
692am2imode(unsigned long address_space, unsigned long *pmode)
693{
694unsigned long mode=0;
695unsigned long pgm = 0;
696
697        mode |= TSI_ITAT_VFS(address_space>>_LD_VME_MODE_PREFETCHSZ);
698
699        if ( VME_AM_IS_2eSST(address_space) ) {
700                        mode |= TSI_ITAT_2eSST;
701                if ( VME_AM_2eSST_BCST & address_space )
702                        mode |= TSI_ITAT_2eSSTB;
703                switch ( VME_AM_IS_2eSST(address_space) ) {
704                        default:
705                        case VME_AM_2eSST_LO:  mode |= TSI_ITAT_2eSSTM_160; break;
706                        case VME_AM_2eSST_MID: mode |= TSI_ITAT_2eSSTM_267; break;
707                        case VME_AM_2eSST_HI:  mode |= TSI_ITAT_2eSSTM_320; break;
708                }
709                address_space = ck2esst(address_space);
710        }
711
712        mode |= TSI_ITAT_BLT;
713        mode |= TSI_ITAT_MBLT;
714
715        mode |= TSI_ITAT_PGM; /* always allow PGM access */
716        mode |= TSI_ITAT_USR; /* always allow USR access */
717
718        switch (address_space & VME_AM_MASK) {
719                case VME_AM_STD_SUP_PGM:
720                case VME_AM_STD_USR_PGM:
721
722                        pgm = 1;
723
724                        /* fall thru */
725                case VME_AM_STD_SUP_BLT:
726                case VME_AM_STD_SUP_MBLT:
727                case VME_AM_STD_USR_BLT:
728                case VME_AM_STD_USR_MBLT:
729                case VME_AM_STD_SUP_DATA:
730                case VME_AM_STD_USR_DATA:
731
732                        mode |= TSI_ITAT_ADMODE_A24;
733                        break;
734
735                case VME_AM_EXT_SUP_PGM:
736                case VME_AM_EXT_USR_PGM:
737                        pgm = 1;
738
739                        /* fall thru */
740                case VME_AM_2eVME_6U:
741                case VME_AM_2eVME_3U:
742                case VME_AM_EXT_SUP_BLT:
743                case VME_AM_EXT_SUP_MBLT:
744                case VME_AM_EXT_USR_BLT:
745                case VME_AM_EXT_USR_MBLT:
746                case VME_AM_EXT_SUP_DATA:
747                case VME_AM_EXT_USR_DATA:
748                        mode |= TSI_ITAT_ADMODE_A32;
749                        break;
750
751                case VME_AM_SUP_SHORT_IO:
752                case VME_AM_USR_SHORT_IO:
753                        mode |= TSI_ITAT_ADMODE_A16;
754                        break;
755
756                case 0: /* disable the port alltogether */
757                        *pmode = 0;
758                        return 0;
759
760                default:
761                        return -1;
762        }
763
764        if ( VME_AM_IS_SUP(address_space) )
765                mode |= TSI_ITAT_SUP;
766
767        if ( !pgm )
768                mode |= TSI_ITAT_DATA;
769
770        *pmode = mode;
771        return 0;
772}
773
774static void
775readTriple(
776        BERegister *base,
777        unsigned reg,
778        unsigned long long *ps,
779        unsigned long long *pl,
780        unsigned long long *po)
781{
782        *ps = TSI_RD(base, reg);
783        *ps = (*ps<<32) | (TSI_RD(base, (reg+4)) & 0xffff0000);
784        *pl = TSI_RD(base, (reg+8));
785        *pl = (*pl<<32) | (TSI_RD(base, (reg+0xc)) & 0xffff0000);
786        *po = TSI_RD(base, (reg+0x10));
787        *po = (*po<<32) | (TSI_RD(base, (reg+0x14)) & 0xffff0000);
788}
789
790
791static unsigned long
792inboundGranularity(unsigned long itat)
793{
794        switch ( itat & TSI_ITAT_AS(-1) ) {
795                case TSI_ITAT_ADMODE_A16:       return 0xf;
796                case TSI_ITAT_ADMODE_A24:       return 0xfff;
797                default:
798                break;
799        }
800        return 0xffff;
801}
802
803static int
804configTsiPort(
805        BERegister              *base,
806        int                             isout,
807        unsigned long   port,
808        unsigned long   address_space,
809        unsigned long   vme_address,
810        unsigned long   pci_address,
811        unsigned long   length)
812{
813unsigned long long      start, limit, offst;
814unsigned long           mode, mask, tat_reg, tsau_reg;
815char                            *name = (isout ? "Outbound" : "Inbound");
816int                                     i,s,l;
817
818        CHECK_BASE(base,0,-1);
819
820        mode = 0; /* silence warning */
821
822        if ( port >= (isout ? TSI148_NUM_OPORTS : TSI148_NUM_IPORTS) ) {
823                uprintf(stderr,"Tsi148 %s Port Cfg: invalid port\n", name);
824                return -1;
825        }
826
827        if ( base == THEBASE && isout && vmeTsi148RegPort == port ) {
828                uprintf(stderr,"Tsi148 %s Port Cfg: invalid port; reserved by the interrupt manager for CRG\n", name);
829                return -1;
830        }
831
832        if ( length && (isout ? am2omode(address_space, &mode) : am2imode(address_space, &mode)) ) {
833                uprintf(stderr,"Tsi148 %s Port Cfg: invalid address space / mode flags\n",name);
834                return -1;
835        }
836
837
838        if ( isout ) {
839                start     = pci_address;
840                offst     = (unsigned long long)vme_address - start;
841                mask      = 0xffff;
842                tat_reg   = TSI_OTAT_REG(port);
843                tsau_reg  = TSI_OTSAU_REG(port);
844                mode     |= TSI_OTAT_EN;
845
846                /* check for overlap */
847                for ( i = 0; i < TSI148_NUM_OPORTS; i++ ) {
848                        /* ignore 'this' port */
849                        if ( i == port || ! (TSI_OTAT_EN & TSI_RD(base, TSI_OTAT_REG(i))) )
850                                continue;
851
852                        /* check requested PCI range against current port 'i' config */
853                        s = TSI_RD(base, TSI_OTSAU_REG(i) + 0x04); /* start */
854                        l = TSI_RD(base, TSI_OTSAU_REG(i) + 0x0c); /* limit */
855                        if ( ! ( start + length <= s || start > s + l ) ) {
856                                uprintf(stderr,"Tsi148 Outbound Port Cfg: PCI address range overlaps with port %i (0x%08x..0x%08x)\n", i, s, l);
857                                return -1;
858                        }
859                }
860        } else {
861                start     = vme_address;
862                offst     = (unsigned long long)pci_address - start;
863                mask      = inboundGranularity(mode);
864                tat_reg   = TSI_ITAT_REG(port);
865                tsau_reg  = TSI_ITSAU_REG(port);
866                mode     |= TSI_ITAT_EN;
867
868                /* check for overlap */
869                for ( i = 0; i < TSI148_NUM_IPORTS; i++ ) {
870                        /* ignore 'this' port */
871                        if ( i == port || ! (TSI_ITAT_EN & (s=TSI_RD(base, TSI_ITAT_REG(i)))) )
872                                continue;
873
874                        if ( (TSI_ITAT_AS(-1) & s) != (TSI_ITAT_AS(-1) & mode) ) {
875                                /* different address space */
876                                continue;
877                        }
878
879                        if ( ! (mode & s & (TSI_ITAT_SUP | TSI_ITAT_USR | TSI_ITAT_PGM | TSI_ITAT_DATA)) ) {
880                                /* orthogonal privileges */
881                                continue;
882                        }
883
884                        /* check requested VME range against current port 'i' config */
885                        s = TSI_RD(base, TSI_ITSAU_REG(i) + 0x04); /* start */
886                        l = TSI_RD(base, TSI_ITSAU_REG(i) + 0x0c); /* limit */
887                        if ( ! ( start + length <= s || start > s + l ) ) {
888                                uprintf(stderr,"Tsi148 Inbound Port Cfg: VME address range overlaps with port %i (0x%08x..0x%08x)\n", i, s, l);
889                                return -1;
890                        }
891                }
892        }
893
894        /* If they pass 'length==0' just disable */
895        if ( 0 == length ) {
896                TSI_WR(base, tat_reg, TSI_RD(base, tat_reg) & ~(isout ? TSI_OTAT_EN : TSI_ITAT_EN));
897                return 0;
898        }
899
900
901        if (   (vme_address & mask)
902            || (pci_address & mask)
903            || (length      & mask) ) {
904                uprintf(stderr,"Tsi148 %s Port Cfg: invalid address/length; must be multiple of 0x%x\n",
905                                name,
906                                mask+1);
907                return -1;
908        }
909
910        limit  = start + length - 1;
911
912        if ( limit >= (unsigned long long)1<<32 ) {
913                uprintf(stderr,"Tsi148 %s Port Cfg: invalid address/length; must be < 1<<32\n", name);
914                return -1;
915        }
916
917        /* Disable port */
918        TSI_WR(base, tat_reg, 0);
919
920        /* Force to 32-bits */
921        TSI_WR(base, tsau_reg       , 0);
922        TSI_WR(base, tsau_reg + 0x04, (uint32_t)start);
923        TSI_WR(base, tsau_reg + 0x08, 0);
924        TSI_WR(base, tsau_reg + 0x0c, (uint32_t)limit);
925        TSI_WR(base, tsau_reg + 0x10, (uint32_t)(offst>>32));
926        TSI_WR(base, tsau_reg + 0x14, (uint32_t)offst);
927
928        /* (outbound only:) leave 2eSST broadcast register alone for user to program */
929
930        /* Set mode and enable */
931        TSI_WR(base, tat_reg, mode);
932        return 0;
933}
934
935static int
936disableTsiPort(
937        BERegister              *base,
938        int                             isout,
939        unsigned long   port)
940{
941        return configTsiPort(base, isout, port, 0, 0, 0, 0);
942}
943
944int
945vmeTsi148InboundPortCfgXX(
946        BERegister              *base,
947        unsigned long   port,
948        unsigned long   address_space,
949        unsigned long   vme_address,
950        unsigned long   pci_address,
951        unsigned long   length)
952{
953        return configTsiPort(base, 0, port, address_space, vme_address, pci_address, length);
954}
955
956int
957vmeTsi148InboundPortCfg(
958        unsigned long   port,
959        unsigned long   address_space,
960        unsigned long   vme_address,
961        unsigned long   pci_address,
962        unsigned long   length)
963{
964        return configTsiPort(THEBASE, 0, port, address_space, vme_address, pci_address, length);
965}
966
967
968int
969vmeTsi148OutboundPortCfgXX(
970        BERegister              *base,
971        unsigned long   port,
972        unsigned long   address_space,
973        unsigned long   vme_address,
974        unsigned long   pci_address,
975        unsigned long   length)
976{
977        return configTsiPort(base, 1, port, address_space, vme_address, pci_address, length);
978}
979
980int
981vmeTsi148OutboundPortCfg(
982        unsigned long   port,
983        unsigned long   address_space,
984        unsigned long   vme_address,
985        unsigned long   pci_address,
986        unsigned long   length)
987{
988        return configTsiPort(THEBASE, 1, port, address_space, vme_address, pci_address, length);
989}
990
991
992static int
993xlateFindPort(
994        BERegister *base,       /* TSI 148 base address */
995        int outbound,           /* look in the outbound windows */
996        int reverse,            /* reverse mapping; for outbound ports: map local to VME */
997        unsigned long as,       /* address space */
998        unsigned long aIn,      /* address to look up */
999        unsigned long *paOut/* where to put result */
1000        )
1001{
1002unsigned long           mode, mode_msk;
1003int                                     port;
1004unsigned long long      start, limit, offst, a;
1005unsigned long           tsau_reg, tat_reg, gran, skip;
1006
1007        CHECK_BASE(base,0,-1);
1008
1009        mode = 0; /* silence warning */
1010
1011        switch ( as & VME_MODE_MATCH_MASK ) {
1012                case VME_MODE_EXACT_MATCH:
1013                        mode_msk = ~0;
1014                break;
1015
1016                case VME_MODE_AS_MATCH:
1017                        if ( outbound )
1018                                mode_msk = TSI_OTAT_ADMODE(-1) | TSI_OTAT_EN;
1019                        else
1020                                mode_msk = TSI_ITAT_AS(-1) | TSI_ITAT_EN;
1021                break;
1022
1023                default:
1024                        if ( outbound )
1025                                mode_msk = TSI_OTAT_PGM | TSI_OTAT_SUP | TSI_OTAT_ADMODE(-1) | TSI_OTAT_EN;
1026                        else
1027                                mode_msk = TSI_ITAT_PGM | TSI_ITAT_DATA | TSI_ITAT_SUP | TSI_ITAT_USR | TSI_ITAT_AS(-1) | TSI_ITAT_EN;
1028                break;
1029        }
1030
1031        as &= ~VME_MODE_MATCH_MASK;
1032
1033        if ( outbound ? am2omode(as,&mode) : am2imode(as,&mode) ) {
1034                uprintf(stderr, "vmeTsi148XlateAddr: invalid address space/mode argument");
1035                return -2;
1036        }
1037
1038        if (outbound ) {
1039                tsau_reg = TSI_OTSAU_REG(0);
1040                tat_reg  = TSI_OTAT_REG(0);
1041                skip     = TSI_OTSAU_SPACING;
1042                mode    |= TSI_OTAT_EN;
1043                gran     = 0x10000;
1044        } else {
1045                tsau_reg = TSI_ITSAU_REG(0);
1046                tat_reg  = TSI_ITAT_REG(0);
1047                skip     = TSI_ITSAU_SPACING;
1048                mode    |= TSI_ITAT_EN;
1049                gran     = inboundGranularity(mode) + 1;
1050        }
1051
1052        for ( port = 0; port < TSI148_NUM_OPORTS; port++, tsau_reg += skip, tat_reg += skip ) {
1053
1054                if ( (mode & mode_msk) == (TSI_RD(base, tat_reg) & mode_msk) ) {
1055
1056                        /* found a window with of the right mode; now check the range */
1057                        readTriple(base, tsau_reg, &start, &limit, &offst);
1058                        limit += gran;
1059
1060                        if ( !reverse ) {
1061                                start += offst;
1062                                limit += offst;
1063                                offst  = -offst;
1064                        }
1065                        a = aIn;
1066                        if ( aIn >= start && aIn <= limit ) {
1067                                /* found it */
1068                                *paOut = (unsigned long)(a + offst);
1069                                return port;
1070                        }
1071                }
1072        }
1073
1074        uprintf(stderr, "vmeTsi148XlateAddr: no matching mapping found\n");
1075        return -1;
1076}
1077
1078int
1079vmeTsi148XlateAddrXX(
1080        BERegister *base,       /* TSI 148 base address */
1081        int outbound,           /* look in the outbound windows */
1082        int reverse,            /* reverse mapping; for outbound ports: map local to VME */
1083        unsigned long as,       /* address space */
1084        unsigned long aIn,      /* address to look up */
1085        unsigned long *paOut/* where to put result */
1086        )
1087{
1088int port = xlateFindPort( base, outbound, reverse, as, aIn, paOut );
1089        return port < 0 ? -1 : 0;
1090}
1091
1092int
1093vmeTsi148XlateAddr(
1094        int outbound,           /* look in the outbound windows */
1095        int reverse,            /* reverse mapping; for outbound ports: map local to VME */
1096        unsigned long as,       /* address space */
1097        unsigned long aIn,      /* address to look up */
1098        unsigned long *paOut/* where to put result */
1099        )
1100{
1101        return vmeTsi148XlateAddrXX(THEBASE, outbound, reverse, as, aIn, paOut);
1102}
1103
1104
1105/* printk cannot format %llx */
1106static void uprintfllx(FILE *f, unsigned long long v)
1107{
1108        if ( v >= ((unsigned long long)1)<<32 )
1109                uprintf(f,"0x%lx%08lx ", (unsigned long)(v>>32), (unsigned long)(v & 0xffffffff));
1110        else
1111                uprintf(f,"0x%08lx ", (unsigned long)(v & 0xffffffff));
1112}
1113
1114void
1115vmeTsi148OutboundPortsShowXX(BERegister *base, FILE *f)
1116{
1117int                             port;
1118unsigned long   mode;
1119char                    tit = 0;
1120
1121unsigned long long      start, limit, offst;
1122
1123        CHECK_BASE(base,0, );
1124
1125        if (!f) f=stdout;
1126        uprintf(f,"Tsi148 Outbound Ports:\n");
1127
1128        for ( port = 0; port < TSI148_NUM_OPORTS; port++ ) {
1129                mode = TSI_RD(base, TSI_OTAT_REG(port));
1130                if ( ! (TSI_OTAT_EN & mode) )
1131                        continue; /* skip disabled ports */
1132
1133                readTriple(base, TSI_OTSAU_REG(port), &start, &limit, &offst);
1134
1135                /* convert limit to size */
1136                limit = limit-start+0x10000;
1137                if ( !tit ) {
1138                        uprintf(f,"Port  VME-Addr   Size       PCI-Adrs   Mode:\n");
1139                        tit = 1;
1140                }
1141                uprintf(f,"%d:    ", port);
1142                uprintfllx(f,start+offst);
1143                uprintfllx(f,limit);
1144                uprintfllx(f,start);
1145                switch( mode & TSI_OTAT_ADMODE(-1) ) {
1146                        case TSI_OTAT_ADMODE_A16: uprintf(f,"A16"); break;
1147                        case TSI_OTAT_ADMODE_A24: uprintf(f,"A24"); break;
1148                        case TSI_OTAT_ADMODE_A32: uprintf(f,"A32"); break;
1149                        case TSI_OTAT_ADMODE_A64: uprintf(f,"A64"); break;
1150                        case TSI_OTAT_ADMODE_CSR: uprintf(f,"CSR"); break;
1151                        default:                  uprintf(f,"A??"); break;
1152                }
1153
1154                if ( mode & TSI_OTAT_PGM ) uprintf(f,", PGM");
1155                if ( mode & TSI_OTAT_SUP ) uprintf(f,", SUP");
1156                if ( ! (TSI_OTAT_MRPFD & mode) ) uprintf(f,", PREFETCH");
1157
1158                switch ( mode & TSI_OTAT_DBW(-1) ) {
1159                        case TSI_OTAT_DBW(0):   uprintf(f,", D16"); break;
1160                        case TSI_OTAT_DBW(1):   uprintf(f,", D32"); break;
1161                        default:                                uprintf(f,", D??"); break;
1162                }
1163
1164                switch( mode & TSI_OTAT_TM(-1) ) {
1165                        case TSI_OTAT_TM(0):    uprintf(f,", SCT");             break;
1166                        case TSI_OTAT_TM(1):    uprintf(f,", BLT");             break;
1167                        case TSI_OTAT_TM(2):    uprintf(f,", MBLT");            break;
1168                        case TSI_OTAT_TM(3):    uprintf(f,", 2eVME");           break;
1169                        case TSI_OTAT_TM(4):    uprintf(f,", 2eSST");           break;
1170                        case TSI_OTAT_TM(5):    uprintf(f,", 2eSST_BCST");      break;
1171                        default:                                uprintf(f," TM??");             break;
1172                }
1173
1174                uprintf(f,"\n");
1175        }
1176}
1177
1178void
1179vmeTsi148OutboundPortsShow(FILE *f)
1180{
1181        vmeTsi148OutboundPortsShowXX(THEBASE, f);
1182}
1183
1184void
1185vmeTsi148InboundPortsShowXX(BERegister *base, FILE *f)
1186{
1187int                             port;
1188unsigned long   mode;
1189char                    tit = 0;
1190
1191unsigned long long      start, limit, offst;
1192
1193        CHECK_BASE(base,0, );
1194
1195        if (!f) f=stdout;
1196        uprintf(f,"Tsi148 Inbound Ports:\n");
1197
1198        for ( port = 0; port < TSI148_NUM_IPORTS; port++ ) {
1199                mode = TSI_RD(base, TSI_ITAT_REG(port));
1200                if ( ! (TSI_ITAT_EN & mode) )
1201                        continue; /* skip disabled ports */
1202
1203                readTriple(base, TSI_ITSAU_REG(port), &start, &limit, &offst);
1204
1205                /* convert limit to size */
1206                limit = limit - start + inboundGranularity(mode) + 1;
1207                if ( !tit ) {
1208                        uprintf(f,"Port  VME-Addr   Size       PCI-Adrs   Mode:\n");
1209                        tit = 1;
1210                }
1211                uprintf(f,"%d:    ", port);
1212                uprintfllx(f,start);
1213                uprintfllx(f,limit);
1214                uprintfllx(f,start+offst);
1215                switch( mode & TSI_ITAT_AS(-1) ) {
1216                        case TSI_ITAT_ADMODE_A16: uprintf(f,"A16"); break;
1217                        case TSI_ITAT_ADMODE_A24: uprintf(f,"A24"); break;
1218                        case TSI_ITAT_ADMODE_A32: uprintf(f,"A32"); break;
1219                        case TSI_ITAT_ADMODE_A64: uprintf(f,"A64"); break;
1220                        default:                  uprintf(f,"A??"); break;
1221                }
1222
1223                if ( mode & TSI_ITAT_PGM )  uprintf(f,", PGM");
1224                if ( mode & TSI_ITAT_DATA ) uprintf(f,", DAT");
1225                if ( mode & TSI_ITAT_SUP )  uprintf(f,", SUP");
1226                if ( mode & TSI_ITAT_USR )  uprintf(f,", USR");
1227
1228                if ( mode & TSI_ITAT_2eSSTB )  uprintf(f,", 2eSSTB");
1229                if ( mode & TSI_ITAT_2eSST  )  uprintf(f,", 2eSST");
1230                if ( mode & TSI_ITAT_2eVME  )  uprintf(f,", 2eVME");
1231                if ( mode & TSI_ITAT_MBLT   )  uprintf(f,", MBLT");
1232                if ( mode & TSI_ITAT_BLT    )  uprintf(f,", BLT");
1233
1234                uprintf(f,"\n");
1235        }
1236}
1237
1238void
1239vmeTsi148InboundPortsShow(FILE *f)
1240{
1241        vmeTsi148InboundPortsShowXX(THEBASE, f);
1242}
1243
1244
1245void
1246vmeTsi148DisableAllInboundPortsXX(BERegister *base)
1247{
1248int port;
1249
1250        for ( port = 0; port < TSI148_NUM_IPORTS; port++ )
1251                if ( disableTsiPort(base, 0, port) )
1252                        break;
1253}
1254
1255void
1256vmeTsi148DisableAllInboundPorts(void)
1257{
1258        vmeTsi148DisableAllInboundPortsXX(THEBASE);
1259}
1260
1261void
1262vmeTsi148DisableAllOutboundPortsXX(BERegister *base)
1263{
1264int port;
1265
1266        for ( port = 0; port < TSI148_NUM_IPORTS; port++ )
1267                if ( disableTsiPort(base, 1, port) )
1268                        break;
1269}
1270
1271void
1272vmeTsi148DisableAllOutboundPorts(void)
1273{
1274        vmeTsi148DisableAllOutboundPortsXX(THEBASE);
1275}
1276
1277
1278/* Map internal register block to VME */
1279
1280int
1281vmeTsi148MapCRGXX(BERegister *b, uint32_t vme_base, uint32_t as )
1282{
1283uint32_t mode;
1284
1285        CHECK_BASE( b, 0, -1 );
1286
1287        if ( vmeTsi148RegPort > -1 && ! vmeTsi148RegCSR ) {
1288        uprintf(stderr,"vmeTsi148: CRG already mapped and in use by interrupt manager\n");
1289                return -1;
1290        }
1291
1292        /* enable all, SUP/USR/PGM/DATA accesses */
1293        mode = TSI_CRGAT_EN | TSI_CRGAT_SUP | TSI_CRGAT_USR | TSI_CRGAT_PGM |  TSI_CRGAT_DATA;
1294
1295        if ( VME_AM_IS_SHORT(as) ) {
1296                mode |= TSI_CRGAT_A16;
1297        } else
1298        if ( VME_AM_IS_STD(as) ) {
1299                mode |= TSI_CRGAT_A24;
1300        } else
1301        if ( VME_AM_IS_EXT(as) ) {
1302                mode |= TSI_CRGAT_A32;
1303        } else {
1304                return -2;
1305        }
1306
1307        /* map CRG to VME bus */
1308        TSI_WR( b, TSI_CBAL_REG, (vme_base & ~(TSI_CRG_SIZE-1)));
1309        TSI_WR( b, TSI_CRGAT_REG, mode );
1310
1311        return 0;
1312}
1313
1314int
1315vmeTsi148MapCRG(uint32_t vme_base, uint32_t as )
1316{
1317        return vmeTsi148MapCRGXX( THEBASE, vme_base, as );
1318}
1319
1320/* Interrupt Subsystem */
1321
1322typedef struct
1323IRQEntryRec_ {
1324                VmeTsi148ISR    isr;
1325                void                    *usrData;
1326} IRQEntryRec, *IRQEntry;
1327
1328static IRQEntry irqHdlTbl[TSI_NUM_INT_VECS]={0};
1329
1330int        vmeTsi148IrqMgrInstalled = 0;
1331int        vmeTsi148RegPort         = -1;
1332int        vmeTsi148RegCSR                      = 0;
1333BERegister *vmeTsi148RegBase        = 0;
1334
1335static volatile unsigned long   wire_mask[TSI_NUM_WIRES]     = {0};
1336/* wires are offset by 1 so we can initialize the wire table to all zeros */
1337static int                                              tsi_wire[TSI_NUM_WIRES] = {0};
1338
1339/* how should we iack a given level, 1,2,4 bytes? */
1340static unsigned char tsi_iack_width[7] = {
1341        1,1,1,1,1,1,1
1342};
1343
1344/* map universe compatible vector # to Tsi slot (which maps to bit layout in stat/enable/... regs) */
1345static int uni2tsi_vec_map[TSI_NUM_INT_VECS-256] = {
1346        /* 256 no VOWN interrupt */                     -1,
1347        /* TSI_DMA_INT_VEC                      257 */  256 + 24 - 8,
1348        /* TSI_LERR_INT_VEC                     258 */  256 + 13 - 8,
1349        /* TSI_VERR_INT_VEC                     259 */  256 + 12 - 8,
1350        /* 260 is reserved       */                     -1,
1351        /* TSI_VME_SW_IACK_INT_VEC      261 */  256 + 10 - 8,
1352        /* 262 no PCI SW IRQ     */                     -1,
1353        /* TSI_SYSFAIL_INT_VEC          263 */  256 +  9 - 8,
1354        /* TSI_ACFAIL_INT_VEC           264 */  256 +  8 - 8,
1355        /* TSI_MBOX0_INT_VEC            265 */  256 + 16 - 8,
1356        /* TSI_MBOX1_INT_VEC            266 */  256 + 17 - 8,
1357        /* TSI_MBOX2_INT_VEC            267 */  256 + 18 - 8,
1358        /* TSI_MBOX3_INT_VEC            268 */  256 + 19 - 8,
1359        /* TSI_LM0_INT_VEC                      269 */  256 + 20 - 8,
1360        /* TSI_LM1_INT_VEC                      270 */  256 + 21 - 8,
1361        /* TSI_LM2_INT_VEC                      271 */  256 + 22 - 8,
1362        /* TSI_LM3_INT_VEC                      272 */  256 + 23 - 8,
1363/* New vectors; only on TSI148 */
1364        /* TSI_VIES_INT_VEC                     273 */  256 + 11 - 8,
1365        /* TSI_DMA1_INT_VEC                     274 */  256 + 25 - 8,
1366};
1367
1368/* and the reverse; map tsi bit number to universe compatible 'special' vector number */
1369static int tsi2uni_vec_map[TSI_NUM_INT_VECS - 256] = {
1370        TSI_ACFAIL_INT_VEC,
1371        TSI_SYSFAIL_INT_VEC,
1372        TSI_VME_SW_IACK_INT_VEC,
1373        TSI_VIES_INT_VEC,
1374        TSI_VERR_INT_VEC,
1375        TSI_LERR_INT_VEC,
1376        -1,
1377        -1,
1378        TSI_MBOX0_INT_VEC,
1379        TSI_MBOX1_INT_VEC,
1380        TSI_MBOX2_INT_VEC,
1381        TSI_MBOX3_INT_VEC,
1382        TSI_LM0_INT_VEC,
1383        TSI_LM1_INT_VEC,
1384        TSI_LM2_INT_VEC,
1385        TSI_LM3_INT_VEC,
1386        TSI_DMA_INT_VEC,
1387        TSI_DMA1_INT_VEC,
1388        -1,
1389};
1390
1391static inline int
1392uni2tsivec(int v)
1393{
1394        if ( v < 0 || v >= TSI_NUM_INT_VECS )
1395                return -1;
1396        return v < 256 ? v : uni2tsi_vec_map[v-256];
1397}
1398
1399static int
1400lvl2bitno(unsigned int level)
1401{
1402        if ( level >= 256 )
1403                return uni2tsivec(level) + 8 - 256;
1404        else if ( level < 8 && level > 0 )
1405                return level;
1406        return -1;
1407}
1408
1409int
1410vmeTsi148IntRoute(unsigned int level, unsigned int pin)
1411{
1412int                             i;
1413unsigned long   mask, shift, mapreg, flags, wire;
1414
1415        if ( pin >= TSI_NUM_WIRES || ! tsi_wire[pin] || !vmeTsi148IrqMgrInstalled )
1416                return -1;
1417
1418        if ( level >= 256 ) {
1419                if ( (i = uni2tsivec(level)) < 0 )
1420                        return -1;
1421                shift = 8 + (i-256);
1422        } else if ( 1 <= level && level <=7 ) {
1423                shift = level;
1424        } else {
1425                return -1;      /* invalid level */
1426        }
1427
1428        mask = 1<<shift;
1429
1430        /* calculate the mapping register and contents */
1431        if ( shift < 16 ) {
1432                mapreg = TSI_INTM2_REG;
1433        } else if ( shift < 32 ) {
1434                shift -= 16;
1435                mapreg = TSI_INTM1_REG;
1436        } else {
1437                return -1;
1438        }
1439
1440        shift <<=1;
1441
1442        /* wires are offset by 1 so we can initialize the wire table to all zeros */
1443        wire = (tsi_wire[pin]-1) << shift;
1444
1445rtems_interrupt_disable(flags);
1446
1447        for ( i = 0; i<TSI_NUM_WIRES; i++ ) {
1448                wire_mask[i] &= ~mask;
1449        }
1450        wire_mask[pin] |= mask;
1451
1452        mask = TSI_RD(THEBASE, mapreg) & ~ (0x3<<shift);
1453        mask |= wire;
1454        TSI_WR( THEBASE, mapreg, mask );
1455
1456rtems_interrupt_enable(flags);
1457        return 0;
1458}
1459
1460VmeTsi148ISR
1461vmeTsi148ISRGet(unsigned long vector, void **parg)
1462{
1463VmeTsi148ISR      rval = 0;
1464unsigned long     flags;
1465volatile IRQEntry *p;
1466int               v = uni2tsivec(vector);
1467
1468
1469        if ( v < 0 )
1470                return rval;
1471
1472        p = irqHdlTbl + v;
1473
1474        rtems_interrupt_disable(flags);
1475                if ( *p ) {
1476                        if ( parg )
1477                                *parg = (*p)->usrData;
1478                        rval = (*p)->isr;
1479                }
1480        rtems_interrupt_enable(flags);
1481
1482        return rval;
1483}
1484
1485static void
1486tsiVMEISR(rtems_irq_hdl_param arg)
1487{
1488int                                     pin = (int)arg;
1489BERegister                      *b  = THEBASE;
1490IRQEntry                        ip;
1491unsigned long           msk,lintstat,vector, vecarg;
1492int                                     lvl;
1493
1494        /* only handle interrupts routed to this pin */
1495
1496        /* NOTE: we read the status register over VME, thus flushing the FIFO
1497         *       where the user ISR possibly left write commands to clear
1498         *       the interrupt condition at the device.
1499         *       This is very important - otherwise, the IRQ level may still be
1500         *       asserted and we would detect an interrupt here but the subsequent
1501         *       IACK would fail since the write operation was flushed to the
1502         *       device in the mean time.
1503         */
1504        while ( (lintstat  = (TSI_RD(vmeTsi148RegBase, TSI_INTS_REG) & wire_mask[pin])) ) {
1505
1506                /* bit 0 is never set since it is never set in wire_mask */
1507
1508                do {
1509                        /* simplicity is king; just handle them in MSB to LSB order; reserved bits read as 0 */
1510#ifdef __PPC__
1511                        asm volatile("cntlzw %0, %1":"=r"(lvl):"r"(lintstat));
1512                        lvl = 31-lvl;
1513                        msk = 1<<lvl;
1514#else
1515                        { static unsigned long m[] = {
1516                                                                                         0xffff0000, 0xff00ff00, 0xf0f0f0f0, 0xcccccccc, 0xaaaaaaaa
1517                                                                                 };
1518                        int      i;
1519                        unsigned tmp;
1520
1521                        /* lintstat has already been checked...
1522                        if ( !lintstat ) {
1523                           lvl = -1; msk = 0;
1524                        } else
1525                         */
1526                        for ( i=0, lvl=0, msk = lintstat; i<5; i++ ) {
1527                                lvl <<= 1;
1528                                if ( (tmp = msk & m[i]) ) {
1529                                        lvl++;
1530                                        msk = tmp;
1531                                } else
1532                                        msk = msk & ~m[i];
1533                        }
1534                        }
1535#endif
1536
1537                        if ( lvl > 7 ) {
1538                                /* clear this interrupt level */
1539                                TSI_WR(b, TSI_INTC_REG, msk);
1540                                vector = 256 + lvl - 8;
1541                                vecarg = tsi2uni_vec_map[lvl-8];
1542                        } else {
1543                                /* need to do get the vector for this level */
1544                                switch ( tsi_iack_width[lvl-1] ) {
1545                                        default:
1546                                        case  1:
1547                                                vector = TSI_RD8(b, TSI_VIACK_1_REG - 4 + (lvl<<2) + 3);
1548                                                break;
1549
1550                                        case  2:
1551                                                vector = TSI_RD16(b, TSI_VIACK_1_REG - 4 + (lvl<<2) + 2);
1552                                                break;
1553
1554                                        case  4:
1555                                                vector = TSI_RD(b, TSI_VIACK_1_REG - 4 + (lvl<<2));
1556                                                break;
1557                                }
1558                                vecarg = vector;
1559                        }
1560
1561                        if ( !(ip=irqHdlTbl[vector])) {
1562                                /* TODO: log error message - RTEMS has no logger :-( */
1563                                vmeTsi148IntDisable(lvl);
1564                                printk("vmeTsi148 ISR: ERROR: no handler registered (level %i) IACK 0x%08lx -- DISABLING level %i\n",
1565                                                lvl, vector, lvl);
1566                        } else {
1567                                /* dispatch handler, it must clear the IRQ at the device */
1568                                ip->isr(ip->usrData, vecarg);
1569                                /* convenience for disobedient users who don't use in_xxx/out_xxx; make
1570                                 * sure we order the subsequent read from the status register after
1571                                 * their business.
1572                                 */
1573                                iobarrier_rw();
1574                        }
1575                } while ( (lintstat &= ~msk) );
1576                /* check if a new irq is pending already */
1577        }
1578}
1579
1580
1581static void
1582my_no_op(const rtems_irq_connect_data * arg)
1583{}
1584
1585static int
1586my_isOn(const rtems_irq_connect_data *arg)
1587{
1588                return (int)(TSI_RD(THEBASE, TSI_INTEO_REG) & TSI_RD(THEBASE, TSI_INTEN_REG));
1589}
1590
1591static void
1592connectIsr(int shared, rtems_irq_hdl isr, int pic_line, int slot)
1593{
1594rtems_irq_connect_data  xx;
1595        xx.on     = my_no_op; /* at _least_ they could check for a 0 pointer */
1596        xx.off    = my_no_op;
1597        xx.isOn   = my_isOn;
1598        xx.hdl    = isr;
1599        xx.handle = (rtems_irq_hdl_param)slot;
1600        xx.name   = pic_line;
1601
1602        if ( shared ) {
1603#if BSP_SHARED_HANDLER_SUPPORT > 0
1604                if (!BSP_install_rtems_shared_irq_handler(&xx))
1605                        rtems_panic("unable to install vmeTsi148 shared irq handler");
1606#else
1607        uprintf(stderr,"vmeTsi148: WARNING: your BSP doesn't support sharing interrupts\n");
1608                if (!BSP_install_rtems_irq_handler(&xx))
1609                        rtems_panic("unable to install vmeTsi148 irq handler");
1610#endif
1611        } else {
1612                if (!BSP_install_rtems_irq_handler(&xx))
1613                        rtems_panic("unable to install vmeTsi148 irq handler");
1614        }
1615}
1616
1617int
1618vmeTsi148InstallIrqMgrAlt(int shared, int tsi_pin0, int pic_pin0, ...)
1619{
1620int             rval;
1621va_list ap;
1622        va_start(ap, pic_pin0);
1623        rval = vmeTsi148InstallIrqMgrVa(shared, tsi_pin0, pic_pin0, ap);
1624        va_end(ap);
1625        return rval;
1626}
1627
1628#ifndef BSP_EARLY_PROBE_VME
1629#define BSP_EARLY_PROBE_VME(addr)       \
1630        (                                                                                                                                                                                                       \
1631                vmeTsi148ClearVMEBusErrorsXX( THEBASE, 0 ),                                                                                             \
1632                ( ((PCI_DEVICE_TSI148 << 16) | PCI_VENDOR_TUNDRA ) == TSI_LE_RD32( ((BERegister*)(addr)), 0 )   \
1633                 && 0 == vmeTsi148ClearVMEBusErrorsXX( THEBASE, 0 ) )                                                                           \
1634        )
1635#endif
1636
1637/* Check if there is a vme address/as is mapped in any of the outbound windows
1638 * and look for the PCI vendordevice ID there.
1639 * RETURNS: -1 on error (no mapping or probe failure), outbound window # (0..7)
1640 *          on success. Address translated into CPU address is returned in *pcpu_addr.
1641 */
1642static int
1643mappedAndProbed(unsigned long vme_addr, unsigned as, unsigned long *pcpu_addr)
1644{
1645int j;
1646char *regtype = (as & VME_AM_MASK) == VME_AM_CSR ? "CSR" : "CRG";
1647
1648        /* try to find mapping */
1649        if ( 0 > (j = xlateFindPort(
1650                                THEBASE,
1651                                1, 0,
1652                                as | VME_MODE_AS_MATCH,
1653                                vme_addr,
1654                                pcpu_addr ) ) ) {
1655                        uprintf(stderr,"vmeTsi148 - Unable to find mapping for %s VME base (0x%08x)\n", regtype, vme_addr);
1656                        uprintf(stderr,"            in outbound windows.\n");
1657        }
1658        else {
1659                        /* found a slot number; probe it */
1660                        *pcpu_addr = BSP_PCI2LOCAL_ADDR( *pcpu_addr );
1661                        if ( BSP_EARLY_PROBE_VME(*pcpu_addr) ) {
1662                                uprintf(stderr,"vmeTsi148 - IRQ manager using VME %s to flush FIFO\n", regtype);
1663                                return j;
1664                        } else {
1665                                uprintf(stderr,"vmeTsi148 - Found slot info but detection of tsi148 in VME %s space failed\n", regtype);
1666                        }
1667        }
1668        return -1;
1669}
1670
1671int
1672vmeTsi148InstallIrqMgrVa(int shared, int tsi_pin0, int pic_pin0, va_list ap)
1673{
1674int     i,j, specialPin, tsi_pin[TSI_NUM_WIRES+1], pic_pin[TSI_NUM_WIRES];
1675unsigned long cpu_base, vme_reg_base;
1676
1677        if (vmeTsi148IrqMgrInstalled)                  return -4;
1678
1679        /* check parameters */
1680
1681        if ( tsi_pin0 < 0 || tsi_pin0 > 3 )            return -1;
1682
1683        tsi_pin[0] = tsi_pin0;
1684        pic_pin[0] = pic_pin0 < 0 ? devs[0].irqLine : pic_pin0;
1685        i = 1;
1686        while ( (tsi_pin[i] = va_arg(ap, int)) >= 0 ) {
1687
1688                if ( i >= TSI_NUM_WIRES ) {
1689                                                               return -5;
1690                }
1691
1692                pic_pin[i] = va_arg(ap,int);
1693
1694                if ( tsi_pin[i] > 3 )                      return -2;
1695                if ( pic_pin[i] < 0 )                      return -3;
1696                i++;
1697        }
1698
1699        /* all routings must be different */
1700        for ( i=0; tsi_pin[i] >= 0; i++ ) {
1701                for ( j=i+1; tsi_pin[j] >= 0; j++ ) {
1702                        if ( tsi_pin[j] == tsi_pin[i] )        return -6;
1703                        if ( pic_pin[j] == pic_pin[i] )        return -7;
1704                }
1705        }
1706
1707        i        = -1;
1708
1709        /* first try VME CSR space; do we have a base address set ? */
1710
1711        uprintf(stderr,"vmeTsi148 IRQ manager: looking for registers on VME...\n");
1712
1713        if ( ( i = ((TSI_RD( THEBASE, TSI_CBAR_REG ) & 0xff) >> 3) ) > 0 ) {
1714                uprintf(stderr,"Trying to find CSR on VME...\n");
1715                vme_reg_base = i*0x80000 + TSI_CSR_OFFSET;
1716                i = mappedAndProbed( vme_reg_base, VME_AM_CSR , &cpu_base);
1717                if ( i >= 0 )
1718                        vmeTsi148RegCSR = 1;
1719        } else {
1720                i = -1;
1721        }
1722
1723        if ( -1 == i ) {
1724
1725                uprintf(stderr,"Trying to find CRG on VME...\n");
1726
1727                /* Next we see if the CRG block is mapped to VME */
1728
1729                if ( (TSI_CRGAT_EN & (j = TSI_RD( THEBASE, TSI_CRGAT_REG ))) ) {
1730                        switch ( j & TSI_CRGAT_AS_MSK ) {
1731                                case TSI_CRGAT_A16 : i = VME_AM_SUP_SHORT_IO; break;
1732                                case TSI_CRGAT_A24 : i = VME_AM_STD_SUP_DATA; break;
1733                                case TSI_CRGAT_A32 : i = VME_AM_EXT_SUP_DATA; break;
1734                                default:
1735                                break;
1736                        }
1737                        vme_reg_base = TSI_RD( THEBASE, TSI_CBAL_REG ) & ~ (TSI_CRG_SIZE - 1);
1738                }
1739
1740                if ( -1 == i ) {
1741                } else {
1742                        i = mappedAndProbed( vme_reg_base, (i & VME_AM_MASK), &cpu_base );
1743                }
1744        }
1745
1746        if ( i < 0 ) {
1747                        uprintf(stderr,"vmeTsi148 IRQ manager - BSP configuration error: registers not found on VME\n");
1748                        uprintf(stderr,"(should open outbound window to CSR space or map CRG [vmeTsi148MapCRG()])\n");
1749                        uprintf(stderr,"Falling back to PCI but you might experience spurious VME interrupts; read a register\n");
1750                        uprintf(stderr,"back from user ISR to flush posted-write FIFO as a work-around\n");
1751                        cpu_base = (unsigned long)THEBASE;
1752                        i        = -1;
1753        }
1754
1755        vmeTsi148RegBase = (BERegister*)cpu_base;
1756        vmeTsi148RegPort = i;
1757
1758        /* give them a chance to override buggy PCI info */
1759        if ( pic_pin[0] >= 0 && devs[0].irqLine != pic_pin[0] ) {
1760                uprintf(stderr,"Overriding main IRQ line PCI info with %d\n",
1761                                pic_pin[0]);
1762                devs[0].irqLine = pic_pin[0];
1763        }
1764
1765        for ( i = 0; tsi_pin[i] >= 0; i++ ) {
1766                /* offset wire # by one so we can initialize to 0 == invalid */
1767                tsi_wire[i] = tsi_pin[i] + 1;
1768                connectIsr(shared, tsiVMEISR, pic_pin[i], i);
1769        }
1770
1771        specialPin = tsi_pin[1] >= 0 ? 1 : 0;
1772
1773        /* setup routing */
1774
1775        /* IntRoute checks for mgr being installed */
1776        vmeTsi148IrqMgrInstalled=1;
1777
1778        /* route 7 VME irqs to first / 'normal' pin */
1779        for ( i=1; i<8; i++ )
1780                vmeTsi148IntRoute( i, 0 );
1781        for ( i=TSI_DMA_INT_VEC; i<TSI_NUM_INT_VECS; i++ )
1782                vmeTsi148IntRoute( i, specialPin );
1783
1784        for ( i = 0; i<TSI_NUM_WIRES; i++ ) {
1785                /* remember (for unloading the driver) */
1786                devs[0].pic_pin[i] = ( ( tsi_pin[i] >=0 ) ? pic_pin[i] : -1 );
1787        }
1788
1789        return 0;
1790}
1791
1792int
1793vmeTsi148InstallISR(unsigned long vector, VmeTsi148ISR hdl, void *arg)
1794{
1795IRQEntry          ip;
1796int                               v;
1797unsigned long     flags;
1798volatile IRQEntry *p;
1799
1800                if ( !vmeTsi148IrqMgrInstalled || (v = uni2tsivec(vector)) < 0 )
1801                        return -1;
1802
1803                p = irqHdlTbl + v;
1804
1805                if (*p || !(ip=(IRQEntry)malloc(sizeof(IRQEntryRec))))
1806                                return -1;
1807
1808                ip->isr=hdl;
1809                ip->usrData=arg;
1810
1811                rtems_interrupt_disable(flags);
1812                if (*p) {
1813                        rtems_interrupt_enable(flags);
1814                        free(ip);
1815                        return -1;
1816                }
1817                *p = ip;
1818                rtems_interrupt_enable(flags);
1819                return 0;
1820}
1821
1822int
1823vmeTsi148RemoveISR(unsigned long vector, VmeTsi148ISR hdl, void *arg)
1824{
1825int               v;
1826IRQEntry          ip;
1827unsigned long     flags;
1828volatile IRQEntry *p;
1829
1830                if ( !vmeTsi148IrqMgrInstalled || (v = uni2tsivec(vector)) < 0 )
1831                        return -1;
1832
1833                p = irqHdlTbl + v;
1834
1835                rtems_interrupt_disable(flags);
1836                ip = *p;
1837                if ( !ip || ip->isr!=hdl || ip->usrData!=arg ) {
1838                                rtems_interrupt_enable(flags);
1839                                return -1;
1840                }
1841                *p = 0;
1842                rtems_interrupt_enable(flags);
1843
1844                free(ip);
1845                return 0;
1846}
1847
1848static int
1849intDoEnDis(unsigned int level, int dis)
1850{
1851BERegister              *b = THEBASE;
1852unsigned long   flags, v;
1853int                             shift;
1854
1855        if (  ! vmeTsi148IrqMgrInstalled || (shift = lvl2bitno(level)) < 0 )
1856                return -1;
1857
1858        v = 1<<shift;
1859
1860        if ( !dis )
1861                return (int)(v & TSI_RD(b, TSI_INTEO_REG) & TSI_RD(b, TSI_INTEN_REG)) ? 1 : 0;
1862
1863        rtems_interrupt_disable(flags);
1864        if ( dis<0 ) {
1865                TSI_WR(b, TSI_INTEN_REG, TSI_RD(b, TSI_INTEN_REG) & ~v);
1866                TSI_WR(b, TSI_INTEO_REG, TSI_RD(b, TSI_INTEO_REG) & ~v);
1867        } else {
1868                TSI_WR(b, TSI_INTEN_REG, TSI_RD(b, TSI_INTEN_REG) |  v);
1869                TSI_WR(b, TSI_INTEO_REG, TSI_RD(b, TSI_INTEO_REG) |  v);
1870        }
1871        rtems_interrupt_enable(flags);
1872        return 0;
1873}
1874
1875int
1876vmeTsi148IntEnable(unsigned int level)
1877{
1878        return intDoEnDis(level, 1);
1879}
1880
1881int
1882vmeTsi148IntDisable(unsigned int level)
1883{
1884        return intDoEnDis(level, -1);
1885}
1886
1887int
1888vmeTsi148IntIsEnabled(unsigned int level)
1889{
1890        return intDoEnDis(level, 0);
1891}
1892
1893/* Set IACK width (1,2, or 4 bytes) for a given interrupt level.
1894 *
1895 * 'width' arg may be 0,1,2 or 4. If zero, the currently active
1896 * value is returned but not modified.
1897 *
1898 * RETURNS: old width or -1 if invalid argument.
1899 */
1900
1901int
1902vmeTsi148SetIackWidth(int level, int width)
1903{
1904int rval;
1905        if ( level < 1 || level > 7 || !vmeTsi148IrqMgrInstalled )
1906                return -1;
1907
1908        switch ( width ) {
1909                default: return -1;
1910                case 0:
1911                case 1:
1912                case 2:
1913                case 4:
1914                break;
1915        }
1916
1917        rval = tsi_iack_width[level-1];
1918        if ( width )
1919                tsi_iack_width[level-1] = width;
1920        return rval;
1921}
1922
1923int
1924vmeTsi148IntRaiseXX(BERegister *base, int level, unsigned vector)
1925{
1926unsigned long v;
1927
1928        CHECK_BASE(base,0,-1);
1929
1930        if ( level < 1 || level > 7 || vector > 255 )
1931                return -1;      /* invalid argument */
1932
1933        /* Check if already asserted */
1934        if ( (v = TSI_RD(base, TSI_VICR_REG)) & TSI_VICR_IRQS ) {
1935                return -2;  /* already asserted */
1936        }
1937
1938        v &= ~255;
1939
1940        v |= TSI_VICR_IRQL(level) | TSI_VICR_STID(vector);
1941
1942        /* Write Vector */
1943        TSI_WR(base, TSI_VICR_REG, v);
1944
1945        return 0;
1946
1947}
1948
1949int
1950vmeTsi148IntRaise(int level, unsigned vector)
1951{
1952        return vmeTsi148IntRaiseXX(THEBASE, level, vector);
1953}
1954
1955/* Loopback test of VME/Tsi148 internal interrupts */
1956
1957typedef struct {
1958        rtems_id        q;
1959        int                     l;
1960} LoopbackTstArgs;
1961
1962static void
1963loopbackTstIsr(void *arg, unsigned long vector)
1964{
1965LoopbackTstArgs *pa = arg;
1966        if ( RTEMS_SUCCESSFUL != rtems_message_queue_send(pa->q, (void*)&vector, sizeof(vector)) ) {
1967                /* Overrun ? */
1968                printk("vmeTsi148IntLoopbackTst: (ISR) message queue full / overrun ? disabling IRQ level %i\n", pa->l);
1969                vmeTsi148IntDisable(pa->l);
1970        }
1971}
1972
1973int
1974vmeTsi148IntLoopbackTst(int level, unsigned vector)
1975{
1976BERegister                      *b = THEBASE;
1977rtems_status_code       sc;
1978rtems_id                        q = 0;
1979int                                     installed = 0;
1980int                                     i, err = 0;
1981int                                     doDisable = 0;
1982size_t                          size;
1983unsigned long           msg;
1984char *                          irqfmt  = "VME IRQ @vector %3i %s";
1985char *                          iackfmt = "VME IACK            %s";
1986LoopbackTstArgs         a;
1987
1988        CHECK_BASE(b,0,-1);
1989
1990        /* arg check */
1991        if ( level < 1 || level > 7 || vector > 255 )
1992                return -1;
1993
1994        /* Create message queue */
1995        if ( RTEMS_SUCCESSFUL != (sc=rtems_message_queue_create(
1996                                                                        rtems_build_name('t' ,'U','I','I'),
1997                                                                        4,
1998                                                                        sizeof(unsigned long),
1999                                                                        0,  /* default attributes: fifo, local */
2000                                                                        &q)) ) {
2001                rtems_error(sc, "vmeTsi148IntLoopbackTst: Unable to create message queue");
2002                goto bail;
2003        }
2004
2005        a.q = q;
2006        a.l = level;
2007
2008        /* Install handlers */
2009        if ( vmeTsi148InstallISR(vector, loopbackTstIsr, (void*)&a) ) {
2010                uprintf(stderr,"Unable to install VME ISR to vector %i\n",vector);
2011                goto bail;
2012        }
2013        installed++;
2014        if ( vmeTsi148InstallISR(TSI_VME_SW_IACK_INT_VEC, loopbackTstIsr, (void*)&a) ) {
2015                uprintf(stderr,"Unable to install VME ISR to IACK special vector %i\n",TSI_VME_SW_IACK_INT_VEC);
2016                goto bail;
2017        }
2018        installed++;
2019
2020        if ( !vmeTsi148IntIsEnabled(level) && 0==vmeTsi148IntEnable(level) )
2021                doDisable = 1;
2022
2023        /* make sure there are no pending interrupts */
2024        TSI_WR(b, TSI_INTC_REG, TSI_INTC_IACKC);
2025
2026        if ( vmeTsi148IntEnable( TSI_VME_SW_IACK_INT_VEC ) ) {
2027                uprintf(stderr,"Unable to enable IACK interrupt\n");
2028                goto bail;
2029        }
2030
2031        printf("vmeTsi148 VME interrupt loopback test; STARTING...\n");
2032        printf(" --> asserting VME IRQ level %i\n", level);
2033        vmeTsi148IntRaise(level, vector);
2034
2035        for ( i = 0; i< 3; i++ ) {
2036        sc = rtems_message_queue_receive(
2037                            q,
2038                            &msg,
2039                            &size,
2040                            RTEMS_WAIT,
2041                            20);
2042                if ( sc ) {
2043                        if ( RTEMS_TIMEOUT == sc && i>1 ) {
2044                                /* OK; we dont' expect more to happen */
2045                                sc = 0;
2046                        } else {
2047                                rtems_error(sc,"Error waiting for interrupts");
2048                        }
2049                        break;
2050                }
2051                if ( msg == vector ) {
2052                        if ( !irqfmt ) {
2053                                printf("Excess VME IRQ received ?? -- BAD\n");
2054                                err = 1;
2055                        } else {
2056                                printf(irqfmt, vector, "received -- PASSED\n");
2057                                irqfmt = 0;
2058                        }
2059                } else if ( msg == TSI_VME_SW_IACK_INT_VEC ) {
2060                        if ( !iackfmt ) {
2061                                printf("Excess VME IACK received ?? -- BAD\n");
2062                                err = 1;
2063                        } else {
2064                                printf(iackfmt, "received -- PASSED\n");
2065                                iackfmt = 0;
2066                        }
2067                } else {
2068                        printf("Unknown IRQ (vector %lu) received -- BAD\n", msg);
2069                        err = 1;
2070                }
2071        }
2072
2073
2074        /* Missing anything ? */
2075        if ( irqfmt ) {
2076                printf(irqfmt,vector, "MISSED -- BAD\n");
2077                err = 1;
2078        }
2079        if ( iackfmt ) {
2080                printf(iackfmt, "MISSED -- BAD\n");
2081                err = 1;
2082        }
2083
2084        printf("FINISHED.\n");
2085
2086bail:
2087        if ( doDisable )
2088                vmeTsi148IntDisable(level);
2089        vmeTsi148IntDisable( TSI_VME_SW_IACK_INT_VEC );
2090        if ( installed > 0 )
2091                vmeTsi148RemoveISR(vector, loopbackTstIsr, (void*)&a);
2092        if ( installed > 1 )
2093                vmeTsi148RemoveISR(TSI_VME_SW_IACK_INT_VEC, loopbackTstIsr, (void*)&a);
2094        if ( q )
2095                rtems_message_queue_delete(q);
2096
2097        return sc ? sc : err;
2098}
2099
2100unsigned long
2101vmeTsi148ClearVMEBusErrorsXX(BERegister *base, uint32_t *paddr)
2102{
2103unsigned long rval;
2104
2105        CHECK_BASE(base,1,-1);
2106
2107        rval = TSI_RD(base, TSI_VEAT_REG);
2108        if ( rval & TSI_VEAT_VES ) {
2109                if ( paddr ) {
2110#if 0 /* no 64-bit support yet */
2111                        *paddr  = ((unsigned long long)TSI_RD(base, TSI_VEAU_REG))<<32;
2112                        *paddr |= TSI_RD(base, TSI_VEAL_REG);
2113#else
2114                        *paddr = TSI_RD(base, TSI_VEAL_REG);
2115#endif
2116                }
2117                /* clear errors */
2118                TSI_WR(base, TSI_VEAT_REG, TSI_VEAT_VESCL);
2119        } else {
2120                rval = 0;
2121        }
2122        return rval;
2123}
2124
2125unsigned long
2126vmeTsi148ClearVMEBusErrors(uint32_t *paddr)
2127{
2128        return vmeTsi148ClearVMEBusErrorsXX(THEBASE, paddr);
2129}
2130
2131/** DMA Support **/
2132
2133/* descriptor must be 8-byte aligned */
2134typedef struct VmeTsi148DmaListDescriptorRec_ {
2135        BEValue                                         dsau,  dsal;
2136        BEValue                                         ddau,  ddal;
2137        BEValue                                         dsat,  ddat;
2138        BEValue                                         dnlau, dnlal;
2139        BEValue                                         dcnt,  ddbs;
2140} VmeTsi148DmaListDescriptorRec;
2141
2142static void     tsi_desc_init  (DmaDescriptor);
2143static int      tsi_desc_setup (DmaDescriptor, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
2144static void     tsi_desc_setnxt(DmaDescriptor, DmaDescriptor);
2145static void     tsi_desc_dump  (DmaDescriptor);
2146static int      tsi_desc_start (volatile void *controller_addr, int channel, DmaDescriptor p);
2147
2148VMEDmaListClassRec      vmeTsi148DmaListClass = {
2149        desc_size:  sizeof(VmeTsi148DmaListDescriptorRec),
2150        desc_align: 8,
2151        freeList:   0,
2152        desc_alloc: 0,
2153        desc_free:  0,
2154        desc_init:  tsi_desc_init,
2155        desc_setnxt:tsi_desc_setnxt,
2156        desc_setup: tsi_desc_setup,
2157        desc_start: tsi_desc_start,
2158        desc_refr:  0,
2159        desc_dump:      tsi_desc_dump,
2160};
2161
2162/* DMA Control */
2163#define TSI_DMA_REG(off,i)      ((off)+(((i)&1)<<7))
2164
2165#define TSI_DCTL_REG(i)         TSI_DMA_REG(0x500,i)
2166#define TSI_DCTL0_REG           0x500
2167#define TSI_DCTL1_REG           0x580
2168#   define TSI_DCTL_ABT         (1<<27) /* abort */
2169#   define TSI_DCTL_PAU         (1<<26) /* pause */
2170#   define TSI_DCTL_DGO         (1<<25) /* GO    */
2171#   define TSI_DCTL_MOD         (1<<23) /* linked list: 0, direct: 1 */
2172#   define TSI_DCTL_VFAR        (1<<17) /* flush FIFO on VME error: 1 (discard: 0) */
2173#   define TSI_DCTL_PFAR        (1<<16) /* flush FIFO on PCI error: 1 (discard: 0) */
2174
2175#   define TSI_DCTL_VBKS(i)     (((i)&7)<<12) /* VME block size */
2176#   define TSI_DCTL_VBKS_32     TSI_DCTL_VBKS(0)
2177#   define TSI_DCTL_VBKS_64     TSI_DCTL_VBKS(1)
2178#   define TSI_DCTL_VBKS_128    TSI_DCTL_VBKS(2)
2179#   define TSI_DCTL_VBKS_256    TSI_DCTL_VBKS(3)
2180#   define TSI_DCTL_VBKS_512    TSI_DCTL_VBKS(4)
2181#   define TSI_DCTL_VBKS_1024   TSI_DCTL_VBKS(5)
2182#   define TSI_DCTL_VBKS_2048   TSI_DCTL_VBKS(6)
2183#   define TSI_DCTL_VBKS_4096   TSI_DCTL_VBKS(7)
2184
2185#   define TSI_DCTL_VBOT(i)     (((i)&7)<< 8) /* VME back-off time */
2186#   define TSI_DCTL_VBOT_0us    TSI_DCTL_VBOT(0)
2187#   define TSI_DCTL_VBOT_1us    TSI_DCTL_VBOT(1)
2188#   define TSI_DCTL_VBOT_2us    TSI_DCTL_VBOT(2)
2189#   define TSI_DCTL_VBOT_4us    TSI_DCTL_VBOT(3)
2190#   define TSI_DCTL_VBOT_8us    TSI_DCTL_VBOT(4)
2191#   define TSI_DCTL_VBOT_16us   TSI_DCTL_VBOT(5)
2192#   define TSI_DCTL_VBOT_32us   TSI_DCTL_VBOT(6)
2193#   define TSI_DCTL_VBOT_64us   TSI_DCTL_VBOT(7)
2194
2195#   define TSI_DCTL_PBKS(i)     (((i)&7)<< 4) /* PCI block size */
2196#   define TSI_DCTL_PBKS_32     TSI_DCTL_PBKS(0)
2197#   define TSI_DCTL_PBKS_64     TSI_DCTL_PBKS(1)
2198#   define TSI_DCTL_PBKS_128    TSI_DCTL_PBKS(2)
2199#   define TSI_DCTL_PBKS_256    TSI_DCTL_PBKS(3)
2200#   define TSI_DCTL_PBKS_512    TSI_DCTL_PBKS(4)
2201#   define TSI_DCTL_PBKS_1024   TSI_DCTL_PBKS(5)
2202#   define TSI_DCTL_PBKS_2048   TSI_DCTL_PBKS(6)
2203#   define TSI_DCTL_PBKS_4096   TSI_DCTL_PBKS(7)
2204
2205#   define TSI_DCTL_PBOT(i)     (((i)&7)<< 0) /* PCI back-off time */
2206#   define TSI_DCTL_PBOT_0us    TSI_DCTL_PBOT(0)
2207#   define TSI_DCTL_PBOT_1us    TSI_DCTL_PBOT(1)
2208#   define TSI_DCTL_PBOT_2us    TSI_DCTL_PBOT(2)
2209#   define TSI_DCTL_PBOT_4us    TSI_DCTL_PBOT(3)
2210#   define TSI_DCTL_PBOT_8us    TSI_DCTL_PBOT(4)
2211#   define TSI_DCTL_PBOT_16us   TSI_DCTL_PBOT(5)
2212#   define TSI_DCTL_PBOT_32us   TSI_DCTL_PBOT(6)
2213#   define TSI_DCTL_PBOT_64us   TSI_DCTL_PBOT(7)
2214
2215/* DMA Status */
2216#define TSI_DSTA_REG(i)         TSI_DMA_REG(0x504,i)
2217#define TSI_DSTA0_REG           0x504
2218#define TSI_DSTA1_REG           0x584
2219#   define TSI_DSTA_ERR         (1<<28)
2220#   define TSI_DSTA_ABT         (1<<27)
2221#   define TSI_DSTA_PAU         (1<<26)
2222#   define TSI_DSTA_DON         (1<<25)
2223#   define TSI_DSTA_BSY         (1<<24)
2224#   define TSI_DSTA_ERRS        (1<<20) /* Error source; PCI:1, VME:0 */
2225#   define TSI_DSTA_ERT_MSK     (3<<16) /* Error type                 */
2226#   define TSI_DSTA_ERT_BERR_E  (0<<16) /* 2eVME even or other bus error */
2227#   define TSI_DSTA_ERT_BERR_O  (1<<16) /* 2eVME odd bus error        */
2228#   define TSI_DSTA_ERT_SLVE_E  (2<<16) /* 2eVME even or other slave termination */
2229#   define TSI_DSTA_ERT_SLVE_O  (3<<16) /* 2eVME odd slave termination; 2eSST read last word invalid */
2230
2231/* DMA Current source address upper */
2232#define TSI_DCSAU_REG(i)        TSI_DMA_REG(0x508,i)
2233#define TSI_DCSAU0_REG          0x508
2234#define TSI_DCSAU1_REG          0x588
2235
2236/* DMA Current source address lower */
2237#define TSI_DCSAL_REG(i)        TSI_DMA_REG(0x50c,i)
2238#define TSI_DCSAL0_REG          0x50c
2239#define TSI_DCSAL1_REG          0x58c
2240
2241/* DMA Current destination address upper */
2242#define TSI_DCDAU_REG(i)        TSI_DMA_REG(0x510,i)
2243#define TSI_DCDAU0_REG          0x510
2244#define TSI_DCDAU1_REG          0x590
2245
2246/* DMA Current destination address lower */
2247#define TSI_DCDAL_REG(i)        TSI_DMA_REG(0x514,i)
2248#define TSI_DCDAL0_REG          0x514
2249#define TSI_DCDAL1_REG          0x594
2250
2251/* DMA Current link address upper */
2252#define TSI_DCLAU_REG(i)        TSI_DMA_REG(0x518,i)
2253#define TSI_DCLAU0_REG          0x518
2254#define TSI_DCLAU1_REG          0x598
2255
2256/* DMA Current link address lower */
2257#define TSI_DCLAL_REG(i)        TSI_DMA_REG(0x51c,i)
2258#define TSI_DCLAL0_REG          0x51c
2259#define TSI_DCLAL1_REG          0x59c
2260
2261/* DMA Source address upper */
2262#define TSI_DSAU_REG(i)         TSI_DMA_REG(0x520,i)
2263#define TSI_DSAU0_REG           0x520
2264#define TSI_DSAU1_REG           0x5a0
2265
2266/* DMA Source address lower */
2267#define TSI_DSAL_REG(i)         TSI_DMA_REG(0x524,i)
2268#define TSI_DSAL0_REG           0x524
2269#define TSI_DSAL1_REG           0x5a4
2270
2271/* DMA Destination address upper */
2272#define TSI_DDAU_REG(i)         TSI_DMA_REG(0x528,i)
2273#define TSI_DDAU0_REG           0x528
2274#define TSI_DDAU1_REG           0x5a8
2275
2276/* DMA Destination address lower */
2277#define TSI_DDAL_REG(i)         TSI_DMA_REG(0x52c,i)
2278#define TSI_DDAL0_REG           0x52c
2279#define TSI_DDAL1_REG           0x5ac
2280
2281/* DMA Source Attribute */
2282#define TSI_DSAT_REG(i)         TSI_DMA_REG(0x530,i)
2283#define TSI_DSAT0_REG           0x530
2284#define TSI_DSAT1_REG           0x5b0
2285
2286/* DMA Destination Attribute */
2287#define TSI_DDAT_REG(i)         TSI_DMA_REG(0x534,i)
2288#define TSI_DDAT0_REG           0x534
2289#define TSI_DDAT1_REG           0x5b4
2290
2291#   define TSI_DXAT_TYP(i)      (((i)&3)<<28)   /* Xfer type */
2292#   define TSI_DXAT_TYP_PCI     TSI_DXAT_TYP(0)
2293#   define TSI_DXAT_TYP_VME     TSI_DXAT_TYP(1)
2294#   define TSI_DSAT_TYP_PAT     TSI_DXAT_TYP(2) /* pattern */
2295
2296#   define TSI_DSAT_PSZ         (1<<25) /* pattern size 32-bit: 0, 8-bit: 1 */
2297#   define TSI_DSAT_NIN         (1<<24) /* no-increment */
2298
2299#       define TSI_DXAT_OTAT_MSK        ((1<<13)-1)     /* get bits compatible with OTAT */
2300
2301#   define TSI_DXAT_SSTM(i)     (((i)&3)<<11)   /* 2eSST Xfer rate (MB/s) */
2302#   define TSI_DXAT_SSTM_116    TSI_DXAT_SSTM(0)
2303#   define TSI_DXAT_SSTM_267    TSI_DXAT_SSTM(1)
2304#   define TSI_DXAT_SSTM_320    TSI_DXAT_SSTM(2)
2305
2306#   define TSI_DXAT_TM(i)       (((i)&7)<< 8) /* VME Xfer mode */
2307#   define TSI_DXAT_TM_SCT      TSI_DXAT_TM(0)
2308#   define TSI_DXAT_TM_BLT      TSI_DXAT_TM(1)
2309#   define TSI_DXAT_TM_MBLT     TSI_DXAT_TM(2)
2310#   define TSI_DXAT_TM_2eVME    TSI_DXAT_TM(3)
2311#   define TSI_DXAT_TM_2eSST    TSI_DXAT_TM(4)
2312#   define TSI_DSAT_TM_2eSST_B  TSI_DXAT_TM(5)  /* 2eSST broadcast */
2313
2314#   define TSI_DXAT_DBW(i)      (((i)&3)<< 6)   /* VME Data width */
2315#   define TSI_DXAT_DBW_16      TSI_DXAT_DBW(0)
2316#   define TSI_DXAT_DBW_32      TSI_DXAT_DBW(1)
2317
2318#   define TSI_DXAT_SUP         (1<<5)  /* supervisor access */
2319#   define TSI_DXAT_PGM         (1<<4)  /* program access    */
2320
2321#   define TSI_DXAT_AM(i)       (((i)&15)<<0)   /* VME Address mode */
2322#   define TSI_DXAT_AM_A16      TSI_DXAT_AM(0)
2323#   define TSI_DXAT_AM_A24      TSI_DXAT_AM(1)
2324#   define TSI_DXAT_AM_A32      TSI_DXAT_AM(2)
2325#   define TSI_DXAT_AM_A64      TSI_DXAT_AM(4)
2326#   define TSI_DXAT_AM_CSR      TSI_DXAT_AM(5)
2327
2328/* DMA Next link address upper */
2329#define TSI_DNLAU_REG(i)        TSI_DMA_REG(0x538,i)
2330#define TSI_DNLAU0_REG          0x538
2331#define TSI_DNLAU1_REG          0x5b8
2332
2333/* DMA Next link address lower */
2334#define TSI_DNLAL_REG(i)        TSI_DMA_REG(0x53c,i)
2335#define TSI_DNLAL0_REG          0x53c
2336#define TSI_DNLAL1_REG          0x5bc
2337
2338#       define TSI_DNLAL_LLA    1       /* last element in chain */
2339
2340/* DMA Byte Count */
2341#define TSI_DCNT_REG(i)         TSI_DMA_REG(0x540,i)
2342#define TSI_DCNT0_REG           0x540
2343#define TSI_DCNT1_REG           0x54c
2344
2345/* DMA 2eSST destination broadcast select */
2346#define TSI_DDBS_REG(i)         TSI_DMA_REG(0x544,i)
2347#define TSI_DDBS0_REG           0x544
2348#define TSI_DDBS1_REG           0x5c4
2349
2350/* Convert canonical xfer_mode into Tsi148 bits; return -1 if invalid */
2351static uint32_t
2352vme_attr(uint32_t xfer_mode)
2353{
2354uint32_t vme_mode;
2355        if ( am2omode(xfer_mode, &vme_mode) )
2356                return BSP_VMEDMA_STATUS_UNSUP;
2357
2358        /* am2omode may set prefetch and other bits */
2359        vme_mode &= TSI_DXAT_OTAT_MSK;
2360        vme_mode |= TSI_DXAT_TYP_VME;
2361
2362        if ( BSP_VMEDMA_MODE_NOINC_VME & xfer_mode )  {
2363                /* no-incr. only supported on source address */
2364                if ( (BSP_VMEDMA_MODE_PCI2VME & xfer_mode) )
2365                        return BSP_VMEDMA_STATUS_UNSUP;
2366                vme_mode |= TSI_DSAT_NIN;
2367        }
2368
2369        return vme_mode;
2370}
2371
2372static uint32_t
2373pci_attr(uint32_t xfer_mode)
2374{
2375uint32_t pci_mode = 0;
2376        if ( BSP_VMEDMA_MODE_NOINC_PCI & xfer_mode )  {
2377                /* no-incr. only supported on source address */
2378                if ( ! (BSP_VMEDMA_MODE_PCI2VME & xfer_mode) )
2379                        return BSP_VMEDMA_STATUS_UNSUP;
2380                pci_mode |= TSI_DSAT_NIN;
2381        }
2382        return pci_mode;
2383}
2384
2385static void tsi_desc_init(DmaDescriptor p)
2386{
2387VmeTsi148DmaListDescriptor d = p;
2388        st_be32( &d->dnlau, 0 );
2389        st_be32( &d->dnlal, TSI_DNLAL_LLA );
2390        st_be32( &d->ddbs, (1<<22)-1 ); /* SSTB broadcast not yet fully supported */
2391}
2392
2393static void
2394tsi_desc_setnxt(DmaDescriptor p, DmaDescriptor n)
2395{
2396VmeTsi148DmaListDescriptor d = p;
2397        if ( 0 == n ) {
2398                st_be32( &d->dnlal, TSI_DNLAL_LLA );
2399        } else {
2400                st_be32( &d->dnlal, BSP_LOCAL2PCI_ADDR((uint32_t)n) );
2401        }
2402}
2403
2404static void
2405tsi_desc_dump(DmaDescriptor p)
2406{
2407VmeTsi148DmaListDescriptor d = p;
2408                printf("   DSA: 0x%08lx%08lx\n", ld_be32(&d->dsau),  ld_be32(&d->dsal));
2409                printf("   DDA: 0x%08lx%08lx\n", ld_be32(&d->ddau),  ld_be32(&d->ddal));
2410                printf("   NLA: 0x%08lx%08lx\n", ld_be32(&d->dnlau), ld_be32(&d->dnlal));
2411                printf("   SAT: 0x%08lx              DAT: 0x%08lx\n", ld_be32(&d->dsat), ld_be32(&d->ddat));
2412                printf("   CNT: 0x%08lx\n",      ld_be32(&d->dcnt));
2413}
2414
2415
2416int
2417vmeTsi148DmaSetupXX(BERegister *base, int channel, uint32_t mode, uint32_t xfer_mode, void *custom)
2418{
2419uint32_t ctl = 0;
2420uint32_t vmeatt, pciatt, sat, dat;
2421
2422        if ( channel < 0 || channel > 1 )
2423                return BSP_VMEDMA_STATUS_UNSUP;
2424
2425        /* Check bus mode */
2426        if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == (vmeatt = vme_attr(xfer_mode)) )
2427                return -2;
2428
2429        /* Check PCI bus mode */
2430        if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == (pciatt = pci_attr(xfer_mode)) )
2431                return -3;
2432
2433        /* Compute control word; bottleneck is VME; */
2434        ctl |= TSI_DCTL_PBKS_32;
2435        ctl |= (BSP_VMEDMA_OPT_THROUGHPUT == mode ? TSI_DCTL_PBOT_0us : TSI_DCTL_PBOT_1us);
2436
2437        switch ( mode ) {
2438                case BSP_VMEDMA_OPT_THROUGHPUT:
2439                        ctl |= TSI_DCTL_VBKS_1024;
2440                        ctl |= TSI_DCTL_VBOT_0us;
2441                break;
2442
2443                case BSP_VMEDMA_OPT_LOWLATENCY:
2444                        ctl |= TSI_DCTL_VBKS_32;
2445                        ctl |= TSI_DCTL_VBOT_0us;
2446                break;
2447
2448                case BSP_VMEDMA_OPT_SHAREDBUS:
2449                        ctl |= TSI_DCTL_VBKS_128;
2450                        ctl |= TSI_DCTL_VBOT_64us;
2451                break;
2452
2453                case BSP_VMEDMA_OPT_CUSTOM:
2454                        ctl = *(uint32_t*)custom;
2455                break;
2456
2457                default:
2458                case BSP_VMEDMA_OPT_DEFAULT:
2459                        ctl = 0;
2460                break;
2461        }
2462        TSI_WR(base, TSI_DCTL_REG(channel), ctl);
2463        if ( BSP_VMEDMA_MODE_PCI2VME & xfer_mode ) {
2464                dat = vmeatt; sat = pciatt;
2465        } else {
2466                sat = vmeatt; dat = pciatt;
2467        }
2468        TSI_WR(base, TSI_DSAT_REG(channel), sat);
2469        TSI_WR(base, TSI_DDAT_REG(channel), dat);
2470        return 0;
2471}
2472
2473int
2474vmeTsi148DmaSetup(int channel, uint32_t mode, uint32_t xfer_mode, void *custom)
2475{
2476BERegister *base = THEBASE;
2477        return vmeTsi148DmaSetupXX(base, channel, mode, xfer_mode, custom);
2478}
2479
2480
2481int
2482vmeTsi148DmaListStartXX(BERegister *base, int channel, VmeTsi148DmaListDescriptor d)
2483{
2484uint32_t ctl;
2485
2486        if ( d ) {
2487                /* Set list pointer and start */
2488                if ( channel < 0 || channel > 1 )
2489                        return BSP_VMEDMA_STATUS_UNSUP;
2490
2491                if ( TSI_DSTA_BSY & TSI_RD(base, TSI_DSTA_REG(channel)) )
2492                        return BSP_VMEDMA_STATUS_BUSY;  /* channel busy */
2493
2494                TSI_WR(base, TSI_DNLAL_REG(channel), (uint32_t)BSP_LOCAL2PCI_ADDR(d));
2495
2496                asm volatile("":::"memory");
2497
2498                /* Start transfer */
2499                ctl  = TSI_RD(base, TSI_DCTL_REG(channel)) | TSI_DCTL_DGO;
2500                ctl &= ~TSI_DCTL_MOD;
2501                TSI_WR(base, TSI_DCTL_REG(channel), ctl);
2502        }
2503        /* else: list vs. direct mode is set by the respective start commands */
2504        return 0;
2505}
2506
2507int
2508vmeTsi148DmaListStart(int channel, VmeTsi148DmaListDescriptor d)
2509{
2510BERegister *base = THEBASE;
2511        return vmeTsi148DmaListStartXX(base, channel, d);
2512}
2513
2514int
2515vmeTsi148DmaStartXX(BERegister *base, int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes)
2516{
2517uint32_t src, dst, ctl;
2518
2519        if ( channel < 0 || channel > 1 )
2520                return BSP_VMEDMA_STATUS_UNSUP;
2521
2522        if ( TSI_DSTA_BSY & TSI_RD(base, TSI_DSTA_REG(channel)) )
2523                return BSP_VMEDMA_STATUS_BUSY;  /* channel busy */
2524
2525        /* retrieve direction from dst attribute */
2526        if ( TSI_DXAT_TYP_VME & TSI_RD(base, TSI_DDAT_REG(channel)) ) {
2527                dst = vme_addr;
2528                src = pci_addr;
2529        } else {
2530                src = vme_addr;
2531                dst = pci_addr;
2532        }
2533        /* FIXME: we leave the 'upper' registers (topmost 32bits) alone.
2534         *        Probably, we should reset them at init...
2535         */
2536        TSI_WR(base, TSI_DSAL_REG(channel), src);
2537        TSI_WR(base, TSI_DDAL_REG(channel), dst);
2538        TSI_WR(base, TSI_DCNT_REG(channel), n_bytes);
2539
2540        asm volatile("":::"memory");
2541
2542        /* Start transfer */
2543        ctl  = TSI_RD(base, TSI_DCTL_REG(channel)) | TSI_DCTL_DGO | TSI_DCTL_MOD;
2544        TSI_WR(base, TSI_DCTL_REG(channel), ctl);
2545
2546        return 0;
2547}
2548
2549int
2550vmeTsi148DmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes)
2551{
2552BERegister *base = THEBASE;
2553        return vmeTsi148DmaStartXX(base, channel, pci_addr, vme_addr, n_bytes);
2554}
2555
2556uint32_t
2557vmeTsi148DmaStatusXX(BERegister *base, int channel)
2558{
2559uint32_t        st = TSI_RD(base, TSI_DSTA_REG(channel));
2560
2561        if ( channel < 0 || channel > 1 )
2562                return BSP_VMEDMA_STATUS_UNSUP;
2563
2564        st = TSI_RD(base, TSI_DSTA_REG(channel));
2565
2566        /* Status can be zero if an empty list (all counts == 0) is executed */
2567        if ( (TSI_DSTA_DON & st) || 0 == st )
2568                return BSP_VMEDMA_STATUS_OK;
2569
2570        if ( TSI_DSTA_BSY & st )
2571                return BSP_VMEDMA_STATUS_BUSY;  /* channel busy */
2572
2573        if ( TSI_DSTA_ERR & st ) {
2574                if ( TSI_DSTA_ERRS & st )
2575                        return BSP_VMEDMA_STATUS_BERR_PCI;
2576                if ( ! (TSI_DSTA_ERT_SLVE_E     & st) )
2577                        return BSP_VMEDMA_STATUS_BERR_VME;
2578        }
2579
2580        return BSP_VMEDMA_STATUS_OERR;
2581}
2582
2583uint32_t
2584vmeTsi148DmaStatus(int channel)
2585{
2586BERegister *base = THEBASE;
2587        return vmeTsi148DmaStatusXX(base, channel);
2588}
2589
2590#define ALL_BITS_NEEDED (BSP_VMEDMA_MSK_ATTR | BSP_VMEDMA_MSK_PCIA | BSP_VMEDMA_MSK_VMEA)
2591
2592static int
2593tsi_desc_setup (
2594                DmaDescriptor p,
2595                uint32_t        attr_mask,
2596                uint32_t        xfer_mode,
2597                uint32_t        pci_addr,
2598                uint32_t        vme_addr,
2599                uint32_t        n_bytes)
2600{
2601VmeTsi148DmaListDescriptor      d = p;
2602uint32_t        vmeatt = 0, pciatt = 0, tmp, src, dst, dat, sat;
2603
2604        /* argument check */
2605
2606        /* since we must vme/pci into src/dst we need the direction
2607         * bit. Reject requests that have only part of the mask
2608         * bits set. It would be possible to be more sophisticated
2609         * by caching more information but we try to be simple here...
2610         */
2611        tmp = attr_mask & ALL_BITS_NEEDED;
2612        if ( tmp != 0 && tmp != ALL_BITS_NEEDED )
2613                return -1;
2614
2615        if ( BSP_VMEDMA_MSK_ATTR & attr_mask ) {
2616                /* Check VME bus mode */
2617                vmeatt = vme_attr(xfer_mode);
2618                if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == vmeatt  )
2619                        return -1;
2620
2621                /* Check PCI bus mode */
2622                pciatt = pci_attr(xfer_mode);
2623                if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == pciatt  )
2624                        return -1;
2625        }
2626
2627        if ( BSP_VMEDMA_MSK_ATTR & attr_mask ) {
2628                if ( BSP_VMEDMA_MODE_PCI2VME & xfer_mode ) {
2629                        dat = vmeatt;   sat = pciatt;
2630                        dst = vme_addr; src = pci_addr;
2631                } else {
2632                        sat = vmeatt;   dat = pciatt;
2633                        src = vme_addr; dst = pci_addr;
2634                }
2635                st_be32( &d->dsau, 0 );   st_be32( &d->dsal, src );
2636                st_be32( &d->ddau, 0 );   st_be32( &d->ddal, dst );
2637                st_be32( &d->dsat, sat ); st_be32( &d->ddat, dat );
2638        }
2639
2640        if ( BSP_VMEDMA_MSK_BCNT & attr_mask )
2641                st_be32( &d->dcnt, n_bytes);
2642
2643        return 0;
2644}
2645
2646static int
2647tsi_desc_start (volatile void *controller_addr, int channel, DmaDescriptor p)
2648{
2649VmeTsi148DmaListDescriptor d = p;
2650        if ( !controller_addr )
2651                controller_addr = THEBASE;
2652        return vmeTsi148DmaListStartXX((BERegister*)controller_addr, channel, d);
2653}
2654
2655#ifdef DEBUG_MODULAR
2656void
2657_cexpModuleInitialize(void* unused)
2658{
2659        vmeTsi148Init();
2660        vmeTsi148Reset();
2661}
2662
2663int
2664_cexpModuleFinalize(void *unused)
2665{
2666int             i;
2667int             rval = 1;
2668void    (*isrs[TSI_NUM_WIRES])() = {
2669        isr_pin0,
2670        isr_pin1,
2671        isr_pin2,
2672        isr_pin3,
2673};
2674
2675rtems_irq_connect_data  xx;
2676        xx.on   = my_no_op; /* at _least_ they could check for a 0 pointer */
2677        xx.off  = my_no_op;
2678        xx.isOn = my_isOn;
2679
2680        TSI_WR(THEBASE, TSI_INTEO_REG, 0);
2681
2682        for ( i=0; i<TSI_NUM_INT_VECS; i++) {
2683                /* Dont even bother to uninstall handlers */
2684        }
2685        if ( vmeTsi148IrqMgrInstalled ) {
2686                for ( i=0; i<TSI_NUM_WIRES; i++ ) {
2687                        if ( (int)(xx.name = devs[0].pic_pin[i]) >=0 ) {
2688                                xx.hdl  = isrs[i];
2689                                rval    = rval && BSP_remove_rtems_irq_handler(&xx);
2690                        }
2691                }
2692        }
2693        return !rval;
2694}
2695#endif
Note: See TracBrowser for help on using the repository browser.