#ifndef __T32_H__
#define __T32_H__

#if defined(_WIN32) || defined(_WIN64) /* Microsoft Visual C++ or GCC-MinGW ? */
# ifndef MS_WINDOWS
#  define MS_WINDOWS
# endif
# define LOW_HIGH
# ifndef _CRT_SECURE_NO_WARNINGS
#  define _CRT_SECURE_NO_WARNINGS /* aBi - eliminate pesky deprecation warnings for older routines */
# endif
#endif

#if defined(MS_WINDOWS) && defined(DLL_BUILD)
# define T32EXTERN  __declspec(dllexport)
# define T32EXPORT  __declspec(dllexport)
#else
# define T32EXTERN  extern
# define T32EXPORT
#endif

#ifdef DEC_VMS
# define LOW_HIGH_BYTE
#endif

#ifdef DEC_OSF1
# define UNIX_V
# define LOW_HIGH_BYTE
#endif

#if defined(T32HOST_HPUX) || defined(HP_UX)
# define UNIX_V
# define HIGH_LOW_BYTE
#endif

#ifdef IBM_AIX
# define UNIX_V
# define HIGH_LOW_BYTE
#endif


#if defined(T32HOST_LINUX_X86) || defined(LINUX_86) || defined(__linux__)
# ifndef LINUX
#  define LINUX
# endif
# define UNIX_V
# define LOW_HIGH_BYTE
#endif

#ifdef T32HOST_LINUX_X64
# define UNIX_V
# define LOW_HIGH_BYTE
#endif

#if defined(T32HOST_LINUX_PPC) || defined(LINUX_PPC)
# ifndef LINUX
#  define LINUX
# endif
# define UNIX_V
# define HIGH_LOW_BYTE
#endif

#ifdef T32HOST_MACOSX_X86
# define UNIX_V
# define LOW_HIGH_BYTE
#endif

#if defined(T32HOST_SOL_SPARC) || defined(SUN_SOL)
# define UNIX_V
# define HIGH_LOW_BYTE
#endif


typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned int dword;


#ifdef HIGH_LOW_BYTE

#define SETWORDCONST(A,B) ( ((unsigned char *)&(A))[0] = (B),((unsigned char *)&(A))[1] = (B)>>8 )
#define SETLONGCONST(A,B) ( ((unsigned char *)&(A))[0] = (B),((unsigned char *)&(A))[1] = (B)>>8,((unsigned char *)&(A))[2] = (B)>>16,((unsigned char *)&(A))[3] = (B)>>24 )

#define SETWORDVAR(A,B) ( ((unsigned char *)&(A))[0] = ((unsigned char *)&(B))[1],((unsigned char *)&(A))[1] = ((unsigned char *)&(B))[0] )
#define SETLONGVAR(A,B) ( ((unsigned char *)&(A))[0] = ((unsigned char *)&(B))[3],((unsigned char *)&(A))[1] = ((unsigned char *)&(B))[2],((unsigned char *)&(A))[2] = ((unsigned char *)&(B))[1],((unsigned char *)&(A))[3] = ((unsigned char *)&(B))[0] )

#endif

#ifdef HIGH_LOW

#define SETWORDCONST(A,B) ((*((unsigned short *)&(A))) = (unsigned short)((((B)>>8)&0xff)|(((B)<<8)&0xff00)))
#define SETLONGCONST(A,B) ((*((int *)&(A))) = (int)((((B)>>24)&0xffl)|(((B)>>8)&0xff00l)|(((B)<<8)&0xff0000l)|(((B)<<24)&0xff000000l)))

#define SETWORDVAR(A,B) ( ((unsigned char *)&(A))[0] = ((unsigned char *)&(B))[1],((unsigned char *)&(A))[1] = ((unsigned char *)&(B))[0] )
#define SETLONGVAR(A,B) ( ((unsigned char *)&(A))[0] = ((unsigned char *)&(B))[3],((unsigned char *)&(A))[1] = ((unsigned char *)&(B))[2],((unsigned char *)&(A))[2] = ((unsigned char *)&(B))[1],((unsigned char *)&(A))[3] = ((unsigned char *)&(B))[0] )

#endif

#ifdef LOW_HIGH

#define SETWORDCONST(A,B) ((*((unsigned short *)&(A))) = (unsigned short)(B))
#define SETLONGCONST(A,B) ((*((int *)&(A))) = (int)(B))

#define SETWORDVAR(A,B) ((*((unsigned short *)&(A))) = (*((unsigned short *)&(B))))
#define SETLONGVAR(A,B) ((*((int *)&(A))) = (*((int *)&(B))))

#endif

#ifdef LOW_HIGH_BYTE

#define SETWORDCONST(A,B) ( ((unsigned char *)&(A))[0] = (B),((unsigned char *)&(A))[1] = (B)>>8 )
#define SETLONGCONST(A,B) ( ((unsigned char *)&(A))[0] = (B),((unsigned char *)&(A))[1] = (B)>>8,((unsigned char *)&(A))[2] = (B)>>16,((unsigned char *)&(A))[3] = (B)>>24 )

#define SETWORDVAR(A,B) ( ((unsigned char *)&(A))[0] = ((unsigned char *)&(B))[0],((unsigned char *)&(A))[1] = ((unsigned char *)&(B))[1] )
#define SETLONGVAR(A,B) ( ((unsigned char *)&(A))[0] = ((unsigned char *)&(B))[0],((unsigned char *)&(A))[1] = ((unsigned char *)&(B))[1],((unsigned char *)&(A))[2] = ((unsigned char *)&(B))[2],((unsigned char *)&(A))[3] = ((unsigned char *)&(B))[3] )

#endif


#define LINE_MBLOCK		16384 	   /* large block mode */
#define LINE_MSIZE		(LINE_MBLOCK+256)

#define T32_DEV_OS		0
#define T32_DEV_ICE		1
#define T32_DEV_ICD		1  /* similar to ICE but clearer for user */

/* Events that can be generated by T32 */
#define T32_MAX_EVENTS 		3
#define T32_E_BREAK 		0x0 /* change in runstate, probably only "break" */
#define T32_E_EDIT              0x1 /* user requested "edit source" in external editor */
#define T32_E_BREAKPOINTCONFIG  0x2 /* breakpoint configuration changed (breakpoint set/removed) */

/* Callbacks should have the following protoypes */
/************************* WARNING *****************************/
/*
 * If you add more callback functions here, make sure you ONLY
 * use 'int', 'unsigned int', 'integral-type *' or 'float-type *' as parameters.
 *
 * No 'long', no 'long long', no 'short', no 'char', no floats, no typedefs
 * and no function pointers!
 * This is because we absolutely need to avoid portability problems here.
 *
 * Explanation:
 * The T32_NotificationCallback_t typedef'd below has an empty parameter list,
 * which we can't change anymore to a va_list because of backwards compatibility.
 * This means only the native types like 'int' and 'integral type *' can be used
 * safely, otherwise we run into hard-to-debug problems with type-promotion and
 * parameter-passing conventions on the varying platforms we support.
 */
extern void T32_callbackBreak(int gen_var);
extern void T32_callbackEditExtern(int gen_var, int lineNr, unsigned char *fileName);
extern void T32_callbackBreakpointConfig(int gen_var);


#define T32_API_RECEIVE         0x1
/* Missing: 0x5, */
#define T32_API_NOTIFICATION    0x6

#define T32_API_SYNCREQUEST     0x02
#define T32_API_SYNCACKN        0x12
#define T32_API_SYNCBACK        0x22

#define T32_PCKLEN_MAX 	1472


typedef struct t32_breakpoint {
    dword address;
    byte  enabled;
    dword type;
    dword auxtype;
} T32_Breakpoint;


typedef struct t32_notification {

  char payload[T32_PCKLEN_MAX]; /* maximum packet size*/

  struct t32_notification *next, *prev;
  /* T32_NotificationPackage *next;
  T32_NotificationPackage *prev; */

} T32_NotificationPackage;

extern T32_NotificationPackage *T32_NotificationHead, *T32_NotificationTail; /* Queue pending notifications */



#define T32_OK                  0
#define T32_COM_RECEIVE_FAIL   -1
#define T32_COM_TRANSMIT_FAIL  -2
#define T32_COM_PARA_FAIL      -3
#define T32_COM_SEQ_FAIL       -4
#define T32_MAX_EVENT_FAIL     -5
#define T32_MALLOC_FAIL        -6


typedef void * T32_TAPACCESS_HANDLE;

/* limited command size through hardcoded buffersizes on host and driver side */
#define EMU_CBMAXDATASIZE 0x3c00
#define T32_TAPACCESS_MAXBITS	EMU_CBMAXDATASIZE * 8

#define T32_TAPACCESS_RELEASE	((T32_TAPACCESS_HANDLE)0)
#define T32_TAPACCESS_HOLD	((T32_TAPACCESS_HANDLE)1)

#define T32_TAPACCESS_TDO	0x00
#define T32_TAPACCESS_TDI	0x04
#define T32_TAPACCESS_TMS	0x08
#define T32_TAPACCESS_TCK	0x0c
#define T32_TAPACCESS_nTRST	0x10
#define T32_TAPACCESS_nRESET	0x14
#define T32_TAPACCESS_nRESET_LATCH 0x18
#define T32_TAPACCESS_VTREF	0x1c
#define T32_TAPACCESS_VTREF_LATCH 0x20
#define T32_TAPACCESS_nENOUT	0x24

#define T32_TAPACCESS_SET(x)	(2|((x)&1))
#define T32_TAPACCESS_SET_LOW	2
#define T32_TAPACCESS_SET_HIGH	3
#define T32_TAPACCESS_SET_0	T32_TAPACCESS_SET_LOW
#define T32_TAPACCESS_SET_1	T32_TAPACCESS_SET_HIGH

#define T32_TAPACCESS_SHIFT	0x30
#define T32_TAPACCESS_SHIFTTMS	0x40
#define T32_TAPACCESS_SHIFTIR	0x50
#define T32_TAPACCESS_SHIFTDR	0x60

#define T32_TAPACCESS_SLEEP_MS 0x7c
#define T32_TAPACCESS_SLEEP_US 0x7d
#define T32_TAPACCESS_SLEEP_HALF_CLOCK 0x7e
#define T32_TAPACCESS_SLEEP	T32_TAPACCESS_SLEEP_MS /*just for backwards compatibility*/

#define HANDSHAKE_RECEIVEBUFFERSIZE 20
#define T32_TAPACCESSSEND_HEADERSIZE 6
#define SHIFTRAW_HEADERSIZE_BITS 8*8

#define SHIFTRAW_OPTION_INTERNAL_TMS 0x0001 /*do not use the internal options*/
#define SHIFTRAW_OPTION_INTERNAL_TDI 0x0002
#define SHIFTRAW_OPTION_INTERNAL_TDO 0x0004
#define SHIFTRAW_OPTION_INTERNAL_ALL 0x0007

#define SHIFTRAW_OPTION_NONE         0x0000
#define SHIFTRAW_OPTION_LASTTMS_ONE  0x0008
#define SHIFTRAW_OPTION_TMS_ONE      0x0010
#define SHIFTRAW_OPTION_TMS_ZERO     0x0000
#define SHIFTRAW_OPTION_TDI_ONE      0x0040
#define SHIFTRAW_OPTION_TDI_ZERO     0x0000
#define SHIFTRAW_OPTION_TDI_LASTTDO  0x0020

#define T32_TAPACCESS_SPECIAL	0x80

#ifdef	__cplusplus
extern "C" {
#endif

#ifndef _NO_PROTO

extern T32EXPORT int T32_Errno;
T32EXTERN int T32_Config( const char *, const char * );
T32EXTERN int T32_Init(void);
T32EXTERN int T32_Exit(void);
T32EXTERN int T32_Nop(void);
T32EXTERN int T32_NopFail(void);
T32EXTERN int T32_Ping(void);
T32EXTERN int T32_Stop(void);
T32EXTERN int T32_GetPracticeState(int * );
T32EXTERN int T32_Attach( int );
T32EXTERN int T32_GetState( int * );
T32EXTERN int T32_GetCpuInfo( char **, word *, word *, word * );
T32EXTERN int T32_GetRam(dword *, dword *, word *);
T32EXTERN int T32_ResetCPU(void);

T32EXTERN int T32_ReadMemory      ( dword address, int access, byte * buffer, int size);
T32EXTERN int T32_WriteMemory     ( dword address, int access, byte * buffer, int size);
T32EXTERN int T32_WriteMemoryPipe ( dword address, int access, byte * buffer, int size);
T32EXTERN int T32_ReadMemoryEx    ( dword address, int segment, int access, int attr, byte * buffer, int size);
T32EXTERN int T32_WriteMemoryEx   ( dword address, int segment, int access, int attr, byte * buffer, int size);


/* Memory access modes used with T32_ReadMemory, T32_WriteMemory, T32_ReadMemoryEx and T32_WriteMemoryEx */
#define T32_MEMORY_ACCESS_DATA                   0x0000
#define T32_MEMORY_ACCESS_PROGRAM                0x0001
#define T32_MEMORY_ACCESS_ARM_CP0                0x0002
#define T32_MEMORY_ACCESS_ARM_ICE                0x0003
#define T32_MEMORY_ACCESS_ARM_ETM                0x0004
#define T32_MEMORY_ACCESS_ARM_CP14               0x0005
#define T32_MEMORY_ACCESS_ARM_CP15               0x0006
#define T32_MEMORY_ACCESS_ARM_ARM                0x0007
#define T32_MEMORY_ACCESS_ARM_THUMB              0x0008
#define T32_MEMORY_ACCESS_ARM_PHYSICAL_ARM       0x0009
#define T32_MEMORY_ACCESS_ARM_PHYSICAL_THUMB     0x000a
#define T32_MEMORY_ACCESS_ARM_ETB                0x000b
#define T32_MEMORY_ACCESS_ARM_PHYSICAL_DATA      0x000c
#define T32_MEMORY_ACCESS_ARM_PHYSICAL_PROGRAM   0x000d
#define T32_MEMORY_ACCESS_ARM_DAP                0x000e
#define T32_MEMORY_ACCESS_ARM_USR                0x000f
#define T32_MEMORY_ACCESS_MMUBYPASS              0x8000 /* T32_ReadMemoryEx and T32_WriteMemoryEx only */

/* Attributes used with T32_ReadMemoryEx and T32_WriteMemoryEx */
#define T32_MEMORY_ATTR_WIDTHMASK                0x000f
#define T32_MEMORY_ATTR_DUALPORT                 0x0400  // 0x0020 ???
#define T32_MEMORY_ATTR_NOINCREMENT              0x4000


T32EXTERN int T32_WriteRegister( dword, dword, dword * );
T32EXTERN int T32_ReadRegister( dword, dword, dword * );
T32EXTERN int T32_ReadRegisterByName( char *, dword *, dword *);
T32EXTERN int T32_ReadPP( dword * );
T32EXTERN int T32_WriteBreakpoint( dword, int, int, int );
T32EXTERN int T32_ReadBreakpoint( dword, int, word * , int );
T32EXTERN int T32_GetBreakpointList( int *, T32_Breakpoint*, int );
T32EXTERN int T32_Step(void);
T32EXTERN int T32_StepMode(int);
T32EXTERN int T32_SetMode(int);
T32EXTERN int T32_Go(void);
T32EXTERN int T32_Break(void);
T32EXTERN int T32_Terminate(int retval);
T32EXTERN int T32_Cmd( const char * );
T32EXTERN int T32_CmdWin( dword, char * );
T32EXTERN int T32_EvalGet ( dword * );
T32EXTERN int T32_GetMessage ( char *, word * );
T32EXTERN int T32_GetTriggerMessage ( char* );
T32EXTERN int T32_GetSymbol ( char *, dword *, dword * , dword * );
T32EXTERN int T32_GetSource ( dword, char *, dword * );
T32EXTERN int T32_GetSelectedSource( char *, dword * );
T32EXTERN int T32_ReadVariableValue ( char *, dword *, dword *);
T32EXTERN int T32_ReadVariableString ( char *, char *, int);

T32EXTERN int T32_AnaStatusGet( byte *, long *, long *, long * );
T32EXTERN int T32_AnaRecordGet( long , byte *, int );
T32EXTERN int T32_GetTraceState(int tracetype, int * state, long * size, long * min, long * max);
T32EXTERN int T32_ReadTrace(int tracetype, long record, int nrecords, unsigned long mask, byte * buffer);

typedef void (*T32_NotificationCallback_i_t)(int);
typedef void (*T32_NotificationCallback_iicp_t)(int, int, unsigned char *);

#ifndef SUPPRESS_FUNCTION_TYPE_WARNING

# if defined(_MSC_VER)
#  pragma warning( push )
#  pragma warning( disable : 4255 )
# endif

typedef void (*T32_NotificationCallback_t)();

# if defined(_MSC_VER)
#  pragma warning( pop )
# endif

extern int T32_NotifyStateEnable( int event, T32_NotificationCallback_t func);
#endif

T32EXTERN int T32_CheckStateNotify( unsigned param1);
T32EXTERN void T32_GetSocketHandle( int *t32soc );

T32EXTERN T32_TAPACCESS_HANDLE T32_TAPAccessAlloc(void);
T32EXTERN int T32_TAPAccessExecute(T32_TAPACCESS_HANDLE connection, T32_TAPACCESS_HANDLE connectionhold);
T32EXTERN int T32_TAPAccessFree(T32_TAPACCESS_HANDLE connection);
T32EXTERN int T32_TAPAccessSetInfo(int irpre, int irpost, int drpre, int drpost, int tristate, int tapstate, int tcklevel, int slave);
T32EXTERN int T32_TAPAccessSetInfo2(T32_TAPACCESS_HANDLE connection, int irpre, int irpost, int drpre, int drpost, int tristate, int tapstate, int tcklevel, int slave);
T32EXTERN int T32_TAPAccessShiftIR(T32_TAPACCESS_HANDLE connection, int numberofbits, byte * poutbits, byte * pinbits);
T32EXTERN int T32_TAPAccessShiftDR(T32_TAPACCESS_HANDLE connection, int numberofbits, byte * poutbits, byte * pinbits);
T32EXTERN int T32_TAPAccessShiftRaw(T32_TAPACCESS_HANDLE connection, int numberofbits, byte * pTMSBits, byte * pTDIBits, byte * pTDOBits, int options);
T32EXTERN int T32_TAPAccessDirect(T32_TAPACCESS_HANDLE connection, int nbytes, byte * poutbytes, byte * pinbytes);
T32EXTERN int T32_TAPAccessRelease(void);
T32EXTERN unsigned int T32_GetMaxRawShiftSize(unsigned int bitsToTransmit, byte* tmsbuf, byte* tdibuf, byte* tdobuf, unsigned int* options);

T32EXTERN int T32_Fdx_Resolve(char * name);
T32EXTERN int T32_Fdx_Open(char * name, char * mode);
T32EXTERN int T32_Fdx_Close(int channel);
T32EXTERN int T32_Fdx_ReceivePoll(int channel, void * data, int width, int maxsize);
T32EXTERN int T32_Fdx_Receive(int channel, void * data, int width, int maxsize);
T32EXTERN int T32_Fdx_SendPoll(int channel, void * data, int width, int size);
T32EXTERN int T32_Fdx_Send(int channel, void * data, int width, int size);

/*
 * New stream structure, to improve performance for PIPE mode.
 */
typedef struct
{
	int blen;
	unsigned char *ptr;
	unsigned char *ptrend;
	int channel;
	unsigned char buffer[4096];
} T32_Fdx_Stream;

T32EXTERN T32_Fdx_Stream *T32_Fdx_OpenStream(char *name, char *mode);
T32EXTERN int T32_Fdx_CloseStream(T32_Fdx_Stream * pstream);
T32EXTERN int T32_Fdx_ReceiveStreamNext(T32_Fdx_Stream * pstream, unsigned char *target, int width, int size);

#define T32_Fdx_ReceiveStream(__pstream,__target,__width,__len)		( \
			(((__pstream)->ptr >= (__pstream)->ptrend) ? \
			    T32_Fdx_ReceiveStreamNext(__pstream,__target,__width,__len) : \
			((__pstream)->blen = ((__pstream)->ptr[0]|((__pstream)->ptr[1]<<8)), memcpy((__target),(__pstream)->ptr+2,(__pstream)->blen), (__pstream)->ptr += 2+(__pstream)->blen, (__pstream)->blen)))

T32EXTERN int   T32_GetChannelSize(void);
T32EXTERN void  T32_GetChannelDefaults(void* line);
T32EXTERN void  T32_SetChannel(void* line);
T32EXTERN void* T32_GetChannel0(void);

#endif

#ifdef	__cplusplus
}
#endif

#endif
