summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/shared/vmeUniverse/vmeUniverse.h
blob: fc996dee04a82b595fe43dee6d07583b4fdeef9b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
/* $Id$ */
#ifndef VME_UNIVERSE_UTIL_H
#define VME_UNIVERSE_UTIL_H

/* Routines to configure and use the Tundra Universe VME bridge
 * Author: Till Straumann <strauman@slac.stanford.edu>
 *         Nov 2000, July 2001
 */

/* Register definitions */
/* NOTE: all registers contents in PCI space are LITTLE ENDIAN */

#ifdef __vxworks
#include <vme.h>
#else
/* vxworks compatible addressing modes */
#define	VME_AM_STD_SUP_ASCENDING	0x3f
#define	VME_AM_STD_SUP_PGM	0x3e
#define	VME_AM_STD_USR_ASCENDING	0x3b
#define	VME_AM_STD_USR_PGM	0x3a
#define	VME_AM_STD_SUP_DATA	0x3d
#define	VME_AM_STD_USR_DATA	0x39
#define	VME_AM_EXT_SUP_ASCENDING	0x0f
#define	VME_AM_EXT_SUP_PGM	0x0e
#define	VME_AM_EXT_USR_ASCENDING	0x0b
#define	VME_AM_EXT_USR_PGM	0x0a
#define	VME_AM_EXT_SUP_DATA	0x0d
#define	VME_AM_EXT_USR_DATA	0x09
#define	VME_AM_SUP_SHORT_IO	0x2d
#define	VME_AM_USR_SHORT_IO	0x29

#define VME_AM_IS_SHORT(a)	(((a) & 0xf0) == 0x20)
#define VME_AM_IS_STD(a)	(((a) & 0xf0) == 0x30)
#define VME_AM_IS_EXT(a)	(((a) & 0xf0) == 0x00)

#endif

typedef unsigned long LERegister; /* emphasize contents are little endian */

/* NOTE: DMA packet descriptors MUST be 32 byte aligned */
typedef struct VmeUniverseDMAPacketRec_ {
	LERegister	dctl	__attribute__((aligned(32)));
	LERegister	dtbc	__attribute__((packed));
	LERegister	dla		__attribute__((packed));
	LERegister	dummy1	__attribute__((packed));
	LERegister	dva		__attribute__((packed));
	LERegister	dummy2	__attribute__((packed));
	LERegister	dcpp	__attribute__((packed));
	LERegister	dummy3	__attribute__((packed));
} VmeUniverseDMAPacketRec, *VmeUniverseDMAPacket;

/* PCI CSR register */
#define		UNIV_REGOFF_PCI_CSR		0x4
# define	UNIV_PCI_CSR_D_PE		(1<<31)	/* detected parity error; write 1 to clear */
# define	UNIV_PCI_CSR_S_SERR		(1<<30)	/* SERR (signalled error) asserted; write 1 to clear */
# define	UNIV_PCI_CSR_R_MA		(1<<29)	/* received master abort; write 1 to clear */
# define	UNIV_PCI_CSR_R_TA		(1<<28)	/* received target abort; write 1 to clear */
# define	UNIV_PCI_CSR_S_TA		(1<<27)	/* signalled target abort; write 1 to clear */
# define	UNIV_PCI_CSR_DEVSEL_MASK (3<<25)	/* device select timing (RO) */
# define	UNIV_PCI_CSR_DP_D		(1<<24)	/* data parity error detected; write 1 to clear */
# define	UNIV_PCI_CSR_TFBBC		(1<<23)	/* target fast back to back capable (RO) */
# define	UNIV_PCI_CSR_MFBBC		(1<<9)	/* master fast back to back capable (RO) */
# define	UNIV_PCI_CSR_SERR_EN	(1<<8)	/* enable SERR driver */
# define	UNIV_PCI_CSR_WAIT		(1<<7)	/* wait cycle control (RO) */
# define	UNIV_PCI_CSR_PERESP		(1<<6)	/* parity error response enable */
# define	UNIV_PCI_CSR_VGAPS		(1<<5)	/* VGA palette snoop (RO) */
# define	UNIV_PCI_CSR_MWI_EN		(1<<4)	/* Memory write and invalidate enable (RO) */
# define	UNIV_PCI_CSR_SC			(1<<3)	/* special cycles (RO) */
# define	UNIV_PCI_CSR_BM			(1<<2)	/* master enable (MUST SET TO ENABLE VME SLAVES) */
# define	UNIV_PCI_CSR_MS			(1<<1)	/* target memory enable */
# define	UNIV_PCI_CSR_IOS		(1<<0)	/* target IO enable */

/* Special cycle (ADOH, RMW) control register */
#define		UNIV_REGOFF_SCYC_CTL	0x170	/* write 0 to disable */
# define	UNIV_SCYC_CTL_LAS_IO	(1<<2)	/* PCI address space (1: IO, 0: mem) */
# define	UNIV_SCYC_CTL_SCYC_RMW	(1<<0)	/* do a RMW cycle when reading  PCI address */
# define	UNIV_SCYC_CTL_SCYC_ADOH	(2<<0)	/* do a ADOH cycle when reading/writing  PCI address */

/* Special cycle address register */
#define		UNIV_REGOFF_SCYC_ADDR	0x174	/* PCI address (must be long word aligned) */

/* Special cycle Swap/Compare/Enable */
#define		UNIV_REGOFF_SCYC_EN	0x178	/* mask determining the bits involved in the compare and swap operations for VME RMW cycles */

/* Special cycle compare data register */
#define		UNIV_REGOFF_SCYC_CMP	0x17c	/* data to compare with word returned from VME RMW read */

/* Special cycle swap data register */
#define		UNIV_REGOFF_SCYC_SWP	0x180	/* If enabled bits of CMP match, corresponding SWP bits are written back to VME (under control of EN) */

/* PCI miscellaneous register */
#define		UNIV_REGOFF_LMISC	0x184
# define	UNIV_LMISC_CRT_MASK	(7<<28)	/* Univ. I only, not used on II */
# define	UNIV_LMISC_CRT_INF	(0<<28)	/* Coupled Request Timeout */
# define	UNIV_LMISC_CRT_128_US	(1<<28)	/* Coupled Request Timeout */
# define	UNIV_LMISC_CRT_256_US	(2<<28)	/* Coupled Request Timeout */
# define	UNIV_LMISC_CRT_512_US	(3<<28)	/* Coupled Request Timeout */
# define	UNIV_LMISC_CRT_1024_US	(4<<28)	/* Coupled Request Timeout */
# define	UNIV_LMISC_CRT_2048_US	(5<<28)	/* Coupled Request Timeout */
# define	UNIV_LMISC_CRT_4096_US	(6<<28)	/* Coupled Request Timeout */

# define	UNIV_LMISC_CWT_MASK	(7<<24)	/* coupled window timer */
# define	UNIV_LMISC_CWT_DISABLE	0	/* disabled (release VME after 1 coupled xaction) */
# define	UNIV_LMISC_CWT_16	(1<<24)	/* 16 PCI clock cycles */
# define	UNIV_LMISC_CWT_32	(2<<24)	/* 32 PCI clock cycles */
# define	UNIV_LMISC_CWT_64	(3<<24)	/* 64 PCI clock cycles */
# define	UNIV_LMISC_CWT_128	(4<<24)	/* 128 PCI clock cycles */
# define	UNIV_LMISC_CWT_256	(5<<24)	/* 256 PCI clock cycles */
# define	UNIV_LMISC_CWT_512	(6<<24)	/* 512 PCI clock cycles */

/* PCI Command Error Log Register */
#define		UNIV_REGOFF_L_CMDERR	0x18c
# define	UNIV_L_CMDERR_CMDERR(reg) (((reg)>>28)&0xf) /* extract PCI cmd error log */
# define	UNIV_L_CMDERR_M_ERR	(1<<27)	/* multiple errors have occurred */
# define	UNIV_L_CMDERR_L_STAT	(1<<23)	/* PCI error log status valid (write 1 to clear and enable logging) */

/* PCI Address Error Log */
#define		UNIV_REGOFF_LAERR	0x190	/* PCI fault address (if L_CMDERR_L_STAT valid) */
/* DMA Xfer Control Register */
#define		UNIV_REGOFF_DCTL	0x200
# define	UNIV_DCTL_L2V		(1<<31)	/* PCI->VME if set */
# define	UNIV_DCTL_VDW_MSK	(3<<22)	/* VME max. width mask 0x00c00000 */
# define	UNIV_DCTL_VDW_8		(0<<22)	/* VME max. width 8 */
# define	UNIV_DCTL_VDW_16	(1<<22)	/* VME max. width 16 */
# define	UNIV_DCTL_VDW_32	(2<<22)	/* VME max. width 32 */
# define	UNIV_DCTL_VDW_64	(3<<22)	/* VME max. width 64 */
# define	UNIV_DCTL_VAS_MSK	(7<<16)	/* VME AS mask 0x00070000 */
# define	UNIV_DCTL_VAS_A16	(0<<16)	/* VME A16 */
# define	UNIV_DCTL_VAS_A24	(1<<16)	/* VME A24 */
# define	UNIV_DCTL_VAS_A32	(2<<16)	/* VME A32 */
# define	UNIV_DCTL_PGM_MSK	(3<<14)	/* VME PGM/DATA mask 0x0000c000 */
# define	UNIV_DCTL_PGM		(1<<14)	/* VME PGM(1)/DATA(0) */
# define	UNIV_DCTL_SUPER_MSK	(3<<12)	/* VME SUPER/USR mask 0x00003000 */
# define	UNIV_DCTL_SUPER		(1<<12)	/* VME SUPER(1)/USR(0) */
# define	UNIV_DCTL_VCT		(1<<8)	/* VME enable BLT */
# define	UNIV_DCTL_LD64EN	(1<<7)	/* PCI 64 enable  */

/* DMA Xfer byte count register (is updated by DMA) */
#define		UNIV_REGOFF_DTBC	0x204
/* DMA Xfer local (PCI) address (direction is  set in DCTL) */
#define		UNIV_REGOFF_DLA		0x208
/* DMA Xfer VME address (direction is  set in DCTL)
 * NOTE: (*UNIV_DVA) & ~7 == (*UNIV_DLA) & ~7 MUST HOLD
 */
#define		UNIV_REGOFF_DVA		0x210

/* DMA Xfer VME command packet pointer
 * NOTE: The address stored here MUST be 32-byte aligned
 */
#define		UNIV_REGOFF_DCPP	0x218
/* these bits are only used in linked lists */
# define	UNIV_DCPP_IMG_NULL	(1<<0)	/* last packet in list */
# define	UNIV_DCPP_IMG_PROCESSED (1<<1)	/* packet processed */

/* DMA Xfer General Control/Status register */
#define		UNIV_REGOFF_DGCS	0x220
# define	UNIV_DGCS_GO		(1<<31)	/* start xfer */
# define	UNIV_DGCS_STOP_REQ	(1<<30) /* stop xfer (immediate abort) */
# define	UNIV_DGCS_HALT_REQ	(1<<29) /* halt xfer (abort after current packet) */
# define	UNIV_DGCS_CHAIN		(1<<27) /* enable linked list mode */
# define	UNIV_DGCS_VON_MSK	(7<<20) /* VON mask */
# define	UNIV_DGCS_VON_DONE	(0<<20) /* VON counter disabled (do until done) */
# define	UNIV_DGCS_VON_256	(1<<20) /* VON yield bus after 256 bytes */
# define	UNIV_DGCS_VON_512	(2<<20) /* VON yield bus after 512 bytes */
# define	UNIV_DGCS_VON_1024	(3<<20) /* VON yield bus after 512 bytes */
# define	UNIV_DGCS_VON_2048	(4<<20) /* VON yield bus after 1024 bytes */
# define	UNIV_DGCS_VON_4096	(5<<20) /* VON yield bus after 4096 bytes */
# define	UNIV_DGCS_VON_8192	(6<<20) /* VON yield bus after 8192 bytes */
# define	UNIV_DGCS_VOFF_MSK	(15<<16) /* VOFF mask */
# define	UNIV_DGCS_VOFF_0_US	(0<<16)	/* re-request VME master after 0 us */
# define	UNIV_DGCS_VOFF_2_US	(8<<16)	/* re-request VME master after 2 us */
# define	UNIV_DGCS_VOFF_4_US	(9<<16)	/* re-request VME master after 4 us */
# define	UNIV_DGCS_VOFF_8_US	(10<<16)/* re-request VME master after 8 us */
# define	UNIV_DGCS_VOFF_16_US	(1<<16)	/* re-request VME master after 16 us */
# define	UNIV_DGCS_VOFF_32_US	(2<<16)	/* re-request VME master after 32 us */
# define	UNIV_DGCS_VOFF_64_US	(3<<16)	/* re-request VME master after 64 us */
# define	UNIV_DGCS_VOFF_128_US	(4<<16)	/* re-request VME master after 128 us */
# define	UNIV_DGCS_VOFF_256_US	(5<<16)	/* re-request VME master after 256 us */
# define	UNIV_DGCS_VOFF_512_US	(6<<16)	/* re-request VME master after 512 us */
# define	UNIV_DGCS_VOFF_1024_US	(7<<16)	/* re-request VME master after 1024 us */
/* Status Bits (write 1 to clear) */
# define	UNIV_DGCS_ACT		(1<<15)	/* DMA active */
# define	UNIV_DGCS_STOP		(1<<14)	/* DMA stopped */
# define	UNIV_DGCS_HALT		(1<<13)	/* DMA halted */
# define	UNIV_DGCS_DONE		(1<<11)	/* DMA done (OK) */
# define	UNIV_DGCS_LERR		(1<<10)	/* PCI bus error */
# define	UNIV_DGCS_VERR		(1<<9)	/* VME bus error */
# define	UNIV_DGCS_P_ERR		(1<<8)	/* programming protocol error (e.g. PCI master disabled) */
# define	UNIV_DGCS_STATUS_CLEAR\
	(UNIV_DGCS_ACT|UNIV_DGCS_STOP|UNIV_DGCS_HALT|\
	 UNIV_DGCS_DONE|UNIV_DGCS_LERR|UNIV_DGCS_VERR|UNIV_DGCS_P_ERR)
# define	UNIV_DGCS_P_ERR		(1<<8)	/* programming protocol error (e.g. PCI master disabled) */
/* Interrupt Mask Bits */
# define	UNIV_DGCS_INT_STOP	(1<<6)	/* interrupt when stopped */
# define	UNIV_DGCS_INT_HALT	(1<<5)  /* interrupt when halted */
# define	UNIV_DGCS_INT_DONE	(1<<3)	/* interrupt when done */
# define	UNIV_DGCS_INT_LERR	(1<<2)	/* interrupt on LERR */
# define	UNIV_DGCS_INT_VERR	(1<<1)	/* interrupt on VERR */
# define	UNIV_DGCS_INT_P_ERR	(1<<0)	/* interrupt on P_ERR */
# define	UNIV_DGCS_INT_MSK	(0x0000006f) /* interrupt mask */

/* DMA Linked List Update Enable Register */
#define		UNIV_REGOFF_D_LLUE	0x224
# define	UNIV_D_LLUE_UPDATE	(1<<31)

/* PCI (local) interrupt enable register */
#define		UNIV_REGOFF_LINT_EN	0x300
# define	UNIV_LINT_EN_LM3	(1<<23)	/* location monitor 3 mask */
# define	UNIV_LINT_EN_LM2	(1<<22)	/* location monitor 2 mask */
# define	UNIV_LINT_EN_LM1	(1<<21)	/* location monitor 1 mask */
# define	UNIV_LINT_EN_LM0	(1<<20)	/* location monitor 0 mask */
# define	UNIV_LINT_EN_MBOX3	(1<<19)	/* mailbox 3 mask */
# define	UNIV_LINT_EN_MBOX2	(1<<18)	/* mailbox 2 mask */
# define	UNIV_LINT_EN_MBOX1	(1<<17)	/* mailbox 1 mask */
# define	UNIV_LINT_EN_MBOX0	(1<<16)	/* mailbox 0 mask */
# define 	UNIV_LINT_EN_ACFAIL	(1<<15)	/* ACFAIL irq mask */
# define 	UNIV_LINT_EN_SYSFAIL	(1<<14)	/* SYSFAIL irq mask */
# define 	UNIV_LINT_EN_SW_INT	(1<<13)	/* PCI (local) software irq */
# define 	UNIV_LINT_EN_SW_IACK	(1<<12)	/* VME software IACK mask */
# define	UNIV_LINT_EN_VERR	(1<<10)	/* PCI VERR irq mask */
# define	UNIV_LINT_EN_LERR	(1<<9)	/* PCI LERR irq mask */
# define	UNIV_LINT_EN_DMA	(1<<8)	/* PCI DMA irq mask */
# define	UNIV_LINT_EN_VIRQ7	(1<<7)	/* VIRQ7 mask (universe does IACK automatically) */
# define	UNIV_LINT_EN_VIRQ6	(1<<6)	/* VIRQ6 mask */
# define	UNIV_LINT_EN_VIRQ5	(1<<5)	/* VIRQ5 mask */
# define	UNIV_LINT_EN_VIRQ4	(1<<4)	/* VIRQ4 mask */
# define	UNIV_LINT_EN_VIRQ3	(1<<3)	/* VIRQ3 mask */
# define	UNIV_LINT_EN_VIRQ2	(1<<2)	/* VIRQ2 mask */
# define	UNIV_LINT_EN_VIRQ1	(1<<1)	/* VIRQ1 mask */
# define	UNIV_LINT_EN_VOWN	(1<<0)	/* VOWN mask */

/* PCI (local) interrupt status register */
#define		UNIV_REGOFF_LINT_STAT	0x304
# define	UNIV_LINT_STAT_LM3	(1<<23)	/* location monitor 3 status */
# define	UNIV_LINT_STAT_LM2	(1<<22)	/* location monitor 2 status */
# define	UNIV_LINT_STAT_LM1	(1<<21)	/* location monitor 1 status */
# define	UNIV_LINT_STAT_LM0	(1<<20)	/* location monitor 0 status */
# define	UNIV_LINT_STAT_MBOX3	(1<<19)	/* mailbox 3 status */
# define	UNIV_LINT_STAT_MBOX2	(1<<18)	/* mailbox 2 status */
# define	UNIV_LINT_STAT_MBOX1	(1<<17)	/* mailbox 1 status */
# define	UNIV_LINT_STAT_MBOX0	(1<<16)	/* mailbox 0 status */
# define 	UNIV_LINT_STAT_ACFAIL	(1<<15)	/* ACFAIL irq status */
# define 	UNIV_LINT_STAT_SYSFAIL	(1<<14)	/* SYSFAIL irq status */
# define 	UNIV_LINT_STAT_SW_INT	(1<<13)	/* PCI (local) software irq */
# define 	UNIV_LINT_STAT_SW_IACK	(1<<12)	/* VME software IACK status */
# define	UNIV_LINT_STAT_VERR		(1<<10)	/* PCI VERR irq status */
# define	UNIV_LINT_STAT_LERR		(1<<9)	/* PCI LERR irq status */
# define	UNIV_LINT_STAT_DMA		(1<<8)	/* PCI DMA irq status */
# define	UNIV_LINT_STAT_VIRQ7	(1<<7)	/* VIRQ7 status */
# define	UNIV_LINT_STAT_VIRQ6	(1<<6)	/* VIRQ6 status */
# define	UNIV_LINT_STAT_VIRQ5	(1<<5)	/* VIRQ5 status */
# define	UNIV_LINT_STAT_VIRQ4	(1<<4)	/* VIRQ4 status */
# define	UNIV_LINT_STAT_VIRQ3	(1<<3)	/* VIRQ3 status */
# define	UNIV_LINT_STAT_VIRQ2	(1<<2)	/* VIRQ2 status */
# define	UNIV_LINT_STAT_VIRQ1	(1<<1)	/* VIRQ1 status */
# define	UNIV_LINT_STAT_VOWN		(1<<0)	/* VOWN status */
# define	UNIV_LINT_STAT_CLR		(0xfff7ff)/* Clear all status bits */

/* PCI (local) interrupt map 0 register */
#define		UNIV_REGOFF_LINT_MAP0	0x308	/* mapping of VME IRQ sources to PCI irqs */
# define	UNIV_LINT_MAP0_VIRQ7(lint)	(((lint)&0x7)<<(7*4))
# define	UNIV_LINT_MAP0_VIRQ6(lint)	(((lint)&0x7)<<(6*4))
# define	UNIV_LINT_MAP0_VIRQ5(lint)	(((lint)&0x7)<<(5*4))
# define	UNIV_LINT_MAP0_VIRQ4(lint)	(((lint)&0x7)<<(4*4))
# define	UNIV_LINT_MAP0_VIRQ3(lint)	(((lint)&0x7)<<(3*4))
# define	UNIV_LINT_MAP0_VIRQ2(lint)	(((lint)&0x7)<<(2*4))
# define	UNIV_LINT_MAP0_VIRQ1(lint)	(((lint)&0x7)<<(1*4))
# define	UNIV_LINT_MAP0_VOWN(lint)	(((lint)&0x7)<<(0*4))

#define		UNIV_REGOFF_LINT_MAP1	0x30c	/* mapping of internal / VME IRQ sources to PCI irqs */
# define	UNIV_LINT_MAP1_ACFAIL(lint)	(((lint)&0x7)<<(7*4))
# define	UNIV_LINT_MAP1_SYSFAIL(lint)	(((lint)&0x7)<<(6*4))
# define	UNIV_LINT_MAP1_SW_INT(lint)	(((lint)&0x7)<<(5*4))
# define	UNIV_LINT_MAP1_SW_IACK(lint)	(((lint)&0x7)<<(4*4))
# define	UNIV_LINT_MAP1_VERR(lint)	(((lint)&0x7)<<(2*4))
# define	UNIV_LINT_MAP1_LERR(lint)	(((lint)&0x7)<<(1*4))
# define	UNIV_LINT_MAP1_DMA(lint)	(((lint)&0x7)<<(0*4))

/* enabling of generation of VME bus IRQs, TODO */
#define		UNIV_REGOFF_VINT_EN		0x310
# define	UNIV_VINT_EN_DISABLE_ALL    0

/* status of generation of VME bus IRQs, TODO */
#define		UNIV_REGOFF_VINT_STAT	0x314
# define	UNIV_VINT_STAT_LINT(lint)	(1<<((lint)&7))
# define	UNIV_VINT_STAT_LINT_MASK	(0xff)
# define	UNIV_VINT_STAT_CLR			(0xfe0f17ff)
#define		UNIV_REGOFF_VINT_MAP0	0x318	/* VME destination of PCI IRQ source, TODO */
#define		UNIV_REGOFF_VINT_MAP1	0x31c	/* VME destination of PCI IRQ source, TODO */
#define		UNIV_REGOFF_VINT_STATID	0x320	/* our status/id response to IACK, TODO */

#define		UNIV_REGOFF_VIRQ1_STATID 0x324	/* status/id of VME IRQ level 1 */
#define		UNIV_REGOFF_VIRQ2_STATID 0x328	/* status/id of VME IRQ level 2 */
#define		UNIV_REGOFF_VIRQ3_STATID 0x32c	/* status/id of VME IRQ level 3 */
#define		UNIV_REGOFF_VIRQ4_STATID 0x330	/* status/id of VME IRQ level 4 */
#define		UNIV_REGOFF_VIRQ5_STATID 0x334	/* status/id of VME IRQ level 5 */
#define		UNIV_REGOFF_VIRQ6_STATID 0x338	/* status/id of VME IRQ level 6 */
#define		UNIV_REGOFF_VIRQ7_STATID 0x33c	/* status/id of VME IRQ level 7 */
# define	UNIV_VIRQ_ERR			(1<<8)	/* set if universe encountered a bus error when doing IACK */
# define	UNIV_VIRQ_STATID_MASK		(0xff)

#define		UNIV_REGOFF_LINT_MAP2	0x340	/* mapping of internal sources to PCI irqs */
# define	UNIV_LINT_MAP2_LM3(lint)	(((lint)&0x7)<<7*4)	/* location monitor 3 */
# define	UNIV_LINT_MAP2_LM2(lint)	(((lint)&0x7)<<6*4)	/* location monitor 2 */
# define	UNIV_LINT_MAP2_LM1(lint)	(((lint)&0x7)<<5*4)	/* location monitor 1 */
# define	UNIV_LINT_MAP2_LM0(lint)	(((lint)&0x7)<<4*4)	/* location monitor 0 */
# define	UNIV_LINT_MAP2_MBOX3(lint)	(((lint)&0x7)<<3*4)	/* mailbox 3 */
# define	UNIV_LINT_MAP2_MBOX2(lint)	(((lint)&0x7)<<2*4)	/* mailbox 2 */
# define	UNIV_LINT_MAP2_MBOX1(lint)	(((lint)&0x7)<<1*4)	/* mailbox 1 */
# define	UNIV_LINT_MAP2_MBOX0(lint)	(((lint)&0x7)<<0*4)	/* mailbox 0 */

#define		UNIV_REGOFF_VINT_MAP2	0x344	/* mapping of internal sources to VME irqs */
# define	UNIV_VINT_MAP2_MBOX3(vint)	(((vint)&0x7)<<3*4)	/* mailbox 3 */
# define	UNIV_VINT_MAP2_MBOX2(vint)	(((vint)&0x7)<<2*4)	/* mailbox 2 */
# define	UNIV_VINT_MAP2_MBOX1(vint)	(((vint)&0x7)<<1*4)	/* mailbox 1 */
# define	UNIV_VINT_MAP2_MBOX0(vint)	(((vint)&0x7)<<0*4)	/* mailbox 0 */

#define		UNIV_REGOFF_MBOX0	0x348	/* mailbox 0 */
#define		UNIV_REGOFF_MBOX1	0x34c	/* mailbox 1 */
#define		UNIV_REGOFF_MBOX2	0x350	/* mailbox 2 */
#define		UNIV_REGOFF_MBOX3	0x354	/* mailbox 3 */

#define		UNIV_REGOFF_SEMA0	0x358	/* semaphore 0 */
#define		UNIV_REGOFF_SEMA1	0x35c	/* semaphore 0 */
/* TODO define semaphore register bits */

#define		UNIV_REGOFF_MAST_CTL	0x400	/* master control register */
# define	UNIV_MAST_CTL_MAXRTRY(val)	(((val)&0xf)<<7*4)	/* max # of pci master retries */
# define	UNIV_MAST_CTL_PWON(val)		(((val)&0xf)<<6*4)	/* posted write xfer count */
# define	UNIV_MAST_CTL_VRL(val)		(((val)&0x3)<<22)	/* VME bus request level */
# define	UNIV_MAST_CTL_VRM			(1<<21)	/* bus request mode (demand = 0, fair = 1) */
# define	UNIV_MAST_CTL_VREL			(1<<20)	/* bus release mode (when done = 0, on request = 1) */
# define	UNIV_MAST_CTL_VOWN			(1<<19)	/* bus ownership (release = 0, acquire/hold = 1) */
# define	UNIV_MAST_CTL_VOWN_ACK		(1<<18)	/* bus ownership (not owned = 0, acquired/held = 1) */
# define	UNIV_MAST_CTL_PABS(val)		(((val)&0x3)<<3*4)	/* PCI aligned burst size (32,64,128 byte / 0x3 is reserved) */
# define	UNIV_MAST_CTL_BUS_NO(val)	(((val)&0xff)<<0*4)	/* PCI bus number */

#define		UNIV_REGOFF_MISC_CTL	0x404	/* misc control register */
# define	UNIV_MISC_CTL_VBTO(val)		(((val)&0x7)<<7*4)	/* VME bus timeout (0=disable, 16*2^(val-1) us) */
# define	UNIV_MISC_CTL_VARB			(1<<26)	/* VME bus arbitration mode (0=round robin, 1= priority) */
# define	UNIV_MISC_CTL_VARBTO(val)	(((val)&0x3)<<6*4)	/* arbitration time out: disable, 16us, 256us, reserved */
# define	UNIV_MISC_CTL_SW_LRST		(1<<23)	/* software PCI reset */
# define	UNIV_MISC_CTL_SW_SYSRST		(1<<22)	/* software VME reset */
# define	UNIV_MISC_CTL_BI			(1<<20)	/* BI mode */
# define	UNIV_MISC_CTL_ENGBI			(1<<19)	/* enable global BI mode initiator */
# define	UNIV_MISC_CTL_SYSCON		(1<<17)	/* (R/W) 1:universe is system controller */
# define	UNIV_MISC_CTL_V64AUTO		(1<<16)	/* (R/W) 1:initiate VME64 auto id slave participation */

/* U2SPEC described in VGM manual */
/* NOTE: the Joerger vtr10012_8 needs the timing to be tweaked!!!! READt27 must be _no_delay_
 */
#define		UNIV_REGOFF_U2SPEC		0x4fc
# define	UNIV_U2SPEC_DTKFLTR			(1<<12)	/* DTAck filter: 0: slow, better filter; 1: fast, poorer filter */
# define	UNIV_U2SPEC_MASt11			(1<<10)	/* Master parameter t11 (DS hi time during BLT and MBLTs) */
# define	UNIV_U2SPEC_READt27_DEFAULT	(0<<8)	/* VME master parameter t27: (latch data after DTAck + 25ns) */
# define	UNIV_U2SPEC_READt27_FAST	(1<<8)	/* VME master parameter t27: (latch data faster than 25ns)  */
# define	UNIV_U2SPEC_READt27_NODELAY	(2<<8)	/* VME master parameter t27: (latch data without any delay)  */
# define	UNIV_U2SPEC_POSt28_FAST		(1<<2)	/* VME slave parameter t28: (faster time of DS to DTAck for posted write) */
# define	UNIV_U2SPEC_PREt28_FAST		(1<<0)	/* VME slave parameter t28: (faster time of DS to DTAck for prefetch read) */

/* Location Monitor control register */
#define		UNIV_REGOFF_LM_CTL		0xf64
# define	UNIV_LM_CTL_EN				(1<<31)	/* image enable */
# define	UNIV_LM_CTL_PGM				(1<<23)	/* program AM */
# define	UNIV_LM_CTL_DATA			(1<<22)	/* data AM */
# define	UNIV_LM_CTL_SUPER			(1<<21)	/* supervisor AM */
# define	UNIV_LM_CTL_USER			(1<<20)	/* user AM */
# define	UNIV_LM_CTL_VAS_A16			(0<<16)	/* A16 */
# define	UNIV_LM_CTL_VAS_A24			(1<<16)	/* A16 */
# define	UNIV_LM_CTL_VAS_A32			(2<<16)	/* A16 */

/* Location Monitor base address */
#define		UNIV_REGOFF_LM_BS		0xf68

/* VMEbus register access image control register */
#define		UNIV_REGOFF_VRAI_CTL	0xf70
# define	UNIV_VRAI_CTL_EN			(1<<31)	/* image enable */
# define	UNIV_VRAI_CTL_PGM			(1<<23)	/* program AM */
# define	UNIV_VRAI_CTL_DATA			(1<<22)	/* data AM */
# define	UNIV_VRAI_CTL_SUPER			(1<<21)	/* supervisor AM */
# define	UNIV_VRAI_CTL_USER			(1<<20)	/* user AM */
# define	UNIV_VRAI_CTL_VAS_A16		(0<<16)	/* A16 */
# define	UNIV_VRAI_CTL_VAS_A24		(1<<16)	/* A16 */
# define	UNIV_VRAI_CTL_VAS_A32		(2<<16)	/* A16 */

/* VMEbus register acces image base address register */
#define		UNIV_REGOFF_VRAI_BS		0xf74

/* VMEbus CSR control register */
#define		UNIV_REGOFF_VCSR_CTL	0xf80
# define	UNIV_VCSR_CTL_EN			(1<<31)	/* image enable */
# define	UNIV_VCSR_CTL_LAS_PCI_MEM	(0<<0)	/* pci mem space */
# define	UNIV_VCSR_CTL_LAS_PCI_IO	(1<<0)	/* pci IO space */
# define	UNIV_VCSR_CTL_LAS_PCI_CFG	(2<<0)	/* pci config space */

/* VMEbus CSR translation offset */
#define		UNIV_REGOFF_VCSR_TO		0xf84

/* VMEbus AM code error log */
#define		UNIV_REGOFF_V_AMERR		0xf88
# define	UNIV_V_AMERR_AMERR(reg)		(((reg)>>26)&0x3f)	/* extract error log code */
# define	UNIV_V_AMERR_IACK			(1<<25)	/* VMEbus IACK signal */
# define	UNIV_V_AMERR_M_ERR			(1<<24)	/* multiple errors occurred */
# define	UNIV_V_AMERR_V_STAT			(1<<23)	/* log status valid (write 1 to clear) */

/* VMEbus address error log */
#define		UNIV_REGOFF_VAERR		0xf8c		/* address of fault address (if MERR_V_STAT valid) */

/* VMEbus CSR bit clear register */
#define		UNIV_REGOFF_VCSR_CLR	0xff4
# define	UNIV_VCSR_CLR_RESET			(1<<31)	/* read/negate LRST (can only be written from VME bus */
# define	UNIV_VCSR_CLR_SYSFAIL		(1<<30)	/* read/negate SYSFAIL */
# define	UNIV_VCSR_CLR_FAIL			(1<<29)	/* read: board has failed */

/* VMEbus CSR bit set register */
#define		UNIV_REGOFF_VCSR_SET		(0xff8)
# define	UNIV_VCSR_SET_RESET			(1<<31)	/* read/assert LRST (can only be written from VME bus */
# define	UNIV_VCSR_SET_SYSFAIL		(1<<30)	/* read/assert SYSFAIL */
# define	UNIV_VCSR_SET_FAIL			(1<<29)	/* read: board has failed */

/* VMEbus CSR base address register */
#define		UNIV_REGOFF_VCSR_BS		0xffc
#define		UNIV_VCSR_BS_MASK			(0xfff80000)

#ifdef __cplusplus
extern "C" {
#endif

/* base address and IRQ line of 1st universe bridge
 * NOTE: vmeUniverseInit() must be called before
 *       these may be used.
 */
extern volatile LERegister *vmeUniverse0BaseAddr;
extern int vmeUniverse0PciIrqLine;

/* Initialize the driver */
int
vmeUniverseInit(void);

/* setup the universe chip, i.e. disable most of its
 * mappings, reset interrupts etc.
 */
void
vmeUniverseReset(void);

/* avoid pulling stdio.h into this header.
 * Applications that want a declaration of the
 * following routines should
 *  #include <stdio.h>
 *  #define _VME_UNIVERSE_DECLARE_SHOW_ROUTINES
 *  #include <vmeUniverse.h>
 */
#ifdef _VME_UNIVERSE_DECLARE_SHOW_ROUTINES
/* print the current configuration of all master ports to
 * f (stderr if NULL)
 */
void
vmeUniverseMasterPortsShow(FILE *f);

/* print the current configuration of all slave ports to
 * f (stderr if NULL)
 */
void
vmeUniverseSlavePortsShow(FILE *f);
#else
void
vmeUniverseMasterPortsShow();
void
vmeUniverseSlavePortsShow();
#endif

/* disable all master or slave ports, respectively */
void
vmeUniverseDisableAllMasters(void);

void
vmeUniverseDisableAllSlaves(void);

/* configure a master port
 *
 *   port:	    port number 0..3  (0..7 for a UniverseII)
 *
 *   address_space: vxWorks compliant addressing mode identifier
 *                  (see vme.h). The most important are:
 *                    0x0d - A32, Sup, Data
 *                    0x3d - A24, Sup, Data
 *                    0x2d - A16, Sup, Data
 *                  additionally, the value 0 is accepted; it will
 *                  disable this port.
 *   vme_address:   address on the vme_bus of this port.
 *   local_address: address on the pci_bus of this port.
 *   length:        size of this port.
 *
 *   NOTE: the addresses and length parameters must be aligned on a
 *         2^16 byte (0x10000) boundary, except for port 4 (only available
 *         on a UniverseII), where the alignment can be 4k (4096).
 *
 *   RETURNS: 0 on success, -1 on failure. Error messages printed to stderr.
 */

int
vmeUniverseMasterPortCfg(
	unsigned long	port,
	unsigned long	address_space,
	unsigned long	vme_address,
	unsigned long	local_address,
	unsigned long	length);

/* translate an address through the bridge
 *
 * vmeUniverseXlateAddr(0,0,addr,as,&result)
 * yields a VME a address that reflects
 * a local memory location as seen from the VME bus through the universe
 * VME slave.
 *
 * likewise does vmeUniverseXlateAddr(1,0,addr,as,&result)
 * translate a VME bus addr (through the VME master) to the
 * PCI side of the bridge.
 *
 * a valid address space modifier must be specified.
 *
 * The 'reverse' parameter may be used to find a reverse
 * mapping, i.e. the pci address in a master window can be
 * found if the respective vme address is known etc.
 *
 * RETURNS: translated address in *pbusAdrs / *plocalAdrs
 *
 *          0:  success
 *          -1: address/modifier not found in any bridge port
 *          -2: invalid modifier
 */
int
vmeUniverseXlateAddr(
	int master, 		/* look in the master windows */
	int reverse,		/* reverse mapping; for masters: map local to VME */
	unsigned long as,	/* address space */
	unsigned long addr,	/* address to look up */
	unsigned long *paOut/* where to put result */
	);

/* configure a VME slave (PCI master) port */
int
vmeUniverseSlavePortCfg(
	unsigned long	port,
	unsigned long	address_space,
	unsigned long	vme_address,
	unsigned long	local_address,
	unsigned long	length);

/* start a (direct, not linked) DMA transfer
 *
 * NOTE:  DCTL and DGCS must be set up
 *        prior to calling this routine
 */
int
vmeUniverseStartDMA(
	unsigned long local_addr,
	unsigned long vme_addr,
	unsigned long count);

/* read a register in PCI memory space
 * (offset being one of the declared constants)
 */
unsigned long
vmeUniverseReadReg(unsigned long offset);

/* write a register in PCI memory space */
void
vmeUniverseWriteReg(unsigned long value, unsigned long offset);

/* convert an array of unsigned long values to LE (as needed
 * when the universe reads e.g. DMA descriptors from PCI)
 */
void
vmeUniverseCvtToLE(unsigned long *ptr, unsigned long num);

/* reset the VME bus */
static inline void
vmeUniverseResetBus(void)
{
	vmeUniverseWriteReg(
		vmeUniverseReadReg(UNIV_REGOFF_MISC_CTL) | UNIV_MISC_CTL_SW_SYSRST,
		UNIV_REGOFF_MISC_CTL);
}

#ifdef __rtems__
/* VME Interrupt Handler functionality */

/* we dont use the current RTEMS/BSP interrupt API for the
 * following reasons:
 *
 *    - RTEMS/BSP API does not pass an argument to the ISR :-( :-(
 *    - no separate vector space for VME vectors. Some vectors would
 *      have to overlap with existing PCI/ISA vectors.
 *    - RTEMS/BSP API allocates a structure for every possible vector
 *    - the irq_on(), irq_off() functions add more bloat than helping.
 *      They are (currently) only used by the framework to disable
 *      interrupts at the device level before removing a handler
 *      and to enable interrupts after installing a handler.
 *      These operations may as well be done by the driver itself.
 *
 * Hence, we maintain our own (VME) handler table and hook our PCI
 * handler into the standard RTEMS/BSP environment. Our handler then
 * dispatches VME interrupts.
 */

typedef void (*VmeUniverseISR) (void *usrArg, unsigned long vector);

/* install a handler for a VME vector
 * RETURNS 0 on success, nonzero on failure.
 */
int
vmeUniverseInstallISR(unsigned long vector, VmeUniverseISR handler, void *usrArg);

/* remove a handler for a VME vector. The vector and usrArg parameters
 * must match the respective parameters used when installing the handler.
 * RETURNS 0 on success, nonzero on failure.
 */
int
vmeUniverseRemoveISR(unsigned long vector, VmeUniverseISR handler, void *usrArg);

/* query for the currently installed ISR and usr parameter at a given vector
 * RETURNS: ISR or 0 (vector too big or no ISR installed)
 */
VmeUniverseISR
vmeUniverseISRGet(unsigned long vector, void **parg);

/* utility routines to enable/disable a VME IRQ level
 *
 * RETURNS 0 on success, nonzero on failure
 */
int
vmeUniverseIntEnable(unsigned int level);
int
vmeUniverseIntDisable(unsigned int level);

/* use these special vectors to connect a handler to the
 * universe specific interrupts (such as "DMA done",
 * VOWN, error irqs etc.)
 * NOTE: The wrapper clears all status LINT bits (except
 * for regular VME irqs). Also note that it is the user's
 * responsibility to enable the necessary interrupts in
 * LINT_EN
 *
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * DO NOT CHANGE THE ORDER OF THESE VECTORS - THE DRIVER
 * DEPENDS ON IT
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 *
 */
#define UNIV_VOWN_INT_VEC			256
#define UNIV_DMA_INT_VEC			257
#define UNIV_LERR_INT_VEC			258
#define UNIV_VERR_INT_VEC			259
#define UNIV_VME_SW_IACK_INT_VEC	260
#define UNIV_PCI_SW_INT_VEC			261
#define UNIV_SYSFAIL_INT_VEC		262
#define UNIV_ACFAIL_INT_VEC			263
#define UNIV_MBOX0_INT_VEC			264
#define UNIV_MBOX1_INT_VEC			265
#define UNIV_MBOX2_INT_VEC			266
#define UNIV_MBOX3_INT_VEC			267
#define UNIV_LM0_INT_VEC			268
#define UNIV_LM1_INT_VEC			269
#define UNIV_LM2_INT_VEC			270
#define UNIV_LM3_INT_VEC			271

#define UNIV_NUM_INT_VECS			272

/* the universe interrupt handler is capable of routing all sorts of
 * (VME) interrupts to 8 different lines (some of) which may be hooked up
 * in a (board specific) way to a PIC.
 *
 * This driver only supports at most two lines. It routes the 7 VME
 * interrupts to the main line and optionally, it routes the 'special'
 * interrupts generated by the universe itself (DMA done, VOWN etc.)
 * to a second line. If no second line is available, all IRQs are routed
 * to the main line.
 *
 * Because the driver has no way to figure out which lines are actually
 * wired to the PIC, this information has to be provided when installing
 * the manager.
 *
 * Hence the manager sets up routing VME interrupts to 1 or 2 universe
 * OUTPUTS. However, it must also be told to which PIC INPUTS they
 * are wired.
 * Optionally, the first PIC input line can be read from PCI config space
 * but the second must be passed to this routine. Note that the info read
 * from PCI config space is wrong for many boards!
 *
 * PARAMETERS:
 *       vmeIrqUnivOut: to which output pin (of the universe) should the 7
 *       				VME irq levels be routed.
 *       vmeIrqPicLine: specifies to which PIC input the 'main' output is
 *                      wired. If passed a value < 0, the driver reads this
 *                      information from PCI config space ("IRQ line").
 *   specialIrqUnivOut: to which output pin (of the universe) should the
 *                      internally irqs be routed. Use 'vmeIRQunivOut'
 *                      if < 0.
 *   specialIrqPicLine: specifies to which PIC input the 'special' output
 *                      pin is wired. The wiring of the 'vmeIRQunivOut' to
 *                      the PIC is determined by reading PCI config space.
 *
 * RETURNS: 0 on success, -1 on failure.
 *
 */
int
vmeUniverseInstallIrqMgr(int vmeIrqUnivOut,
						 int vmeIrqPicLine,
						 int specialIrqUnivOut,
						 int specialIrqPicLine);

#endif

#ifdef __cplusplus
}
#endif

#endif