Changeset 622


Ignore:
Timestamp:
Jan 29, 2014, 9:30:38 AM (9 years ago)
Author:
alain
Message:

Introducing a minimal GIET:

  • no virtual memory
  • no conyext switch
  • no system calls
Location:
trunk/softs/giet_tsar
Files:
3 added
10 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/softs/giet_tsar/block_device.h

    r158 r622  
    3737    BLOCK_DEVICE_SIZE,
    3838    BLOCK_DEVICE_BLOCK_SIZE,
     39    BLOCK_DEVICE_BUFFER_EXT,
    3940};
    4041
  • trunk/softs/giet_tsar/stdio.c

    r158 r622  
    1 /*********************************************************************
    2     fichier stdio.c
    3     Written Alain greiner & Nicolas Pouillon
    4     Date : 19/10/2009
    5 
    6  These function implement the drivers for the SoCLib peripherals.
    7  *********************************************************************/
    8 
    9 #include <stdarg.h>
     1////////////////////////////////////////////////////////////////////////////////////////
     2// File : stdio.c
     3// Written by Alain Greiner
     4// Date : janvier 2014
     5//
     6// This file define varions functions that can be used by applications to access
     7// peripherals, for the TSAR multi-processors multi_clusters architecture.
     8// There is NO separation between application code and system code, as the
     9// application are running in kernel mode without system calls.
     10// This basic GIET does not support virtual memory, and does not support multi-tasking.
     11//
     12// The supported peripherals are:
     13// - the SoClib multi_tty
     14// - The SoCLib frame_buffer
     15// - The SoCLib block_device
     16//
     17// The following parameters must be defined in the hard_config.h file.
     18// - X_SIZE          : number of clusters in a row
     19// - Y_SIZE          : number of clusters in a column
     20// - X_WIDTH         : number of bits for X field in proc_id
     21// - Y_WIDTH         : number of bits for Y field in proc_id
     22// - NB_PROCS_MAX    : max number of processor per cluster
     23// - NB_TTY_CHANNELS : max number of TTY channels
     24//
     25// The follobing base addresses must be defined in the ldscript
     26// - seg_tty_base
     27// - seg_fbf_base
     28// - seg_ioc_base
     29////////////////////////////////////////////////////////////////////////////////////////
    1030
    1131#include "stdio.h"
    1232
    13 #include "timer.h"
    14 #include "tty.h"
    15 #include "gcd.h"
    16 #include "icu.h"
    17 #include "dma.h"
    18 #include "block_device.h"
    19 
    20 /*********************************************************************
    21   We define a generic C function to implement all system calls.
    22  *********************************************************************/
    23 inline int sys_call( int call_no,
    24         int arg_0,
    25         int arg_1,
    26         int arg_2,
    27         int arg_3 )
    28 {
    29     register int reg_no_and_output asm("v0") = call_no;
    30     register int reg_a0 asm("a0") = arg_0;
    31     register int reg_a1 asm("a1") = arg_1;
    32     register int reg_a2 asm("a2") = arg_2;
    33     register int reg_a3 asm("a3") = arg_3;
    34 
    35     asm volatile(
    36             "syscall"
    37             : "=r" (reg_no_and_output)  // arguments de sortie
    38             : "r" (reg_a0),         // arguments d'entrée
    39             "r" (reg_a1),
    40             "r" (reg_a2),
    41             "r" (reg_a3),
    42             "r" (reg_no_and_output)
    43             : "memory",             // ressources modifiees:
    44             "at",
    45             "v1",
    46             "ra",            // Ces registres persistants seront sauvegardes
    47             "t0",            // sur la pile par le compilateur
    48             "t1",            // seulement s'ils contiennent des donnees
    49             "t2",            // calculees par la fonction effectuant le syscall,
    50             "t3",            // et que ces valeurs sont reutilisees par cette
    51             "t4",            // fonction au retour du syscall.
    52             "t5",
    53             "t6",
    54             "t7",
    55             "t8",
    56             "t9"
    57                );
    58     return reg_no_and_output;
    59 }
    60 
    61 /********************************************************************
    62   procid()
    63   Returns the processor ident.
    64  ********************************************************************/
    65 int procid()
    66 {
    67     return sys_call(SYSCALL_PROCID, 0, 0, 0, 0);
    68 }
    69 /********************************************************************
    70   proctime()
    71   Returns the local processor time.
    72  ********************************************************************/
    73 int proctime()
    74 {
    75     return sys_call(SYSCALL_PROCTIME, 0, 0, 0, 0);
    76 }
    77 /********************************************************************
    78   procnumber()
    79   Returns the number of processors controled by the system.
    80  ********************************************************************/
    81 int procnumber()
    82 {
    83     return sys_call(SYSCALL_PROCNUMBER, 0, 0, 0, 0);
    84 }
    85 /********************************************************************
    86   exit()
    87   Exit the program with a TTY message, and enter an infinite loop...
    88  ********************************************************************/
    89 int exit()
    90 {
    91     int proc_index = procid();
    92     return sys_call(SYSCALL_EXIT, proc_index, 0, 0, 0);
    93 }
    94 /********************************************************************
    95   rand()
    96   Returns a pseudo-random value derived from the processor cycle count.
    97   This value is comprised between 0 & 65535.
    98  ********************************************************************/
    99 int rand()
    100 {
    101     int x = sys_call(SYSCALL_PROCTIME, 0, 0, 0, 0);
    102     if((x & 0xF) > 7)
    103         return (x*x & 0xFFFF);
     33#define NB_LOCKS      256
     34#define NB_BARRIERS   16
     35
     36#define in_drivers __attribute__((section (".drivers")))
     37#define in_unckdata __attribute__((section (".unckdata")))
     38
     39//////////////////////////////////////////////////////////////
     40// various informations that must be defined in ldscript
     41//////////////////////////////////////////////////////////////
     42
     43struct plouf;
     44
     45extern struct plouf seg_tty_base;
     46extern struct plouf seg_fbf_base;
     47extern struct plouf seg_ioc_base;
     48extern struct plouf seg_mmc_base;
     49
     50////////////////////////////////////////////////////////////////////////////////////////
     51//  Global uncachable variables for synchronization between drivers and ISRs
     52////////////////////////////////////////////////////////////////////////////////////////
     53
     54in_unckdata int volatile    _ioc_lock    = 0;
     55in_unckdata int volatile    _ioc_done    = 0;
     56in_unckdata int volatile    _ioc_status;
     57
     58in_unckdata char volatile   _tty_get_buf[NB_TTY_CHANNELS];
     59in_unckdata int volatile    _tty_get_full[NB_TTY_CHANNELS] = { [0 ... NB_TTY_CHANNELS-1] = 0 };
     60
     61////////////////////////////////////////////////////////////////////////////////////////
     62//  Global uncachable variables for inter-task barriers
     63////////////////////////////////////////////////////////////////////////////////////////
     64
     65in_unckdata int volatile    _barrier_value[NB_BARRIERS]  = { [0 ... NB_BARRIERS-1] = 0 };
     66in_unckdata int volatile    _barrier_count[NB_BARRIERS]  = { [0 ... NB_BARRIERS-1] = 0 };
     67in_unckdata int volatile    _barrier_lock[NB_BARRIERS]   = { [0 ... NB_BARRIERS-1] = 0 };
     68
     69////////////////////////////////////////////////////////////////////////////////////////
     70//  Global uncachable variables for spin_locks using LL/C instructions
     71////////////////////////////////////////////////////////////////////////////////////////
     72
     73in_unckdata int volatile    _spin_lock[NB_LOCKS] =    { [0 ... NB_LOCKS-1] = 0 };
     74
     75////////////////////////////////////////////////////////////////////////////////////////
     76// Taken from MutekH.
     77////////////////////////////////////////////////////////////////////////////////////////
     78in_drivers void* _memcpy( void*        _dst,
     79                          const void*  _src,
     80                          unsigned int size )
     81{
     82    unsigned int *dst = _dst;
     83    const unsigned int *src = _src;
     84    if ( ! ((unsigned int)dst & 3) && ! ((unsigned int)src & 3) )
     85    {
     86        while (size > 3)
     87        {
     88            *dst++ = *src++;
     89            size -= 4;
     90        }
     91    }
     92
     93    unsigned char *cdst = (unsigned char*)dst;
     94    unsigned char *csrc = (unsigned char*)src;
     95
     96    while (size--)
     97    {
     98        *cdst++ = *csrc++;
     99    }
     100    return _dst;
     101}
     102
     103////////////////////////////////////////////////////////////////////////////////////////
     104// Access CP0 and returns processor ident
     105// No more than 1024 processors...
     106////////////////////////////////////////////////////////////////////////////////////////
     107in_drivers unsigned int _procid()
     108{
     109    unsigned int ret;
     110    asm volatile( "mfc0 %0, $15, 1": "=r"(ret) );
     111    return (ret & 0x3FF);
     112}
     113////////////////////////////////////////////////////////////////////////////////////////
     114// Access CP0 and returns processor time
     115////////////////////////////////////////////////////////////////////////////////////////
     116in_drivers unsigned int _proctime()
     117{
     118    unsigned int ret;
     119    asm volatile( "mfc0 %0, $9": "=r"(ret) );
     120    return ret;
     121}
     122////////////////////////////////////////////////////////////////////////////////////////
     123// Returns the number of processsors controled by the GIET
     124////////////////////////////////////////////////////////////////////////////////////////
     125in_drivers unsigned int _procnumber()
     126{
     127    return (unsigned int)(NB_PROCS_MAX * X_SIZE * Y_SIZE);
     128}
     129////////////////////////////////////////////////////////////////////////////////////////
     130// Access CP0 and mask IRQs
     131////////////////////////////////////////////////////////////////////////////////////////
     132in_drivers void _it_mask()
     133{
     134    int tmp;
     135    asm volatile("mfc0  %0, $12"    : "=r" (tmp) );
     136    asm volatile("ori   %0, %0, 1"  : "=r" (tmp) );
     137    asm volatile("mtc0  %0, $12"    : "=r" (tmp) );
     138}
     139////////////////////////////////////////////////////////////////////////////////////////
     140// Access CP0 and enable IRQs
     141////////////////////////////////////////////////////////////////////////////////////////
     142in_drivers void _it_enable()
     143{
     144    int tmp;
     145    asm volatile("mfc0  %0, $12"    : "=r" (tmp) );
     146    asm volatile("addi  %0, %0, -1" : "=r" (tmp) );
     147    asm volatile("mtc0  %0, $12"    : "=r" (tmp) );
     148}
     149//////////////////////////////////////////////////////////////////////
     150// Invalidate all cache lines corresponding to a memory buffer.
     151// This is used by the block_device driver.
     152/////////////////////////////////////////////////////////////////////////
     153in_drivers void _dcache_buf_invalidate(const void * buffer, size_t size)
     154{
     155    size_t i;
     156    size_t dcache_line_size;
     157
     158    // retrieve dcache line size from config register (bits 12:10)
     159    asm volatile("mfc0 %0, $16, 1" : "=r" (dcache_line_size));
     160
     161    dcache_line_size = 2 << ((dcache_line_size>>10) & 0x7);
     162
     163    // iterate on lines to invalidate each one of them
     164    for ( i=0; i<size; i+=dcache_line_size )
     165        asm volatile(" cache %0, %1"
     166                :
     167                :"i" (0x11), "R" (*((char*)buffer+i)));
     168}
     169
     170///////////////////////////////////////////////////////////////////////////////////////
     171// Exit (suicide) after printing message on  a TTY terminal.
     172///////////////////////////////////////////////////////////////////////////////////////
     173in_drivers void _exit()
     174{
     175    unsigned int proc_id = _procid();
     176    unsigned int l       = proc_id % NB_PROCS_MAX;
     177    unsigned int x       = (proc_id / NB_PROCS_MAX) >> Y_WIDTH;
     178    unsigned int y       = (proc_id / NB_PROCS_MAX) & ((1<<Y_WIDTH) - 1);
     179
     180    _tty_printf("\n\n!!!  Exit  Processor (%d,%d,%d)  !!!\n", x, y, l );
     181
     182    while(1) asm volatile("nop");   // infinite loop...
     183}
     184
     185/////////////////////////////////////////////////////////////////////////
     186// convert a 32 bits unsigned int to a string of 10 decimal characters.
     187/////////////////////////////////////////////////////////////////////////
     188in_drivers void _itoa_dec(unsigned val, char* buf)
     189{
     190    const char  DecTab[] = "0123456789";
     191    unsigned int i;
     192    for( i=0 ; i<10 ; i++ )
     193    {
     194        if( (val!=0) || (i==0) ) buf[9-i] = DecTab[val % 10];
     195        else                     buf[9-i] = 0x20;
     196        val /= 10;
     197    }
     198}
     199//////////////////////////////////////////////////////////////////////////
     200// convert a 32 bits unsigned int to a string of 8 hexadecimal characters.
     201///////////////////////////////////////////////////////////////////////////
     202in_drivers void _itoa_hex(unsigned int val, char* buf)
     203{
     204    const char  HexaTab[] = "0123456789ABCD";
     205    unsigned int i;
     206    for( i=0 ; i<8 ; i++ )
     207    {
     208        buf[7-i] = HexaTab[val % 16];
     209        val /= 16;
     210    }
     211}
     212
     213
     214///////////////////////////////////////////////////////////////////////////////////////
     215// VCI MULTI_TTY
     216///////////////////////////////////////////////////////////////////////////////////////
     217//  The total number of TTY terminals is defined by NB_TTY_CHANNELS.
     218//  1. If there is only one terminal, it is supposed to be shared, and used by
     219//     all processors: a lock must be taken before display.
     220//  2. If there is several terminals, and the number of processors is smaller
     221//     than the number of terminals, there is one terminal per processor, but
     222//     the TTY index is not equal to the proc_id, due to cluster indexing policy:
     223//     - proc_id = cluster_xy * NB_PROCS_MAX + local_id (with cluster_xy = x << Y_WIDTH + y)
     224//     - tty_id  = cluster_id * NB_PROCS_MAX + local_id (with cluster_id = x * Y_SIZE + y)
     225//  3. If the computed tty_id is larger than NB_TTY_CHANNELS, an error is returned.
     226///////////////////////////////////////////////////////////////////////////////////////
     227// Write one or several characters directly from a fixed length user buffer
     228// to the TTY_WRITE register of the TTY controler.
     229// This is a non blocking call : it test the TTY_STATUS register.
     230// If the TTY_STATUS_WRITE bit is set, the transfer stops and the function
     231// returns  the number of characters that have been actually written.
     232///////////////////////////////////////////////////////////////////////////////////////
     233in_drivers int _tty_write( char*           buffer,
     234                           unsigned int    length,
     235                           unsigned int    channel )
     236{
     237    char*           tty_address;
     238    unsigned int    base                = (unsigned int)&seg_tty_base;
     239    unsigned int    nwritten    = 0;
     240    int i;
     241
     242    tty_address = (char*)(base + channel*TTY_SPAN*4);
     243
     244    for ( i=0 ; i < length ; i++ )
     245    {
     246        if((tty_address[TTY_STATUS*4] & 0x2) == 0x2)  break;
     247        else
     248        {
     249            tty_address[TTY_WRITE*4] = buffer[i]; // write character
     250            nwritten++;
     251        }
     252    }
     253
     254    return nwritten;
     255}
     256///////////////////////////////////////////////////////////////////////////////////////
     257// Fetch one character directly from the TTY_READ register of the TTY controler,
     258// and writes this character to the user buffer.
     259// This is a non blocking call : it returns 0 if the register is empty,
     260// and returns 1 if the register is full.
     261///////////////////////////////////////////////////////////////////////////////////////
     262in_drivers int _tty_read( char*          buffer,
     263                          unsigned int   channel )
     264{
     265    char*           tty_address;
     266    unsigned int    base                = (unsigned int)&seg_tty_base;
     267
     268    tty_address = (char*)(base + channel*TTY_SPAN*4);
     269
     270    if((tty_address[TTY_STATUS*4] & 0x1) == 0x1)
     271    {
     272        buffer[0] = tty_address[TTY_READ*4];
     273        return 1;
     274    }
    104275    else
    105         return (x*x*x & 0xFFFF);
    106 }
    107 
    108 /*************************************************************************
    109   MULTI-TTY
    110  **************************************************************************
    111  tty_putc()
    112  Display a single ascii character on a terminal.
    113  The terminal index is implicitely defined by the processor ID.
    114  (and by the task ID in case of multi-tasking)
    115  It doesn't use the TTY_PUT_IRQ interrupt, and the associated kernel buffer.
    116  This function returns 0 in case of success.
    117  ******************************i*******************************************/
    118 int tty_putc(char byte)
    119 {
    120     return sys_call(SYSCALL_TTY_WRITE,
    121             (int)(&byte),
    122             1,
    123             0,0);
    124 }
    125 /*************************************************************************
    126   tty_puts()
    127   Display a string on a terminal.
    128   The terminal index is implicitely defined by the processor ID.
    129   (and by the task ID in case of multi-tasking)
    130   The string must be terminated by a NUL character.
    131   It doesn't use the TTY_PUT_IRQinterrupt, and the associated kernel buffer.
    132   This function returns 0 in case of success.
    133  **************************************************************************/
    134 int tty_puts(char* string)
     276    {
     277        return 0;
     278    }
     279}
     280//////////////////////////////////////////////////////////////////////////////
     281// This function displays a string on TTY0.
     282// The string must be terminated by a NUL character.
     283//////////////////////////////////////////////////////////////////////////////
     284in_drivers void _tty_puts( char* string )
    135285{
    136286    int length = 0;
    137     while (string[length] != 0) {
    138         length++;
    139     }
    140     return sys_call(SYSCALL_TTY_WRITE,
    141             (int)string,
    142             length,
    143             0,0);
    144 }
    145 /*************************************************************************
    146   tty_putw()
    147   Display the value of a 32 bits word (decimal characters).
    148   The terminal index is implicitely defined by the processor ID.
    149   (and by pthe task ID in case of multi-tasking)
    150   It doesn't use the TTY_PUT_IRQ interrupt, and the associated kernel buffer.
    151   This function returns 0 in case of success.
    152  **************************************************************************/
    153 int tty_putw(int val)
    154 {
    155     char buf[10];
    156     int i;
    157     for( i=0 ; i<10 ; i++ ) {
    158         buf[9-i] = (val % 10) + 0x30;
    159         val = val / 10;
    160     }
    161     return sys_call(SYSCALL_TTY_WRITE,
    162             (int)buf,
    163             10,
    164             0,0);
    165 }
    166 /********************************************************************
    167   tty_getc()
    168   Fetch a single ascii character from a terminal.
    169   The terminal index is implicitely defined by the processor ID.
    170   (and by the task ID in case of multi-tasking)
    171   It doesn't use the IRQ_GET interrupt, and the associated kernel buffer.
    172   It is a blocking function that returns 0 if a valid char is stored
    173   in the buffer, and returns -1 in case of error.
    174  ********************************************************************/
    175 int tty_getc(char* buf)
    176 {
    177     int ret = 0;
    178     while( ret == 0 )
    179     {
    180         ret = sys_call(SYSCALL_TTY_READ,
    181                 (int)buf,
    182                 1,
    183                 0,0);
    184         if ((ret < 0) || (ret > 1)) return -1;  // return error
    185     }
    186     return 0;   // return ok
    187 }
    188 /********************************************************************
    189   tty_getc_irq()
    190   Fetch a single ascii character from a terminal.
    191   The terminal index is implicitely defined by the processor ID.
    192   (and by the task ID in case of multi-tasking)
    193   It uses the IRQ_GET interrupt, and the associated kernel buffer.
    194   It is a blocking function that returns 0 if a valid char is stored
    195   in the buffer, and returns -1 in case of error.
    196  ********************************************************************/
    197 int tty_getc_irq(char* buf)
    198 {
    199     int ret = 0;
    200     while( ret == 0 )
    201     {
    202         ret = sys_call(SYSCALL_TTY_READ_IRQ,
    203                 (int)buf,
    204                 1,
    205                 0,0);
    206         if ((ret < 0) || (ret > 1)) return -1;  // return error
    207     }
    208     return 0;   // return ok
    209 }
    210 /********************************************************************
    211   tty_gets_irq()
    212   Fetch a string from a terminal to a bounded length buffer.
    213   The terminal index is implicitely defined by the processor ID.
    214   (and by the task ID in case of multi-tasking)
    215   It uses the TTY_GET_IRQ interrupt, anf the associated kernel buffer.
    216   It is a blocking function that returns 0 if a valid string is stored
    217   in the buffer, and returns -1 in case of error.
    218   Up to (bufsize - 1) characters (including the non printable
    219   characters) will be copied into buffer, and the string is
    220   always completed by a NUL character.
    221   The <LF> character is interpreted, as the function close
    222   the string with a NUL character if <LF> is read.
    223   The <DEL> character is interpreted, and the corresponding
    224   character(s) are removed from the target buffer.
    225  ********************************************************************/
    226 int tty_gets_irq(char* buf, int bufsize)
    227 {
    228     int ret;
    229     unsigned char byte;
    230     unsigned int index = 0;
    231 
    232     while( index < (bufsize-1) )
    233     {
    234         ret = sys_call(SYSCALL_TTY_READ_IRQ,
    235                 (int)(&byte),
    236                 1,
    237                 0,0);
    238 
    239         if ((ret < 0) || (ret > 1)) return -1;  // return error
    240 
    241         else if ( ret == 1 )            // valid character
    242         {
    243             if ( byte == 0x0A ) break; // LF
    244             else if ((byte == 0x7F) && (index>0)) index--; // DEL
    245             else
     287    while (string[length] != 0) length++;
     288    _tty_write( string, length, 0 );
     289}
     290
     291///////////////////////////////////////////////////////////////////////////////
     292// This function displays a 32 bits unsigned int as an hexa string on TTY0.
     293///////////////////////////////////////////////////////////////////////////////
     294in_drivers void _tty_putx(unsigned int val)
     295{
     296    static const char HexaTab[] = "0123456789ABCDEF";
     297    char buf[11];
     298    unsigned int c;
     299
     300    buf[0] = '0';
     301    buf[1] = 'x';
     302    buf[10] = 0;
     303
     304    for (c = 0; c < 8; c++)
     305    {
     306        buf[9 - c] = HexaTab[val & 0xF];
     307        val = val >> 4;
     308    }
     309    _tty_puts( buf );
     310}
     311
     312///////////////////////////////////////////////////////////////////////////////
     313// This function displays a 32 bits unsigned int as a decimal string on TTY0.
     314///////////////////////////////////////////////////////////////////////////////
     315in_drivers void _tty_putd( unsigned int val )
     316{
     317    static const char DecTab[] = "0123456789";
     318    char buf[11];
     319    unsigned int i;
     320    unsigned int first;
     321
     322    buf[10] = 0;
     323
     324    for (i = 0; i < 10; i++)
     325    {
     326        if ((val != 0) || (i == 0))
     327        {
     328            buf[9 - i] = DecTab[val % 10];
     329            first = 9 - i;
     330        }
     331        else
     332        {
     333            break;
     334        }
     335        val /= 10;
     336    }
     337    _tty_puts( &buf[first] );
     338}
     339
     340//////////////////////////////////////////////////////////////////////////////
     341// This function try to take the hardwired lock protecting exclusive access
     342// to TTY terminal identified by the channel argument.
     343// It returns only when the lock has been successfully taken.
     344//////////////////////////////////////////////////////////////////////////////
     345in_drivers void _tty_get_lock( unsigned int channel )
     346{
     347    unsigned int* tty_address = (unsigned int *) &seg_tty_base;
     348    while ( tty_address[channel * TTY_SPAN + TTY_CONFIG] ) asm volatile("nop");
     349}
     350
     351//////////////////////////////////////////////////////////////////////////////
     352// This function releases the hardwired lock protecting exclusive access
     353// to TTY terminal identified by the channel argument.
     354//////////////////////////////////////////////////////////////////////////////
     355in_drivers void _tty_release_lock( unsigned int channel )
     356{
     357    unsigned int* tty_address = (unsigned int *) &seg_tty_base;
     358    tty_address[channel * TTY_SPAN + TTY_CONFIG] = 0;
     359}
     360
     361//////////////////////////////////////////////////////////////////////////////
     362// This function fetch a single ascii character from a terminal
     363// implicitely defined by the processor ID.
     364// It is a blocking function.
     365//////////////////////////////////////////////////////////////////////////////
     366in_drivers void _tty_getc( char* buf )
     367{
     368    unsigned int proc_id = _procid();
     369    unsigned int channel;
     370    unsigned int l;
     371    unsigned int x;
     372    unsigned int y;
     373
     374    // compute TTY terminal index
     375    if ( NB_TTY_CHANNELS == 1 )
     376    {
     377        channel = 0;
     378    }
     379    else
     380    {
     381        l           = (proc_id % NB_PROCS_MAX);
     382        x           = (proc_id / NB_PROCS_MAX) >> Y_WIDTH;
     383        y           = (proc_id / NB_PROCS_MAX) & ((1<<Y_WIDTH) - 1);
     384        channel = (x * Y_SIZE + y) * NB_PROCS_MAX + l;
     385        if (channel >= NB_TTY_CHANNELS )
     386        {
     387            _tty_get_lock( 0 );
     388            _tty_puts( "ERROR in _tty_getc()\n" );
     389            _tty_release_lock( 0 );
     390            _exit();
     391        }
     392    }
     393
     394    while( _tty_read( buf, channel ) == 0 ) asm volatile("nop");
     395}
     396
     397//////////////////////////////////////////////////////////////////////////////
     398//  Fetch a string of decimal characters (most significant digit first)
     399//  to build a 32 bits unsigned int.
     400//  The terminal index is implicitely defined by the processor ID.
     401//  This is a blocking function.
     402//  The decimal characters are written in a 32 characters buffer
     403//  until a <LF> or <CR> character is read.
     404//  The <DEL> character is interpreted, and previous characters can be
     405//  cancelled. All others characters are ignored.
     406//  When the <LF> or <CR> character is received, the string is converted
     407//  to an unsigned int value. If the number of decimal digit is too large
     408//  for the 32 bits range, the zero value is returned.
     409//////////////////////////////////////////////////////////////////////////////
     410in_drivers void _tty_getw( unsigned int* word_buffer )
     411{
     412    char          buf[32];
     413    char          byte;
     414    char          cancel_string[3] = { 0x08, 0x20, 0x08 };
     415    char          zero             = 0x30;
     416    unsigned int  save = 0;
     417    unsigned int  val = 0;
     418    unsigned int  done = 0;
     419    unsigned int  overflow = 0;
     420    unsigned int  max = 0;
     421    unsigned int  proc_id = _procid();
     422    unsigned int  i;
     423    unsigned int  channel;
     424    unsigned int  l;
     425    unsigned int  x;
     426    unsigned int  y;
     427
     428    // compute TTY terminal index
     429    if ( NB_TTY_CHANNELS == 1 )
     430    {
     431        channel = 0;
     432    }
     433    else
     434    {
     435        l           = (proc_id % NB_PROCS_MAX);
     436        x           = (proc_id / NB_PROCS_MAX) >> Y_WIDTH;
     437        y           = (proc_id / NB_PROCS_MAX) & ((1<<Y_WIDTH) - 1);
     438        channel = (x * Y_SIZE + y) * NB_PROCS_MAX + l;
     439        if (channel >= NB_TTY_CHANNELS )   
     440        {
     441            _tty_get_lock( 0 );
     442            _tty_puts( "ERROR in _tty_getw()\n" );
     443            _tty_release_lock( 0 );
     444            _exit();
     445        }
     446    }
     447
     448    while( done == 0 )
     449    {
     450        _tty_read( &byte, channel );
     451
     452        if (( byte > 0x2F) && (byte < 0x3A))  // decimal character
     453        {
     454            buf[max] = byte;
     455            max++;
     456            _tty_write( &byte, 1, channel );
     457        }
     458        else if ( (byte == 0x0A) || (byte == 0x0D) ) // LF or CR character
     459        {
     460            done = 1;
     461        }
     462        else if ( byte == 0x7F )        // DEL character
     463        {
     464            if (max > 0)
    246465            {
    247                 buf[index] = byte;
    248                 index++;
    249             }
    250         }
    251     } // end while
    252     buf[index] = 0;
    253     return 0;       // return ok
    254 }
    255 /********************************************************************
    256   tty_getw_irq()
    257   Fetch a string of decimal characters (most significant digit first)
    258   to build a 32 bits unsigned int.
    259   The terminal index is implicitely defined by the processor ID.
    260   (and by the task ID in case of multi-tasking)
    261   This is a blocking function that returns 0 if a valid unsigned int
    262   is stored in the buffer, and returns -1 in case of error.
    263   It uses the TTY_GET_IRQ interrupt, anf the associated kernel buffer.
    264   The non-blocking system function _tty_read_irq is called several times,
    265   and the decimal characters are written in a 32 characters buffer
    266   until a <LF> character is read.
    267   The <DEL> character is interpreted, and previous characters can be
    268   cancelled. All others characters are ignored.
    269   When the <LF> character is received, the string is converted to
    270   an unsigned int value. If the number of decimal digit is too large
    271   for the 32 bits range, the zero value is returned.
    272  ********************************************************************/
    273 int tty_getw_irq(int* word_buffer)
    274 {
    275     unsigned char buf[32];
    276     unsigned char byte;
    277     unsigned int save = 0;
    278     unsigned int val = 0;
    279     unsigned int done = 0;
    280     unsigned int overflow = 0;
    281     unsigned int max = 0;
    282     unsigned int i;
    283     int ret;
    284 
    285     while(done == 0)
    286     {
    287         ret = sys_call(SYSCALL_TTY_READ_IRQ,
    288                 (int)(&byte),
    289                 1,
    290                 0,0);
    291         if ((ret < 0) || (ret > 1)) return -1;  // return error
    292 
    293         if ( ret == 1 )     // get one character
    294         {
    295             if (( byte > 0x2F) && (byte < 0x3A))  // decimal character
    296             {
    297                 buf[max] = byte;
    298                 max++;
    299                 tty_putc(byte);
    300             }
    301             else if ( (byte == 0x0A) || (byte == 0x0D) ) // LF or CR character
    302             {
    303                 done = 1;
    304             }
    305             else if ( byte == 0x7F )        // DEL character
    306             {
    307                 if (max > 0)
    308                 {
    309                     max--;          // cancel the character
    310                     tty_putc(0x08);
    311                     tty_putc(0x20);
    312                     tty_putc(0x08);
    313                 }
    314             }
    315             if ( max == 32 )            // decimal string overflow
    316             {
    317                 for( i=0 ; i<max ; i++)     // cancel the string
    318                 {
    319                     tty_putc(0x08);
    320                     tty_putc(0x20);
    321                     tty_putc(0x08);
    322                 }
    323                 tty_putc(0x30);
    324                 *word_buffer = 0;           // return 0 value
    325                 return 0;
     466                max--;          // cancel the character
     467                _tty_write( cancel_string, 3, channel );
    326468            }
    327469        }
     
    343485        for( i=0 ; i<max ; i++)     // cancel the string
    344486        {
    345             tty_putc(0x08);
    346             tty_putc(0x20);
    347             tty_putc(0x08);
    348         }
    349         tty_putc(0x30);
     487            _tty_write( cancel_string, 3, channel );
     488        }
     489        _tty_write( &zero, 1, channel );
    350490        *word_buffer = 0;       // return 0 value
    351491    }
    352     return 0;
    353 }
    354 /*********************************************************************
    355   tty_printf()
    356   This function is a simplified version of the mutek_printf() function.
    357   The terminal index is implicitely defined by the processor ID.
    358   (and by the task ID in case of multi-tasking)
    359   It doesn't use the IRQ_PUT interrupt, anf the associated kernel buffer.
    360   Only a limited number of formats are supported:
    361   - %d : signed decimal
    362   - %u : unsigned decimal
    363   - %x : hexadecimal
    364   - %c : char
    365   - %s : string
    366  *********************************************************************/
    367 int tty_printf(char *format, ...)
     492}
     493
     494//////////////////////////////////////////////////////////////////////////////
     495//  This function is a simplified version of the mutek_printf() function.
     496//  It takes the TTY lock on the selected channel for exclusive access.
     497//  Only a limited number of formats are supported:
     498//  - %d : signed decimal
     499//  - %u : unsigned decimal
     500//  - %x : hexadecimal
     501//  - %c : char
     502//  - %s : string
     503//////////////////////////////////////////////////////////////////////////////
     504in_drivers void _tty_printf( char *format, ...)
    368505{
    369506    va_list ap;
    370     va_start(ap, format);
     507    va_start( ap, format );
     508
     509    unsigned int channel;
     510    unsigned int l;
     511    unsigned int x;
     512    unsigned int y;
     513    unsigned int proc_id = _procid();
     514
     515    // compute TTY channel
     516    if ( NB_TTY_CHANNELS == 1 )
     517    {
     518        channel = 0;
     519    }
     520    else
     521    {
     522        l           = (proc_id % NB_PROCS_MAX);
     523        x           = (proc_id / NB_PROCS_MAX) >> Y_WIDTH;
     524        y           = (proc_id / NB_PROCS_MAX) & ((1<<Y_WIDTH) - 1);
     525        channel = (x * Y_SIZE + y) * NB_PROCS_MAX + l;
     526        if (channel >= NB_TTY_CHANNELS )
     527        {
     528            _tty_get_lock( 0 );
     529            _tty_puts("ERROR in _tty_printf() for proc[" );
     530            _tty_putd( x );
     531            _tty_puts(",");
     532            _tty_putd( y );
     533            _tty_puts(",");
     534            _tty_putd( l );
     535            _tty_puts("] / TTY channel too large = ");
     536            _tty_putd( channel );
     537            _tty_puts("\n");
     538            _tty_release_lock( 0 );
     539            _exit();
     540        }
     541    }
     542
     543    // take the TTY lock
     544    _tty_get_lock( channel );
    371545
    372546printf_text:
    373547
    374     while (*format) {
     548    while (*format)
     549    {
    375550        unsigned int i;
    376551        for (i = 0; format[i] && format[i] != '%'; i++)
    377552            ;
    378         if (i) {
    379             sys_call(SYSCALL_TTY_WRITE,
    380                     (int)format,
    381                     i,
    382                     0,0);
     553        if (i)
     554        {
     555            _tty_write( format, i, channel );
    383556            format += i;
    384557        }
    385         if (*format == '%') {
     558        if (*format == '%')
     559        {
    386560            format++;
    387561            goto printf_arguments;
     
    389563    } // end while
    390564
    391     va_end(ap);
    392     return 0;
     565    va_end( ap );
     566
     567    // release lock
     568    _tty_release_lock( 0 );
     569
     570    return;
    393571
    394572printf_arguments:
    395573
    396574    {
    397         int         val = va_arg(ap, long);
    398         char            buf[20];
    399         char*           pbuf;
     575        int                 val = va_arg(ap, long);
     576        char                buf[20];
     577        char*               pbuf;
    400578        unsigned int        len = 0;
    401579        static const char   HexaTab[] = "0123456789ABCDEF";
     
    409587                break;
    410588            case ('d'):             // decimal signed integer
    411                 if (val < 0) {
     589                if (val < 0)
     590                {
    412591                    val = -val;
    413                     sys_call(SYSCALL_TTY_WRITE,
    414                             (int)"-",
    415                             1,
    416                             0,0);
     592                    _tty_write( "_" , 1, channel );
    417593                }
    418594            case ('u'):             // decimal unsigned integer
    419                 for( i=0 ; i<10 ; i++) {
     595                for( i=0 ; i<10 ; i++)
     596                {
    420597                    buf[9-i] = HexaTab[val % 10];
    421598                    if (!(val /= 10)) break;
     
    425602                break;
    426603            case ('x'):             // hexadecimal integer
    427                 sys_call(SYSCALL_TTY_WRITE,
    428                         (int)"0x",
    429                         2,
    430                         0,0);
    431                 for( i=0 ; i<8 ; i++) {
     604                _tty_write( "0x", 2, channel );
     605                for( i=0 ; i<8 ; i++)
     606                {
    432607                    buf[7-i] = HexaTab[val % 16U];
    433608                    if (!(val /= 16U)) break;
     
    447622        } // end switch
    448623
    449         sys_call(SYSCALL_TTY_WRITE,
    450                 (int)pbuf,
    451                 len,
    452                 0,0);
     624        _tty_write( pbuf, len, channel );
    453625        goto printf_text;
    454626    }
    455627} // end printf()
    456628
    457 /********************************************************************
    458   MULTI-TIMER
    459   For all system calls, the first argument is the Timer index.
    460  *********************************************************************
    461  timer_set_mode()
    462  The possible values for the TIMER_MODE register are
    463  - 0x0 : Timer not activated
    464  - 0x1 : Timer activated, but no interrupt is generated
    465  - 0x3 : Timer activarted and periodic interrupts generated
    466  ********************************************************************/
    467 int timer_set_mode(int timer_index, int val)
    468 {
    469     return sys_call(SYSCALL_TIMER_WRITE,
    470             timer_index,
    471             TIMER_MODE,
    472             val,
    473             0);
    474 }
    475 /********************************************************************
    476   timer_set_period()
    477   Defines the period value for the periodic interrupt.
    478  ********************************************************************/
    479 int timer_set_period(int timer_index, int val)
    480 {
    481     return sys_call(SYSCALL_TIMER_WRITE,
    482             timer_index,
    483             TIMER_PERIOD,
    484             val,
    485             0);
    486 }
    487 /********************************************************************
    488   timer_reset_irq()
    489  ********************************************************************/
    490 int timer_reset_irq(int timer_index)
    491 {
    492     return sys_call(SYSCALL_TIMER_WRITE,
    493             timer_index,
    494             TIMER_RESETIRQ,
    495             0, 0);
    496 }
    497 /********************************************************************
    498   timer_get_time()
    499   returns the current timer value.
    500  ********************************************************************/
    501 int timer_get_time(int timer_index, int* time)
    502 {
    503     return sys_call(SYSCALL_TIMER_READ,
    504             timer_index,
    505             TIMER_VALUE,
    506             (int)time,
    507             0);
    508 }
    509 
    510 /********************************************************************
    511   GCD COPROCESSOR
    512  *********************************************************************
    513  gcd_set_opa(int val)
    514  Set operand A in the GCD (Greater Common Divider) coprocessor.
    515  ********************************************************************/
    516 int gcd_set_opa(int val)
    517 {
    518     return sys_call(SYSCALL_GCD_WRITE,
    519             GCD_OPA,
    520             val,
    521             0, 0);
    522 }
    523 /********************************************************************
    524   gcd_set_opb(int val)
    525   Set operand B in the GCD (Greater Common Divider) coprocessor.
    526  ********************************************************************/
    527 int gcd_set_opb(int val)
    528 {
    529     return sys_call(SYSCALL_GCD_WRITE,
    530             GCD_OPB,
    531             val,
    532             0, 0);
    533 }
    534 /********************************************************************
    535   gcd_start()
    536   Start computation in the GCD (Greater Common Divider) coprocessor.
    537  ********************************************************************/
    538 int gcd_start(int val)
    539 {
    540     return sys_call(SYSCALL_GCD_WRITE,
    541             GCD_START,
    542             0, 0, 0);
    543 }
    544 /********************************************************************
    545   gcd_get_status(int* val)
    546   Get status fromn the GCD (Greater Common Divider) coprocessor.
    547   The value is nul when the coprocessor is idle (computation completed)
    548  ********************************************************************/
    549 int gcd_get_status(int* val)
    550 {
    551     return sys_call(SYSCALL_GCD_READ,
    552             GCD_STATUS,
    553             (int)val,
    554             0, 0);
    555 }
    556 /********************************************************************
    557   gcd_get_result(int* val)
    558   Get result fromn the GCD (Greater Common Divider) coprocessor.
    559  ********************************************************************/
    560 int gcd_get_result(int* val)
    561 {
    562     return sys_call(SYSCALL_GCD_READ,
    563             GCD_OPA,
    564             (int)val,
    565             0, 0);
    566 }
    567 
    568 /********************************************************************
    569   ICU(s)
    570  *********************************************************************
    571  icu_set_mask()
    572  Set some bits in the Interrupt Enable Mask of the ICU component.
    573  Each bit set in the written word will be set in the Mask Enable.
    574  ********************************************************************/
    575 int icu_set_mask(int val)
    576 {
    577     return sys_call(SYSCALL_ICU_WRITE,
    578             ICU_MASK_SET,
    579             val,
    580             0, 0);
    581 }
    582 /********************************************************************
    583   icu_clear_mask()
    584   Reset some bits in the Interrupt Enable Mask of the ICU component.
    585   Each bit set in the written word will be reset in the Mask Enable.
    586  ********************************************************************/
    587 int icu_clear_mask(int val)
    588 {
    589     return sys_call(SYSCALL_ICU_WRITE,
    590             ICU_MASK_CLEAR,
    591             val,
    592             0, 0);
    593 }
    594 /********************************************************************
    595   icu_get_mask()
    596   Read the Interrupt Enable Mask of the ICU component.
    597  ********************************************************************/
    598 int icu_get_mask(int* buffer)
    599 {
    600     return sys_call(SYSCALL_ICU_READ,
    601             ICU_MASK,
    602             (int)buffer,
    603             0, 0);
    604 }
    605 /********************************************************************
    606   icu_get_irqs()
    607   Read the value of the 32 interrupt lines (IRQ inputs).
    608  ********************************************************************/
    609 int icu_get_irqs(int* buffer)
    610 {
    611     return sys_call(SYSCALL_ICU_READ,
    612             ICU_INT,
    613             (int)buffer,
    614             0, 0);
    615 }
    616 /********************************************************************
    617   icu_get_index()
    618   Read the index of the highest priority active interrupt.
    619   (If no active interrupt, -1 is returned).
    620  ********************************************************************/
    621 int icu_get_index(int* buffer)
    622 {
    623     return sys_call(SYSCALL_ICU_READ,
    624             ICU_IT_VECTOR,
    625             (int)buffer,
    626             0, 0);
    627 }
    628 
    629 /********************************************************************
    630   LOCKS
    631  *********************************************************************
    632  lock_acquire()
    633  This system call performs a spin-lock acquisition.
    634  It is dedicated to the SoCLib LOCKS peripheral.
    635  In case of busy waiting, there is a random delay
    636  of about 100 cycles between two successive lock read,
    637  to avoid bus saturation.
    638  ********************************************************************/
    639 int lock_acquire(int lock_index)
    640 {
    641     return sys_call(SYSCALL_LOCKS_READ,
    642             lock_index,
    643             0, 0, 0);
    644 }
    645 
    646 /********************************************************************
    647   lock_release()
    648   You must use this system call to release a spin-lock,
    649   as the LOCKS peripheral is in the kernel segment.
    650  ********************************************************************/
    651 int lock_release(int lock_index)
    652 {
    653     return sys_call(SYSCALL_LOCKS_WRITE,
    654             lock_index,
    655             0, 0, 0);
    656 }
    657 
    658 /********************************************************************
    659   I/O BLOCK DEVICE
    660  *********************************************************************
    661  ioc_write()
    662  Transfer data from a memory buffer to a file on the block_device.
    663  - lba        : Logical Block Address (first block index)
    664  - buffer     : base address of the memory buffer
    665  - count      : number of blocks to be transfered
    666  This function returns 0 if the transfert can be done.
    667  It returns -1 if the buffer is not in user address space.
    668  ********************************************************************/
    669 int ioc_write(size_t lba, void* buffer, size_t count)
    670 {
    671     return sys_call(SYSCALL_IOC_WRITE,
    672             lba,
    673             (int)buffer,
    674             count,
    675             0);
    676 }
    677 /********************************************************************
    678   ioc_read()
    679   Transfer data from a file on the block_device to a memory buffer.
    680   - lba        : Logical Block Address (first block index)
    681   - buffer     : base address of the memory buffer
    682   - count      : number of blocks to be transfered
    683   This function returns 0 if the transfert can be done.
    684   It returns -1 if the buffer is not in user address space.
    685  ********************************************************************/
    686 int ioc_read(size_t lba, void* buffer, size_t count)
    687 {
    688     return sys_call(SYSCALL_IOC_READ,
    689             lba,
    690             (int)buffer,
    691             count,
    692             0);
    693 }
    694 /********************************************************************
    695   ioc_completed()
    696   This blocking function returns 0 when the I/O transfer is
    697   successfully completed, and returns -1 if an address error
    698   has been detected.
    699  ********************************************************************/
    700 int ioc_completed()
    701 {
    702     return sys_call(SYSCALL_IOC_COMPLETED,
    703             0, 0, 0, 0);
    704 }
    705 
    706 /********************************************************************
    707   FRAME BUFFER
    708  *********************************************************************
    709  fb_sync_write()
    710  This blocking function use a memory copy strategy to transfer data
    711  from a user buffer to the frame buffer device in kernel space,
    712  - offset     : offset (in bytes) in the frame buffer
    713  - buffer     : base address of the memory buffer
    714  - length     : number of bytes to be transfered
    715  It returns 0 when the transfer is completed.
    716  ********************************************************************/
    717 int fb_sync_write(size_t offset, void* buffer, size_t length)
    718 {
    719     return sys_call(SYSCALL_FB_SYNC_WRITE,
    720             offset,
    721             (int)buffer,
    722             length,
    723             0);
    724 }
    725 /********************************************************************
    726   fb_sync_read()
    727   This blocking function use a memory copy strategy to transfer data
    728   from the frame buffer device in kernel space to an user buffer.
    729   - offset     : offset (in bytes) in the frame buffer
    730   - buffer     : base address of the user buffer
    731   - length     : number of bytes to be transfered
    732   It returns 0 when the transfer is completed.
    733  ********************************************************************/
    734 int fb_sync_read(size_t offset, void* buffer, size_t length)
    735 {
    736     return sys_call(SYSCALL_FB_SYNC_READ,
    737             offset,
    738             (int)buffer,
    739             length,
    740             0);
    741 }
    742 /********************************************************************
    743   fb_write()
    744   This non-blocking function use the DMA coprocessor to transfer data
    745   from a user buffer to the frame buffer device in kernel space,
    746   - offset     : offset (in bytes) in the frame buffer
    747   - buffer     : base address of the user buffer
    748   - length     : number of bytes to be transfered
    749   It returns 0 when the transfer can be started.
    750   It returns -1 if the buffer is not in user address space.
    751   The transfer completion is signaled by an IRQ, and must be
    752   tested by the fb_completed() function.
    753  ********************************************************************/
    754 int fb_write(size_t offset, void* buffer, size_t length)
    755 {
    756     return sys_call(SYSCALL_FB_WRITE,
    757             offset,
    758             (int)buffer,
    759             length,
    760             0);
    761 }
    762 /********************************************************************
    763   fb_read()
    764   This non-blocking function use the DMA coprocessor to transfer data
    765   from the frame buffer device in kernel space to an user buffer.
    766   - offset     : offset (in bytes) in the frame buffer
    767   - buffer     : base address of the memory buffer
    768   - length     : number of bytes to be transfered
    769   It returns 0 when the transfer can be started.
    770   It returns -1 if the buffer is not in user address space.
    771   The transfer completion is signaled by an IRQ, and must be
    772   tested by the fb_completed() function.
    773  ********************************************************************/
    774 int fb_read(size_t offset, void* buffer, size_t length)
    775 {
    776     return sys_call(SYSCALL_FB_READ,
    777             offset,
    778             (int)buffer,
    779             length,
    780             0);
    781 }
    782 /********************************************************************
    783   fb_completed()
    784   This blocking function returns when the transfer is completed.
    785   It returns 0 if the transfer is successful.
    786   It returns -1 if an address error has been detected.
    787  ********************************************************************/
    788 int fb_completed()
    789 {
    790     return sys_call(SYSCALL_FB_COMPLETED,
    791             0, 0, 0, 0);
    792 }
    793 
    794 /********************************************************************
    795   SYNCHRONISATION BARRIERS
    796  *********************************************************************
    797   barrier_init()
    798   This function initializes the counter for barrier[index].
    799   - index     : index of the barrier (between 0 & 7)
    800   - count     : number of tasks to be synchronized.
    801   The GIET supports up to 8 independant barriers.
    802   It returns a non zero value when the barrier index is larger than 7.
    803 * ********************************************************************/
    804 int barrier_init(size_t index, size_t count)
    805 {
    806     return sys_call(SYSCALL_BARRIER_INIT,
    807             (int)index,
    808             (int)count,
    809             0, 0);
    810 }
    811 /********************************************************************
    812   barrier_wait()
    813   This blocking function use a busy waiting policy, and returns only
    814   when all synchonized asks have reached the barrier.
    815   - index     : index of the barrier (between 0 & 7)
    816   The GIET supports up to 8 independant barriers.
    817   It returns a non zero value when the barrier index is larger than 7.
    818  ********************************************************************/
    819 int barrier_wait(size_t index)
    820 {
    821     return sys_call(SYSCALL_BARRIER_WAIT,
    822             (int)index,
    823             0, 0, 0);
    824 }
     629//////////////////////////////////////////////////////////////////////////////////////
     630//  These functions are the ISRs that must be executed when an IRQ is activated
     631//  by the TTY: _tty_isr_X is associated to channel [X].
     632//  It save the character in the communication buffer _tty_get_buf[X],
     633//  and set the set/reset variable _tty_get_full[X].
     634//  A character is lost if the buffer is full when the ISR is executed.
     635//////////////////////////////////////////////////////////////////////////////////////
     636in_drivers void _tty_isr_indexed(size_t index)
     637{
     638    char*   base = (char*)&seg_tty_base;
     639    char*   tty_address = (char*)(base + index*TTY_SPAN*4);
     640
     641    _tty_get_buf[index]  = tty_address[TTY_READ*4];     // save character and reset IRQ
     642    _tty_get_full[index] = 1;                       // signals character available
     643}
     644
     645in_drivers void _tty_isr_00() { _tty_isr_indexed(0); }
     646in_drivers void _tty_isr_01() { _tty_isr_indexed(1); }
     647in_drivers void _tty_isr_02() { _tty_isr_indexed(2); }
     648in_drivers void _tty_isr_03() { _tty_isr_indexed(3); }
     649in_drivers void _tty_isr_04() { _tty_isr_indexed(4); }
     650in_drivers void _tty_isr_05() { _tty_isr_indexed(5); }
     651in_drivers void _tty_isr_06() { _tty_isr_indexed(6); }
     652in_drivers void _tty_isr_07() { _tty_isr_indexed(7); }
     653in_drivers void _tty_isr_08() { _tty_isr_indexed(8); }
     654in_drivers void _tty_isr_09() { _tty_isr_indexed(9); }
     655in_drivers void _tty_isr_10() { _tty_isr_indexed(10); }
     656in_drivers void _tty_isr_11() { _tty_isr_indexed(11); }
     657in_drivers void _tty_isr_12() { _tty_isr_indexed(12); }
     658in_drivers void _tty_isr_13() { _tty_isr_indexed(13); }
     659in_drivers void _tty_isr_14() { _tty_isr_indexed(14); }
     660in_drivers void _tty_isr_15() { _tty_isr_indexed(15); }
     661in_drivers void _tty_isr_16() { _tty_isr_indexed(16); }
     662in_drivers void _tty_isr_17() { _tty_isr_indexed(17); }
     663in_drivers void _tty_isr_18() { _tty_isr_indexed(18); }
     664in_drivers void _tty_isr_19() { _tty_isr_indexed(19); }
     665in_drivers void _tty_isr_20() { _tty_isr_indexed(20); }
     666in_drivers void _tty_isr_21() { _tty_isr_indexed(21); }
     667in_drivers void _tty_isr_22() { _tty_isr_indexed(22); }
     668in_drivers void _tty_isr_23() { _tty_isr_indexed(23); }
     669in_drivers void _tty_isr_24() { _tty_isr_indexed(24); }
     670in_drivers void _tty_isr_25() { _tty_isr_indexed(25); }
     671in_drivers void _tty_isr_26() { _tty_isr_indexed(26); }
     672in_drivers void _tty_isr_27() { _tty_isr_indexed(27); }
     673in_drivers void _tty_isr_28() { _tty_isr_indexed(28); }
     674in_drivers void _tty_isr_29() { _tty_isr_indexed(29); }
     675in_drivers void _tty_isr_30() { _tty_isr_indexed(30); }
     676in_drivers void _tty_isr_31() { _tty_isr_indexed(31); }
     677
     678
     679//////////////////////////////////////////////////////////////////////////////////////////
     680//  I/O BLOCK_DEVICE
     681// The three functions below use the three variables _ioc_lock _ioc_done,
     682// and _ioc_status for synchronisation.
     683// - As the IOC component can be used by several programs running in parallel,
     684// the _ioc_lock variable guaranties exclusive access to the device.
     685// The _ioc_read() and _ioc_write() functions use atomic LL/SC to get the lock.
     686// and set _ioc_lock to a non zero value.
     687// The _ioc_write() and _ioc_read() functions are blocking, polling the _ioc_lock
     688// variable until the device is available.
     689// - When the tranfer is completed, the ISR routine activated by the IOC IRQ
     690// set the _ioc_done variable to a non-zero value. Possible address errors detected
     691// by the IOC peripheral are reported by the ISR in the _ioc_status variable.
     692// The _ioc_completed() function is polling the _ioc_done variable, waiting for
     693// tranfer conpletion. When the completion is signaled, the _ioc_completed() function
     694// reset the _ioc_done variable to zero, and releases the _ioc_lock variable.
     695///////////////////////////////////////////////////////////////////////////////////////
     696// This blocking function is used by the _ioc_read() and _ioc_write() functions
     697// to get _ioc_lock using LL/SC.
     698///////////////////////////////////////////////////////////////////////////////////////
     699in_drivers void _ioc_get_lock()
     700{
     701    register unsigned int*      plock = (unsigned int*)&_ioc_lock;                     
     702
     703    asm volatile ("_ioc_llsc:                       \n"
     704                  "ll   $2,    0(%0)                \n" // $2 <= _ioc_lock
     705                  "bnez $2,    _ioc_llsc            \n" // retry  if busy
     706                  "li   $3,    1                    \n" // prepare argument for sc 
     707                  "sc   $3,    0(%0)                \n" // try to set _ioc_busy
     708                  "beqz $3,    _ioc_llsc            \n" // retry if not atomic
     709                  ::"r"(plock):"$2","$3");
     710}
     711//////////////////////////////////////////////////////////////////////////////////////
     712// Transfer data from a memory buffer to the block_device.
     713// - lba    : first block index on the disk
     714// - buffer : base address of the memory buffer
     715// - count  : number of blocks to be transfered
     716// The source buffer must be in user address space.
     717///////////////////////////////////////////////////////////////////////////////////////
     718in_drivers void _ioc_write( size_t   lba,
     719                            void*    buffer,
     720                            size_t   count,
     721                            size_t   ext )
     722{
     723    volatile unsigned int*      ioc_address = (unsigned int*)&seg_ioc_base;
     724
     725    // get the lock
     726    _ioc_get_lock();
     727
     728    // block_device configuration
     729    ioc_address[BLOCK_DEVICE_BUFFER]     = (unsigned int)buffer;
     730    ioc_address[BLOCK_DEVICE_BUFFER_EXT] = ext;
     731    ioc_address[BLOCK_DEVICE_COUNT]      = count;
     732    ioc_address[BLOCK_DEVICE_LBA]        = lba;
     733    ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;
     734    ioc_address[BLOCK_DEVICE_OP]         = BLOCK_DEVICE_WRITE;
     735}
     736///////////////////////////////////////////////////////////////////////////////////////
     737// Transfer data from a file on the block device to a memory buffer.
     738// - lba    : first block index on the disk
     739// - buffer : base address of the memory buffer
     740// - count  : number of blocks to be transfered
     741// The destination buffer must be in user address space.
     742// All cache lines corresponding to the the target buffer must be invalidated
     743// for cache coherence.
     744///////////////////////////////////////////////////////////////////////////////////////
     745in_drivers void _ioc_read( size_t   lba,
     746                           void*    buffer,
     747                           size_t   count,
     748                           size_t   ext )
     749{
     750    volatile unsigned int*      ioc_address = (unsigned int*)&seg_ioc_base;
     751
     752    // get the lock
     753    _ioc_get_lock();
     754
     755    // block_device configuration
     756    ioc_address[BLOCK_DEVICE_BUFFER]     = (unsigned int)buffer;
     757    ioc_address[BLOCK_DEVICE_BUFFER_EXT] = ext;
     758    ioc_address[BLOCK_DEVICE_COUNT]      = count;
     759    ioc_address[BLOCK_DEVICE_LBA]        = lba;
     760    ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;
     761    ioc_address[BLOCK_DEVICE_OP]         = BLOCK_DEVICE_READ;
     762}
     763///////////////////////////////////////////////////////////////////////////////////////
     764// This blocking function cheks completion of an I/O transfer and reports errors.
     765// It returns 0 if the transfer is successfully completed.
     766// It returns -1 if an error has been reported.
     767///////////////////////////////////////////////////////////////////////////////////////
     768in_drivers void _ioc_completed()
     769{
     770    // waiting for completion
     771    while (_ioc_done == 0)  asm volatile("nop");
     772   
     773    // reset synchronisation variables
     774    _ioc_done = 0;
     775    _ioc_lock = 0;
     776
     777    if( (_ioc_status != BLOCK_DEVICE_READ_SUCCESS) &&
     778        (_ioc_status != BLOCK_DEVICE_WRITE_SUCCESS) )
     779    {
     780        _tty_get_lock( 0 );
     781        _tty_puts( "ERROR in _ioc_completed()\n");
     782        _tty_release_lock( 0 );
     783        _exit();
     784    }
     785}
     786//////////////////////////////////////////////////////////////////////////////////////
     787//  This ISR must be executed when an IRQ is activated by IOC to signal completion.
     788//  It acknowledge the IRQ using the ioc base address, save the status in _ioc_status,
     789//  and set the _ioc_done variable to signal completion.
     790//  This variable is defined in the drivers.c file.
     791//////////////////////////////////////////////////////////////////////////////////////
     792in_drivers void _ioc_isr()
     793{
     794    int* ioc_address = (int*)&seg_ioc_base;
     795   
     796    _ioc_status = ioc_address[BLOCK_DEVICE_STATUS];     // save status & reset IRQ
     797    _ioc_done   = 1;                                                // signals completion
     798}
     799
     800//////////////////////////////////////////////////////////////////////////////////////
     801//  This ISR must be executed when an IRQ is activated by MEMC to signal
     802//  an error detected by the TSAR memory cache after a write transaction.
     803//  It displays an error message on the TTY terminal allocated to the processor
     804//  executing the ISR.
     805//////////////////////////////////////////////////////////////////////////////////////
     806in_drivers void _mmc_isr()
     807{
     808    int*         mmc_address = (int*)&seg_mmc_base;
     809    unsigned int cluster_xy  = _procid() / NB_PROCS_MAX;
     810   
     811    _tty_printf( "WRITE ERROR signaled by Memory Cache in cluster %x\n", cluster_xy );
     812}
     813
     814//////////////////////////////////////////////////////////////////////////////////////
     815//  FRAME_BUFFER
     816// The _fb_sync_write & _fb_sync_read functions use a memcpy strategy to implement
     817// the transfer between a data buffer and the frame buffer.
     818// They are blocking until completion of the transfer.
     819//////////////////////////////////////////////////////////////////////////////////////
     820//  _fb_sync_write()
     821// Transfer data from an user buffer to the frame_buffer device with a memcpy.
     822// - offset     : offset (in bytes) in the frame buffer
     823// - buffer : base address of the memory buffer
     824// - length : number of bytes to be transfered
     825//////////////////////////////////////////////////////////////////////////////////////
     826in_drivers void _fb_sync_write( size_t  offset,
     827                                void*   buffer,
     828                                size_t  length,
     829                                size_t  ext )
     830{
     831    volatile char*  fb = (char*)(void*)&seg_fbf_base + offset;
     832    char*       ub = buffer;
     833
     834    _memcpy( (void*)fb, (void*)ub, length );
     835}
     836///////////////////////////////////////////////////////////////////////////////////////
     837//  _fb_sync_read()
     838// Transfer data from the frame_buffer device to an user buffer with a memcpy.
     839// - offset     : offset (in bytes) in the frame buffer
     840// - buffer : base address of the memory buffer
     841// - length : number of bytes to be transfered
     842//////////////////////////////////////////////////////////////////////////////////////
     843in_drivers void  _fb_sync_read( size_t  offset,
     844                                void*   buffer,
     845                                size_t  length,
     846                                size_t  ext )
     847{
     848    volatile char*  fb = (char*)(void*)&seg_fbf_base + offset;
     849    char*       ub = buffer;
     850
     851    _memcpy( (void*)ub, (void*)fb, length );
     852}
     853
     854///////////////////////////////////////////////////////////////////////////////////////
     855// Release a software spin-lock
     856///////////////////////////////////////////////////////////////////////////////////////
     857in_drivers void _release_lock(size_t index)
     858
     859{
     860    if( index >= NB_LOCKS )
     861    {
     862        _tty_get_lock( 0 );
     863        _tty_puts( "ERROR in _release_lock()" );
     864        _tty_release_lock( 0 );
     865        _exit();
     866    }
     867   
     868    _spin_lock[index] = 0;
     869}
     870///////////////////////////////////////////////////////////////////////////////////////
     871// Try to take a software spin-lock.
     872// This is a blocking call, as there is a busy-waiting loop,
     873// until the lock is granted to the requester.
     874// There is an internal delay of about 100 cycles between
     875// two successive lock read, to avoid bus saturation.
     876///////////////////////////////////////////////////////////////////////////////////////
     877in_drivers void _get_lock(size_t index)
     878{
     879    if( index >= NB_LOCKS )
     880    {
     881        _tty_get_lock( 0 );
     882        _tty_puts( "ERROR in _get_lock()" );
     883        _tty_release_lock( 0 );
     884        _exit();
     885    }
     886
     887    register int   delay = ((_proctime() +_procid()) & 0xF) << 4;
     888    register int * plock = (int *) &_spin_lock[index];                 
     889
     890    asm volatile ("_locks_llsc:                 \n"
     891                  "ll   $2,    0(%0)            \n"     // $2 <= _locks_lock
     892                  "bnez $2,    _locks_delay     \n"     // random delay if busy
     893                  "li   $3,    1            \n"     // prepare argument for sc 
     894                  "sc   $3,    0(%0)            \n"     // try to set _locks_busy
     895                  "bnez $3,    _locks_ok    \n"     // exit if atomic
     896                  "_locks_delay:            \n"
     897                  "move $4,    %1           \n"     // $4 <= delay
     898                  "_locks_loop:             \n"
     899                  "addi $4,    $4,    -1    \n"     // $4 <= $4 - 1
     900                  "beqz $4,    _locks_loop  \n"     // test end delay
     901                  "j           _locks_llsc  \n"     // retry
     902                  "_locks_ok:                   \n"
     903                  ::"r"(plock),"r"(delay):"$2","$3","$4");
     904}
     905
     906
     907//////////////////////////////////////////////////////////////////////////////////////
     908// This function makes a cooperative initialisation of the barrier:
     909// - barrier_count[index] <= N
     910// - barrier_lock[index]  <= 0
     911// All tasks try to initialize the barrier, but the initialisation
     912// is done by only one task, using LL/SC instructions.
     913// This cooperative initialisation is questionnable,
     914// because the barrier can ony be initialised once...
     915//////////////////////////////////////////////////////////////////////////////////////
     916in_drivers void _barrier_init(unsigned int index, unsigned int value)
     917{
     918
     919    register int* pinit         = (int*)&_barrier_value[index];
     920    register int* pcount        = (int*)&_barrier_count[index];
     921    register int* plock         = (int*)&_barrier_lock[index];
     922
     923    if ( index >= NB_BARRIERS )
     924    {
     925        _tty_get_lock( 0 );
     926        _tty_puts( "ERROR in _barrier_init()" );
     927        _tty_release_lock( 0 );
     928        _exit();
     929    }
     930
     931    // parallel initialisation using atomic instructions LL/SC
     932    asm volatile ("_barrier_init_test:                  \n"
     933                  "ll   $2,     0(%0)                   \n"     // read barrier_value
     934                  "bnez $2,     _barrier_init_done      \n"
     935                  "move $3,     %3                              \n"
     936                  "sc   $3,     0(%0)                   \n"     // try to write barrier_value
     937                  "beqz $3,     _barrier_init_test      \n"
     938                  "move $3,     %3                                  \n"
     939                  "sw   $3,     0(%1)                           \n"     // barrier_count <= barrier_value
     940                  "move $3, $0                      \n" //
     941                  "sw   $3,     0(%2)                           \n"     // barrier_lock <= 0
     942                  "_barrier_init_done:                  \n"
     943                  ::"r"(pinit),"r"(pcount),"r"(plock),"r"(value):"$2","$3");
     944}
     945//////////////////////////////////////////////////////////////////////////////////////
     946// This blocking function uses a busy_wait technics (on the barrier_lock value),
     947// because the GIET does not support dynamic scheduling/descheduling of tasks.
     948// The barrier state is actually defined by two variables:
     949// _barrier_count[index] define the number of particpants that are waiting
     950// _barrier_lock[index] define the bool variable whose value is polled
     951// The last participant change the value of _barrier_lock[index] to release the barrier...
     952// There is at most 16 independant barriers, and an error is returned
     953// if the barrier index is larger than 15.
     954//////////////////////////////////////////////////////////////////////////////////////
     955in_drivers void _barrier_wait(unsigned int index)
     956{
     957    register int*       pcount          = (int*)&_barrier_count[index];         
     958    register int        count;
     959
     960    int                lock             = _barrier_lock[index];         
     961
     962    if ( index >= NB_BARRIERS )
     963    {
     964        _tty_get_lock( 0 );
     965        _tty_puts( "ERROR in _barrier_wait()" );
     966        _tty_release_lock( 0 );
     967        _exit();
     968    }
     969   
     970    // parallel decrement _barrier_count[index] using atomic instructions LL/SC
     971    // input : pointer on _barrier_count[index]
     972    // output : count = _barrier_count[index] (before decrementation)
     973    asm volatile ("_barrier_decrement:                          \n"
     974                  "ll   %0,     0(%1)                           \n"
     975                  "addi $3,     %0,     -1                      \n"
     976                  "sc   $3,     0(%1)                           \n"
     977                  "beqz $3,     _barrier_decrement              \n"
     978                  :"=&r"(count)
     979                  :"r"(pcount)
     980                  :"$2","$3");
     981
     982    // the last task re-initializes the barrier_ count variable
     983    // and the barrier_lock variable, waking up all other waiting tasks
     984
     985    if ( count == 1 )    // last task
     986    {
     987        _barrier_count[index] = _barrier_value[index];
     988        asm volatile( "sync" );
     989        _barrier_lock[index]   = (lock == 0) ? 1 : 0;
     990    }
     991    else                // other tasks
     992    {
     993        while ( lock == _barrier_lock[index] )  asm volatile("nop");
     994    }
     995}
     996
     997
    825998// Local Variables:
    826999// tab-width: 4;
  • trunk/softs/giet_tsar/stdio.h

    r158 r622  
    1 /*********************************************************************************
    2     fichier stdio.h
    3     Written Alain greiner & Nicolas Pouillon
    4     Date : 15/09/2009
    5  *********************************************************************************/
     1////////////////////////////////////////////////////////////////////////////////////////
     2// File : stdio.h
     3// Written by Alain Greiner
     4// Date : 17/01/2014
     5//
     6// This file define varions functions that can be used by applications to access
     7// peripherals, or other ressources such as processor registers, spin_locks
     8// or synchronisation barriers.
     9// It is dedicated for the TSAR multi-processors multi_clusters architecture.
     10// There is NO separation between application code and system code.
     11// This basic GIET does not use the virtual memory, and does nort support multi-tasking.
     12//
     13//The supported peripherals are:
     14//- the SoClib multi_tty
     15//- The SoCLib frame_buffer
     16//- The SoCLib block_device
     17//
     18//The following parameters must be defined in the hard_config.h file.
     19//- X_SIZE          : number of clusters in a row
     20//- Y_SIZE          : number of clusters in a column
     21//- X_WIDTH         : number of bits for X field in proc_id
     22//- Y_WIDTH         : number of bits for Y field in proc_id
     23//- NB_PROCS_MAX    : max number of processor per cluster
     24//- NB_TTY_CHANNELS : max number of TTY channels
     25//
     26//The follobing base addresses must be defined in the ldscript
     27//- seg_tty_base
     28//- seg_fbf_base
     29//- seg_ioc_base
     30////////////////////////////////////////////////////////////////////////////////////////
    631
    7 #ifndef _STDIO_H_
    8 #define _STDIO_H_
     32#ifndef _GIET_STDIO_H_
     33#define _GIET_STDIO_H_
    934
    10 #define SYSCALL_PROCID          0x00
    11 #define SYSCALL_PROCTIME        0x01
    12 #define SYSCALL_TTY_WRITE       0x02
    13 #define SYSCALL_TTY_READ        0x03
    14 #define SYSCALL_TIMER_WRITE     0x04
    15 #define SYSCALL_TIMER_READ      0x05
    16 #define SYSCALL_GCD_WRITE       0x06
    17 #define SYSCALL_GCD_READ        0x07
    18 #define SYSCALL_ICU_WRITE       0x08
    19 #define SYSCALL_ICU_READ        0x09
    20 #define SYSCALL_TTY_READ_IRQ    0x0A
    21 #define SYSCALL_TTY_WRITE_IRQ   0x0B
    22 #define SYSCALL_LOCKS_WRITE     0x0C
    23 #define SYSCALL_LOCKS_READ      0x0D
    24 #define SYSCALL_EXIT            0x0E
    25 #define SYSCALL_PROCNUMBER      0x0F
     35#include "tty.h"
     36#include "block_device.h"
     37#include "hard_config.h"
     38#include <stdarg.h>
    2639
    27 #define SYSCALL_FB_SYNC_WRITE   0x10
    28 #define SYSCALL_FB_SYNC_READ    0x11
    29 #define SYSCALL_FB_WRITE        0x12
    30 #define SYSCALL_FB_READ         0x13
    31 #define SYSCALL_FB_COMPLETED    0x14
    32 #define SYSCALL_IOC_WRITE       0x15
    33 #define SYSCALL_IOC_READ        0x16
    34 #define SYSCALL_IOC_COMPLETED   0x17
    35 #define SYSCALL_BARRIER_INIT    0x18
    36 #define SYSCALL_BARRIER_WAIT    0x19
     40typedef unsigned int    size_t;
    3741
    38 typedef unsigned int size_t;
     42// global variables defined in stdio.c
    3943
    40 /****************************************************************
    41   this is a generic C function to implement all system calls.
    42   - The first argument is the system call index.
    43   - The four next arguments are the system call arguments.
    44   They will be written in registers $2, $4, $5, $6, $7.
    45  ****************************************************************/
    46 int sys_call(int call_no,
    47         int arg_o,
    48         int arg_1,
    49         int arg_2,
    50         int arg_3);
     44extern  int volatile    _ioc_lock;
     45extern  int volatile    _ioc_done;
     46extern  int volatile    _ioc_status;
    5147
    52 /****************************************************************
    53   These functions access the MIPS protected registers
    54  ****************************************************************/
    55 int procid();
    56 int proctime();
    57 int procnumber();
    58 int exit();
    59 int rand();
     48extern  char volatile   _tty_get_buf[];
     49extern  int volatile    _tty_get_full[];
    6050
    61 /****************************************************************
    62   These functions access the MULTI_TTY peripheral
    63  ****************************************************************/
    64 int tty_puts(char* string);
    65 int tty_putc(char byte);
    66 int tty_putw(int word);
    67 int tty_getc(char* byte);
    68 int tty_getc_irq(char* byte);
    69 int tty_gets_irq(char* buf, int bufsize);
    70 int tty_getw_irq(int* word);
    71 int tty_printf(char* format,...);
     51extern int volatile     _barrier_value[];
     52extern int volatile     _barrier_count[];
     53extern int volatile     _barrier_lock[];
    7254
    73 /****************************************************************
    74   These functions access the MULTI_TIMER peripheral
    75  ****************************************************************/
    76 int timer_set_mode(int timer_index, int mode);
    77 int timer_set_period(int timer_index, int period);
    78 int timer_reset_irq(int timer_index);
    79 int timer_get_time(int timer_index, int* time);
     55extern int volatile     _spin_lock[];
    8056
    81 /****************************************************************
    82   These functions access the GCD peripheral
    83  ****************************************************************/
    84 int gcd_set_opa(int val);
    85 int gcd_set_opb(int val);
    86 int gcd_start();
    87 int gcd_get_result(int* val);
    88 int gcd_get_status(int* val);
     57// functions defined in stdio.c
    8958
    90 /****************************************************************
    91   These functions access the ICU peripheral
    92  ****************************************************************/
    93 int icu_set_mask(int val);
    94 int icu_clear_mask(int val);
    95 int icu_get_mask(int* buffer);
    96 int icu_get_irqs(int* buffer);
    97 int icu_get_index(int* buffer);
     59void*           _memcpy( void* dst, const void* src, size_t size );
    9860
    99 /****************************************************************
    100   These functions access the LOCKS peripheral
    101  ****************************************************************/
    102 int lock_acquire(int lock_index);
    103 int lock_release(int lock_index);
     61unsigned int    _procid();
     62unsigned int    _proctime();
     63unsigned int    _procnumber();
    10464
    105 /****************************************************************
    106   These functions access the BLOCK_DEVICE peripheral
    107  ****************************************************************/
    108 int ioc_read(size_t lba, void* buffer, size_t count);
    109 int ioc_write(size_t lba, void* buffer, size_t count);
    110 int ioc_completed();
     65void            _it_mask();
     66void            _it_enable();
    11167
    112 /****************************************************************
    113   These functions access the FRAME_BUFFER peripheral
    114  ****************************************************************/
    115 int fb_read(size_t offset, void* buffer, size_t length);
    116 int fb_write(size_t offset, void* buffer, size_t length);
    117 int fb_completed();
    118 int fb_sync_read(size_t offset, void* buffer, size_t length);
    119 int fb_sync_write(size_t offset, void* buffer, size_t length);
     68void            _dcache_buf_invalidate( const void* buffer, size_t size );
    12069
    121 /****************************************************************
    122   These functions access the synchronization barriers
    123  ****************************************************************/
    124 int barrier_init(size_t index, size_t count);
    125 int barrier_wait(size_t index);
     70void            _exit();
     71
     72void            _itoa_dec( unsigned int val, char* buf );
     73void            _itoa_hex( unsigned int val, char* buf );
     74
     75int             _tty_write( char* buffer, size_t length, size_t channel );
     76int             _tty_read( char* buffer, size_t channel );
     77void            _tty_puts( char* string );
     78void            _tty_putd( unsigned int val );
     79void            _tty_putx( unsigned int val );
     80void            _tty_get_lock( size_t channel );
     81void            _tty_release_lock( size_t channel );
     82void            _tty_getc( char* buffer );
     83void            _tty_getw( unsigned int* buffer );
     84void            _tty_printf( char* format, ... );
     85
     86void            _ioc_get_lock();
     87void            _ioc_write( size_t lba, void* buffer, size_t count, size_t ext );
     88void            _ioc_read (size_t lba, void* buffer, size_t count, size_t ext );
     89void            _ioc_completed();
     90void            _ioc_isr();
     91
     92void            _mmc_isr();
     93
     94void            _fb_sync_write( size_t offset, void* buffer, size_t length, size_t ext );
     95void            _fb_sync_read( size_t offset, void* buffer, size_t length, size_t ext );
     96
     97void            _release_lock( size_t lock_index );
     98void            _get_lock( size_t lock_index );
     99
     100void            _barrier_init(size_t index, size_t count);
     101void            _barrier_wait(size_t index);
    126102
    127103#endif
Note: See TracChangeset for help on using the changeset viewer.