source: rtems/bsps/powerpc/shared/vme/vmeTsi148.c @ 8a640bf

Last change on this file since 8a640bf was 8a640bf, checked in by Sebastian Huber <sebastian.huber@…>, on 02/25/22 at 09:42:04

bsps/powerpc: Do no use Newlib internals

The struct _reent::sdidinit member was renamed in a recent Newlib.

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