/*   SCE CONFIDENTIAL                                       */
/*   PLAYSTATION(R)3 Programmer Tool Runtime Library 084.006 */
/*   Copyright (C) 2005 Sony Computer Entertainment Inc.    */
/*   All Rights Reserved.                                   */

/** \ingroup all_syscall
 * \defgroup spu_thread_group SPU Thread Groups
 * \brief system calls defined in sys/spu_thread_group.h
 *
 * Interfaces defined in sys/spu_thread_group.h.
 *
 * Refer to <i>Cell OS Lv-2 User's Manual</i> for the detailed description.
 */


/*@{*/

#ifndef __LV2_KERNEL_SPU_SYSCALL_SPU_THREAD_GROUP_H__
#define __LV2_KERNEL_SPU_SYSCALL_SPU_THREAD_GROUP_H__

#include <sys/cdefs.h>
#include <sys/syscall.h>

#include <sys/integertypes.h>
#include <sys/return_code.h>
#include <sys/types.h>

CDECL_BEGIN


#define SYS_SPU_THREAD_GROUP_TYPE_NORMAL	 0x0
#define SYS_SPU_THREAD_GROUP_TYPE_SEQUENTIAL     0x1

#define SYS_SPU_THREAD_GROUP_JOIN_GROUP_EXIT		0x0001
#define SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT	0x0002
#define SYS_SPU_THREAD_GROUP_JOIN_TERMINATED		0x0004

#define SYS_SPU_THREAD_GROUP_EVENT_RUN           0x1
#define SYS_SPU_THREAD_GROUP_EVENT_RUN_KEY       0xFFFFFFFF53505500ULL
#define SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION     0x2
#define SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION_KEY 0xFFFFFFFF53505503ULL

/* exception causes */
#define SYS_SPU_EXCEPTION_DMA_ALIGNMENT  0x0001U
#define SYS_SPU_EXCEPTION_DMA_COMMAND    0x0002U
#define SYS_SPU_EXCEPTION_SPU_ERROR      0x0004U
#define SYS_SPU_EXCEPTION_MFC_FIR        0x0008U
#define SYS_SPU_EXCEPTION_MFC_SEGMENT    0x0010U
#define SYS_SPU_EXCEPTION_MFC_STORAGE    0x0020U
#define SYS_SPU_EXCEPTION_STOP_CALL      0x0100U
#define SYS_SPU_EXCEPTION_STOP_BREAK     0x0200U
#define SYS_SPU_EXCEPTION_HALT           0x0400U
#define SYS_SPU_EXCEPTION_UNKNOWN_SIGNAL 0x0800U
#define SYS_SPU_EXCEPTION_NO_VALUE          0x0U



/** \brief SPU thread group attribute structure
 *
 * The sys_spu_thread_group_attribute_t structure type is used to set
 * attributes to an SPU thread group by sys_spu_thread_group_create().
 *
 * \a type must be one of the following values.
 *  - SYS_SPU_THREAD_GROUP_TYPE_NORMAL \n
 *    Normal SPU thread group.
 *  - SYS_SPU_THREAD_GROUP_TYPE_SEQUENTIAL \n
 *    An SPU thread group whose execution is triggered by termination of 
 *    other SPU thread groups.
 *
 * \see sys_spu_thread_group_create
 */
struct sys_spu_thread_group_attribute {
	/** The length of \a name including the null terminator */
	__CSTD size_t nsize;
	/** A string of the name for this SPU thread group */
	const char *name;
	/** SPU thread group type */
	int type;
};
typedef struct sys_spu_thread_group_attribute sys_spu_thread_group_attribute_t;

static inline int sys_spu_thread_group_create(sys_spu_thread_group_t * id,
											  unsigned int num, int prio,
											  sys_spu_thread_group_attribute_t *
											  attr)
{
	system_call(4, SYS_SPU_THREAD_GROUP_CREATE, (uint32_t) id, num, prio,
				(uint32_t) attr);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_CREATE
	REG_PASS_SYS_SPU_THREAD_GROUP_CREATE;
#endif
	return_to_user_prog(int);
}

static inline int sys_spu_thread_group_destroy(sys_spu_thread_group_t id)
{
	system_call(1, SYS_SPU_THREAD_GROUP_DESTROY, id);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_DESTROY
	REG_PASS_SYS_SPU_THREAD_GROUP_DESTROY;
#endif
	return_to_user_prog(int);
}


static inline int sys_spu_thread_group_start(sys_spu_thread_group_t id)
{
	system_call(1, SYS_SPU_THREAD_GROUP_START, id);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_START
	REG_PASS_SYS_SPU_THREAD_GROUP_START;
#endif
	return_to_user_prog(int);
}

static inline int sys_spu_thread_group_start_on_exit(sys_spu_thread_group_t gid,
													 int ngroups,
													 sys_spu_thread_group_t *
													 groups)
{
	system_call(3, SYS_SPU_THREAD_GROUP_START_ON_EXIT, gid, ngroups,
				(uint32_t) groups);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_START_ON_EXIT
	REG_PASS_SYS_SPU_THREAD_GROUP_START_ON_EXIT;
#endif
	return_to_user_prog(int);
}


static inline int sys_spu_thread_group_terminate(sys_spu_thread_group_t id,
												 int value)
{
	system_call(2, SYS_SPU_THREAD_GROUP_TERMINATE, id, value);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_TERMINATE
	REG_PASS_SYS_SPU_THREAD_GROUP_TERMINATE;
#endif
	return_to_user_prog(int);
}


static inline int sys_spu_thread_group_suspend(sys_spu_thread_group_t id)
{
	system_call(1, SYS_SPU_THREAD_GROUP_SUSPEND, id);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_SUSPEND
	REG_PASS_SYS_SPU_THREAD_GROUP_SUSPEND;
#endif
	return_to_user_prog(int);
}

static inline int sys_spu_thread_group_resume(sys_spu_thread_group_t id)
{
	system_call(1, SYS_SPU_THREAD_GROUP_RESUME, id);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_RESUME
	REG_PASS_SYS_SPU_THREAD_GROUP_RESUME;
#endif
	return_to_user_prog(int);
}


static inline int sys_spu_thread_group_yield(sys_spu_thread_group_t id)
{
	system_call(1, SYS_SPU_THREAD_GROUP_YIELD, id);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_YIELD
	REG_PASS_SYS_SPU_THREAD_GROUP_YIELD;
#endif
	return_to_user_prog(int);
}


static inline int sys_spu_thread_group_set_priority(sys_spu_thread_group_t id,
													int priority)
{
	system_call(2, SYS_SPU_THREAD_GROUP_SET_PRIORITY, id, priority);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_SET_PRIORITY
	REG_PASS_SYS_SPU_THREAD_GROUP_SET_PRIORITY;
#endif
	return_to_user_prog(int);
}

static inline int sys_spu_thread_group_get_priority(sys_spu_thread_group_t id,
													int *priority)
{
	system_call(2, SYS_SPU_THREAD_GROUP_GET_PRIORITY, id, (uint32_t) priority);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_GET_PRIORITY
	REG_PASS_SYS_SPU_THREAD_GROUP_GET_PRIORITY;
#endif
	return_to_user_prog(int);
}


static inline int sys_spu_thread_group_join(sys_spu_thread_group_t gid,
											int *cause, int *status)
{
	system_call(3, SYS_SPU_THREAD_GROUP_JOIN, gid, (uint32_t) cause,
				(uint32_t) status);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_JOIN
	REG_PASS_SYS_SPU_THREAD_GROUP_JOIN;
#endif
	return_to_user_prog(int);
}


static inline int sys_spu_thread_group_connect_event(sys_spu_thread_group_t id,
													 sys_event_queue_t eq,
													 sys_event_type_t et)
{
	system_call(3, SYS_SPU_THREAD_GROUP_CONNECT_EVENT, id, eq, et);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_CONNECT_EVENT
	REG_PASS_SYS_SPU_THREAD_GROUP_CONNECT_EVENT;
#endif
	return_to_user_prog(int);
}

static inline int sys_spu_thread_group_disconnect_event(sys_spu_thread_group_t
														id, sys_event_type_t et)
{
	system_call(2, SYS_SPU_THREAD_GROUP_DISCONNECT_EVENT, id, et);

#ifdef REG_PASS_SYS_SPU_THREAD_GROUP_DISCONNECT_EVENT
	REG_PASS_SYS_SPU_THREAD_GROUP_DISCONNECT_EVENT;
#endif
	return_to_user_prog(int);
}




CDECL_END

#endif /* __LV2_KERNEL_SPU_SYSCALL_SPU_THREAD_GROUP_H__ */
/*@}*/
