// XtratuM.h
// Main include of the XtratuM
// Don't include this file from domains, use XtratuM_API.h instead!!!
// version: 0.3
//
// (c) 2004, Miguel Masmano <mimastel@doctor.upv.es>
// Released under the terms of GPL License v2

#ifndef _XtratuM_H_
#define _XtratuM_H_

#include <arch/XtratuM_events_def.h>
#include <XtratuM_linux_imported.h>
#include <XtratuM_config.h>
#include <bitmap.h>
#include <assert.h>

#ifdef XtratuM_TIMER_SUPPORT
#include <arch/XtratuM_timer_arch.h>
#include <XtratuM_timer.h>
#endif

#ifdef XtratuM_XFB_SUPPORT
#include <XtratuM_xfb.h>
#include <queue.h>
#endif

// When  an  event (an  hardware  int) arrives  to  the  bus, the  PIC
// disables it till somebody enables it again, In the case that nobody
// connects it, must  be the root domain itself who  has to enable the
// received   hardware    interrupt   in   the    PIC   device.    The
// global_pending_events lets  us to control whether  a received event
// has already been enabled or not.

extern bitmap_t global_pending_events;

// Handler prototipe, used in XtratuM_API as well
typedef void (*handler_t) (int, struct pt_regs *);

// The definition of a XtratuM domain
typedef struct xm_domain_struct {
  unsigned long *stack; // Don't change, it is hardcoded
  unsigned long *begining_stack;
  char *name;
  unsigned int priority;

  bitmap_t intercepted_events;
  bitmap_t masked_events;
  bitmap_t pending_events;
 
#if defined (XtratuM_USER_LEVEL_SUPPORT)
  unsigned long pd;  // page directory
#endif
#ifdef XtratuM_USER_LEVEL_SUPPORT
  unsigned long esp0; // stack supervisor mode
#endif

  handler_t event_handler [MAX_EVENTS];
  handler_t trap_handler [MAX_TRAPS];

#ifdef XtratuM_TIMER_SUPPORT
  // the definition of the timer is architecture dependent
  xm_timer_param_t timer [MAX_ARCH_TIMER_DEFINED];
  int xm_heap_entry;
#endif

#ifdef XtratuM_XFB_SUPPORT
  xfb_info_t xfb_info;
  unsigned char *k_videoaddress;
  queue_t keyb_queue;
  mouse_info_t mouse_info;
#endif

  ///////////////////
  // Domain flags: //
  ///////////////////
  
  // 31 .. 11 : reserved
  // 10 : indicates whether the current domain's xfb is being displayed 
  //     at this moment, if it is set, the domain can't be killed
  // 9 : points out whether the domain is using a xfb or not
  // 8 : indicates whether the current domain can receive events or not
  // 7 : indicates whether the frame buffer needs to be updated or not
  // 6 : indicates if the domain executes its handlers in user mode
  // 5 : indicates if the domain handles its own stack 0 and stack 3
  // 4 : indicates if the domain handles its own page_directory 
  // 3..0 : state (4 bits, 16 possible states)
  unsigned long flags; 
  struct xm_domain_struct *prev, *next;
} *xm_domain_t;

////////////////////// POSSIBLE STATES OF A DOMAIN

#define xm_STATE_MASK 0xF // 4 bits (3..0)
#define xm_DOMAIN_ACTIVE 0x0
#define xm_DOMAIN_SUSPENDED 0x1
#define xm_DOMAIN_FINISHED 0x2

///////////////////// PAGE DIRECTORY

#define xm_PAGE_DIRECTORY_FLAG 0x10 // 1 bit (4)

///////////////////// USER LEVEL DOMAIN

#define xm_UL_DOMAIN_FLAG 0x20 // 1 bit (5)

///////////////////// HANDLERS USER LEVEL

#define xm_HANDLERS_IN_USER_LEVEL 0x40 // 1 bit (6)

///////////////////// EVENTS ENABLED

#define xm_EVENTS_ENABLED 0x100 // 1 bit (8)

///////////////////// USING XFB
#define xm_USING_XFB_FLAG 0x200 // 1 bit (9)

///////////////////// DISPLAYING XFB
#define xm_DISPLAYING_XFB_FLAG 0x400 // 1 bit (10)

///////////////////// UPDATE XFB
#define xm_UPDATE_XFB_FLAG 0x80 // 1 bit (7)

////////////////////////////////////////////////////


#define xm_set_domain_state(d, state) \
  d -> flags = ((d -> flags & ~(xm_STATE_MASK)) | state)

#define xm_get_domain_state(d) \
  (d -> flags & xm_STATE_MASK)

#ifdef XtratuM_XFB_SUPPORT

#define xm_get_xfb_flag(d) \
  (d -> flags & xm_USING_XFB_FLAG)

#define xm_set_xfb_flag(d) \
  d -> flags |= xm_USING_XFB_FLAG

#define xm_unset_xfb_flag(d) \
  d -> flags &= ~(xm_USING_XFB_FLAG)

#define xm_get_displaying_xfb_flag(d) \
  (d -> flags & xm_DISPLAYING_XFB_FLAG)

#define xm_set_displaying_xfb_flag(d) \
  d -> flags |= xm_DISPLAYING_XFB_FLAG

#define xm_unset_displaying_xfb_flag(d) \
  d -> flags &= ~(xm_DISPLAYING_XFB_FLAG)

#define xm_get_update_xfb_flag(d) \
  (d -> flags & xm_UPDATE_XFB_FLAG)

#define xm_set_update_xfb_flag(d) \
  d -> flags |= xm_UPDATE_XFB_FLAG

#define xm_unset_update_xfb_flag(d) \
  d -> flags &= ~(xm_UPDATE_XFB_FLAG)
  
#endif

#ifdef XtratuM_USER_LEVEL_SUPPORT
#define xm_get_page_directory_flag(d) \
  (d -> flags & xm_PAGE_DIRECTORY_FLAG)

#define xm_set_page_directory_flag(d) \
  d -> flags |= xm_PAGE_DIRECTORY_FLAG

#define xm_unset_page_directory_flag(d) \
  d -> flags &= ~(xm_PAGE_DIRECTORY_FLAG)

#define xm_get_ul_domain_flag(d) \
  (d -> flags & xm_UL_DOMAIN_FLAG)

#define xm_set_ul_domain_flag(d) \
  d -> flags |= xm_UL_DOMAIN_FLAG

#define xm_unset_ul_domain_flag(d) \
  d -> flags &= ~(xm_UL_DOMAIN_FLAG)

#define xm_get_handlers_in_ul_flag(d) \
  (d -> flags & xm_HANDLERS_IN_USER_LEVEL)

#define xm_set_handlers_in_ul_flag(d) \
  d -> flags |= xm_HANDLERS_IN_USER_LEVEL

#define xm_unset_handlers_in_ul_flag(d) \
  d -> flags &= ~(xm_HANDLERS_IN_USER_LEVEL)

#endif

#define xm_is_events_flag_enabled(d) \
  (d -> flags & xm_EVENTS_ENABLED)

#define xm_enable_events_flag(d) \
  d -> flags |= xm_EVENTS_ENABLED

#define xm_disable_events_flag(d) \
  d -> flags &= ~(xm_EVENTS_ENABLED)

#ifndef xm_min_priority
#define xm_min_priority() UINT_MAX
#endif

#ifndef xm_max_priority
#define xm_max_priority() 0
#endif

#ifdef XtratuM_USER_LEVEL_SUPPORT
extern struct tss_struct *tss;
#endif

extern struct xm_domain_struct *xm_domain_list, 
  *root_domain, *current_domain;

#ifdef XtratuM_PROC_INFO
extern void *create_xm_proc (void);
extern void remove_xm_proc (void);
#endif

extern int xm_sched (void);
extern void xm_sync_events(void);


// xm_raise_event and xm_raise_event_all_domain flags
#define xm_DEFER_EVENT 0x0
#define xm_RAISE_EVENT_NOW 0x1

#define xm_create_domain(domain, name, priority, main_func) \
  __xm_create_domain(domain, name, priority, main_func, 0)

#define xm_min_priority() UINT_MAX

#define xm_max_priority() 0

extern int __xm_create_domain (xm_domain_t *domain, char *name, 
			       unsigned int priority,
			       int (*main_func) (void), 
			       unsigned long pd);

extern void xm_end_domain (struct xm_domain_struct *domain);

extern void xm_suspend_domain (void);

extern void xm_set_domain_priority (unsigned int priority);

// Handler prototipe as defined int XtratuM.h
// typedef void (*handler_t) (int, struct pt_regs *);

extern int xm_install_event_handler (int event, handler_t handler);

extern int xm_install_trap_handler (int trap, handler_t handler);

extern int xm_write_domain (char *buffer, unsigned long size);

// Flags definited in the section of macros of this file
extern int xm_raise_event_all_domains (int event, int flags);

// Flags definited in the section of macros of this file
extern int xm_raise_event (xm_domain_t domain, int event, int flags);

// When  an event  arrives to  the bus,  XtratuM disables  the bus
// automaticaly for all domains, the domain which deals with the event
// has to decide whether the bus has to be enabled again or not 

// Please, remember that if nobody enables an event, it will be disable 
// forever
extern void xm_disable_bus_event (int event);

extern void xm_enable_bus_event (int event);

extern void xm_enable_events (void);

extern void xm_disable_events (void);

extern void xm_unmask_event (int event);

extern void xm_mask_event (int event);

extern void xm_save_mask_events (bitmap_t *old_mask);

extern void xm_mask_all_events (void);

extern void xm_pass_event (int event);

extern void xm_unmask_all_events (void);

extern void xm_restore_mask_events (bitmap_t mask);

extern xm_domain_t xm_domain_self(void);

extern int xm_are_events_enabled (void);

#ifdef XtratuM_XFB_SUPPORT
extern unsigned char *xm_attach_xfb (int width, int height, int depth);
extern int xm_detach_xfb (void);
extern int xm_read_xfb_buffer (char *buffer, int size);
extern void xm_flush_xfb_buffer (void);
extern void xm_update_xfb_screen (void);
extern void xm_get_mouse_info (mouse_info_t *mouse);
#endif

#endif
