/****************************************************************************/
/*	Copyright (c) 2009, Bendor Research Pty. Ltd. All rights reserved.		*/
/*	This software is released under the GNU General Public License, version	*/
/*	3, with the exemptions that 1) the header files installed by this 	 	*/
/*	package can be included in closed-source code and 2) the libraries		*/
/*	built by this package can be statically linked into a closed-source 	*/
/*	binary. See the file LICENSE for the details.							*/
/*	This software is provided "AS IS", without any warranty or guarantee.	*/
/*	By using this software you acknowledge that neither Bendor Research nor	*/
/*	any of its personnel or affiliates can be held liable for any damages,	*/
/*	including, but not limited to, loss of business, loss of money, loss of */
/*	life, loss of reputation, arising out of this software being faulty or	*/
/*	not performing as advertised, even if Bendor Research was aware of such	*/
/*	faults in the software. You use this software at your own risk, any and */
/*	all liabilities that arise out of your using this software are strictly	*/
/*	yours.																	*/
/****************************************************************************/

#ifndef _BZ_H
#define	_BZ_H

/****************************************************************************/
/*				Definitions needed for local macros							*/
/****************************************************************************/

#ifndef NULL
#define	NULL	((void*)0)
#endif

/****************************************************************************/
/*		Structures that the user should not touch but needs to allocate		*/
/****************************************************************************/

typedef struct {

	int		mask;					// Current event mask
	int		sigs;					// Current pending events
	int		*cntx;					// Thread context (i.e. stackpointer)

} BZ_PROC;

typedef struct {

	unsigned char	sig;			// Signal to deliver when msg is available
	unsigned char	pid;			// Process that owns this port
	unsigned char	head;			// Head of list of messages on the port
	unsigned char	tail;			// Tail of list of messages on the port

} BZ_PORT;

typedef struct bz_time {

	unsigned int	time;			// Remaining time
	unsigned int	rept;			// Periodic time
	struct bz_time	*next;			// Next timer on the queue
	unsigned char	proc;			// Process to signal
	unsigned char	sign;			// Signal to send

} BZ_TIME;

typedef unsigned char	BZ_LOCK;
typedef unsigned int	BZ_SEMA;

/****************************************************************************/
/*				Various definitions the user should know about				*/
/****************************************************************************/

/** @addtogroup coop */
/** @{ */

/**
*	Message packet structure.
*/

typedef struct {

	unsigned int	lpar;			//!< Message 32-bit parameter
	unsigned short	spar;			//!< Message 16-bit parameter
	unsigned char	type;			//!< Message code (8-bit)
	unsigned char	link;			//!< Internally used field

} BZ_MESG;

/**
*	Kernel initialisation structure.
*/

typedef struct {

	void			(*idle)(void);	//!< Idle processing
	void			(*irqs)(void);	//!< Interrupt service routine entry
	void			(*init)(void);	//!< The first process to wake up
	int				*init_stk;		//!< Stack for the init process
	BZ_PROC			*proc_tab;		//!< Pointer to the process table
	BZ_PORT			*port_tab;		//!< Pointer to the port table
	BZ_MESG			*mesg_tab;		//!< Pointer to the message pool
	unsigned char	proc_num;		//!< Number of processes
	unsigned char	port_num;		//!< Number of message ports
	unsigned char	mesg_num;		//!< Number of messages
	unsigned char	schedule;		//!< Priority scheduling
	unsigned char	init_pid;		//!< Process ID for the init process

} BZ_INIT;

/**
*	Pre-defined signals (events)
*/

enum {

	BZ_EVENT_ALWAYS	= 0x80000000,	//!< Event that is always pending
	BZ_EVENT_LOCK	= 0x40000000,	//!< Event used internally by the kernel
	BZ_EVENT_SEMA	= 0x20000000,	//!< Event used internally by the kernel
	BZ_EVENT_MAX	= 29			//!< Number of available events
};

/**
*	Error codes
*/

enum {

	BZ_ILLEGAL_PID	= -1,			//!< The specified PID is not valid
	BZ_IN_USE		= -2,			//!< The resource is in use
	BZ_NOT_OWNER	= -3,			//!< The caller does not own the resource
	BZ_ILLEGAL_PORT	= -4,			//!< The port specified is not valid
	BZ_SIGNAL		= -5,			//!< The specified signal is not valid
	BZ_NOT_OPEN		= -6,			//!< The port is not open
	BZ_OUT_OF_MESG	= -7,			//!< The kernel is out of message buffers
};

#define	BZ_PID_BCAST	255			//!< Broadcast PID

/** @} */

/****************************************************************************/
/*						API functions										*/
/****************************************************************************/

void	BZ_Init( const BZ_INIT *init ) __attribute__ ((noreturn));
int		BZ_ProcSelf( void );
int		BZ_ProcSpawn( int pid, int *stack, void (*func)( void *), void *parm );
int		BZ_EventWait( int mask );
int		BZ_EventPost( int pid, int event );
int		BZ_EventRead( void );
void	BZ_EventClear( int mask );
void	BZ_LockInit( BZ_LOCK *lock );
int		BZ_LockObtain( BZ_LOCK *lock );
int		BZ_LockRelease( BZ_LOCK *lock );
int		BZ_LockAttempt( BZ_LOCK *lock );
void	BZ_SemaInit( BZ_SEMA *sema, unsigned howmuch );
void	BZ_SemaGet( BZ_SEMA *sema, unsigned howmuch );
int		BZ_SemaTry( BZ_SEMA *sema, unsigned howmuch );
void	BZ_SemaPut( BZ_SEMA *sema, unsigned howmuch );
int		BZ_PortClose( int port );
int		BZ_PortOpen( int portid, int signal );
int		BZ_PortRead( int portid, BZ_MESG *message );
int		BZ_PortSend( int port, int type, int spar, int lpar );
int		BZ_IrqDisable( int irq );
int		BZ_FiqDisable( int fiq );
int		BZ_SwapWord( int data, int *addr );
char	BZ_SwapByte( char data, char *addr );
void	BZ_TimerTick( unsigned us );
int		BZ_TimerCancel( BZ_TIME *timer );
unsigned long long 	BZ_TimerUptime( void );
int		BZ_TimerStart( BZ_TIME *timer, unsigned initial, unsigned repeat,
				   	   int pid, int event );

#endif

