
/*
 Copyright 1999 by Digi International (www.digi.com)

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the 
 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 PURPOSE.  See the GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
 *	$Id: triglbl.h,v 1.37 2001/02/22 16:45:17 robertw Exp $
 *
 *	Herein we describe the three possible global structures
 *	pointed to by the global data pointer located at offset
 *	GLOBAL_DATA_OFFSET (currently: 0x1000, but please do use
 *	the #define from the appropriate *mmap.h as this is subject
 *	to change).
 *
 *	By decree, all three of the structures will have a common
 *	structure at the beginning which drivers can use to determine
 *	what code is currently running, and what its status is.
 *	After that, the program that is running is free to define
 *	any additional data it wants to expose to the driver.
 *
 *	The user must supply a few scalar typedef's to use these structures:
 *
 *	host_*		values that are written by the host, read by board
 *	board_*		values that are written by the board, read by host.
 *	shared_*	values that can be read and written by either.
 *	pad_*		padding, not used.
 *
 *	These typedef's are for the purpose of suggesting and/or
 *	enforcing the usage of each member (depending on the compiler).
 *	Items that are of type shared_* must always be written using
 *	uncached accesses.
 *
 *	Suggested typedefs for i386 host's are:
 *		typedef volatile const ulong	board_uint32;
 *		typedef ulong			host_uint32;
 *		typedef volatile ulong		shared_uint32;
 *		typedef ulong			pad_32;
 *	Suggested typedefs for 4640 board processors are:
 *		typedef ulong			board_uint32;
 *		typedef volatile const ulong	host_uint32;
 *		typedef volatile ulong		shared_uint32;
 *		typedef ulong			pad_32;
 *
 *	Endianess is not indicated by these types.  Endianess for
 *	all these types is currently dictated to be little-endian.
 *	For the BOOT and the POST, the endianess must be fixed, since
 *	they do not know the endianess of the host yet.  For the current
 *	FEP, the endianess is also fixed to be little endian.  But the
 *	FEP allows for future *runtime* adjustment of the endianess
 *	of these types (using C++ classes instead of the plain typedefs
 *	suggested above).
 *
 *	A three phase boot scheme is used.  See specs.
 *
 *
 *	NOTE: Somewhat related to these structures are the structures
 *	used only for *debugging purposes*.  These include the debugger
 *	queues, temp counters, temp flags, printf buffers for firmware not
 *	yet to the point that it can communicate thru channel structures,
 *	and statistical program counter sampling.  You can find these
 *	structures in header file "debugcomm.h".
 */
#ifndef _TRIGLBL_H
#define _TRIGLBL_H

/*
 *	A macro to make 4 byte magic numbers from cute character strings
 */
#define	MKMAGIC(A,B,C,D)	(A + (B<<8) + (C<<16) + (D<<24))

/*
 *	There are three important values fixed in location at
 *	GLOBAL_DATA_OFFSET in board shared memory.  GLOBAL_DATA_OFFSET
 *	is a fixed location whose value is defined in *mmap.h
 *
 *	Here is the structure that defines the three important values.
 */
typedef struct
{
	/*
	 *	Offset in shared memory where GLOBAL_*_DATA structure can
	 *	be found.
	 */
	board_uint32_le	global_data_offset;

	/*
	 *	Physical address in host memory where GLOBAL_HOST_DATA
	 *	can be found.
	 */
	host_uint32_le	global_host_paddr;

	/*
	 *	Boolean set by host to indicate endianness
	 */
	host_uint32_le	global_endian;
			/*
			 * Convenience values for readability only
			 */
			#define GLOBAL_ENDIAN_LITTLE	0
			#define	GLOBAL_ENDIAN_BIG	0x11111111
} GLOBAL_DATA;

/*
 *	The new read/write structure
 *
 *	This structure is cacheline-32 safe *only* if the firmware always
 *	uses uncached accesses to clear the shared rw_req member.
 */
typedef struct rwdata
{
	/*
	 *	This is the request type
	 */
	shared_uint32_le	rw_req;
			#define RW_IDLE	  0	/* Idle */
			#define	RW_READ	  1	/* Read request */
			#define	RW_WRITE  2	/* Write request */
			#define	RW_EXEC	  3	/* Jump to address */
			#define	RW_RESET  4	/* Reset board */
			#define	RW_CONT   5	/* Break out of spinloop */
			#define	RW_CALL	  6	/* Call procedure */
			#define RW_FLSH	  7	/* Flush write-back cache */
			#define RW_POST   8	/* POST special functions */
			#define RW_BBFLSH 9     /* Flush Block Box cache */

	/*
	 *	For read/write requests, what device to access
	 */
	host_uint32_le	rw_type;
			#define	RW_RAM	0
			#define	RW_CONC	1
			#define	RW_DSP	2

			/* POST special functions */
			#define RW_POST_LOOPBACK_INTERNAL	0
			#define RW_POST_LOOPBACK_EXTERNAL	1
			#define RW_POST_CROSSOVER			2
			#define RW_POST_H110_STREAMS		3
			#define RW_POST_H110_CLKS			4

	/*
	 *	For CONC and DSP types, the DSP or concentrator number
	 *	For DSP types - this also indicates PM vs DM:
	 *		0x000tnnnn
	 *			t => memory type & overlay (RW_DM/RW_PM)
	 *			nnnn => dsp number.
	 */
	host_uint32_le	rw_subtype;
			#define	RW_DM	0		/* access DM */
			#define	RW_PM	(1 << 16)	/* access PM */
			#define RW_DSP_MEM(x)		((x) & RW_PM)
			#define	RW_DSP_NUM(x)		((x) & 0x0000ffff)

	/*
	 *	Now the address, size, and buffer
	 */
	host_uint32_le	rw_addr;	/* Memory/jump address */
	host_uint32_le	rw_size;	/* Read/write length */

	pad_32		pad[3];

	shared_uint8	rw_data[128];	/* Data buffer */

} RWDATA;

/*
 *	The common portion of the global data (cacheline-32 safe)
 */
typedef struct global_common
{
	/*
	 *	Magic number of currently running firmware
	 */
	board_uint32_le	magic;
			#define	MAGIC_BOOT	MKMAGIC('b','o','o','t')
			#define	MAGIC_POST	MKMAGIC('p','o','s','t')
			#define	MAGIC_FEP	MKMAGIC('g','l','b','l')

	/*
	 *	Initialization status of currently running firmware
	 *
	 *	Values of 0 thru (STATUS_RUN-1) mean the firmware is in the
	 *	midst of initialization.  If this value gets "stuck" in this
	 *	range, the board firmware has failed initialization
	 *	for some reason.  The actual reason for failure may
	 *	be indicated by this value, or the firmware is free
	 *	to provide additional information concerning the
	 *	reason in additional structure members below.
	 *
	 *	A value >= STATUS_RUN means the firmware is in its normal
	 *	running state.  Its background main loop or scheduler is fully
	 *	operating.
	 *
	 *	STATUS_RUN does not necessarily mean that the firmware
	 *	encountered no errors.  For example, the BOOT firmware
	 *	could have detected that there is no valid POST in flash.
	 *	It indicates this is in an additional member below, but
	 *	proceeds into STATUS_RUN.  This guarantees to the driver
	 *	that the BOOT is executing out of RAM and is waiting for
	 *	the driver to write a valid POST image to flash and then
	 *	prod it with a reset.  Likewise, the POST may determine
	 *	that non-critical hardware has failed on the board.  It
	 *	will indicate the exact failure(s) in additional members
	 *	below, then proceed into STATUS_RUN state.  This indicates
	 *	to the driver that, should anybody desire, they can do
	 *	a "cu" to the POSTs TCL interpreter and perform more
	 *	in-depth failure analysis.
	 *	
	 */
	board_uint32_le	status;
			#define	STATUS_INIT	0
			#define	STATUS_RUN	0x10000	

	/*
	 *	This is an arbitrary revision number assigned to the
	 *	firmware for identification and compatibility purposes.
	 *	The process assigning revision numbers is TBD.  Could
	 *	be time is seconds since the epoch, could be a build number,
	 *	could be a number incremented once per release.
	 */
	board_uint32_le	revision;

	/*
	 *	All firmware must provide a heartbeat that increments
	 *	this counter once around the lowest priority background
	 *	main loop, but no less than twice per second.  The host
	 *	uses this to determine if the board has gone insane.
	 */
	board_uint32_le	heartbeat;

	/*
	 *	The endianess of the board CPU is indicated here.
	 *	Non-zero means bigendian.  This is provided for
	 *	informational purposes only.  The host driver is not
	 *	expected to have to use this information (except,
	 *	possibly, for debugging tools which peer into private
	 *	board RAM).
	 */
	board_uint32_le	bigendian_board;	

	/*
	 *	we need padding here, to force rw structure onto a
	 *	cacheline boundary.
	 */
	pad_32		pad1[3];	/* FIXME: should be 3!!!! */
					/* FIXED! was 5 */

	/*
	 *	The read-write structure.  This structure allows the
	 *	host to command arbitrary reads and writes of memory,
	 *	force execution to call a specific address, and to
	 *	force a software reset on hardware that does not have a
	 *	host-accessable register to cause a hardware reset,
	 *	such as the Galileo-9.
	 *
	 *	There are three important uses for this structure that
	 *	should be pointed out.
	 *	1) RW_RESET is used by the host driver after writing a
	 *	   new POST in flash.
	 *	2) RW_RESET is used by the host driver when it unloads
	 *	   so that the BOOT and POST are re-executed immediately
	 *	   so that the board will be ready for the next time the
	 *	   driver is loaded.
	 *	3) RW_EXEC is used by the host driver to transfer control
	 *	   to the FEP after the driver has loaded the FEP into
	 *	   memory on the board.
	 *	
	 */
	RWDATA		rw;

} GLOBAL_COMMON;

/*
 *	When the BOOT program is running, this is its global data.
 *	By decree, all data in this structure is little endian.
 *	This structure is cacheline-32 safe, even though the
 *	boot program always uses uncached accesses for reliability.
 */
typedef struct global_boot_data
{
	/*
	 *	The common data required by all firmware
	 */
	GLOBAL_COMMON	common;

	/*
	 *	Failure of the CRC of the flash containing the POST firwmare,
 	 *	or anything else that the BOOT cares about is indicated here
	 *	in this bitmask.  The driver can use this information to
	 *	determine if it should try to reporgram the post in flash,
	 *	or just give up.  This data is valid only if BOOT is in
	 *	the STATUS_RUN state.  If no failures are detected, the
	 *	BOOT never enters the STATUS_RUN state -- it simply loads
	 *	the POST and jumps to it.
	 */
	board_uint32_le	failure;
			#define	FAIL_OTHER	0x80000000
			#define	FAIL_POSTFLASH	0x40000000
			#define		FAIL_POSTJUMP	1
			#define		FAIL_POSTCRC	2
			#define		FAIL_POSTLENGTH	3
			#define		FAIL_POSTHEADER	4
			#define	FAIL_RAMTEST	0x20000000

	/*
	 *	If RAM has failed, here is the address and data pattern
	 */
	board_uint32_le	ramaddr;
	board_uint32_le	ramdata;

	pad_32		pad1[5];	/* FIXME: should be 5!!!! */
					/* FIXED! was 7 */

} GLOBAL_BOOT_DATA;

/*
 *	This is the format for error reports from the POST. If
 *	errors exist, the error_list pointer will point to a
 *	linear array of these structures. They will be at least
 *	error_count informative entries in this array, as well
 *	as an arbitrary number of no-op entries. The list is always
 *	terminated by an end-of-list entry. Neither nop or eol
 *	entries contribute to error_count.
 */
typedef struct post_error_report
{
	/*
	 * Indentify the failing component referred to by this entry.
	 */
	board_uint16_le	identifier ;

#define POST_ERROR_ADAPTER	0xc000
#define POST_ERROR_LINE		0x8000
#define POST_ERROR_CHANNEL	0x4000
#define	POST_ERROR_EOL		0xffff

#define	POST_ERROR_NOP		0x0000
#define		POST_INFO_CPUSPEED		(POST_ERROR_NOP + 1)
#define		POST_INFO_GALPARMS		(POST_ERROR_NOP + 2)
#define		POST_INFO_STAC_ID		(POST_ERROR_NOP + 3)
#define		POST_INFO_DAATYPE		(POST_ERROR_NOP + 4)
#define		POST_INFO_CODECTRIES	(POST_ERROR_NOP + 5)
#define		POST_INFO_TSATRIES		(POST_ERROR_NOP + 6)
#define		POST_INFO_T8100_ID		(POST_ERROR_NOP + 7)
#define		POST_INFO_GEOADDR		(POST_ERROR_NOP + 8)

    /* adapter level errors */
#define	POST_ERROR_CPU		POST_ERROR_ADAPTER + 0x0010

#define	POST_ERROR_RAM		POST_ERROR_ADAPTER + 0x0020
#define		POST_ERROR_RAM_WALKING1		(POST_ERROR_RAM + 1)
#define		POST_ERROR_RAM_WALKING0		(POST_ERROR_RAM + 2)
#define		POST_ERROR_RAM_ADDRESSTAG	(POST_ERROR_RAM + 3)

#define	POST_ERROR_GPP		POST_ERROR_ADAPTER + 0x0030
#define		POST_ERROR_GPP16_WALKING1	(POST_ERROR_GPP + 1)
#define		POST_ERROR_GPP16_WALKING0	(POST_ERROR_GPP + 2)
#define		POST_ERROR_GPP8_WALKING1	(POST_ERROR_GPP + 3)
#define		POST_ERROR_GPP8_WALKING0	(POST_ERROR_GPP + 4)

#define	POST_ERROR_PCI		POST_ERROR_ADAPTER + 0x0040

#define	POST_ERROR_DMA		POST_ERROR_ADAPTER + 0x0050

#define	POST_ERROR_STAC		POST_ERROR_ADAPTER + 0x0060
#define		POST_ERROR_STAC_TOOMANYRETRIES	(POST_ERROR_STAC + 1)
#define		POST_ERROR_STAC_CONFIG		(POST_ERROR_STAC + 2)
#define		POST_ERROR_STAC_ID		(POST_ERROR_STAC + 3)
#define		POST_ERROR_STAC_CRAMWALKING1	(POST_ERROR_STAC + 4)
#define		POST_ERROR_STAC_CRAMWALKING0	(POST_ERROR_STAC + 5)
#define		POST_ERROR_STAC_CRAMADDRESSTAG	(POST_ERROR_STAC + 6) 

#define	POST_ERROR_MVIP		POST_ERROR_ADAPTER + 0x0070

#define POST_ERROR_CFG		POST_ERROR_ADAPTER + 0x0080
#define		POST_ERROR_CFG_T1E1MISMATCH	(POST_ERROR_CFG + 1)
#define		POST_ERROR_CFG_WRONGDAUGHTER	(POST_ERROR_CFG + 2)

#define POST_ERROR_EEPROM	POST_ERROR_ADAPTER + 0x0090
#define		POST_ERROR_EEPROM_BADSIGNATURE	(POST_ERROR_EEPROM + 1)
#define		POST_ERROR_EEPROM_FPGAERROR	(POST_ERROR_EEPROM + 2)

#define POST_ERROR_LOOPBACK	POST_ERROR_ADAPTER + 0x00a0
#define		POST_ERROR_LOOPBACK_UNSUPPORTED \
						(POST_ERROR_LOOPBACK + 1)

#define POST_ERROR_CROSSOVER	POST_ERROR_ADAPTER + 0x00b0
#define		POST_ERROR_CROSSOVER_UNSUPPORTED \
						(POST_ERROR_CROSSOVER + 1)

#define	POST_ERROR_INVALID_RWREQ	POST_ERROR_ADAPTER + 0x00c0

#define POST_ERROR_H110			POST_ERROR_ADAPTER + 0x00d0
#define		POST_ERROR_H110_ID				(POST_ERROR_H110 + 1)
#define		POST_ERROR_H110_WALKING1		(POST_ERROR_H110 + 2)
#define		POST_ERROR_H110_WALKING0		(POST_ERROR_H110 + 3)
#define		POST_ERROR_H110_ADDRESS			(POST_ERROR_H110 + 4)
#define		POST_ERROR_H110_CHILOOPBK		(POST_ERROR_H110 + 5)
#define		POST_ERROR_H110_CLOCKS			(POST_ERROR_H110 + 6)

#define POST_ERROR_HOTSWAP		POST_ERROR_ADAPTER + 0x00e0
#define		POST_ERROR_HOTSWAP_EJECTOR		(POST_ERROR_HOTSWAP + 1)

    /* line level errors */
#define POST_ERROR_FRAMER	POST_ERROR_LINE + 0x0010
#define		POST_ERROR_FRAMER_WALKING1		(POST_ERROR_FRAMER + 1)
#define		POST_ERROR_FRAMER_WALKING0		(POST_ERROR_FRAMER + 2)
#define		POST_ERROR_FRAMER_ADDRESSTAG	(POST_ERROR_FRAMER + 3)
#define		POST_ERROR_FRAMER_CONFIG		(POST_ERROR_FRAMER + 4)
#define		POST_ERROR_FRAMER_CHILOOPBK		(POST_ERROR_FRAMER + 5)

#define POST_ERROR_PRILIU	POST_ERROR_LINE + 0x0020
#define		POST_ERROR_PRILIU_WALKING1	(POST_ERROR_PRILIU + 1)
#define		POST_ERROR_PRILIU_WALKING0	(POST_ERROR_PRILIU + 2)
#define		POST_ERROR_PRILIU_CONFIG	(POST_ERROR_PRILIU + 3)

#define POST_ERROR_PRID		POST_ERROR_LINE + 0x0030
#define		POST_ERROR_PRID_WALKING1	(POST_ERROR_PRID + 1)
#define		POST_ERROR_PRID_WALKING0	(POST_ERROR_PRID + 2)
#define		POST_ERROR_PRID_CONFIG		(POST_ERROR_PRID + 3)

#define POST_ERROR_BRILIU	POST_ERROR_LINE + 0x0040
#define		POST_ERROR_BRILIU_WRITE		(POST_ERROR_BRILIU + 1)
#define		POST_ERROR_BRILIU_READ		(POST_ERROR_BRILIU + 2)
#define		POST_ERROR_BRILIU_WRITECMD	(POST_ERROR_BRILIU + 3)
#define		POST_ERROR_BRILIU_CONFIG	(POST_ERROR_BRILIU + 4)
#define		POST_ERROR_BRILIU_NOACTIVATE	(POST_ERROR_BRILIU + 5)
#define		POST_ERROR_BRILIU_RESET		(POST_ERROR_BRILIU + 6)

#define POST_ERROR_BRID		POST_ERROR_LINE + 0x0050

#define POST_ERROR_CODEC	POST_ERROR_LINE + 0x0060
#define		POST_ERROR_CODEC_WRITE		(POST_ERROR_CODEC + 1)
#define		POST_ERROR_CODEC_READ		(POST_ERROR_CODEC + 2)
#define		POST_ERROR_CODEC_RWMISCOMPARE	(POST_ERROR_CODEC + 3)


    /* channel level errors */
#define	POST_ERROR_DSP		POST_ERROR_CHANNEL + 0x0010
#define		POST_ERROR_DSP_WALKING1		(POST_ERROR_DSP + 1)
#define		POST_ERROR_DSP_WALKING0		(POST_ERROR_DSP + 2)
#define		POST_ERROR_DSP_PM		(POST_ERROR_DSP + 3)
#define		POST_ERROR_DSP_DM		(POST_ERROR_DSP + 4)
#define		POST_ERROR_DSP_POST		(POST_ERROR_DSP + 5)
#define		POST_ERROR_DSP_POSTTIMEOUT	(POST_ERROR_DSP + 6)
	
	/*
	 * For port and channel level errors, this identifies
	 * the specific instance or in some cases, a specific
	 * subtest number.
	 */
	board_uint16_le	ordinal ;

	/*
	 * The syndromes are identifier specific and TBD.
	 */
	board_uint32_le	syndrome[3] ;
} POST_ERROR_REPORT ;

/*
 * The summary report generated by the POST. This points to
 * one or more POST_ERROR_REPORTs, if required.
 */
typedef struct post_summary
{
	/*
	 *	Hardware information detected by POST and available
	 *	for use by the driver and the FEP.
	 */
	board_uint32_le	board_type ;
			#define	POST_TYPE_HOUSTON_T1	0x0001
			#define	POST_TYPE_HOUSTON_E1	0x0002
			#define	POST_TYPE_LONDON_U		0x0003
			#define	POST_TYPE_LONDON_ST		0x0004
			#define	POST_TYPE_CHASKA		0x0005
			#define POST_TYPE_CAMPINAS_T1	0x0006
			#define POST_TYPE_CAMPINAS_E1	0x0007
			#define POST_TYPE_AP2K2_232	0x0101
			#define POST_TYPE_AP2K4_232	0x0102
			#define POST_TYPE_AP2K8_232	0x0103
			#define POST_TYPE_AP2K16_232	0x0104
			#define POST_TYPE_AP2K32_232	0X0108
    
			#define POST_TYPE_AP2K4_MPI	0x0105
			#define POST_TYPE_AP2K8_MPI	0x0106
			#define POST_TYPE_AP2K16_MPI	0x0107

			#define POST_SN_SIZE 32
	board_uint8	serial[POST_SN_SIZE] ;
	
	board_uint32_le	memsize;	/* Bytes of RAM detected by POST */
	board_uint32_le	nport;	 	/* Physical # of ports on board */
	board_uint32_le	cpp ;		/* # of channels per port */
	board_uint32_le	nchan ;		/* # of channels physically present */

	board_uint32_le	error_count ;	/* count of errors found. */
			/* maximum number we will log (including NOP entries)*/
			#define POST_MAX_ENTRIES		128
	board_uint32_le	error_list_offset ; /* offset to list of errors */

	pad_32		pad1[1];	/* Pad to cache line */
} POST_SUMMARY ;

/*
 *	When the POST program is running, this is its global data.
 *	By decree, all data in this structure is little endian.
 *	This structure is cacheline-32 safe.
 */
typedef struct global_post_data
{
	/*
	 *	The common data required by all firmware
	 */
	GLOBAL_COMMON	common;

	POST_SUMMARY	summary ;

	/*
	 *	Host endianess.  The host can indicate its endianess
	 *	here.  This is typically written by the host driver
	 *	just before it loads and executes the FEP.  The FEP
	 *	saves this information before switching the global
	 *	area to its own area.
	 *
	 *	AT SOME FUTURE TIME, the FEP *may* be modified so that
	 *	its global data and channel, event, and command structures
	 *	are automatically set to the endianess of the host.  But
	 *	this is not currently implemented.
	 */
	host_uint32_le	bigendian_host;	

	pad_32		pad2[7];

} GLOBAL_POST_DATA;


/*
 *	See fepglbl.h for the definition of the global structure
 *	when the FEP is running...
 */

#endif
