/*
 * system.h
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) Equator Technologies
 */

#ifndef _ASM_BSP_SYSTEM_H_
#define _ASM_BSP_SYSTEM_H_

#include <linux/kernel.h>

#ifdef __KERNEL__

#include <linux/types.h>
#include <linux/unistd.h>

#include <asm/segment.h>
#include <asm/debug.h>

#include <eti/mm.h>
#include <libdev/etiRegisters.h>



/* interrupt control.. cli=disable, sti=enable*/
#define __sti()             { UInt32 flags; bspregEnableInterrupts (flags); }
#define __cli()             { UInt32 flags; bspregDisableInterrupts(flags); }
#define __save_flags(x)     { x = hmpv_read_eer_cl0(); }
#define __restore_flags(x)  { bspregRestoreInterrupts(x); }



#define cli()			__cli()
#define sti()			__sti()
#define save_flags(x)		__save_flags(x)
#define restore_flags(x)	__restore_flags(x)
#define save_and_cli(x)		{ bspregDisableInterrupts(x); }

#define __ste()			{UInt32 flags; bspregEnableExceptions (flags);}
#define __cle()			{UInt32 flags; bspregDisableExceptions(flags);}
#define __psw_save_flags(x)     { x = hmpv_read_psw_cl0(); }
#define __psw_restore_flags(x)  { hmpv_write_psw_cl0(x); }
#define __psw_save_and_cle(x)   bspregDisableExceptions(x)

/* mb(): Make sure all pending writes are sent to the other CPUs
 *       before *continuing (since some CPUs 'write-cache' writes to 
 *       memory */
#define mb()			hmpv_endtrace()
#define rmb()			mb()
#define wmb()			mb()


extern struct task_struct *__switch_to( struct task_struct *prev, struct task_struct *next );

#define switch_to(p,n,l) \
{                        \
   l= __switch_to(p,n);  \
}

#define INITIATE_SWITCH()       cli()
#define SAVE_CONTEXT(c)         ctxSaveThreadContext(c)
#define RESTORE_CONTEXT(c)      ctxRestoreThreadContext(c,1)
#define TERMINATE_SWITCH()      current_var=current; sti()


extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
{
	unsigned long flags, retval;

	save_flags(flags);
	cli();
	retval = *m;
	*m = val;
	restore_flags(flags);
	return retval;
}

/*
 * This function doesn't exist, so you'll get a linker error
 * if something tries to do an invalid xchg().
 *
 * This only works if the compiler isn't horribly bad at optimizing.
 * gcc-2.5.8 reportedly can't handle this, but I define that one to
 * be dead anyway.
 */
extern void __xchg_called_with_bad_pointer(void);

#define xchg(ptr,x)	((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
#define tas(ptr)	(xchg((ptr),1))

static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
	switch (size) {
		case 4:
			return xchg_u32(ptr, x);
	}
	__xchg_called_with_bad_pointer();
	return x;
}

extern NORET_TYPE void bsp_panic( const char* s, ... );

#endif	/* __KERNEL__ */

#endif	/* _ASM_BSP_SYSTEM_H_ */
