#include <hal_user.h>
#include <almos-mkh.h>
#include <stdio.h>
#include <syscalls_numbers.h>


#define  reg_t     int

/////////////     Non standard system calls ////////////////////////////////////


//////////////////////////
int fg( unsigned int pid )
{
    return hal_user_syscall( SYS_FG,
                             (reg_t)pid, 0, 0, 0 );
}

//////////////////////////////////////
int get_config( unsigned int * x_size,
                unsigned int * y_size,
                unsigned int * ncores )
{
    return hal_user_syscall( SYS_GET_CONFIG,
                             (reg_t)x_size,
                             (reg_t)y_size,
                             (reg_t)ncores, 0 );
}

/////////////////////////////////
int get_core( unsigned int * cxy,
              unsigned int * lid )
{
    return hal_user_syscall( SYS_GET_CORE,
                             (reg_t)cxy,
                             (reg_t)lid, 0, 0 );
}

////////////////////////////////////
void display_string( char * string )
{
    hal_user_syscall( SYS_DISPLAY,
                      DISPLAY_STRING,
                      (reg_t)string, 0, 0 );
}

///////////////////////////////////
int display_vmm( unsigned int cxy, unsigned int pid )
{
    return hal_user_syscall( SYS_DISPLAY,
                             DISPLAY_VMM,
                             (reg_t)pid,
                             (reg_t)cxy, 0 );
} 

////////////////////////////////
int display_sched( unsigned int cxy,
                   unsigned int lid )
{
    return hal_user_syscall( SYS_DISPLAY,
                             DISPLAY_SCHED,
                             (reg_t)cxy,
                             (reg_t)lid, 0 );
} 

/////////////////////////////////////////////////
int display_cluster_processes( unsigned int cxy )
{
    return hal_user_syscall( SYS_DISPLAY,
                             DISPLAY_CLUSTER_PROCESSES,
                             (reg_t)cxy, 0, 0 );
} 

///////////////////
int display_chdev()
{
    return hal_user_syscall( SYS_DISPLAY,
                             DISPLAY_CHDEV, 0, 0, 0 );
} 

/////////////////
int display_vfs()
{
    return hal_user_syscall( SYS_DISPLAY,
                             DISPLAY_VFS, 0, 0, 0 );
} 

////////////////////////////////////////////////
int display_txt_processes( unsigned int txt_id )
{
    return hal_user_syscall( SYS_DISPLAY,
                             DISPLAY_TXT_PROCESSES,
                             (reg_t)txt_id, 0, 0 );
} 

///////////////////////////////////////////
int get_cycle( unsigned long long * cycle )
{
    return hal_user_syscall( SYS_GET_CYCLE,
                             (reg_t)cycle, 0, 0, 0 );
}

//////////////////////////////////
int trace( unsigned int active,
           unsigned int pid, 
           unsigned int lid )
{
    return hal_user_syscall( SYS_TRACE,
                             (reg_t)active,
                             (reg_t)pid,
                             (reg_t)lid, 0 );
}

/////////////////////////////////
int utls( unsigned int operation,
          unsigned int value )
{
    return hal_user_syscall( SYS_UTLS,
                             (reg_t)operation,
                             (reg_t)value, 0, 0 );
}


////////////
int getint()
{
    unsigned int  i;
    int           val;    // ASCII character value

    unsigned char buf[32];
    unsigned int  save          = 0;
    unsigned int  dec           = 0;
    unsigned int  done          = 0;
    unsigned int  overflow      = 0;
    unsigned int  length        = 0;
 
    // get characters
    while (done == 0) 
    {
        // read one character
        val = getchar();

        // analyse character
        if ((val > 0x2F) && (val < 0x3A))         // decimal character 
        {
            buf[length] = (unsigned char)val;
            length++;                      
            putchar( val );                       // echo
        }
        else if (val == 0x0A)                     // LF character 
        {
            done = 1;
        }
        else if ( (val == 0x7F) ||                // DEL character
                  (val == 0x08) )                 // BS  character 
        {
            if ( length > 0 ) 
            {
                length--;          
                printf("\b \b");                  // BS /  / BS 
            }
        }
        else if ( val == 0 )                      // EOF
        {
            return -1;
        }

        // test buffer overflow
        if ( length >= 32 )  
        {
            overflow = 1;
            done     = 1;
        }
    }  // end while characters

    // string to int conversion with overflow detection 
    if ( overflow == 0 )
    {
        for (i = 0; (i < length) && (overflow == 0) ; i++) 
        {
            dec = dec * 10 + (buf[i] - 0x30);
            if (dec < save)  overflow = 1; 
            save = dec;
        }
    } 

    // final evaluation 
    if ( overflow == 0 )
    {
        // return value
        return dec;
    }
    else
    {
        // cancel all echo characters
        for (i = 0; i < length ; i++) 
        {
            printf("\b \b");                  // BS /  / BS 
        }

        // echo character '0'
        putchar( '0' );

        // return 0 value 
        return 0;
    }
}  // end getint()

///////////
void idbg()
{
   char          cmd;
   unsigned int  cxy;
   unsigned int  lid;
   unsigned int  txt;
   unsigned int  active;

   while( 1 )
   {
        printf("\n[idbg] cmd = ");
        cmd = (char)getchar();

        if( cmd == 'h' )
        {
            printf("h\n"
                   "p : display on TXT0 process descriptors in cluster[cxy]\n"
                   "s : display on TXT0 scheduler state for core[cxy,lid]\n"
                   "v : display on TXT0 VMM for calling process in cluster [cxy]\n"
                   "t : display on TXT0 process decriptors attached to TXT[tid]\n"
                   "y : activate/desactivate trace for core[cxy,lid]\n"
                   "x : force calling process to exit\n"
                   "c : resume calling process execution\n"
                   "h : list supported commands\n");
        }
        else if( cmd == 'p' )
        {
            printf("p / cxy = ");
            cxy = getint();
            display_cluster_processes( cxy );
        }
        else if( cmd == 's' )
        {
            printf("s / cxy = ");
            cxy = getint();
            printf(" / lid = ");
            lid = getint();
            display_sched( cxy , lid );
        }
        else if( cmd == 'v' )
        {
            printf("v / cxy = ");
            cxy = getint();
            display_vmm( cxy , (unsigned int)getpid() );
        }
        else if( cmd == 't' )
        {
            printf("t / txt_id = ");
            txt = getint();
            display_txt_processes( txt );
        }
        else if( cmd == 'y' )
        {
            printf("y / active = ");
            active = getint();
            printf(" / cxy = ");
            cxy    = getint();
            printf(" / lid = ");
            lid    = getint();
            trace( active , cxy , lid );
        }
        else if( cmd == 'x' )
        {
            printf("x\n");
            exit( 0 );
        }
        else if( cmd == 'c' )
        {
            printf("c\n");
            break;
        }
    }
}  // end idbg()



