/*
 *	The structures for the Galileo 64011 PCI I/F and 4640 controller
 */
#ifndef _H_64011
#define	_H_64011

#if defined (UNITTEST)
	typedef unsigned long uint32;
#endif

#define	_(X)	uint32 reserved##X

/*
 *	Galileo 64011 registers
 */
typedef struct reg64011
{
	/*
	 *	CPU interface
	 */
	uint32	cpu_interface;
	_(1);
		#define	CPU_ENDIANESS		(1<<12)
		#define	CPU_BIG_ENDIAN		(0<<12)
		#define	CPU_LITTLE_ENDIAN	(1<<12)

	/*
	 *	Processor address space
	 */
	uint32	ras10_low_decode;
	_(2);
	uint32	ras10_high_decode;
	_(3);
	uint32	ras32_low_decode;
	_(4);
	uint32	ras32_high_decode;
	_(5);
	uint32	cs20_low_decode;
	_(6);
	uint32	cs20_high_decode;
	_(7);
	uint32	cs3boot_low_decode;
	_(8);
	uint32	cs3boot_high_decode;
	_(9);
	uint32	pci_io_low_decode;
	_(10);
	uint32	pci_io_high_decode;
	_(11);
	uint32	pci_mem0_low_decode;
	_(12);
	uint32	pci_mem0_high_decode;
	_(13);
	uint32	internal_space_decode;
	_(14);
	uint32	bus_error_address;
	_(15);
	uint32	read_only_0;
	_(16);
	uint32	pci_mem1_low_decode;
	_(17);
	uint32	pci_mem1_high_decode;
	_(18);

	uint32	skip1[220];
	
	/*
	 *	DRAM and device address space
	 */
	uint32	ras0_low_decode;
	uint32	ras0_high_decode;
	uint32	ras1_low_decode;
	uint32	ras1_high_decode;
	uint32	ras2_low_decode;
	uint32	ras2_high_decode;
	uint32	ras3_low_decode;
	uint32	ras3_high_decode;
	uint32	cs0_low_decode;
	uint32	cs0_high_decode;
	uint32	cs1_low_decode;
	uint32	cs1_high_decode;
	uint32	cs2_low_decode;
	uint32	cs2_high_decode;
	uint32	cs3_low_decode;
	uint32	cs3_high_decode;
	uint32	bootcs_low_decode;
	uint32	bootcs_high_decode;

	/*
	 *	DRAM configuration
	 */
	uint32	dram_configuration;
	uint32	dram_bank[4];
	uint32	device_bank[4];
	uint32	device_bootbank;

	uint32	address_decode_error;

	uint32	skip2[227];

	/*
	 *	DMA Record
	 */
	volatile uint32	dma_byte_count[4];
	volatile uint32	dma_src_addr[4];
	volatile uint32	dma_dst_addr[4];
	volatile uint32	dma_next[4];
	volatile uint32	dma_control[4];
			#define	DMA_LCL2LCL	(0<<0)
			#define	DMA_PCI2LCL	(1<<0)
			#define	DMA_LCL2PCI	(2<<0)
			#define	DMA_PCI2PCI	(3<<0)

			#define	DMA_INCSRC	(0<<2)
			#define	DMA_DECSRC	(1<<2)
			#define	DMA_HOLDSRC	(2<<2)

			#define	DMA_INCDST	(0<<4)
			#define	DMA_DECDST	(1<<4)
			#define	DMA_HOLDDST	(2<<4)

			#define DMA_1BYTE	(5<<6)
			#define DMA_2BYTE	(6<<6)
			#define DMA_4BYTE	(0<<6)
			#define DMA_8BYTE	(1<<6)
			#define DMA_16BYTE	(3<<6)
			#define DMA_32BYTE	(7<<6)

			#define DMA_CHAINED	(0<<9)
			#define DMA_NONCHAINED	(1<<9)

			#define DMA_INTR_COUNT	(0<<10)
			#define DMA_INTR_NULL	(1<<10)

			#define DMA_DEMANDMODE	(0<<11)
			#define DMA_BLOCKMODE	(1<<11)

			#define DMA_ENABLED	(1<<12)
			#define DMA_FETCHNEXT	(1<<13)
			#define DMA_ACTIVE	(1<<14)

	/*
	 *	Timer/Counters
	 *
	 *	timer[0] is 32 bits, the rest are 24 bits.
	 *
	 */
	volatile uint32	timer[4];
	uint32	arbiter_ctrl;
	uint32	timer_ctrl;
			#define TC_ENABLE(NUM)	(1 << (NUM*2))
			#define TC_COUNTER(NUM)	(0 << (NUM*2 + 1))
			#define TC_TIMER(NUM)	(1 << (NUM*2 + 1))

	uint32	skip3[230];

	/*
	 *	PCI internal
	 */
	uint32	command;
		#define	CMD_NOBYTESWAP	0x0001

	uint32	timeout_retry;
	uint32	ras10_bank_size;
	uint32	ras32_bank_size;
	uint32	cs20_bank_size;
	uint32	cs3boot_bank_size;

	/*
	 *	Interrupts
	 */
	uint32	intr_cause;	/* Cause register */
	uint32	cpu_mask;	/* Masks interrupts from host *to* the CPU */
	uint32	skip4;
	uint32	pci_mask;	/* Masks interrupts from CPU *to* the host */
		/* 
		 * Masks, status, and causes for the above registers
		 */
		#define INT_INTSUM	(1<<0)	/* 0x0000.0001 */
		#define INT_MEMOUT	(1<<1)
		#define INT_DMAOUT	(1<<2)
		#define INT_CPUOUT	(1<<3)	/* 0x0000.0008 */

		#define INT_DMA0COMP	(1<<4)	/* 0x0000.0010 */
		#define INT_DMA1COMP	(1<<5)
		#define INT_DMA2COMP	(1<<6)
		#define INT_DMA3COMP	(1<<7)	/* 0x0000.0080 */

		#define INT_T0EXP	(1<<8)	/* 0x0000.0100 */
		#define INT_T1EXP	(1<<9)
		#define INT_T2EXP	(1<<10)
		#define INT_T3EXP	(1<<11)	/* 0x0000.0800 */

		#define INT_MASRDERR	(1<<12)	/* 0x0000.1000 */
		#define INT_SLVWRERR	(1<<13)
		#define INT_MASWRERR	(1<<14)
		#define INT_SLVRDERR	(1<<15)	/* 0x0000.8000 */

		#define INT_ADDRERR	(1<<16)	/* 0x0001.0000 */
		#define INT_MEMERR	(1<<17)
		#define INT_MASABORT	(1<<18)
		#define INT_TARABORT	(1<<19)	/* 0x0008.0000 */
		#define INT_RETRYCTR	(1<<20)	/* 0x0010.0000 */

		/*
		 *	The board *zeroes* an INT_CPU* bit in the intr_cause
		 *	register to *cause* a PCI interrupt.  The host
		 *	*zeroes* the INT_CPU* bit(s) to clear the interrupt.
		 */
		#define INT_CPUINT0	(1<<21)
		#define INT_CPUINT1	(1<<22)
		#define INT_CPUINT2	(1<<23)	/* 0x0080.0000 */
		#define INT_CPUINT3	(1<<24)	/* 0x0100.0000 */
		#define INT_CPUINT4	(1<<25)

		/*
		 *	The host *zeroes* an INT_PCI* bit in the intr_cause
		 *	register to *cause* a board interrupt.  The board
		 *	*zeroes* the INT_PCI* bit(s) to clear the interrupt.
		 */
		#define INT_PCIINT0	(1<<26)
		#define INT_PCIINT1	(1<<27)	/* 0x0800.0000 */
		#define INT_PCIINT2	(1<<28)	/* 0x1000.0000 */
		#define INT_PCIINT3	(1<<29)

		#define INT_CPUINTSUM	(1<<30)
		#define INT_PCIINTSUM	(1<<31)	/* 0x8000.0000 */

		#define INT_ALLCPUINTS	( INT_CPUINT0 | INT_CPUINT1 | \
					  INT_CPUINT2 | INT_CPUINT3 | \
					  INT_CPUINT4)
		#define INT_ALLPCIINTS	( INT_PCIINT0 | INT_PCIINT1 | \
					  INT_PCIINT2 | INT_PCIINT3)

	/*
	 *	System Error
	 */
	uint32	serr_mask;

	uint32	skip5[2];

	/*
	 *	A 4640 read from this register causes a PCI bus interrupt
	 *	acknowledge cycle.  I'm clueless as to when this is needed.
	 */
	uint32	intr_ack;

	uint32	base_addr_reg_enable;

	uint32	skip6[47];

	uint32	config_addr;
		#define CONFIG_ENABLE	0x80000000
	uint32	config_data;
} REG64011;


#undef _

/*
 *	DMA record for chained DMA
 */
typedef struct dma64011
{
	volatile uint32	dma_byte_count;
	volatile uint32	dma_src_addr;
	volatile uint32	dma_dst_addr;
	volatile uint32	dma_next;
} DMA64011;

/*
 *	Macros for converting addresses to decodes
 */
#define	ADDR2COARSE_LOW(X) ( (X)>>21 )
#define	ADDR2COARSE_HIGH(X) ( ((X)>>21) & 0x7f )
#define	ADDR2FINE(X) ( ((X)>>20) & 0x7f )

/*
 *	The address of the registers in the local address space
 *	is defined in the linker file by this symbol.
 */
extern volatile REG64011 reg64011;
extern volatile REG64011 Reg64011;



/*
 *	Check to make sure structure elements are at correct offsets
 */
#if UNITTEST

#include <stdio.h>
/* #include <environ.h> */
#include <linux/stddef.h>
#include <assert.h>

void
main(int argc, char **argv)
{
	assert(offsetof(REG64011, cpu_interface) == 0x000);
	assert(offsetof(REG64011, pci_mem1_high_decode) == 0x088);

	assert(offsetof(REG64011, ras0_low_decode) == 0x400);
	assert(offsetof(REG64011, address_decode_error) == 0x470);

	assert(offsetof(REG64011, dma_byte_count[0]) == 0x800);
	assert(offsetof(REG64011, timer_ctrl) == 0x864);

	assert(offsetof(REG64011, command) == 0xC00);
	assert(offsetof(REG64011, serr_mask) == 0xC28);
	assert(offsetof(REG64011, intr_cause) == 0xC18);
	assert(offsetof(REG64011, intr_ack) == 0xC34);

	assert(offsetof(REG64011, config_addr) == 0xcf8);
	assert(offsetof(REG64011, config_data) == 0xcfc);

	if (0) printf("size = 0x%02x\n", sizeof(REG64011));

	assert(sizeof(REG64011) == 0xd00);
}
#endif

#endif
