source: rtems/c/src/lib/libbsp/shared/vmeUniverse/vmeTsi148.c @ c2fc65b

4.104.114.84.95
Last change on this file since c2fc65b was c2fc65b, checked in by Till Straumann <strauman@…>, on 01/12/06 at 00:00:38
  • vmeUniverse/vmeTsi148.c, vmeUniverse/vmeTsi148.h:

Eliminate obsolete types.

  • Property mode set to 100644
File size: 39.0 KB
Line 
1/* $Id$ */
2
3/* Routines to configure the VME interface
4 * Author: Till Straumann <strauman@slac.stanford.edu>
5 *         Nov 2000, Oct 2001, Jan 2002
6 */
7
8#include <rtems.h>
9#include <stdio.h>
10#include <stdarg.h>
11#include <bsp/irq.h>
12#include <stdlib.h>
13#include <rtems/bspIo.h>        /* printk */
14#include <rtems/error.h>        /* printk */
15#include <bsp/pci.h>
16#include <bsp.h>
17#include <libcpu/byteorder.h>
18
19#include "vmeTsi148.h"
20
21#define STATIC static
22
23/* The tsi has 4 'local' wires that can be hooked to a PIC */
24
25#define TSI_NUM_WIRES                   4
26
27#define TSI148_NUM_OPORTS               8 /* number of outbound ports */
28#define TSI148_NUM_IPORTS               8 /* number of inbound  ports */
29
30#define NUM_TSI_DEVS                    2 /* number of instances supported */
31
32#define PCI_VENDOR_TUNDRA       0x10e3
33#define PCI_DEVICE_TSI148       0x0148
34
35#define TSI_OTSAU_SPACING       0x020
36
37#define TSI_OTSAU0_REG          0x100
38#define TSI_OTSAL0_REG          0x104
39#define TSI_OTEAU0_REG          0x108
40#define TSI_OTEAL0_REG          0x10c
41#define TSI_OTOFU0_REG          0x110
42#define TSI_OTOFL0_REG          0x114
43#define TSI_OTBS0_REG           0x118   /* 2eSST broadcast select */
44#define TSI_OTAT0_REG           0x11c
45#define TSI_OTSAU_REG(port)     (TSI_OTSAU0_REG + ((port)<<5))
46#define TSI_OTSAL_REG(port)     (TSI_OTSAL0_REG + ((port)<<5))
47#define TSI_OTEAU_REG(port)     (TSI_OTEAU0_REG + ((port)<<5))
48#define TSI_OTEAL_REG(port)     (TSI_OTEAL0_REG + ((port)<<5))
49#define TSI_OTOFU_REG(port)     (TSI_OTOFU0_REG + ((port)<<5))
50#define TSI_OTOFL_REG(port)     (TSI_OTOFL0_REG + ((port)<<5))
51#define TSI_OTBS_REG(port)      (TSI_OTBS0_REG + ((port)<<5))
52#define TSI_OTAT_REG(port)      (TSI_OTAT0_REG + ((port)<<5))
53#       define TSI_OTAT_EN                      (1<<31)
54#       define TSI_OTAT_MRPFD           (1<<18)
55#       define TSI_OTAT_PFS(x)          (((x)&3)<<16)
56#       define TSI_OTAT_2eSSTM(x)       (((x)&7)<<11)
57#       define TSI_OTAT_TM(x)           (((x)&7)<<8)
58#       define TSI_OTAT_DBW(x)          (((x)&3)<<6)
59#       define TSI_OTAT_SUP                     (1<<5)
60#       define TSI_OTAT_PGM                     (1<<4)
61#       define TSI_OTAT_ADMODE(x)       (((x)&0xf))
62#       define TSI_OTAT_ADMODE_A16      0
63#       define TSI_OTAT_ADMODE_A24      1
64#       define TSI_OTAT_ADMODE_A32      2
65#       define TSI_OTAT_ADMODE_A64      4
66#       define TSI_OTAT_ADMODE_USR1     8
67#       define TSI_OTAT_ADMODE_USR2     9
68#       define TSI_OTAT_ADMODE_USR3     0xa
69#       define TSI_OTAT_ADMODE_USR4     0xb
70
71#define TSI_VIACK_1_REG         0x204
72
73#define TSI_VEAU_REG            0x260
74#define TSI_VEAL_REG            0x264
75#define TSI_VEAT_REG            0x268
76
77#define TSI_ITSAU_SPACING       0x020
78
79#define TSI_ITSAU0_REG          0x300
80#define TSI_ITSAL0_REG          0x304
81#define TSI_ITEAU0_REG          0x308
82#define TSI_ITEAL0_REG          0x30c
83#define TSI_ITOFU0_REG          0x310
84#define TSI_ITOFL0_REG          0x314
85#define TSI_ITAT0_REG           0x318
86#define TSI_ITSAU_REG(port)     (TSI_ITSAU0_REG + ((port)<<5))
87#define TSI_ITSAL_REG(port)     (TSI_ITSAL0_REG + ((port)<<5))
88#define TSI_ITEAU_REG(port)     (TSI_ITEAU0_REG + ((port)<<5))
89#define TSI_ITEAL_REG(port)     (TSI_ITEAL0_REG + ((port)<<5))
90#define TSI_ITOFU_REG(port)     (TSI_ITOFU0_REG + ((port)<<5))
91#define TSI_ITOFL_REG(port)     (TSI_ITOFL0_REG + ((port)<<5))
92#define TSI_ITAT_REG(port)      (TSI_ITAT0_REG + ((port)<<5))
93
94#       define TSI_ITAT_EN                      (1<<31)
95#       define TSI_ITAT_TH                      (1<<18)
96#       define TSI_ITAT_VFS(x)          (((x)&3)<<16)
97#       define TSI_ITAT_2eSSTM(x)       (((x)&7)<<12)
98#       define TSI_ITAT_2eSSTB          (1<<11)
99#       define TSI_ITAT_2eSST           (1<<10)
100#       define TSI_ITAT_2eVME           (1<<9)
101#       define TSI_ITAT_MBLT            (1<<8)
102#       define TSI_ITAT_BLT                     (1<<7)
103#       define TSI_ITAT_AS(x)           (((x)&7)<<4)
104#       define TSI_ITAT_ADMODE_A16      (0<<4)
105#       define TSI_ITAT_ADMODE_A24      (1<<4)
106#       define TSI_ITAT_ADMODE_A32      (2<<4)
107#       define TSI_ITAT_ADMODE_A64      (4<<4)
108#       define TSI_ITAT_SUP                     (1<<3)
109#       define TSI_ITAT_USR                     (1<<2)
110#       define TSI_ITAT_PGM                     (1<<1)
111#       define TSI_ITAT_DATA            (1<<0)
112
113#define TSI_VICR_REG            0x440
114#   define TSI_VICR_CNTS(v)             (((v)&3)<<30)
115#   define TSI_VICR_CNTS_DIS    (0<<30)
116#   define TSI_VICR_CNTS_IRQ1   (1<<30)
117#   define TSI_VICR_CNTS_IRQ2   (2<<30)
118#   define TSI_VICR_EDGIS(v)    (((v)&3)<<28)
119#   define TSI_VICR_EDGIS_DIS   (0<<28)
120#   define TSI_VICR_EDGIS_IRQ1  (1<<28)
121#   define TSI_VICR_EDGIS_IRQ2  (2<<28)
122#   define TSI_VICR_IRQ1F(v)    (((v)&3)<<26)
123#   define TSI_VICR_IRQ1F_NORML (0<<26)
124#   define TSI_VICR_IRQ1F_PULSE (1<<26)
125#   define TSI_VICR_IRQ1F_CLOCK (2<<26)
126#   define TSI_VICR_IRQ1F_1MHZ  (3<<26)
127#   define TSI_VICR_IRQ2F(v)    (((v)&3)<<24)
128#   define TSI_VICR_IRQ2F_NORML (0<<24)
129#   define TSI_VICR_IRQ2F_PULSE (1<<24)
130#   define TSI_VICR_IRQ2F_CLOCK (2<<24)
131#   define TSI_VICR_IRQ2F_1MHZ  (3<<24)
132#   define TSI_VICR_BIP                 (1<<23)
133#   define TSI_VICR_BIPS                (1<<22)
134#   define TSI_VICR_IRQC                (1<<15)
135#   define TSI_VICR_IRQLS(v)    (((v)&7)<<12)
136#   define TSI_VICR_IRQS                (1<<11)
137#   define TSI_VICR_IRQL(v)             (((v)&7)<<8)
138#   define TSI_VICR_STID(v)             ((v)&0xff)
139#define TSI_INTEN_REG           0x448
140#define TSI_INTEO_REG           0x44c
141#define TSI_INTS_REG            0x450
142#   define TSI_INTS_IRQ1S       (1<<1)
143#   define TSI_INTS_IRQ2S       (1<<2)
144#   define TSI_INTS_IRQ3S       (1<<3)
145#   define TSI_INTS_IRQ4S       (1<<4)
146#   define TSI_INTS_IRQ5S       (1<<5)
147#   define TSI_INTS_IRQ6S       (1<<6)
148#   define TSI_INTS_IRQ7S       (1<<7)
149#   define TSI_INTS_ACFLS       (1<<8)
150#   define TSI_INTS_SYSFLS      (1<<9)
151#   define TSI_INTS_IACKS       (1<<10)
152#   define TSI_INTS_VIES        (1<<11)
153#   define TSI_INTS_VERRS       (1<<12)
154#   define TSI_INTS_PERRS       (1<<13)
155#   define TSI_INTS_MB0S        (1<<16)
156#   define TSI_INTS_MB1S        (1<<17)
157#   define TSI_INTS_MB2S        (1<<18)
158#   define TSI_INTS_MB3S        (1<<19)
159#   define TSI_INTS_LM0S        (1<<20)
160#   define TSI_INTS_LM1S        (1<<21)
161#   define TSI_INTS_LM2S        (1<<22)
162#   define TSI_INTS_LM3S        (1<<23)
163#   define TSI_INTS_DMA0S       (1<<24)
164#   define TSI_INTS_DMA1S       (1<<25)
165#define TSI_INTC_REG            0x454
166#   define TSI_INTC_ACFLC       (1<<8)
167#   define TSI_INTC_SYSFLC      (1<<9)
168#   define TSI_INTC_IACKC       (1<<10)
169#   define TSI_INTC_VIEC        (1<<11)
170#   define TSI_INTC_VERRC       (1<<12)
171#   define TSI_INTC_PERRC       (1<<13)
172#   define TSI_INTC_MB0C        (1<<16)
173#   define TSI_INTC_MB1C        (1<<17)
174#   define TSI_INTC_MB2C        (1<<18)
175#   define TSI_INTC_MB3C        (1<<19)
176#   define TSI_INTC_LM0C        (1<<20)
177#   define TSI_INTC_LM1C        (1<<21)
178#   define TSI_INTC_LM2C        (1<<22)
179#   define TSI_INTC_LM3C        (1<<23)
180#   define TSI_INTC_DMA0C       (1<<24)
181#   define TSI_INTC_DMA1C       (1<<25)
182#define TSI_INTM1_REG           0x458
183#define TSI_INTM2_REG           0x45c
184
185
186#define TSI_RD(base, reg)                               in_be32(((base) + (reg)/sizeof(*base)))
187#define TSI_RD16(base, reg)                             in_be16((volatile unsigned short *)(base) + (reg)/sizeof(short))
188#define TSI_RD8(base, reg)                              *((volatile unsigned char *)(base) + (reg))
189#define TSI_WR(base, reg, val)                  out_be32(((base) + (reg)/sizeof(*base)), val)
190
191#define UNIV_SCTL_AM_MASK       (UNIV_CTL_VAS | UNIV_SCTL_PGM | UNIV_SCTL_DAT | UNIV_SCTL_USER | UNIV_SCTL_SUPER)
192
193
194/* allow the BSP to override the default routines */
195#ifndef BSP_PCI_FIND_DEVICE
196#define BSP_PCI_FIND_DEVICE             pci_find_device
197#endif
198#ifndef BSP_PCI_CONFIG_IN_LONG
199#define BSP_PCI_CONFIG_IN_LONG  pci_read_config_dword
200#endif
201#ifndef BSP_PCI_CONFIG_IN_SHORT
202#define BSP_PCI_CONFIG_IN_SHORT pci_read_config_word
203#endif
204#ifndef BSP_PCI_CONFIG_OUT_SHORT
205#define BSP_PCI_CONFIG_OUT_SHORT pci_write_config_word
206#endif
207#ifndef BSP_PCI_CONFIG_IN_BYTE
208#define BSP_PCI_CONFIG_IN_BYTE  pci_read_config_byte
209#endif
210
211typedef unsigned int pci_ulong;
212
213/* PCI_MEM_BASE is a possible offset between CPU- and PCI addresses.
214 * Should be defined by the BSP.
215 */
216#define PCI_TO_LOCAL_ADDR(memaddr) ((pci_ulong)(memaddr) + PCI_MEM_BASE)
217
218typedef struct {
219        BERegister *base;
220        int                     irqLine;
221        int                     pic_pin[TSI_NUM_WIRES];
222} Tsi148Dev;
223
224static Tsi148Dev devs[NUM_TSI_DEVS] = {{0}};
225
226/* registers should be mapped to guarded, non-cached memory; hence
227 * subsequent stores are ordered. eieio is only needed to enforce
228 * ordering of loads with respect to stores.
229 */
230
231/* private printing wrapper */
232static void
233uprintf(FILE *f, char *fmt, ...)
234{
235va_list ap;
236        va_start(ap, fmt);
237        if (!f || !_impure_ptr->__sdidinit) {
238                /* Might be called at an early stage when
239                 * to a buffer.
240                 */
241                vprintk(fmt,ap);
242        } else
243        {
244                vfprintf(f,fmt,ap);
245        }
246        va_end(ap);
247}
248
249#define CHECK_BASE(base,quiet,rval)     \
250        do {                                                    \
251                if ( !base ) {                          \
252                        if ( !quiet ) {                 \
253                                uprintf(stderr,"Tsi148: Driver not initialized\n");     \
254                        }                                               \
255                        return rval;                    \
256                }                                                       \
257        } while (0)
258
259int
260vmeTsi148FindPciBase(
261        int instance,
262        BERegister **pbase
263        )
264{
265int                                     bus,dev,fun;
266pci_ulong                       busaddr;
267unsigned char           irqline;
268unsigned short          wrd;
269
270        if (BSP_PCI_FIND_DEVICE(
271                        PCI_VENDOR_TUNDRA,
272                        PCI_DEVICE_TSI148,
273                        instance,
274                        &bus,
275                        &dev,
276                        &fun))
277                return -1;
278        if (BSP_PCI_CONFIG_IN_LONG(bus,dev,fun,PCI_BASE_ADDRESS_0,&busaddr))
279                return -1;
280        /* Assume upper BAR is zero */
281
282        *pbase=(BERegister*)(PCI_TO_LOCAL_ADDR(busaddr) & ~0xff);
283
284        if (BSP_PCI_CONFIG_IN_BYTE(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline))
285                return -1;
286
287        /* Enable PCI master and memory access */
288        BSP_PCI_CONFIG_IN_SHORT(bus, dev, fun, PCI_COMMAND, &wrd);
289        BSP_PCI_CONFIG_OUT_SHORT(bus, dev, fun, PCI_COMMAND, wrd | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
290
291        return irqline;
292}
293
294int
295vmeTsi148InitInstance(unsigned instance)
296{
297int                                     irq;
298BERegister *base;
299
300        if ( instance >= NUM_TSI_DEVS )
301                return  -1;
302        if ( devs[instance].base )
303                return  -1;
304
305        if ((irq=vmeTsi148FindPciBase(instance,&base)) < 0) {
306                uprintf(stderr,"unable to find a Tsi148 in pci config space\n");
307        } else {
308                uprintf(stderr,"Tundra Tsi148 PCI-VME bridge detected at 0x%08x, IRQ %d\n",
309                                (unsigned int)base, irq);
310        }
311        devs[0].base    = base;
312        devs[0].irqLine = irq;
313
314        return irq < 0 ? -1 : 0;
315}
316
317int
318vmeTsi148Init(void)
319{
320        return vmeTsi148InitInstance(0);
321}
322
323
324void
325vmeTsi148ResetXX(BERegister *base)
326{
327int port;
328
329        CHECK_BASE(base,0, );
330
331        vmeTsi148DisableAllOutboundPortsXX(base);
332        for ( port=0; port < TSI148_NUM_OPORTS; port++ )
333                TSI_WR(base, TSI_OTBS_REG(port), 0);
334        TSI_WR(base, TSI_INTEO_REG, 0);
335        TSI_WR(base, TSI_INTEN_REG, 0);
336        TSI_WR(base, TSI_INTC_REG, 0xffffffff);
337        TSI_WR(base, TSI_INTM1_REG, 0);
338        TSI_WR(base, TSI_INTM2_REG, 0);
339        TSI_WR(base, TSI_VICR_REG, 0);
340        TSI_WR(base, TSI_VEAT_REG, TSI_VEAT_VESCL);
341}
342
343void
344vmeTsi148Reset()
345{
346        vmeTsi148ResetXX(devs[0].base);
347}
348
349/* convert an address space selector to a corresponding
350 * Tsi148 control mode word
351 */
352
353STATIC int
354am2omode(unsigned long address_space, unsigned long *pmode)
355{
356unsigned long mode=0;
357unsigned long tm, mask;
358
359        if ( ! (VME_MODE_DBW32_DISABLE  & address_space ) )
360                mode |= TSI_OTAT_DBW(1);
361        if ( ! (VME_MODE_PREFETCH_ENABLE & address_space) )
362                mode |= TSI_OTAT_MRPFD;
363        else {
364                mode |= TSI_OTAT_PFS(address_space>>12);
365        }
366        mode |= TSI_OTAT_2eSSTM(address_space>>16);
367
368        for ( tm = 1, mask = VME_MODE_BLT; ! (mask & address_space); tm++, mask<<=1 ) {
369                if ( VME_MODE_2eSST_BCST == mask ) {
370                        tm = 0; /* select default: BLT enabled */
371                        break;
372                }
373        }
374        mode |= TSI_OTAT_TM(tm);
375
376        switch (address_space & VME_AM_MASK) {
377                case VME_AM_STD_SUP_PGM:
378                case VME_AM_STD_USR_PGM:
379
380                        mode |= TSI_OTAT_PGM;
381
382                        /* fall thru */
383                case VME_AM_STD_SUP_DATA:
384                case VME_AM_STD_USR_DATA:
385
386                        mode |= TSI_OTAT_ADMODE_A24;
387                        break;
388
389                case VME_AM_EXT_SUP_PGM:
390                case VME_AM_EXT_USR_PGM:
391                        mode |= TSI_OTAT_PGM;
392
393                        /* fall thru */
394                case VME_AM_EXT_SUP_DATA:
395                case VME_AM_EXT_USR_DATA:
396                        mode |= TSI_OTAT_ADMODE_A32;
397                        break;
398
399                case VME_AM_SUP_SHORT_IO:
400                case VME_AM_USR_SHORT_IO:
401                        mode |= TSI_OTAT_ADMODE_A16;
402                        break;
403
404                case 0: /* disable the port alltogether */
405                        break;
406
407                default:
408                        return -1;
409        }
410        if ( VME_AM_IS_SUP(address_space) )
411                mode |= TSI_OTAT_SUP;
412        *pmode = mode;
413        return 0;
414}
415
416STATIC int
417am2imode(unsigned long address_space, unsigned long *pmode)
418{
419unsigned long mode=0;
420unsigned long tm, mask;
421
422        mode |= TSI_ITAT_VFS(address_space>>12);
423        mode |= TSI_ITAT_2eSSTM(address_space>>16);
424
425        mode |= TSI_ITAT_BLT;
426
427        mask = VME_MODE_BLT;
428        tm = TSI_ITAT_BLT;
429        do {
430                mask<<=1; tm<<=1;
431                if ( address_space & mask )
432                        mode |= tm;
433        } while ( TSI_ITAT_2eSSTB != tm );
434
435        tm = 0;
436
437        switch (address_space & VME_AM_MASK) {
438                case VME_AM_STD_SUP_PGM:
439                case VME_AM_STD_USR_PGM:
440
441                        tm = 1;
442
443                        /* fall thru */
444                case VME_AM_STD_SUP_DATA:
445                case VME_AM_STD_USR_DATA:
446
447                        mode |= TSI_ITAT_ADMODE_A24;
448                        break;
449
450                case VME_AM_EXT_SUP_PGM:
451                case VME_AM_EXT_USR_PGM:
452                        tm = 1;
453
454                        /* fall thru */
455                case VME_AM_EXT_SUP_DATA:
456                case VME_AM_EXT_USR_DATA:
457                        mode |= TSI_ITAT_ADMODE_A32;
458                        break;
459
460                case VME_AM_SUP_SHORT_IO:
461                case VME_AM_USR_SHORT_IO:
462                        mode |= TSI_ITAT_ADMODE_A16;
463                        break;
464
465                case 0: /* disable the port alltogether */
466                        *pmode = 0;
467                        return 0;
468
469                default:
470                        return -1;
471        }
472
473        if ( VME_AM_IS_SUP(address_space) )
474                mode |= TSI_ITAT_SUP;
475        else
476                mode |= TSI_ITAT_USR;
477
478        if ( tm )
479                mode |= TSI_ITAT_PGM;
480        else
481                mode |= TSI_ITAT_DATA;
482
483        *pmode = mode;
484        return 0;
485}
486
487static void
488readTriple(
489        BERegister *base,
490        unsigned reg,
491        unsigned long long *ps,
492        unsigned long long *pl,
493        unsigned long long *po)
494{
495        *ps = TSI_RD(base, reg);
496        *ps = (*ps<<32) | (TSI_RD(base, (reg+4)) & 0xffff0000);
497        *pl = TSI_RD(base, (reg+8));
498        *pl = (*pl<<32) | (TSI_RD(base, (reg+0xc)) & 0xffff0000);
499        *po = TSI_RD(base, (reg+0x10));
500        *po = (*po<<32) | (TSI_RD(base, (reg+0x14)) & 0xffff0000);
501}
502
503
504static unsigned long
505inboundGranularity(unsigned long itat)
506{
507        switch ( itat & TSI_ITAT_AS(-1) ) {
508                case TSI_ITAT_ADMODE_A16:       return 0xf;
509                case TSI_ITAT_ADMODE_A24:       return 0xfff;
510                default:
511                break;
512        }
513        return 0xffff;
514}
515
516static int
517configTsiPort(
518        BERegister              *base,
519        int                             isout,
520        unsigned long   port,
521        unsigned long   address_space,
522        unsigned long   vme_address,
523        unsigned long   pci_address,
524        unsigned long   length)
525{
526unsigned long long      start, limit, offst;
527unsigned long           mode, mask, tat_reg, tsau_reg;
528char                            *name = (isout ? "Outbound" : "Inbound");
529
530        CHECK_BASE(base,0,-1);
531
532        mode = 0; /* silence warning */
533
534        if ( port >= (isout ? TSI148_NUM_OPORTS : TSI148_NUM_IPORTS) ) {
535                uprintf(stderr,"Tsi148 %s Port Cfg: invalid port\n", name);
536                return -1;
537        }
538
539        if ( length && (isout ? am2omode(address_space, &mode) : am2imode(address_space, &mode)) ) {
540                uprintf(stderr,"Tsi148 %s Port Cfg: invalid address space / mode flags\n",name);
541                return -1;
542        }
543
544
545        if ( isout ) {
546                start     = pci_address;
547                offst     = (unsigned long long)vme_address - start;
548                mask      = 0xffff;
549                tat_reg   = TSI_OTAT_REG(port);
550                tsau_reg  = TSI_OTSAU_REG(port);
551                mode     |= TSI_OTAT_EN;
552        } else {
553                start     = vme_address;
554                offst     = (unsigned long long)pci_address - start;
555                mask      = inboundGranularity(mode);
556                tat_reg   = TSI_ITAT_REG(port);
557                tsau_reg  = TSI_ITSAU_REG(port);
558                mode     |= TSI_ITAT_EN;
559        }
560
561        /* If they pass 'length==0' just disable */
562        if ( 0 == length ) {
563                TSI_WR(base, tat_reg, TSI_RD(base, tat_reg) & ~(isout ? TSI_OTAT_EN : TSI_ITAT_EN));
564                return 0;
565        }
566
567
568        if (   (vme_address & mask)
569            || (pci_address & mask)
570            || (length      & mask) ) {
571                uprintf(stderr,"Tsi148 %s Port Cfg: invalid address/length; must be multiple of 0x%x\n",
572                                name,
573                                mask+1);
574                return -1;
575        }
576
577        limit  = start + length - 1;
578
579        if ( limit >= (unsigned long long)1<<32 ) {
580                uprintf(stderr,"Tsi148 %s Port Cfg: invalid address/length; must be < 1<<32\n", name);
581                return -1;
582        }
583
584        /* Disable port */
585        TSI_WR(base, tat_reg, 0);
586
587        /* Force to 32-bits */
588        TSI_WR(base, tsau_reg       , 0);
589        TSI_WR(base, tsau_reg + 0x04, (uint32_t)start);
590        TSI_WR(base, tsau_reg + 0x08, 0);
591        TSI_WR(base, tsau_reg + 0x0c, (uint32_t)limit);
592        TSI_WR(base, tsau_reg + 0x10, (uint32_t)(offst>>32));
593        TSI_WR(base, tsau_reg + 0x14, (uint32_t)offst);
594
595        /* (outbound only:) leave 2eSST broadcast register alone for user to program */
596
597        /* Set mode and enable */
598        TSI_WR(base, tat_reg, mode);
599        return 0;
600}
601
602static int
603disableTsiPort(
604        BERegister              *base,
605        int                             isout,
606        unsigned long   port)
607{
608        return configTsiPort(base, isout, port, 0, 0, 0, 0);
609}
610
611int
612vmeTsi148InboundPortCfgXX(
613        BERegister              *base,
614        unsigned long   port,
615        unsigned long   address_space,
616        unsigned long   vme_address,
617        unsigned long   pci_address,
618        unsigned long   length)
619{
620        return configTsiPort(base, 0, port, address_space, vme_address, pci_address, length);
621}
622
623int
624vmeTsi148InboundPortCfg(
625        unsigned long   port,
626        unsigned long   address_space,
627        unsigned long   vme_address,
628        unsigned long   pci_address,
629        unsigned long   length)
630{
631        return configTsiPort(devs[0].base, 0, port, address_space, vme_address, pci_address, length);
632}
633
634
635int
636vmeTsi148OutboundPortCfgXX(
637        BERegister              *base,
638        unsigned long   port,
639        unsigned long   address_space,
640        unsigned long   vme_address,
641        unsigned long   pci_address,
642        unsigned long   length)
643{
644        return configTsiPort(base, 1, port, address_space, vme_address, pci_address, length);
645}
646
647int
648vmeTsi148OutboundPortCfg(
649        unsigned long   port,
650        unsigned long   address_space,
651        unsigned long   vme_address,
652        unsigned long   pci_address,
653        unsigned long   length)
654{
655        return configTsiPort(devs[0].base, 1, port, address_space, vme_address, pci_address, length);
656}
657
658
659int
660vmeTsi148XlateAddrXX(
661        BERegister *base,       /* TSI 148 base address */
662        int outbound,           /* look in the outbound windows */
663        int reverse,            /* reverse mapping; for outbound ports: map local to VME */
664        unsigned long as,       /* address space */
665        unsigned long aIn,      /* address to look up */
666        unsigned long *paOut/* where to put result */
667        )
668{
669unsigned long           mode, mode_msk;
670int                                     port;
671unsigned long long      start, limit, offst, a;
672unsigned long           tsau_reg, tat_reg, gran, skip;
673
674        CHECK_BASE(base,0,-1);
675
676        mode = 0; /* silence warning */
677
678        if ( VME_MODE_EXACT_MATCH & as ) {
679                mode_msk = ~0;
680        } else {
681                if ( outbound )
682                        mode_msk = TSI_OTAT_PGM | TSI_OTAT_SUP | TSI_OTAT_ADMODE(-1) | TSI_OTAT_EN;
683                else
684                        mode_msk = TSI_ITAT_PGM | TSI_ITAT_DATA | TSI_ITAT_SUP | TSI_ITAT_USR | TSI_ITAT_AS(-1) | TSI_ITAT_EN;
685        }
686
687        as &= ~VME_MODE_EXACT_MATCH;
688
689        if ( outbound ? am2omode(as,&mode) : am2imode(as,&mode) ) {
690                uprintf(stderr, "vmeTsi148XlateAddr: invalid address space/mode argument");
691                return -2;
692        }
693
694        if (outbound ) {
695                tsau_reg = TSI_OTSAU_REG(0);
696                tat_reg  = TSI_OTAT_REG(0);
697                skip     = TSI_OTSAU_SPACING;
698                mode    |= TSI_OTAT_EN;
699                gran     = 0x10000;
700        } else {
701                tsau_reg = TSI_ITSAU_REG(0);
702                tat_reg  = TSI_ITAT_REG(0);
703                skip     = TSI_ITSAU_SPACING;
704                mode    |= TSI_ITAT_EN;
705                gran     = inboundGranularity(mode) + 1;
706        }
707
708        for ( port = 0; port < TSI148_NUM_OPORTS; port++, tsau_reg += skip, tat_reg += skip ) {
709
710                if ( (mode & mode_msk) == (TSI_RD(base, tat_reg) & mode_msk) ) {
711
712                        /* found a window with of the right mode; now check the range */
713                        readTriple(base, tsau_reg, &start, &limit, &offst);
714                        limit += gran;
715
716                        if ( !reverse ) {
717                                start += offst;
718                                limit += offst;
719                                offst  = -offst;
720                        }
721                        a = aIn;
722                        if ( aIn >= start && aIn <= limit ) {
723                                /* found it */
724                                *paOut = (unsigned long)(a + offst);
725                                return 0;
726                        }
727                }
728        }
729
730        uprintf(stderr, "vmeTsi148XlateAddr: no matching mapping found\n");
731        return -1;
732}
733
734int
735vmeTsi148XlateAddr(
736        int outbound,           /* look in the outbound windows */
737        int reverse,            /* reverse mapping; for outbound ports: map local to VME */
738        unsigned long as,       /* address space */
739        unsigned long aIn,      /* address to look up */
740        unsigned long *paOut/* where to put result */
741        )
742{
743        return vmeTsi148XlateAddrXX(devs[0].base, outbound, reverse, as, aIn, paOut);
744}
745
746
747/* printk cannot format %llx */
748static void uprintfllx(FILE *f, unsigned long long v)
749{
750        if ( v >= ((unsigned long long)1)<<32 )
751                uprintf(f,"0x%lx%08lx ", (unsigned long)(v>>32), (unsigned long)(v & 0xffffffff));
752        else
753                uprintf(f,"0x%08lx ", (unsigned long)(v & 0xffffffff));
754}
755
756void
757vmeTsi148OutboundPortsShowXX(BERegister *base, FILE *f)
758{
759int                             port;
760unsigned long   mode;
761char                    tit = 0;
762
763unsigned long long      start, limit, offst;
764
765        CHECK_BASE(base,0, );
766
767        if (!f) f=stdout;
768        uprintf(f,"Tsi148 Outbound Ports:\n");
769
770        for ( port = 0; port < TSI148_NUM_OPORTS; port++ ) {
771                mode = TSI_RD(base, TSI_OTAT_REG(port));
772                if ( ! (TSI_OTAT_EN & mode) )
773                        continue; /* skip disabled ports */
774
775                readTriple(base, TSI_OTSAU_REG(port), &start, &limit, &offst);
776
777                /* convert limit to size */
778                limit = limit-start+0x10000;
779                if ( !tit ) {
780                        uprintf(f,"Port  VME-Addr   Size       PCI-Adrs   Mode:\n");
781                        tit = 1;
782                }
783                uprintf(f,"%d:    ", port);
784                uprintfllx(f,start+offst);
785                uprintfllx(f,limit);
786                uprintfllx(f,start);
787                switch( mode & TSI_OTAT_ADMODE(-1) ) {
788                        case TSI_OTAT_ADMODE_A16: uprintf(f,"A16"); break;
789                        case TSI_OTAT_ADMODE_A24: uprintf(f,"A24"); break;
790                        case TSI_OTAT_ADMODE_A32: uprintf(f,"A32"); break;
791                        case TSI_OTAT_ADMODE_A64: uprintf(f,"A64"); break;
792                        default:                  uprintf(f,"A??"); break;
793                }
794
795                if ( mode & TSI_OTAT_PGM ) uprintf(f,", PGM");
796                if ( mode & TSI_OTAT_SUP ) uprintf(f,", SUP");
797                if ( ! (TSI_OTAT_MRPFD & mode) ) uprintf(f,", PREFETCH");
798
799                switch ( mode & TSI_OTAT_DBW(-1) ) {
800                        case TSI_OTAT_DBW(0):   uprintf(f,", D16"); break;
801                        case TSI_OTAT_DBW(1):   uprintf(f,", D32"); break;
802                        default:                                uprintf(f,", D??"); break;
803                }
804
805                switch( mode & TSI_OTAT_TM(-1) ) {
806                        case TSI_OTAT_TM(0):    uprintf(f,", SCT");             break;
807                        case TSI_OTAT_TM(1):    uprintf(f,", BLT");             break;
808                        case TSI_OTAT_TM(2):    uprintf(f,", MBLT");            break;
809                        case TSI_OTAT_TM(3):    uprintf(f,", 2eVME");           break;
810                        case TSI_OTAT_TM(4):    uprintf(f,", 2eSST");           break;
811                        case TSI_OTAT_TM(5):    uprintf(f,", 2eSST_BCST");      break;
812                        default:                                uprintf(f," TM??");             break;
813                }
814
815                uprintf(f,"\n");
816        }
817}
818
819void
820vmeTsi148OutboundPortsShow(FILE *f)
821{
822        vmeTsi148OutboundPortsShowXX(devs[0].base, f);
823}
824
825void
826vmeTsi148InboundPortsShowXX(BERegister *base, FILE *f)
827{
828int                             port;
829unsigned long   mode;
830char                    tit = 0;
831
832unsigned long long      start, limit, offst;
833
834        CHECK_BASE(base,0, );
835
836        if (!f) f=stdout;
837        uprintf(f,"Tsi148 Inbound Ports:\n");
838
839        for ( port = 0; port < TSI148_NUM_IPORTS; port++ ) {
840                mode = TSI_RD(base, TSI_ITAT_REG(port));
841                if ( ! (TSI_ITAT_EN & mode) )
842                        continue; /* skip disabled ports */
843
844                readTriple(base, TSI_ITSAU_REG(port), &start, &limit, &offst);
845
846                /* convert limit to size */
847                limit = limit - start + inboundGranularity(mode) + 1;
848                if ( !tit ) {
849                        uprintf(f,"Port  VME-Addr   Size       PCI-Adrs   Mode:\n");
850                        tit = 1;
851                }
852                uprintf(f,"%d:    ", port);
853                uprintfllx(f,start);
854                uprintfllx(f,limit);
855                uprintfllx(f,start+offst);
856                switch( mode & TSI_ITAT_AS(-1) ) {
857                        case TSI_ITAT_ADMODE_A16: uprintf(f,"A16"); break;
858                        case TSI_ITAT_ADMODE_A24: uprintf(f,"A24"); break;
859                        case TSI_ITAT_ADMODE_A32: uprintf(f,"A32"); break;
860                        case TSI_ITAT_ADMODE_A64: uprintf(f,"A64"); break;
861                        default:                  uprintf(f,"A??"); break;
862                }
863
864                if ( mode & TSI_ITAT_PGM )  uprintf(f,", PGM");
865                if ( mode & TSI_ITAT_DATA ) uprintf(f,", DAT");
866                if ( mode & TSI_ITAT_SUP )  uprintf(f,", SUP");
867                if ( mode & TSI_ITAT_USR )  uprintf(f,", USR");
868
869                if ( mode & TSI_ITAT_2eSSTB )  uprintf(f,", 2eSSTB");
870                if ( mode & TSI_ITAT_2eSST  )  uprintf(f,", 2eSST");
871                if ( mode & TSI_ITAT_2eVME  )  uprintf(f,", 2eVME");
872                if ( mode & TSI_ITAT_MBLT   )  uprintf(f,", MBLT");
873                if ( mode & TSI_ITAT_BLT    )  uprintf(f,", BLT");
874
875                uprintf(f,"\n");
876        }
877}
878
879void
880vmeTsi148InboundPortsShow(FILE *f)
881{
882        vmeTsi148InboundPortsShowXX(devs[0].base, f);
883}
884
885
886void
887vmeTsi148DisableAllInboundPortsXX(BERegister *base)
888{
889int port;
890
891        for ( port = 0; port < TSI148_NUM_IPORTS; port++ )
892                if ( disableTsiPort(base, 0, port) )
893                        break;
894}
895
896void
897vmeTsi148DisableAllInboundPorts(void)
898{
899        vmeTsi148DisableAllInboundPortsXX(devs[0].base);
900}
901
902void
903vmeTsi148DisableAllOutboundPortsXX(BERegister *base)
904{
905int port;
906
907        for ( port = 0; port < TSI148_NUM_IPORTS; port++ )
908                if ( disableTsiPort(base, 1, port) )
909                        break;
910}
911
912void
913vmeTsi148DisableAllOutboundPorts(void)
914{
915        vmeTsi148DisableAllOutboundPortsXX(devs[0].base);
916}
917
918
919/* Interrupt Subsystem */
920
921typedef struct
922IRQEntryRec_ {
923                VmeTsi148ISR    isr;
924                void                    *usrData;
925} IRQEntryRec, *IRQEntry;
926
927static IRQEntry irqHdlTbl[TSI_NUM_INT_VECS]={0};
928
929int        vmeTsi148IrqMgrInstalled=0;
930
931static volatile unsigned long   wire_mask[TSI_NUM_WIRES]     = {0};
932/* wires are offset by 1 so we can initialize the wire table to all zeros */
933static int                                              tsi_wire[TSI_NUM_WIRES] = {0};
934
935/* how should we iack a given level, 1,2,4 bytes? */
936static unsigned char tsi_iack_width[7] = {
937        1,1,1,1,1,1,1
938};
939
940/* map universe compatible vector # to Tsi slot (which maps to bit layout in stat/enable/... regs) */
941static int uni2tsi_vec_map[TSI_NUM_INT_VECS-256] = {
942        /* 256 no VOWN interrupt */                     -1,
943        /* TSI_DMA_INT_VEC                      257 */  256 + 24 - 8,
944        /* TSI_LERR_INT_VEC                     258 */  256 + 13 - 8,
945        /* TSI_VERR_INT_VEC                     259 */  256 + 12 - 8,
946        /* 260 is reserved       */                     -1,
947        /* TSI_VME_SW_IACK_INT_VEC      261 */  256 + 10 - 8,
948        /* 262 no PCI SW IRQ     */                     -1,
949        /* TSI_SYSFAIL_INT_VEC          263 */  256 +  9 - 8,
950        /* TSI_ACFAIL_INT_VEC           264 */  256 +  8 - 8,
951        /* TSI_MBOX0_INT_VEC            265 */  256 + 16 - 8,
952        /* TSI_MBOX1_INT_VEC            266 */  256 + 17 - 8,
953        /* TSI_MBOX2_INT_VEC            267 */  256 + 18 - 8,
954        /* TSI_MBOX3_INT_VEC            268 */  256 + 19 - 8,
955        /* TSI_LM0_INT_VEC                      269 */  256 + 20 - 8,
956        /* TSI_LM1_INT_VEC                      270 */  256 + 21 - 8,
957        /* TSI_LM2_INT_VEC                      271 */  256 + 22 - 8,
958        /* TSI_LM3_INT_VEC                      272 */  256 + 23 - 8,
959/* New vectors; only on TSI148 */
960        /* TSI_VIES_INT_VEC                     273 */  256 + 11 - 8,
961        /* TSI_DMA1_INT_VEC                     274 */  256 + 25 - 8,
962};
963
964/* and the reverse; map tsi bit number to universe compatible 'special' vector number */
965static int tsi2uni_vec_map[TSI_NUM_INT_VECS - 256] = {
966        TSI_ACFAIL_INT_VEC,
967        TSI_SYSFAIL_INT_VEC,
968        TSI_VME_SW_IACK_INT_VEC,
969        TSI_VIES_INT_VEC,
970        TSI_VERR_INT_VEC,
971        TSI_LERR_INT_VEC,
972        -1,
973        -1,
974        TSI_MBOX0_INT_VEC,
975        TSI_MBOX1_INT_VEC,
976        TSI_MBOX2_INT_VEC,
977        TSI_MBOX3_INT_VEC,
978        TSI_LM0_INT_VEC,
979        TSI_LM1_INT_VEC,
980        TSI_LM2_INT_VEC,
981        TSI_LM3_INT_VEC,
982        TSI_DMA_INT_VEC,
983        TSI_DMA1_INT_VEC,
984        -1,
985};
986
987static inline int
988uni2tsivec(int v)
989{
990        if ( v < 0 || v >= TSI_NUM_INT_VECS )
991                return -1;
992        return v < 256 ? v : uni2tsi_vec_map[v-256];
993}
994
995static int
996lvl2bitno(unsigned int level)
997{
998        if ( level >= 256 )
999                return uni2tsivec(level) + 8 - 256;
1000        else if ( level < 8 && level > 0 )
1001                return level;
1002        return -1;
1003}
1004
1005int
1006vmeTsi148IntRoute(unsigned int level, unsigned int pin)
1007{
1008int                             i;
1009unsigned long   mask, shift, mapreg, flags, wire;
1010
1011        if ( pin >= TSI_NUM_WIRES || ! tsi_wire[pin] || !vmeTsi148IrqMgrInstalled )
1012                return -1;
1013
1014        if ( level >= 256 ) {
1015                if ( (i = uni2tsivec(level)) < 0 )
1016                        return -1;
1017                shift = 8 + (i-256);
1018        } else if ( 1 <= level && level <=7 ) {
1019                shift = level;
1020        } else {
1021                return -1;      /* invalid level */
1022        }
1023
1024        mask = 1<<shift;
1025
1026        /* calculate the mapping register and contents */
1027        if ( shift < 16 ) {
1028                mapreg = TSI_INTM2_REG;
1029        } else if ( shift < 32 ) {
1030                shift -= 16;
1031                mapreg = TSI_INTM1_REG;
1032        } else {
1033                return -1;
1034        }
1035
1036        shift <<=1;
1037
1038        /* wires are offset by 1 so we can initialize the wire table to all zeros */
1039        wire = (tsi_wire[pin]-1) << shift;
1040
1041rtems_interrupt_disable(flags);
1042
1043        for ( i = 0; i<TSI_NUM_WIRES; i++ ) {
1044                wire_mask[i] &= ~mask;
1045        }
1046        wire_mask[pin] |= mask;
1047
1048        mask = TSI_RD(devs[0].base, mapreg) & ~ (0x3<<shift);
1049        mask |= wire;
1050        TSI_WR( devs[0].base, mapreg, mask );
1051
1052rtems_interrupt_enable(flags);
1053        return 0;
1054}
1055
1056VmeTsi148ISR
1057vmeTsi148ISRGet(unsigned long vector, void **parg)
1058{
1059VmeTsi148ISR      rval = 0;
1060unsigned long     flags;
1061volatile IRQEntry *p;
1062int               v = uni2tsivec(vector);
1063
1064
1065        if ( v < 0 )
1066                return rval;
1067
1068        p = irqHdlTbl + v;
1069
1070        rtems_interrupt_disable(flags);
1071                if ( *p ) {
1072                        if ( parg )
1073                                *parg = (*p)->usrData;
1074                        rval = (*p)->isr;
1075                }
1076        rtems_interrupt_enable(flags);
1077
1078        return rval;
1079}
1080
1081static void
1082tsiVMEISR(rtems_irq_hdl_param arg)
1083{
1084int                                     pin = (int)arg;
1085BERegister                      *b  = devs[0].base;
1086IRQEntry                        ip;
1087unsigned long           msk,lintstat,vector, vecarg;
1088int                                     lvl;
1089
1090        /* only handle interrupts routed to this pin */
1091        while ( (lintstat  = (TSI_RD(b, TSI_INTS_REG) & wire_mask[pin])) ) {
1092
1093                /* bit 0 is never set since it is never set in wire_mask */
1094
1095                do {
1096                        /* simplicity is king; just handle them in MSB to LSB order; reserved bits read as 0 */
1097#ifdef __PPC__
1098                        asm volatile("cntlzw %0, %1":"=r"(lvl):"r"(lintstat));
1099                        lvl = 31-lvl;
1100                        msk = 1<<lvl;
1101#else
1102                        { static unsigned long m[] = {
1103                                                                                         0xffff0000, 0xff00ff00, 0xf0f0f0f0, 0xcccccccc, 0xaaaaaaaa
1104                                                                                 };
1105                        int      i;
1106                        unsigned tmp;
1107
1108                        /* lintstat has already been checked...
1109                        if ( !lintstat ) {
1110                           lvl = -1; msk = 0;
1111                        } else
1112                         */
1113                        for ( i=0, lvl=0, msk = lintstat; i<5; i++ ) {
1114                                lvl <<= 1;
1115                                if ( (tmp = msk & m[i]) ) {
1116                                        lvl++;
1117                                        msk = tmp;
1118                                } else
1119                                        msk = msk & ~m[i];
1120                        }
1121                        }
1122#endif
1123
1124                        if ( lvl > 7 ) {
1125                                /* clear this interrupt level */
1126                                TSI_WR(b, TSI_INTC_REG, msk);
1127                                vector = 256 + lvl - 8;
1128                                vecarg = tsi2uni_vec_map[lvl-8];
1129                        } else {
1130                                /* need to do get the vector for this level */
1131                                switch ( tsi_iack_width[lvl-1] ) {
1132                                        default:
1133                                        case  1:
1134                                                vector = TSI_RD8(b, TSI_VIACK_1_REG - 4 + (lvl<<2) + 3);
1135                                                break;
1136
1137                                        case  2:
1138                                                vector = TSI_RD16(b, TSI_VIACK_1_REG - 4 + (lvl<<2) + 2);
1139                                                break;
1140
1141                                        case  4:
1142                                                vector = TSI_RD(b, TSI_VIACK_1_REG - 4 + (lvl<<2));
1143                                                break;
1144                                }
1145                                vecarg = vector;
1146                        }
1147
1148                        if ( !(ip=irqHdlTbl[vector])) {
1149                                /* TODO: log error message - RTEMS has no logger :-( */
1150                                printk("vmeTsi148 ISR: ERROR: no handler registered (level %i) IACK 0x%08x\n",
1151                                                lvl, vector);
1152                        } else {
1153                                /* dispatch handler, it must clear the IRQ at the device */
1154                                ip->isr(ip->usrData, vecarg);
1155                        }
1156                } while ( (lintstat &= ~msk) );
1157                /* check if a new irq is pending already */
1158        }
1159}
1160
1161
1162static void
1163my_no_op(const rtems_irq_connect_data * arg)
1164{}
1165
1166static int
1167my_isOn(const rtems_irq_connect_data *arg)
1168{
1169                return (int)(TSI_RD(devs[0].base, TSI_INTEO_REG) & TSI_RD(devs[0].base, TSI_INTEN_REG));
1170}
1171
1172static void
1173connectIsr(int shared, rtems_irq_hdl isr, int pic_line, int slot)
1174{
1175rtems_irq_connect_data  xx;
1176        xx.on     = my_no_op; /* at _least_ they could check for a 0 pointer */
1177        xx.off    = my_no_op;
1178        xx.isOn   = my_isOn;
1179        xx.hdl    = isr;
1180        xx.handle = (rtems_irq_hdl_param)slot;
1181        xx.name   = pic_line;
1182
1183        if ( shared ) {
1184#if BSP_SHARED_HANDLER_SUPPORT > 0
1185                if (!BSP_install_rtems_shared_irq_handler(&xx))
1186                        BSP_panic("unable to install vmeTsi148 shared irq handler");
1187#else
1188        uprintf(stderr,"vmeTsi148: WARNING: your BSP doesn't support sharing interrupts\n");
1189                if (!BSP_install_rtems_irq_handler(&xx))
1190                        BSP_panic("unable to install vmeTsi148 irq handler");
1191#endif
1192        } else {
1193                if (!BSP_install_rtems_irq_handler(&xx))
1194                        BSP_panic("unable to install vmeTsi148 irq handler");
1195        }
1196}
1197
1198int
1199vmeTsi148InstallIrqMgrAlt(int shared, int tsi_pin0, int pic_pin0, ...)
1200{
1201int             rval;
1202va_list ap;
1203        va_start(ap, pic_pin0);
1204        rval = vmeTsi148InstallIrqMgrVa(shared, tsi_pin0, pic_pin0, ap);
1205        va_end(ap);
1206        return rval;
1207}
1208
1209int
1210vmeTsi148InstallIrqMgrVa(int shared, int tsi_pin0, int pic_pin0, va_list ap)
1211{
1212int     i,j, specialPin, tsi_pin[TSI_NUM_WIRES+1], pic_pin[TSI_NUM_WIRES];
1213
1214        if (vmeTsi148IrqMgrInstalled)                  return -4;
1215
1216        /* check parameters */
1217
1218        if ( tsi_pin0 < 0 || tsi_pin0 > 3 )            return -1;
1219
1220        tsi_pin[0] = tsi_pin0;
1221        pic_pin[0] = pic_pin0 < 0 ? devs[0].irqLine : pic_pin0;
1222        i = 1;
1223        while ( (tsi_pin[i] = va_arg(ap, int)) >= 0 ) {
1224               
1225                if ( i >= TSI_NUM_WIRES ) {
1226                                                               return -5;
1227                }
1228
1229                pic_pin[i] = va_arg(ap,int);
1230
1231                if ( tsi_pin[i] > 3 )                      return -2;
1232                if ( pic_pin[i] < 0 )                      return -3;
1233                i++;
1234        }
1235
1236        /* all routings must be different */
1237        for ( i=0; tsi_pin[i] >= 0; i++ ) {
1238                for ( j=i+1; tsi_pin[j] >= 0; j++ ) {
1239                        if ( tsi_pin[j] == tsi_pin[i] )        return -6;
1240                        if ( pic_pin[j] == pic_pin[i] )        return -7;
1241                }
1242        }
1243
1244        /* give them a chance to override buggy PCI info */
1245        if ( pic_pin[0] >= 0 && devs[0].irqLine != pic_pin[0] ) {
1246                uprintf(stderr,"Overriding main IRQ line PCI info with %d\n",
1247                                pic_pin[0]);
1248                devs[0].irqLine = pic_pin[0];
1249        }
1250
1251        for ( i = 0; tsi_pin[i] >= 0; i++ ) {
1252                /* offset wire # by one so we can initialize to 0 == invalid */
1253                tsi_wire[i] = tsi_pin[i] + 1;
1254                connectIsr(shared, tsiVMEISR, pic_pin[i], i);
1255        }
1256
1257        specialPin = tsi_pin[1] >= 0 ? 1 : 0;
1258
1259        /* setup routing */
1260       
1261        /* IntRoute checks for mgr being installed */
1262        vmeTsi148IrqMgrInstalled=1;
1263
1264        /* route 7 VME irqs to first / 'normal' pin */
1265        for ( i=1; i<8; i++ )
1266                vmeTsi148IntRoute( i, 0 );
1267        for ( i=TSI_DMA_INT_VEC; i<TSI_NUM_INT_VECS; i++ )
1268                vmeTsi148IntRoute( i, specialPin );
1269
1270        for ( i = 0; i<TSI_NUM_WIRES; i++ ) {
1271                /* remember (for unloading the driver) */
1272                devs[0].pic_pin[i] = ( ( tsi_pin[i] >=0 ) ? pic_pin[i] : -1 );
1273        }
1274
1275        return 0;
1276}
1277
1278int
1279vmeTsi148InstallISR(unsigned long vector, VmeTsi148ISR hdl, void *arg)
1280{
1281IRQEntry          ip;
1282int                               v;
1283unsigned long     flags;
1284volatile IRQEntry *p;
1285
1286                if ( !vmeTsi148IrqMgrInstalled || (v = uni2tsivec(vector)) < 0 )
1287                        return -1;
1288
1289                p = irqHdlTbl + v;
1290
1291                if (*p || !(ip=(IRQEntry)malloc(sizeof(IRQEntryRec))))
1292                                return -1;
1293
1294                ip->isr=hdl;
1295                ip->usrData=arg;
1296
1297                rtems_interrupt_disable(flags);
1298                if (*p) {
1299                        rtems_interrupt_enable(flags);
1300                        free(ip);
1301                        return -1;
1302                }
1303                *p = ip;
1304                rtems_interrupt_enable(flags);
1305                return 0;
1306}
1307
1308int
1309vmeTsi148RemoveISR(unsigned long vector, VmeTsi148ISR hdl, void *arg)
1310{
1311int               v;
1312IRQEntry          ip;
1313unsigned long     flags;
1314volatile IRQEntry *p;
1315
1316                if ( !vmeTsi148IrqMgrInstalled || (v = uni2tsivec(vector)) < 0 )
1317                        return -1;
1318
1319                p = irqHdlTbl + v;
1320
1321                rtems_interrupt_disable(flags);
1322                ip = *p;
1323                if ( !ip || ip->isr!=hdl || ip->usrData!=arg ) {
1324                                rtems_interrupt_enable(flags);
1325                                return -1;
1326                }
1327                *p = 0;
1328                rtems_interrupt_enable(flags);
1329
1330                free(ip);
1331                return 0;
1332}
1333
1334static int
1335intDoEnDis(unsigned int level, int dis)
1336{
1337BERegister              *b = devs[0].base;
1338unsigned long   flags, v;
1339int                             shift;
1340
1341        if (  ! vmeTsi148IrqMgrInstalled || (shift = lvl2bitno(level)) < 0 )
1342                return -1;
1343
1344        v = 1<<shift;
1345
1346        if ( !dis )
1347                return (int)(v & TSI_RD(b, TSI_INTEO_REG) & TSI_RD(b, TSI_INTEN_REG)) ? 1 : 0;
1348
1349        rtems_interrupt_disable(flags);
1350        if ( dis<0 ) {
1351                TSI_WR(b, TSI_INTEN_REG, TSI_RD(b, TSI_INTEN_REG) & ~v);
1352                TSI_WR(b, TSI_INTEO_REG, TSI_RD(b, TSI_INTEO_REG) & ~v);
1353        } else {
1354                TSI_WR(b, TSI_INTEN_REG, TSI_RD(b, TSI_INTEN_REG) |  v);
1355                TSI_WR(b, TSI_INTEO_REG, TSI_RD(b, TSI_INTEO_REG) |  v);
1356        }
1357        rtems_interrupt_enable(flags);
1358        return 0;
1359}
1360
1361int
1362vmeTsi148IntEnable(unsigned int level)
1363{
1364        return intDoEnDis(level, 1);
1365}
1366
1367int
1368vmeTsi148IntDisable(unsigned int level)
1369{
1370        return intDoEnDis(level, -1);
1371}
1372
1373int
1374vmeTsi148IntIsEnabled(unsigned int level)
1375{
1376        return intDoEnDis(level, 0);
1377}
1378
1379/* Set IACK width (1,2, or 4 bytes) for a given interrupt level.
1380 *
1381 * 'width' arg may be 0,1,2 or 4. If zero, the currently active
1382 * value is returned but not modified.
1383 *
1384 * RETURNS: old width or -1 if invalid argument.
1385 */
1386
1387int
1388vmeTsi148SetIackWidth(int level, int width)
1389{
1390int rval;
1391        if ( level < 1 || level > 7 || !vmeTsi148IrqMgrInstalled )
1392                return -1;
1393
1394        switch ( width ) {
1395                default: return -1;
1396                case 0:
1397                case 1:
1398                case 2:
1399                case 4:
1400                break;
1401        }
1402
1403        rval = tsi_iack_width[level-1];
1404        if ( width )
1405                tsi_iack_width[level-1] = width;
1406        return rval;
1407}
1408
1409int
1410vmeTsi148IntRaiseXX(BERegister *base, int level, unsigned vector)
1411{
1412unsigned long v;
1413
1414        CHECK_BASE(base,0,-1);
1415
1416        if ( level < 1 || level > 7 || vector > 255 )
1417                return -1;      /* invalid argument */
1418
1419        /* Check if already asserted */
1420        if ( (v = TSI_RD(base, TSI_VICR_REG)) & TSI_VICR_IRQS ) {
1421                return -2;  /* already asserted */
1422        }
1423
1424        v &= ~255;
1425
1426        v |= TSI_VICR_IRQL(level) | TSI_VICR_STID(vector);
1427
1428        /* Write Vector */
1429        TSI_WR(base, TSI_VICR_REG, v);
1430
1431        return 0;
1432       
1433}
1434
1435int
1436vmeTsi148IntRaise(int level, unsigned vector)
1437{
1438        return vmeTsi148IntRaiseXX(devs[0].base, level, vector);
1439}
1440
1441/* Loopback test of VME/Tsi148 internal interrupts */
1442
1443typedef struct {
1444        rtems_id        q;
1445        int                     l;
1446} LoopbackTstArgs;
1447
1448static void
1449loopbackTstIsr(void *arg, unsigned long vector)
1450{
1451LoopbackTstArgs *pa = arg;
1452        if ( RTEMS_SUCCESSFUL != rtems_message_queue_send(pa->q, (void*)&vector, sizeof(vector)) ) {
1453                /* Overrun ? */
1454                printk("vmeTsi148IntLoopbackTst: (ISR) message queue full / overrun ? disabling IRQ level %i\n", pa->l);
1455                vmeTsi148IntDisable(pa->l);
1456        }
1457}
1458
1459int
1460vmeTsi148IntLoopbackTst(int level, unsigned vector)
1461{
1462BERegister                      *b = devs[0].base;
1463rtems_status_code       sc;
1464rtems_id                        q = 0;
1465int                                     installed = 0;
1466int                                     i, err = 0;
1467int                                     doDisable = 0;
1468uint32_t                        size;
1469unsigned long           msg;
1470char *                          irqfmt  = "VME IRQ @vector %3i %s";
1471char *                          iackfmt = "VME IACK            %s";
1472LoopbackTstArgs         a;
1473
1474        CHECK_BASE(b,0,-1);
1475
1476        /* arg check */
1477        if ( level < 1 || level > 7 || vector > 255 )
1478                return -1;
1479
1480        /* Create message queue */
1481        if ( RTEMS_SUCCESSFUL != (sc=rtems_message_queue_create(
1482                                                                        rtems_build_name('t' ,'U','I','I'),
1483                                                                        4,
1484                                                                        sizeof(unsigned long),
1485                                                                        0,  /* default attributes: fifo, local */
1486                                                                        &q)) ) {
1487                rtems_error(sc, "vmeTsi148IntLoopbackTst: Unable to create message queue");
1488                goto bail;
1489        }
1490
1491        a.q = q;
1492        a.l = level;
1493
1494        /* Install handlers */
1495        if ( vmeTsi148InstallISR(vector, loopbackTstIsr, (void*)&a) ) {
1496                uprintf(stderr,"Unable to install VME ISR to vector %i\n",vector);
1497                goto bail;
1498        }
1499        installed++;
1500        if ( vmeTsi148InstallISR(TSI_VME_SW_IACK_INT_VEC, loopbackTstIsr, (void*)&a) ) {
1501                uprintf(stderr,"Unable to install VME ISR to IACK special vector %i\n",TSI_VME_SW_IACK_INT_VEC);
1502                goto bail;
1503        }
1504        installed++;
1505
1506        if ( !vmeTsi148IntIsEnabled(level) && 0==vmeTsi148IntEnable(level) )
1507                doDisable = 1;
1508       
1509        /* make sure there are no pending interrupts */
1510        TSI_WR(b, TSI_INTC_REG, TSI_INTC_IACKC);
1511
1512        if ( vmeTsi148IntEnable( TSI_VME_SW_IACK_INT_VEC ) ) {
1513                uprintf(stderr,"Unable to enable IACK interrupt\n");
1514                goto bail;
1515        }
1516
1517        printf("vmeTsi148 VME interrupt loopback test; STARTING...\n");
1518        printf(" --> asserting VME IRQ level %i\n", level);
1519        vmeTsi148IntRaise(level, vector);
1520
1521        for ( i = 0; i< 3; i++ ) {
1522        sc = rtems_message_queue_receive(
1523                            q,
1524                            &msg,
1525                            &size,
1526                            RTEMS_WAIT,
1527                            20);
1528                if ( sc ) {
1529                        if ( RTEMS_TIMEOUT == sc && i>1 ) {
1530                                /* OK; we dont' expect more to happen */
1531                                sc = 0;
1532                        } else {
1533                                rtems_error(sc,"Error waiting for interrupts");
1534                        }
1535                        break;
1536                }
1537                if ( msg == vector ) {
1538                        if ( !irqfmt ) {
1539                                printf("Excess VME IRQ received ?? -- BAD\n");
1540                                err = 1;
1541                        } else {
1542                                printf(irqfmt, vector, "received -- PASSED\n");
1543                                irqfmt = 0;
1544                        }
1545                } else if ( msg == TSI_VME_SW_IACK_INT_VEC ) {
1546                        if ( !iackfmt ) {
1547                                printf("Excess VME IACK received ?? -- BAD\n");
1548                                err = 1;
1549                        } else {
1550                                printf(iackfmt, "received -- PASSED\n");
1551                                iackfmt = 0;
1552                        }
1553                } else {
1554                        printf("Unknown IRQ (vector %lu) received -- BAD\n", msg);
1555                        err = 1;
1556                }
1557        }
1558
1559
1560        /* Missing anything ? */
1561        if ( irqfmt ) {
1562                printf(irqfmt,vector, "MISSED -- BAD\n");
1563                err = 1;
1564        }
1565        if ( iackfmt ) {
1566                printf(iackfmt, "MISSED -- BAD\n");
1567                err = 1;
1568        }
1569
1570        printf("FINISHED.\n");
1571
1572bail:
1573        if ( doDisable )
1574                vmeTsi148IntDisable(level);
1575        vmeTsi148IntDisable( TSI_VME_SW_IACK_INT_VEC );
1576        if ( installed > 0 )
1577                vmeTsi148RemoveISR(vector, loopbackTstIsr, (void*)&a);
1578        if ( installed > 1 )
1579                vmeTsi148RemoveISR(TSI_VME_SW_IACK_INT_VEC, loopbackTstIsr, (void*)&a);
1580        if ( q )
1581                rtems_message_queue_delete(q);
1582
1583        return sc ? sc : err;
1584}
1585
1586unsigned long
1587vmeTsi148ClearVMEBusErrorsXX(BERegister *base, unsigned long long *paddr)
1588{
1589unsigned long rval;
1590
1591        CHECK_BASE(base,1,-1);
1592
1593        rval = TSI_RD(base, TSI_VEAT_REG);
1594        if ( rval & TSI_VEAT_VES ) {
1595                if ( paddr ) {
1596                        *paddr  = ((unsigned long long)TSI_RD(base, TSI_VEAU_REG))<<32;
1597                        *paddr |= TSI_RD(base, TSI_VEAL_REG);
1598                }
1599                /* clear errors */
1600                TSI_WR(base, TSI_VEAT_REG, TSI_VEAT_VESCL);
1601        } else {
1602                rval = 0;
1603        }
1604        return rval;
1605}
1606
1607unsigned long
1608vmeTsi148ClearVMEBusErrors(unsigned long long *paddr)
1609{
1610        return vmeTsi148ClearVMEBusErrorsXX(devs[0].base, paddr);
1611}
1612
1613#ifdef DEBUG_MODULAR
1614void
1615_cexpModuleInitialize(void* unused)
1616{
1617        vmeTsi148Init();
1618        vmeTsi148Reset();
1619}
1620
1621int
1622_cexpModuleFinalize(void *unused)
1623{
1624int             i;
1625int             rval = 1;
1626void    (*isrs[TSI_NUM_WIRES])() = {
1627        isr_pin0,
1628        isr_pin1,
1629        isr_pin2,
1630        isr_pin3,
1631};
1632
1633rtems_irq_connect_data  xx;
1634        xx.on   = my_no_op; /* at _least_ they could check for a 0 pointer */
1635        xx.off  = my_no_op;
1636        xx.isOn = my_isOn;
1637
1638        TSI_WR(devs[0].base, TSI_INTEO_REG, 0);
1639
1640        for ( i=0; i<TSI_NUM_INT_VECS; i++) {
1641                /* Dont even bother to uninstall handlers */
1642        }
1643        if ( vmeTsi148IrqMgrInstalled ) {
1644                for ( i=0; i<TSI_NUM_WIRES; i++ ) {
1645                        if ( (int)(xx.name = devs[0].pic_pin[i]) >=0 ) {
1646                                xx.hdl  = isrs[i];
1647                                rval    = rval && BSP_remove_rtems_irq_handler(&xx);
1648                        }
1649                }
1650        }
1651        return !rval;
1652}
1653#endif
Note: See TracBrowser for help on using the repository browser.