OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [lib/] [libbsp/] [shared/] [vmeUniverse/] [vmeUniverse.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/* vmeUniverse.c,v 1.1 2002/05/14 17:04:40 joel Exp */
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
#if 0
9
 * vmeUniverse.c,v
10
 * Revision 1.1  2002/05/14 17:04:40  joel
11
 * 2001-05-14   Till Straumann <strauman@slac.stanford.edu>
12
 *
13
 *      * vmeUniverse/README.universe, vmeUniverse/vmeUniverse.c,
14
 *      vmeUniverse/vmeUniverse.h: New files.
15
 *      * Makefile.am: Modified to reflect addition of files.
16
 *      * Per PR214, contributes a driver for the TUNDRA UNIVERSE
17
 *      VME-PCI bridge to libbsp/shared.
18
 *      NOTE: This driver is maintained _outside_ RTEMS by Till.  Please
19
 *      forward future modifications to him.
20
 *
21
 * Revision 1.21  2002/04/11 06:54:48  till
22
 *  - silenced message about 'successfully configured a port'
23
 *
24
 * Revision 1.20  2002/03/27 21:14:50  till
25
 *  - fix: handler table holds pointers, so hdlrTbl[vector]->usrData etc.
26
 *    not hdlrTbl[vector].usrData...
27
 *
28
 * Revision 1.19  2002/03/09 00:14:36  till
29
 *  - added vmeUniverseISRGet() to retrieve the currently installed
30
 *    ISR for a given vector
31
 *  - swapped the argument order for ISRs to (usrarg, vector)
32
 *
33
 * Revision 1.18  2002/02/07 19:53:48  till
34
 *  - reverted back to publish base_addr/irq_line as variables rather than
35
 *    through functions: the irq_line is read by the interrupt dispatcher...
36
 *
37
 * Revision 1.17  2002/01/24 08:28:10  till
38
 *  - initialize driver when reading base address or irq line.
39
 *    however, this requires the pci driver to be working already.
40
 *
41
 * Revision 1.16  2002/01/24 08:21:48  till
42
 *  - replaced public global vars for base address/irq line by routines.
43
 *
44
 * Revision 1.15  2002/01/23 06:15:30  till
45
 *   - changed master port data width to 64 bit.
46
 *     /* NOTE: reading the CY961 (Echotek ECDR814) with VDW32
47
 *      *       generated bus errors when reading 32-bit words
48
 *      *       - very weird, because the registers are 16-bit
49
 *      *         AFAIK.
50
 *      *       - 32-bit accesses worked fine on vxWorks which
51
 *      *         has the port set to 64-bit.
52
 *      *       ????????
53
 *      */
54
 *
55
 * Revision 1.14  2002/01/11 19:30:54  till
56
 *  - added more register defines to header
57
 *  - completed vmeUniverseReset
58
 *
59
 * Revision 1.13  2002/01/11 05:06:18  till
60
 *  - fixed VMEISR failing to check (lint_stat & msk) when determining
61
 *    the highes level...
62
 *  - tested interrupt handling & nesting. Seems to work.
63
 *
64
 * Revision 1.12  2002/01/11 02:25:55  till
65
 *  - added interrupt manager
66
 *
67
 * Revision 1.11  2002/01/08 03:59:52  till
68
 *  - vxworks always defines _LITTLE_ENDIAN, fixed the conditionals
69
 *    so it should work on __vxworks and on __rtems now.
70
 *  - rtems uprintf wrapper reverts to printk if stdio is not yet
71
 *    initialized (uses _impure_ptr->__sdidinit)
72
 *  - tested bus address translation utility routines
73
 *
74
 * Revision 1.9  2002/01/05 02:36:32  till
75
 *  - added vmeUniverseBusToLocalAdrs / vmeUniverseLocalToBusAdrs for address
76
 *    space translations.
77
 *  - include bsp.h under rtems to hack around the libcpu/powerpc/shared/io.h
78
 *    #define _IO_BASE & friends problem.
79
 *
80
 * Revision 1.8  2002/01/04 04:12:51  till
81
 *  - changed some rtems/pci related names
82
 *
83
 * Revision 1.7  2002/01/04 03:06:30  till
84
 *  - added further register definitions
85
 *
86
 * Revision 1.6  2001/12/20 04:42:44  till
87
 *  - fixed endianness stuff; theoretically, PPC could be LITTLE_ENDIAN...
88
 *
89
 * Revision 1.4  2001/12/19 01:59:02  till
90
 *  - started adding interrupt stuff
91
 *  - private implementation of PCI scanning if necessary
92
 *
93
 * Revision 1.3  2001/07/27 22:22:51  till
94
 *  - added more DMA support routines and defines to include file
95
 *  - xxxPortsShow can now print to a given file descriptor argument
96
 *
97
 * Revision 1.2  2001/07/26 18:06:13  till
98
 *  - ported to RTEMS
99
 *  - fixed a couple of wrong pointer calculations.
100
 *
101
 * Revision 1.1.1.1  2001/07/12 23:15:19  till
102
 *  - cvs import
103
 *
104
#endif
105
 
106
#include <stdio.h>
107
#include <stdarg.h>
108
#include "vmeUniverse.h"
109
 
110
#define UNIV_NUM_MPORTS         8 /* number of master ports */
111
#define UNIV_NUM_SPORTS         8 /* number of slave ports */
112
 
113
#define PCI_VENDOR_TUNDRA       0x10e3
114
#define PCI_DEVICE_UNIVERSEII   0
115
#define PCI_UNIVERSE_BASE0      0x10
116
#define PCI_UNIVERSE_BASE1      0x14
117
 
118
#define UNIV_REGOFF_PCITGT0_CTRL 0x100
119
#define UNIV_REGOFF_PCITGT4_CTRL 0x1a0
120
#define UNIV_REGOFF_VMESLV0_CTRL 0xf00
121
#define UNIV_REGOFF_VMESLV4_CTRL 0xf90
122
 
123
#define UNIV_CTL_VAS16          (0x00000000)
124
#define UNIV_CTL_VAS24          (0x00010000)
125
#define UNIV_CTL_VAS32          (0x00020000)
126
#define UNIV_CTL_VAS            (0x00070000)
127
 
128
#define UNIV_MCTL_EN            (0x80000000)
129
#define UNIV_MCTL_PWEN          (0x40000000)
130
#define UNIV_MCTL_PGM           (0x00004000)
131
#define UNIV_MCTL_VCT           (0x00000100)
132
#define UNIV_MCTL_SUPER         (0x00001000)
133
#define UNIV_MCTL_VDW32         (0x00800000)
134
#define UNIV_MCTL_VDW64         (0x00c00000)
135
 
136
#define UNIV_MCTL_AM_MASK       (UNIV_CTL_VAS | UNIV_MCTL_PGM | UNIV_MCTL_SUPER)
137
 
138
#define UNIV_SCTL_EN            (0x80000000)
139
#define UNIV_SCTL_PWEN          (0x40000000)
140
#define UNIV_SCTL_PREN          (0x20000000)
141
#define UNIV_SCTL_PGM           (0x00800000)
142
#define UNIV_SCTL_DAT           (0x00400000)
143
#define UNIV_SCTL_SUPER         (0x00200000)
144
#define UNIV_SCTL_USER          (0x00100000)
145
 
146
#define UNIV_SCTL_AM_MASK       (UNIV_CTL_VAS | UNIV_SCTL_PGM | UNIV_SCTL_DAT | UNIV_SCTL_USER | UNIV_SCTL_SUPER)
147
 
148
/* we rely on a vxWorks definition here */
149
#define VX_AM_SUP               4
150
 
151
#ifdef __rtems
152
 
153
#include <stdlib.h>
154
#include <rtems/bspIo.h>        /* printk */
155
#include <bsp/pci.h>
156
#include <bsp.h>
157
 
158
#define pciFindDevice   BSP_pciFindDevice
159
#define pciConfigInLong pci_read_config_dword
160
#define pciConfigInByte pci_read_config_byte
161
 
162
typedef unsigned int pci_ulong;
163
#define PCI_TO_LOCAL_ADDR(memaddr) ((pci_ulong)(memaddr) + PCI_MEM_BASE)
164
 
165
 
166
#elif defined(__vxworks)
167
typedef unsigned long pci_ulong;
168
#define PCI_TO_LOCAL_ADDR(memaddr) (memaddr)
169
#define PCI_INTERRUPT_LINE      0x3c
170
#else
171
#error "vmeUniverse not ported to this architecture yet"
172
#endif
173
 
174
 
175
volatile LERegister *vmeUniverse0BaseAddr=0;
176
int vmeUniverse0PciIrqLine=-1;
177
 
178
#if 0
179
/* public access functions */
180
volatile LERegister *
181
vmeUniverseBaseAddr(void)
182
{
183
        if (!vmeUniverse0BaseAddr) vmeUniverseInit();
184
        return vmeUniverse0BaseAddr;
185
}
186
 
187
int
188
vmeUniversePciIrqLine(void)
189
{
190
        if (vmeUniverse0PciIrqLine<0) vmeUniverseInit();
191
        return vmeUniverse0PciIrqLine;
192
}
193
#endif
194
 
195
static inline void
196
WRITE_LE(
197
        unsigned long val,
198
        volatile LERegister    *adrs,
199
        unsigned long off)
200
{
201
#if (__LITTLE_ENDIAN__ == 1)
202
        *(volatile unsigned long*)(((unsigned long)adrs)+off)=val;
203
#elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
204
        /* offset is in bytes and MUST not end up in r0 */
205
        __asm__ __volatile__("stwbrx %1, %0, %2" :: "b"(off),"r"(val),"r"(adrs));
206
#elif defined(__rtems)
207
        st_le32((volatile unsigned long*)(((unsigned long)adrs)+off), val);
208
#else
209
#error "little endian register writing not implemented"
210
#endif
211
}
212
 
213
#if defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)
214
#define SYNC __asm__ __volatile__("sync")
215
#else
216
#define SYNC
217
#warning "SYNC instruction unknown for this architecture"
218
#endif
219
 
220
/* registers should be mapped to guarded, non-cached memory; hence
221
 * subsequent stores are ordered. eieio is only needed to enforce
222
 * ordering of loads with respect to stores.
223
 */
224
#define EIEIO_REG
225
 
226
static inline unsigned long
227
READ_LE0(volatile LERegister *adrs)
228
{
229
#if (__LITTLE_ENDIAN__ == 1)
230
        return *(volatile unsigned long *)adrs;
231
#elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
232
register unsigned long rval;
233
__asm__ __volatile__("lwbrx %0, 0, %1":"=r"(rval):"r"(adrs));
234
        return rval;
235
#elif defined(__rtems)
236
        return ld_le32((volatile unsigned long*)adrs);
237
#else
238
#error "little endian register reading not implemented"
239
#endif
240
}
241
 
242
static inline unsigned long
243
READ_LE(volatile LERegister *adrs, unsigned long off)
244
{
245
#if (__LITTLE_ENDIAN__ == 1)
246
        return  *((volatile LERegister *)(((unsigned long)adrs)+off));
247
#elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
248
register unsigned long rval;
249
        /* offset is in bytes and MUST not end up in r0 */
250
__asm__ __volatile__("lwbrx %0, %2, %1"
251
                                : "=r"(rval)
252
                                : "r"(adrs), "b"(off));
253
#if 0
254
__asm__ __volatile__("eieio");
255
#endif
256
return rval;
257
#else
258
return READ_LE0((volatile LERegister *)(((unsigned long)adrs)+off));
259
#endif
260
}
261
 
262
#define PORT_UNALIGNED(addr,port) \
263
        ( (port)%4 ? ((addr) & 0xffff) : ((addr) & 4095) )
264
 
265
 
266
#define UNIV_REV(base) (READ_LE(base,2*sizeof(LERegister)) & 0xff)
267
 
268
#ifdef __rtems
269
static int
270
uprintk(char *fmt, va_list ap)
271
{
272
int             rval;
273
/* during bsp init, there is no malloc and no stdio,
274
 * hence we assemble the message on the stack and revert
275
 * to printk
276
 */
277
char    buf[200];
278
        rval = vsprintf(buf,fmt,ap);
279
        if (rval > sizeof(buf))
280
                        BSP_panic("vmeUniverse/uprintk: buffer overrun");
281
        printk(buf);
282
        return rval;
283
}
284
#endif
285
 
286
 
287
/* private printing wrapper */
288
static int
289
uprintf(FILE *f, char *fmt, ...)
290
{
291
va_list ap;
292
int     rval;
293
        va_start(ap, fmt);
294
#ifdef __rtems
295
        if (!f || !_impure_ptr->__sdidinit) {
296
                /* Might be called at an early stage when
297
                 * stdio is not yet initialized.
298
                 * There is no vprintk, hence we must assemble
299
                 * to a buffer.
300
                 */
301
                rval=uprintk(fmt,ap);
302
        } else
303
#endif
304
        {
305
                rval=vfprintf(f,fmt,ap);
306
        }
307
        va_end(ap);
308
        return rval;
309
}
310
 
311
int
312
vmeUniverseFindPciBase(
313
        int instance,
314
        volatile LERegister **pbase
315
        )
316
{
317
int bus,dev,fun;
318
pci_ulong busaddr;
319
unsigned char irqline;
320
 
321
        if (pciFindDevice(
322
                        PCI_VENDOR_TUNDRA,
323
                        PCI_DEVICE_UNIVERSEII,
324
                        instance,
325
                        &bus,
326
                        &dev,
327
                        &fun))
328
                return -1;
329
        if (pciConfigInLong(bus,dev,fun,PCI_UNIVERSE_BASE0,&busaddr))
330
                return -1;
331
        if ((unsigned long)(busaddr) & 1) {
332
                /* it's IO space, try BASE1 */
333
                if (pciConfigInLong(bus,dev,fun,PCI_UNIVERSE_BASE1,&busaddr)
334
                   || ((unsigned long)(busaddr) & 1))
335
                        return -1;
336
        }
337
        *pbase=(volatile LERegister*)PCI_TO_LOCAL_ADDR(busaddr);
338
 
339
        if (pciConfigInByte(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline))
340
                return -1;
341
        else
342
                vmeUniverse0PciIrqLine = irqline;
343
 
344
        return 0;
345
}
346
 
347
/* convert an address space selector to a corresponding
348
 * universe control mode word
349
 */
350
 
351
static int
352
am2mode(int ismaster, unsigned long address_space, unsigned long *pmode)
353
{
354
unsigned long mode=0;
355
        if (!ismaster) {
356
                mode |= UNIV_SCTL_DAT | UNIV_SCTL_PGM;
357
                mode |= UNIV_SCTL_USER;
358
        }
359
        switch (address_space) {
360
                case VME_AM_STD_SUP_PGM:
361
                case VME_AM_STD_USR_PGM:
362
                        if (ismaster)
363
                                mode |= UNIV_MCTL_PGM ;
364
                        else {
365
                                mode &= ~UNIV_SCTL_DAT;
366
                        }
367
                        /* fall thru */
368
                case VME_AM_STD_SUP_DATA:
369
                case VME_AM_STD_USR_DATA:
370
                        mode |= UNIV_CTL_VAS24;
371
                        break;
372
 
373
                case VME_AM_EXT_SUP_PGM:
374
                case VME_AM_EXT_USR_PGM:
375
                        if (ismaster)
376
                                mode |= UNIV_MCTL_PGM ;
377
                        else {
378
                                mode &= ~UNIV_SCTL_DAT;
379
                        }
380
                        /* fall thru */
381
                case VME_AM_EXT_SUP_DATA:
382
                case VME_AM_EXT_USR_DATA:
383
                        mode |= UNIV_CTL_VAS32;
384
                        break;
385
 
386
                case VME_AM_SUP_SHORT_IO:
387
                case VME_AM_USR_SHORT_IO:
388
                        mode |= UNIV_CTL_VAS16;
389
                        break;
390
 
391
                case 0: /* disable the port alltogether */
392
                        break;
393
 
394
                default:
395
                        return -1;
396
        }
397
        if (address_space & VX_AM_SUP)
398
                mode |= (ismaster ? UNIV_MCTL_SUPER : UNIV_SCTL_SUPER);
399
        *pmode = mode;
400
        return 0;
401
}
402
 
403
static int
404
disableUniversePort(int ismaster, int portno, volatile unsigned long *preg, void *param)
405
{
406
unsigned long cntrl;
407
        cntrl=READ_LE0(preg);
408
        cntrl &= ~(ismaster ? UNIV_MCTL_EN : UNIV_SCTL_EN);
409
        WRITE_LE(cntrl,preg,0);
410
        SYNC; /* make sure this command completed */
411
        return 0;
412
}
413
 
414
static int
415
cfgUniversePort(
416
        unsigned long   ismaster,
417
        unsigned long   port,
418
        unsigned long   address_space,
419
        unsigned long   vme_address,
420
        unsigned long   local_address,
421
        unsigned long   length)
422
{
423
#define base vmeUniverse0BaseAddr
424
volatile LERegister *preg=base;
425
unsigned long   p=port;
426
unsigned long   mode=0;
427
 
428
        /* check parameters */
429
        if (port >= (ismaster ? UNIV_NUM_MPORTS : UNIV_NUM_SPORTS)) {
430
                uprintf(stderr,"invalid port\n");
431
                return -1;
432
        }
433
        /* port start, bound addresses and offset must lie on 64k boundary
434
         * (4k for port 0 and 4)
435
         */
436
        if ( PORT_UNALIGNED(local_address,port) ) {
437
                uprintf(stderr,"local address misaligned\n");
438
                return -1;
439
        }
440
        if ( PORT_UNALIGNED(vme_address,port) ) {
441
                uprintf(stderr,"vme address misaligned\n");
442
                return -1;
443
        }
444
        if ( PORT_UNALIGNED(length,port) ) {
445
                uprintf(stderr,"length misaligned\n");
446
                return -1;
447
        }
448
 
449
        /* check address space validity */
450
        if (am2mode(ismaster,address_space,&mode)) {
451
                uprintf(stderr,"invalid address space\n");
452
                return -1;
453
        }
454
 
455
        /* get the universe base address */
456
        if (!base && vmeUniverseInit()) {
457
                return -1;
458
        }
459
 
460
        /* find out if we have a rev. II chip */
461
        if ( UNIV_REV(base) < 2 ) {
462
                if (port>3) {
463
                        uprintf(stderr,"Universe rev. < 2 has only 4 ports\n");
464
                        return -1;
465
                }
466
        }
467
 
468
        /* finally, configure the port */
469
 
470
        /* find the register set for our port */
471
        if (port<4) {
472
                preg += (ismaster ? UNIV_REGOFF_PCITGT0_CTRL : UNIV_REGOFF_VMESLV0_CTRL)/sizeof(LERegister);
473
        } else {
474
                preg += (ismaster ? UNIV_REGOFF_PCITGT4_CTRL : UNIV_REGOFF_VMESLV4_CTRL)/sizeof(LERegister);
475
                p-=4;
476
        }
477
        preg += 5 * p;
478
 
479
        /* temporarily disable the port */
480
        disableUniversePort(ismaster,port,preg,0);
481
 
482
        /* address_space == 0 means disable */
483
        if (address_space != 0) {
484
                unsigned long start,offst;
485
                /* set the port starting address;
486
                 * this is the local address for the master
487
                 * and the VME address for the slave
488
                 */
489
                if (ismaster) {
490
                        start=local_address;
491
                        /* let it overflow / wrap around 0 */
492
                        offst=vme_address-local_address;
493
                } else {
494
                        start=vme_address;
495
                        /* let it overflow / wrap around 0 */
496
                        offst=local_address-vme_address;
497
                }
498
#undef TSILL
499
#ifdef TSILL
500
                uprintf(stderr,"writing 0x%08x to 0x%08x + 4\n",start,preg);
501
#else
502
                WRITE_LE(start,preg,4);
503
#endif
504
                /* set bound address */
505
                length+=start;
506
#ifdef TSILL
507
                uprintf(stderr,"writing 0x%08x to 0x%08x + 8\n",length,preg);
508
#else
509
                WRITE_LE(length,preg,8);
510
#endif
511
                /* set offset */
512
#ifdef TSILL
513
                uprintf(stderr,"writing 0x%08x to 0x%08x + 12\n",offst,preg);
514
#else
515
                WRITE_LE(offst,preg,12);
516
#endif
517
                /* calculate configuration word and enable the port */
518
                /* NOTE: reading the CY961 (Echotek ECDR814) with VDW32
519
                 *       generated bus errors when reading 32-bit words
520
                 *       - very weird, because the registers are 16-bit
521
                 *         AFAIK.
522
                 *       - 32-bit accesses worked fine on vxWorks which
523
                 *         has the port set to 64-bit.
524
                 *       ????????
525
                 */
526
                if (ismaster)
527
                        mode |= UNIV_MCTL_EN | UNIV_MCTL_PWEN | UNIV_MCTL_VDW64 | UNIV_MCTL_VCT;
528
                else
529
                        mode |= UNIV_SCTL_EN | UNIV_SCTL_PWEN | UNIV_SCTL_PREN;
530
 
531
#ifdef TSILL
532
                uprintf(stderr,"writing 0x%08x to 0x%08x + 0\n",mode,preg);
533
#else
534
                EIEIO_REG;      /* make sure mode is written last */
535
                WRITE_LE(mode,preg,0);
536
                SYNC;           /* enforce completion */
537
#endif
538
 
539
#ifdef TSILL
540
                uprintf(stderr,
541
                        "universe %s port %lu successfully configured\n",
542
                                ismaster ? "master" : "slave",
543
                                port);
544
#endif
545
 
546
#ifdef __vxworks
547
                if (ismaster)
548
                        uprintf(stderr,
549
                        "WARNING: on the synergy, sysMasterPortsShow() may show incorrect settings (it uses cached values)\n");
550
#endif
551
        }
552
        return 0;
553
#undef base
554
}
555
 
556
 
557
static int
558
showUniversePort(
559
                int             ismaster,
560
                int             portno,
561
                volatile LERegister *preg,
562
                void            *parm)
563
{
564
        FILE *f=parm ? (FILE *)parm : stdout;
565
        unsigned long cntrl, start, bound, offst, mask;
566
 
567
        cntrl = READ_LE0(preg++);
568
#undef TSILL
569
#ifdef TSILL
570
        uprintf(stderr,"showUniversePort: *(0x%08x): 0x%08x\n",preg-1,cntrl);
571
#endif
572
#undef TSILL
573
 
574
        /* skip this port if disabled */
575
        if (!(cntrl & (ismaster ? UNIV_MCTL_EN : UNIV_SCTL_EN)))
576
                return 0;
577
 
578
        /* for the master `start' is the PCI address,
579
         * for the slave  `start' is the VME address
580
         */
581
        mask = ~PORT_UNALIGNED(0xffffffff,portno);
582
 
583
        start = READ_LE0(preg++)&mask;
584
        bound = READ_LE0(preg++)&mask;
585
        offst = READ_LE0(preg++)&mask;
586
 
587
        offst+=start; /* calc start on the other bus */
588
 
589
        if (ismaster) {
590
                uprintf(f,"%i:    0x%08lx 0x%08lx 0x%08lx ",
591
                        portno,offst,bound-start,start);
592
        } else {
593
                uprintf(f,"%i:    0x%08lx 0x%08lx 0x%08lx ",
594
                        portno,start,bound-start,offst);
595
        }
596
 
597
        switch (cntrl & UNIV_CTL_VAS) {
598
                case UNIV_CTL_VAS16: uprintf(f,"A16, "); break;
599
                case UNIV_CTL_VAS24: uprintf(f,"A24, "); break;
600
                case UNIV_CTL_VAS32: uprintf(f,"A32, "); break;
601
                default: uprintf(f,"A??, "); break;
602
        }
603
 
604
        if (ismaster) {
605
                uprintf(f,"%s, %s",
606
                        cntrl&UNIV_MCTL_PGM ?   "Pgm" : "Dat",
607
                        cntrl&UNIV_MCTL_SUPER ? "Sup" : "Usr");
608
        } else {
609
                uprintf(f,"%s %s %s %s",
610
                        cntrl&UNIV_SCTL_PGM ?   "Pgm," : "    ",
611
                        cntrl&UNIV_SCTL_DAT ?   "Dat," : "    ",
612
                        cntrl&UNIV_SCTL_SUPER ? "Sup," : "    ",
613
                        cntrl&UNIV_SCTL_USER  ? "Usr" :  "");
614
        }
615
        uprintf(f,"\n");
616
        return 0;
617
}
618
 
619
typedef struct XlatRec_ {
620
        unsigned long   address;
621
        unsigned long   aspace;
622
} XlatRec, *Xlat;
623
 
624
/* try to translate an address through the bridge
625
 *
626
 * IN:  l->address, l->aspace
627
 * OUT: l->address (translated address)
628
 *
629
 * RETURNS: -1: invalid space
630
 *           0: invalid address (not found in range)
631
 *           1: success
632
 */
633
 
634
static int
635
xlatePort(int ismaster, int port, volatile LERegister *preg, void *parm)
636
{
637
Xlat    l=(Xlat)parm;
638
unsigned long cntrl, start, bound, offst, mask, x;
639
 
640
        cntrl = READ_LE0(preg++);
641
 
642
        /* skip this port if disabled */
643
        if (!(cntrl & (ismaster ? UNIV_MCTL_EN : UNIV_SCTL_EN)))
644
                return 0;
645
 
646
        /* check for correct address space */
647
        if ( am2mode(ismaster,l->aspace,&offst) ) {
648
                uprintf(stderr,"vmeUniverse WARNING: invalid adressing mode 0x%x\n",
649
                               l->aspace);
650
                return -1;
651
        }
652
        if ( (cntrl & (ismaster ? UNIV_MCTL_AM_MASK : UNIV_SCTL_AM_MASK))
653
            != offst )
654
                return 0; /* mode doesn't match requested AM */
655
 
656
        /* OK, we found a matching mode, now we must check the address range */
657
        mask = ~PORT_UNALIGNED(0xffffffff,port);
658
 
659
        /* for the master `start' is the PCI address,
660
         * for the slave  `start' is the VME address
661
         */
662
        start = READ_LE0(preg++) & mask;
663
        bound = READ_LE0(preg++) & mask;
664
        offst = READ_LE0(preg++) & mask;
665
 
666
        /* translate address to the other bus */
667
        x = l->address - offst;
668
 
669
        if (x >= start && x < bound) {
670
                /* valid address found */
671
                l->address = x;
672
                return 1;
673
        }
674
        return 0;
675
}
676
 
677
 
678
static int
679
mapOverAll(int ismaster, int (*func)(int,int,volatile LERegister *,void*), void *arg)
680
{
681
#define base    vmeUniverse0BaseAddr
682
volatile LERegister     *rptr;
683
unsigned long   port;
684
int     rval;
685
 
686
        /* get the universe base address */
687
        if (!base && vmeUniverseInit()) {
688
                uprintf(stderr,"unable to find the universe in pci config space\n");
689
                return -1;
690
        }
691
        rptr = (base +
692
                (ismaster ? UNIV_REGOFF_PCITGT0_CTRL : UNIV_REGOFF_VMESLV0_CTRL)/sizeof(LERegister));
693
#undef TSILL
694
#ifdef TSILL
695
        uprintf(stderr,"mapoverall: base is 0x%08x, rptr 0x%08x\n",base,rptr);
696
#endif
697
#undef TSILL
698
        for (port=0; port<4; port++) {
699
                if ((rval=func(ismaster,port,rptr,arg))) return rval;
700
                rptr+=5; /* register block spacing */
701
        }
702
 
703
        /* only rev. 2 has 8 ports */
704
        if (UNIV_REV(base)<2) return -1;
705
 
706
        rptr = (base +
707
                (ismaster ? UNIV_REGOFF_PCITGT4_CTRL : UNIV_REGOFF_VMESLV4_CTRL)/sizeof(LERegister));
708
        for (port=4; port<UNIV_NUM_MPORTS; port++) {
709
                if ((rval=func(ismaster,port,rptr,arg))) return rval;
710
                rptr+=5; /* register block spacing */
711
        }
712
        return 0;
713
#undef base
714
}
715
 
716
static void
717
showUniversePorts(int ismaster, FILE *f)
718
{
719
        if (!f) f=stdout;
720
        uprintf(f,"Universe %s Ports:\n",ismaster ? "Master" : "Slave");
721
        uprintf(f,"Port  VME-Addr   Size       PCI-Adrs   Mode:\n");
722
        mapOverAll(ismaster,showUniversePort,f);
723
}
724
 
725
static int xlate(int ismaster, unsigned long as, unsigned long aIn, unsigned long *paOut)
726
{
727
int     rval;
728
XlatRec l;
729
        l.aspace = as;
730
        l.address = aIn;
731
        /* map result -1/0/1 to -2/-1/0 with 0 on success */
732
        rval = mapOverAll(ismaster,xlatePort,(void*)&l) - 1;
733
        *paOut = l.address;
734
        return rval;
735
}
736
 
737
/* public functions */
738
int
739
vmeUniverseLocalToBusAdrs(unsigned long as, unsigned long localAdrs, unsigned long *pbusAdrs)
740
{
741
        return xlate(0,as,localAdrs,pbusAdrs);
742
}
743
 
744
int
745
vmeUniverseBusToLocalAdrs(unsigned long as, unsigned long busAdrs, unsigned long *plocalAdrs)
746
{
747
        return xlate(1,as,busAdrs,plocalAdrs);
748
}
749
 
750
void
751
vmeUniverseReset(void)
752
{
753
        /* disable/reset special cycles (ADOH, RMW) */
754
        vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_CTL);
755
        vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_ADDR);
756
        vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_EN);
757
 
758
        /* set coupled window timeout to 0 (release VME after each transaction)
759
         * CRT (coupled request timeout) is unused by Universe II
760
         */
761
        vmeUniverseWriteReg(UNIV_LMISC_CRT_128_US, UNIV_REGOFF_LMISC);
762
 
763
        /* disable/reset DMA engine */
764
        vmeUniverseWriteReg(0, UNIV_REGOFF_DCTL);
765
        vmeUniverseWriteReg(0, UNIV_REGOFF_DTBC);
766
        vmeUniverseWriteReg(0, UNIV_REGOFF_DLA);
767
        vmeUniverseWriteReg(0, UNIV_REGOFF_DVA);
768
        vmeUniverseWriteReg(0, UNIV_REGOFF_DCPP);
769
 
770
        /* disable location monitor */
771
        vmeUniverseWriteReg(0, UNIV_REGOFF_LM_CTL);
772
 
773
        /* disable universe register access from VME bus */
774
        vmeUniverseWriteReg(0, UNIV_REGOFF_VRAI_CTL);
775
 
776
        /* disable VME bus image of VME CSR */
777
        vmeUniverseWriteReg(0, UNIV_REGOFF_VCSR_CTL);
778
 
779
        /* disable interrupts, reset routing */
780
        vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_EN);
781
        vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP0);
782
        vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP1);
783
 
784
        vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_EN);
785
        vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_MAP0);
786
        vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_MAP1);
787
 
788
        vmeUniverseDisableAllSlaves();
789
 
790
        vmeUniverseDisableAllMasters();
791
 
792
        vmeUniverseWriteReg(UNIV_VCSR_CLR_SYSFAIL, UNIV_REGOFF_VCSR_CLR);
793
 
794
        /* clear interrupt status bits */
795
        vmeUniverseWriteReg(UNIV_LINT_STAT_CLR, UNIV_REGOFF_LINT_STAT);
796
        vmeUniverseWriteReg(UNIV_VINT_STAT_CLR, UNIV_REGOFF_VINT_STAT);
797
 
798
        vmeUniverseWriteReg(UNIV_V_AMERR_V_STAT, UNIV_REGOFF_V_AMERR);
799
 
800
        vmeUniverseWriteReg(
801
                vmeUniverseReadReg(UNIV_REGOFF_PCI_CSR) |
802
                UNIV_PCI_CSR_D_PE | UNIV_PCI_CSR_S_SERR | UNIV_PCI_CSR_R_MA |
803
                UNIV_PCI_CSR_R_TA | UNIV_PCI_CSR_S_TA,
804
                UNIV_REGOFF_PCI_CSR);
805
 
806
        vmeUniverseWriteReg(UNIV_L_CMDERR_L_STAT, UNIV_REGOFF_L_CMDERR);
807
 
808
        vmeUniverseWriteReg(
809
                UNIV_DGCS_STOP | UNIV_DGCS_HALT | UNIV_DGCS_DONE |
810
                UNIV_DGCS_LERR | UNIV_DGCS_VERR | UNIV_DGCS_P_ERR,
811
                UNIV_REGOFF_DGCS);
812
}
813
 
814
int
815
vmeUniverseInit(void)
816
{
817
int rval;
818
        if ((rval=vmeUniverseFindPciBase(0,&vmeUniverse0BaseAddr))) {
819
                uprintf(stderr,"unable to find the universe in pci config space\n");
820
        } else {
821
                uprintf(stderr,"Universe II PCI-VME bridge detected at 0x%08x, IRQ %i\n",
822
                                (unsigned int)vmeUniverse0BaseAddr, vmeUniverse0PciIrqLine);
823
        }
824
        return rval;
825
}
826
 
827
void
828
vmeUniverseMasterPortsShow(FILE *f)
829
{
830
        showUniversePorts(1,f);
831
}
832
 
833
void
834
vmeUniverseSlavePortsShow(FILE *f)
835
{
836
        showUniversePorts(0,f);
837
}
838
 
839
int
840
vmeUniverseMasterPortCfg(
841
        unsigned long   port,
842
        unsigned long   address_space,
843
        unsigned long   vme_address,
844
        unsigned long   local_address,
845
        unsigned long   length)
846
{
847
        return cfgUniversePort(1,port,address_space,vme_address,local_address,length);
848
}
849
 
850
int
851
vmeUniverseSlavePortCfg(
852
        unsigned long   port,
853
        unsigned long   address_space,
854
        unsigned long   vme_address,
855
        unsigned long   local_address,
856
        unsigned long   length)
857
{
858
        return cfgUniversePort(0,port,address_space,vme_address,local_address,length);
859
}
860
 
861
void
862
vmeUniverseDisableAllSlaves(void)
863
{
864
        mapOverAll(0,disableUniversePort,0);
865
}
866
 
867
void
868
vmeUniverseDisableAllMasters(void)
869
{
870
        mapOverAll(1,disableUniversePort,0);
871
}
872
 
873
int
874
vmeUniverseStartDMA(
875
        unsigned long local_addr,
876
        unsigned long vme_addr,
877
        unsigned long count)
878
{
879
 
880
        if (!vmeUniverse0BaseAddr && vmeUniverseInit()) return -1;
881
        if ((local_addr & 7) != (vme_addr & 7)) {
882
                uprintf(stderr,"vmeUniverseStartDMA: misaligned addresses\n");
883
                return -1;
884
        }
885
 
886
        {
887
        /* help the compiler allocate registers */
888
        register volatile LERegister *b=vmeUniverse0BaseAddr;
889
        register unsigned long dgcsoff=UNIV_REGOFF_DGCS,dgcs;
890
 
891
        dgcs=READ_LE(b, dgcsoff);
892
 
893
        /* clear status and make sure CHAIN is clear */
894
        dgcs &= ~UNIV_DGCS_CHAIN;
895
        WRITE_LE(dgcs,
896
                      b, dgcsoff);
897
        WRITE_LE(local_addr,
898
                      b, UNIV_REGOFF_DLA);
899
        WRITE_LE(vme_addr,
900
                      b, UNIV_REGOFF_DVA);
901
        WRITE_LE(count,
902
                      b, UNIV_REGOFF_DTBC);
903
        dgcs |= UNIV_DGCS_GO;
904
        EIEIO_REG; /* make sure GO is written after everything else */
905
        WRITE_LE(dgcs,
906
                      b, dgcsoff);
907
        }
908
        SYNC; /* enforce command completion */
909
        return 0;
910
}
911
 
912
unsigned long
913
vmeUniverseReadReg(unsigned long offset)
914
{
915
unsigned long rval;
916
        rval = READ_LE(vmeUniverse0BaseAddr,offset);
917
        return rval;
918
}
919
 
920
void
921
vmeUniverseWriteReg(unsigned long value, unsigned long offset)
922
{
923
        WRITE_LE(value, vmeUniverse0BaseAddr, offset);
924
}
925
 
926
void
927
vmeUniverseCvtToLE(unsigned long *ptr, unsigned long num)
928
{
929
#if !defined(__LITTLE_ENDIAN__) || (__LITTLE_ENDIAN__ != 1)
930
register unsigned long *p=ptr+num;
931
        while (p > ptr) {
932
#if (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
933
                __asm__ __volatile__(
934
                        "lwzu 0, -4(%0)\n"
935
                        "stwbrx 0, 0, %0\n"
936
                        : "=r"(p) : "r"(p) : "r0"
937
                        );
938
#elif defined(__rtems)
939
                p--; st_le32(p, *p);
940
#else
941
#error  "vmeUniverse: endian conversion not implemented for this architecture"
942
#endif
943
        }
944
#endif
945
}
946
 
947
/* RTEMS interrupt subsystem */
948
 
949
#ifdef __rtems
950
#include <bsp/irq.h>
951
 
952
typedef struct
953
UniverseIRQEntryRec_ {
954
                VmeUniverseISR  isr;
955
                void                    *usrData;
956
} UniverseIRQEntryRec, *UniverseIRQEntry;
957
 
958
static UniverseIRQEntry universeHdlTbl[257]={0};
959
 
960
static int mgrInstalled=0;
961
static int vmeIrqUnivOut=-1;
962
static int specialIrqUnivOut=-1;
963
 
964
VmeUniverseISR
965
vmeUniverseISRGet(unsigned long vector, void **parg)
966
{
967
        if (vector>255) return 0;
968
        if (parg)
969
                *parg=universeHdlTbl[vector]->usrData;
970
        return universeHdlTbl[vector]->isr;
971
}
972
 
973
static void
974
universeSpecialISR(void)
975
{
976
UniverseIRQEntry ip;
977
        /* try the special handler */
978
        if ((ip=universeHdlTbl[UNIV_SPECIAL_IRQ_VECTOR])) {
979
                ip->isr(ip->usrData, UNIV_SPECIAL_IRQ_VECTOR);
980
        }
981
        /* clear all special interrupts */
982
        vmeUniverseWriteReg(
983
                                        ~((UNIV_LINT_STAT_VIRQ7<<1)-UNIV_LINT_STAT_VIRQ1),
984
                                        UNIV_REGOFF_LINT_STAT
985
                                        );
986
 
987
/*
988
 *      clear our line in the VINT_STAT register
989
 *  seems to be not neccessary...
990
        vmeUniverseWriteReg(
991
                                        UNIV_VINT_STAT_LINT(specialIrqUnivOut),
992
                                        UNIV_REGOFF_VINT_STAT);
993
 */
994
}
995
 
996
/*
997
 * interrupts from VME to PCI seem to be processed more or less
998
 * like this:
999
 *
1000
 *
1001
 *   VME IRQ ------
1002
 *                  & ----- LINT_STAT ----
1003
 *                  |                       &  ---------- PCI LINE
1004
 *                  |                       |
1005
 *                  |                       |
1006
 *       LINT_EN ---------------------------
1007
 *
1008
 *  I.e.
1009
 *   - if LINT_EN is disabled, a VME IRQ will not set LINT_STAT.
1010
 *   - while LINT_STAT is set, it will pull the PCI line unless
1011
 *     masked by LINT_EN.
1012
 *   - VINT_STAT(lint_bit) seems to have no effect beyond giving
1013
 *     status info.
1014
 *
1015
 *  Hence, it is possible to
1016
 *    - arm (set LINT_EN, routing etc.)
1017
 *    - receive an irq (sets. LINT_STAT)
1018
 *    - the ISR then:
1019
 *                * clears LINT_EN, results in masking LINT_STAT (which
1020
 *                  is still set to prevent another VME irq at the same
1021
 *                  level to be ACKEd by the universe.
1022
 *                * do PCI_EOI to allow nesting of higher VME irqs.
1023
 *                  (previous step also cleared LINT_EN of lower levels)
1024
 *                * when the handler returns, clear LINT_STAT
1025
 *                * re-enable setting LINT_EN.
1026
 */
1027
 
1028
static void
1029
universeVMEISR(void)
1030
{
1031
UniverseIRQEntry ip;
1032
unsigned long lvl,msk,lintstat,linten,status;
1033
 
1034
                /* determine the highest priority IRQ source */
1035
                lintstat=vmeUniverseReadReg(UNIV_REGOFF_LINT_STAT);
1036
                for (msk=UNIV_LINT_STAT_VIRQ7, lvl=7;
1037
                         lvl>0;
1038
                         lvl--, msk>>=1) {
1039
                        if (lintstat & msk) break;
1040
                }
1041
                if (!lvl) {
1042
                                /* try the special handler */
1043
                                universeSpecialISR();
1044
 
1045
                                /*
1046
                                 * let the pic end this cycle
1047
                                 */
1048
                                BSP_PIC_DO_EOI;
1049
 
1050
                                return;
1051
                }
1052
                linten = vmeUniverseReadReg(UNIV_REGOFF_LINT_EN);
1053
 
1054
                /* mask this and all lower levels */
1055
                vmeUniverseWriteReg(
1056
                                                linten & ~((msk<<1)-UNIV_LINT_STAT_VIRQ1),
1057
                                                UNIV_REGOFF_LINT_EN
1058
                                                );
1059
 
1060
                /* end this interrupt
1061
                 * cycle on the PCI bus, so higher level interrupts can be
1062
                 * caught from now on...
1063
                 */
1064
                BSP_PIC_DO_EOI;
1065
 
1066
                /* get vector and dispatch handler */
1067
                status = vmeUniverseReadReg(UNIV_REGOFF_VIRQ1_STATID - 4 + (lvl<<2));
1068
                /* determine the highest priority IRQ source */
1069
 
1070
                if (status & UNIV_VIRQ_ERR) {
1071
                                /* TODO: log error message - RTEMS has no logger :-( */
1072
                } else if (!(ip=universeHdlTbl[status & UNIV_VIRQ_STATID_MASK])) {
1073
                                /* TODO: log error message - RTEMS has no logger :-( */
1074
                } else {
1075
                                /* dispatch handler, it must clear the IRQ at the device */
1076
                                ip->isr(ip->usrData, status&UNIV_VIRQ_STATID_MASK);
1077
                }
1078
 
1079
                /* clear this interrupt level */
1080
                vmeUniverseWriteReg(msk, UNIV_REGOFF_LINT_STAT);
1081
/*
1082
 *  this seems not to be necessary; we just leave the
1083
 *  bit set to save a couple of instructions...
1084
                vmeUniverseWriteReg(
1085
                                        UNIV_VINT_STAT_LINT(vmeIrqUnivOut),
1086
                                        UNIV_REGOFF_VINT_STAT);
1087
*/
1088
 
1089
 
1090
                /* re-enable the previous level */
1091
                vmeUniverseWriteReg(linten, UNIV_REGOFF_LINT_EN);
1092
}
1093
 
1094
/* STUPID API */
1095
static void
1096
my_no_op(const rtems_irq_connect_data * arg)
1097
{}
1098
 
1099
static int
1100
my_isOn(const rtems_irq_connect_data *arg)
1101
{
1102
                return (int)vmeUniverseReadReg(UNIV_REGOFF_LINT_EN);
1103
}
1104
 
1105
int
1106
vmeUniverseInstallIrqMgr(int vmeOut, int specialOut, int specialIrqPicLine)
1107
{
1108
rtems_irq_connect_data aarrggh;
1109
 
1110
        /* check parameters */
1111
        if ((vmeIrqUnivOut=vmeOut) < 0 || vmeIrqUnivOut > 7) return -1;
1112
        if ((specialIrqUnivOut=specialOut) > 7) return -2;
1113
        if (specialIrqPicLine < 0) return -3;
1114
 
1115
        if (mgrInstalled) return -4;
1116
 
1117
        aarrggh.on=my_no_op; /* at _least_ they could check for a 0 pointer */
1118
        aarrggh.off=my_no_op;
1119
        aarrggh.isOn=my_isOn;
1120
        aarrggh.hdl=universeVMEISR;
1121
        aarrggh.name=vmeUniverse0PciIrqLine + BSP_PCI_IRQ0;
1122
        if (!BSP_install_rtems_irq_handler(&aarrggh))
1123
                        BSP_panic("unable to install vmeUniverse irq handler");
1124
        if (specialIrqUnivOut > 0) {
1125
                        /* install the special handler to a separate irq */
1126
                        aarrggh.hdl=universeSpecialISR;
1127
                        aarrggh.name=specialIrqPicLine + BSP_PCI_IRQ0;
1128
                        if (!BSP_install_rtems_irq_handler(&aarrggh))
1129
                                BSP_panic("unable to install vmeUniverse secondary irq handler");
1130
        } else {
1131
                specialIrqUnivOut = vmeIrqUnivOut;
1132
        }
1133
        /* setup routing */
1134
 
1135
        vmeUniverseWriteReg(
1136
                (UNIV_LINT_MAP0_VIRQ7(vmeIrqUnivOut) |
1137
                 UNIV_LINT_MAP0_VIRQ6(vmeIrqUnivOut) |
1138
                 UNIV_LINT_MAP0_VIRQ5(vmeIrqUnivOut) |
1139
                 UNIV_LINT_MAP0_VIRQ4(vmeIrqUnivOut) |
1140
                 UNIV_LINT_MAP0_VIRQ3(vmeIrqUnivOut) |
1141
                 UNIV_LINT_MAP0_VIRQ2(vmeIrqUnivOut) |
1142
                 UNIV_LINT_MAP0_VIRQ1(vmeIrqUnivOut) |
1143
                 UNIV_LINT_MAP0_VOWN(specialIrqUnivOut)
1144
                ),
1145
                UNIV_REGOFF_LINT_MAP0);
1146
        vmeUniverseWriteReg(
1147
                (UNIV_LINT_MAP1_ACFAIL(specialIrqUnivOut) |
1148
                 UNIV_LINT_MAP1_SYSFAIL(specialIrqUnivOut) |
1149
                 UNIV_LINT_MAP1_SW_INT(specialIrqUnivOut) |
1150
                 UNIV_LINT_MAP1_SW_IACK(specialIrqUnivOut) |
1151
                 UNIV_LINT_MAP1_VERR(specialIrqUnivOut) |
1152
                 UNIV_LINT_MAP1_LERR(specialIrqUnivOut) |
1153
                 UNIV_LINT_MAP1_DMA(specialIrqUnivOut)
1154
                ),
1155
                UNIV_REGOFF_LINT_MAP1);
1156
        mgrInstalled=1;
1157
        return 0;
1158
}
1159
 
1160
 
1161
int
1162
vmeUniverseInstallISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
1163
{
1164
UniverseIRQEntry ip;
1165
 
1166
                if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !mgrInstalled)
1167
                                return -1;
1168
 
1169
                ip=universeHdlTbl[vector];
1170
 
1171
                if (ip || !(ip=(UniverseIRQEntry)malloc(sizeof(UniverseIRQEntryRec))))
1172
                                return -1;
1173
                ip->isr=hdl;
1174
                ip->usrData=arg;
1175
                universeHdlTbl[vector]=ip;
1176
                return 0;
1177
}
1178
 
1179
int
1180
vmeUniverseRemoveISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
1181
{
1182
UniverseIRQEntry ip;
1183
 
1184
                if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !mgrInstalled)
1185
                                return -1;
1186
 
1187
                ip=universeHdlTbl[vector];
1188
 
1189
                if (!ip || ip->isr!=hdl || ip->usrData!=arg)
1190
                                return -1;
1191
                universeHdlTbl[vector]=0;
1192
                free(ip);
1193
                return 0;
1194
}
1195
 
1196
int
1197
vmeUniverseIntEnable(unsigned int level)
1198
{
1199
                if (!mgrInstalled || level<1 || level>7)
1200
                                return -1;
1201
                vmeUniverseWriteReg(
1202
                                (vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) |
1203
                                 (UNIV_LINT_EN_VIRQ1 << (level-1))
1204
                                ),
1205
                                UNIV_REGOFF_LINT_EN);
1206
                return 0;
1207
}
1208
 
1209
int
1210
vmeUniverseIntDisable(unsigned int level)
1211
{
1212
                if (!mgrInstalled || level<1 || level>7)
1213
                                return -1;
1214
                vmeUniverseWriteReg(
1215
                                (vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) &
1216
                                 ~ (UNIV_LINT_EN_VIRQ1 << (level-1))
1217
                                ),
1218
                                UNIV_REGOFF_LINT_EN);
1219
                return 0;
1220
}
1221
 
1222
 
1223
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.