/* Copyright (c) 1995 Simtec / Neil A Carson / WonderWorks
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are not permitted without express permission of the Authors.
 */

/* C language header file for Hydra concurrent kernel / support code
 */
#ifndef __HYDRA_H

#define __HYDRA_H

#ifndef __OS_H
    #include "kernel.h"
#endif

/******************************************************************************/

typedef int hydra_chunk;                        /* Chunk handle */
typedef int hydra_thread;                       /* Thread handle */

/* Maximum Hydra CPUs present
 */
#define hydra_Max_CPUs 4

/* For holding processor ID's
 */
typedef struct
{
    int cpu[4];
} hydra_cpu_id_block;

/* Bit--mask for selecting processors
 */
typedef enum
{
    MASK_cpu0 = (1 << 0),
    MASK_cpu1 = (1 << 1),
    MASK_cpu2 = (1 << 2),
    MASK_cpu3 = (1 << 3)
} hydra_cpu_mask;

/* CPU register snapshot
 */
typedef struct
{
    int user_regs[15];
    int pc;
    int cpsr;
} hydra_cpu_snapshot;

/* Access modes for a chunk
 */
typedef enum
{
    ACCESS_ro = 1,
    ACCESS_rw = 0
} hydra_access;

/* Chunk mapping reason
 */
typedef enum
{
    MAP_map = 0,
    MAP_unmap = 1
} hydra_map_type;

/* Information needed for allocating a chunk of memory
 */
typedef struct
{
    char name[32];                              /* NULL--terminated string */
    int init_size;                              /* Initial size (bytes) */
    int max_size;                               /* Maximum size (bytes) */
    void *base_addr;                            /* Mapped base */
    hydra_access mode;                          /* Access mode */
} hydra_chunk_parms;

/* Information needed when getting information on a chunk of memory
 */
typedef struct
{
    void *host_base;
    int size;
    void *slave_base;
    hydra_cpu_mask owned;
} hydra_chunk_data;

/* Information needed when polling a thread
 */
typedef enum
{
    THREAD_error = -1,
    THREAD_pending = 0,
    THREAD_executing = 1,
    THREAD_complete = 2
} hydra_thread_state;

/******************************************************************************/

/* Description      :  Get version of Hydra support code
 * Formal parameters:  ---
 * Return           :  Code version *100, or -1 if not present
 */
extern int hydra_version(void);

/* Description      :  Return the type words for processors
 * Formal parameters:  processor_id_block
 * Return           :  ---
 */
extern _kernel_oserror *hydra_processors(hydra_cpu_id_block *);

/* Description      :  Reset one or more slave processors
 * Formal parameters:  bit mask of processors to reset
 * Return           :  ---
 */
extern _kernel_oserror *hydra_reset(hydra_cpu_mask);

/* Description      :  Snapshot a CPU's registers
 * Formal parameters:  Processor number, a word--aligned 17--word block
 * Return           :  ---
 */
extern _kernel_oserror *hydra_snapshot_regs(int cpu_number, hydra_cpu_snapshot *regs);

/* Description      :  Allocate a chunk of memory which may be mapped into
 *                     slave address space
 * Formal parameters:  Chunk's name, Initial size, Maximum size, Base address,
 *                     Access mode (all as structure)
 * Return           :  Chunk handle, Base address (NULL if error)
 */
extern void *hydra_new_chunk(hydra_chunk_parms *info,
                             hydra_chunk *returned_handle);

/* Description      :  Free a previously allocated chunk of memory
 * Formal parameters:  Chunk handle to be freed
 * Return           :  ---
 */
extern _kernel_oserror *hydra_free_chunk(hydra_chunk);

/* Description      :  Change the size of a slave chunk
 * Formal parameters:  Chunk handle to be adjusted, amount to grow by
 * Return           :  ---
 */
extern _kernel_oserror *hydra_resize_chunk(hydra_chunk, int size_change);

/* Description      :  Map a chunk of memory into a CPU's page tables
 * Formal parameters:  Chunk, Processor number, Reason code
 * Return           :  ---
 */
extern _kernel_oserror *hydra_map_chunk(hydra_chunk, int cpu_number, hydra_map_type);

/* Description      :  Call application code on a slave
 * Formal parameters:  Processor number, address to call
 * Return           :  ---
 */
extern _kernel_oserror *hydra_call(int cpu_number, void *address);

/* Description      :  Load an executable into a new chunk
 * Formal parameters:  Filename, Dest. handle, Dest. base, Dest. size
 * Return           :  ---
 */
extern _kernel_oserror *hydra_load_chunk(char *filename, hydra_chunk *handle,
                                         int **base, int *chunk_size);

/* Description      :  Get information about a memory chunk
 * Formal parameters:  Chunk handle
 * Return           :  Structure containing data (as in SWI)
 */
extern _kernel_oserror *hydra_chunk_info(hydra_chunk handle, hydra_chunk_data *info);

/* Description      :  Add a thread to the queue for later execution
 * Formal parameters:  Code chunk handle, data chunk handle
 * Return           :  Thread handle
 */
extern _kernel_oserror *hydra_queue_task(hydra_chunk code, hydra_chunk data,
                                  hydra_thread *thread_handle);

/* Description      :  Check the state of a queued thread
 * Formal parameters:  Thread handle returned by hydra_queue_task()
 * Return           :  Thread state,
 */
extern hydra_thread_state hydra_poll_task(hydra_thread);

/* Description      :  Create a chunk for an existing dynamic area
 * Formal parameters:  Slave base address, dyamic area handle, access mode,
 *                     returned chunk handle.
 * Return           :  New chunk
 */
extern _kernel_oserror *hydra_new_alias(void *base_addr, int handle, hydra_access, hydra_chunk *h);

#endif
