source: soft/giet_vm/giet_libs/stdio.c @ 369

Last change on this file since 369 was 368, checked in by alain, 10 years ago

1) Introducing the SBT barrier (Sliced Binary Tree)

in the barrier.h library.

2) Introducing a new remote_malloc.h library.

  • Property svn:executable set to *
File size: 19.5 KB
RevLine 
[258]1//////////////////////////////////////////////////////////////////////////////////
2// File     : stdio.c         
3// Date     : 01/04/2010
4// Author   : alain greiner & Joel Porquet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The stdio.c and stdio.h files are part of the GIET_VM nano-kernel.
8// This library contains all user-level functions that contain a system call
9// to access protected or shared ressources.
10///////////////////////////////////////////////////////////////////////////////////
11
12#include <stdarg.h>
13#include <stdio.h>
[267]14#include <giet_config.h>
[258]15
16////////////////////////////////////////////////////////////////////////////////////
[295]17/////////////////////  TTY device related system calls /////////////////////////////
[258]18////////////////////////////////////////////////////////////////////////////////////
[295]19
[352]20///////////////////////////////////////////////////////////////////////
[345]21static int __printf( char* format, unsigned int channel, va_list* args) 
[258]22{
[345]23    int ret;                    // return value from the syscalls
[258]24
[295]25printf_text:
[258]26
[295]27    while (*format) 
[258]28    {
[295]29        unsigned int i;
30        for (i = 0 ; format[i] && (format[i] != '%') ; i++);
31        if (i) 
32        {
33            ret = sys_call(SYSCALL_TTY_WRITE, 
34                           (unsigned int)format,
35                           i, 
36                           channel,
[258]37                           0);
38
[295]39            if (ret != i) goto return_error;
40
41            format += i;
[258]42        }
[295]43        if (*format == '%') 
[258]44        {
[295]45            format++;
46            goto printf_arguments;
[258]47        }
48    }
49
[345]50    return 0;
[295]51
52printf_arguments:
53
[258]54    {
[295]55        char buf[20];
56        char * pbuf;
57        unsigned int len = 0;
58        static const char HexaTab[] = "0123456789ABCDEF";
59        unsigned int i;
[258]60
[295]61        switch (*format++) 
[258]62        {
[295]63            case ('c'):             /* char conversion */
[258]64            {
[345]65                int val = va_arg( *args, int );
[295]66                len = 1;
67                buf[0] = val;
68                pbuf = &buf[0];
69                break;
[258]70            }
[295]71            case ('d'):             /* 32 bits decimal signed integer */
[258]72            {
[345]73                int val = va_arg( *args, int );
[295]74                if (val < 0) 
75                {
76                    val = -val;
77                    ret = sys_call(SYSCALL_TTY_WRITE, 
78                                   (unsigned int)"-",
79                                   1,
80                                   channel,
81                                   0);
82                    if (ret != 1) goto return_error;
83                }
84                for(i = 0; i < 10; i++) 
85                {
86                    buf[9 - i] = HexaTab[val % 10];
87                    if (!(val /= 10)) break;
88                }
89                len =  i + 1;
90                pbuf = &buf[9 - i];
91                break;
[258]92            }
[295]93            case ('u'):             /* 32 bits decimal unsigned integer */
94            {
[345]95                unsigned int val = va_arg( *args, unsigned int );
[295]96                for(i = 0; i < 10; i++) 
97                {
98                    buf[9 - i] = HexaTab[val % 10];
99                    if (!(val /= 10)) break;
100                }
101                len =  i + 1;
102                pbuf = &buf[9 - i];
103                break;
104            }
105            case ('x'):             /* 32 bits hexadecimal integer */
106            {
[345]107                unsigned int val = va_arg( *args, unsigned int );
[295]108                ret = sys_call(SYSCALL_TTY_WRITE,
109                               (unsigned int)"0x",
110                               2,
111                               channel,
112                               0);
113                if (ret != 2) goto return_error;       
114                for(i = 0; i < 8; i++) 
115                {
116                    buf[7 - i] = HexaTab[val % 16];
117                    if (!(val /= 16))  break;
118                }
119                len =  i + 1;
120                pbuf = &buf[7 - i];
121                break;
122            }
123            case ('l'):            /* 64 bits hexadecimal unsigned */
124            {
[345]125                unsigned long long val = va_arg( *args, unsigned long long );
[295]126                ret = sys_call(SYSCALL_TTY_WRITE,
127                               (unsigned int)"0x",
128                               2,
129                               channel,
130                               0);
131                if (ret != 2) goto return_error;
132                for(i = 0; i < 16; i++) 
133                {
134                    buf[15 - i] = HexaTab[val % 16];
135                    if (!(val /= 16))  break;
136                }
137                len =  i + 1;
138                pbuf = &buf[15 - i];
139                break;
140            }
141            case ('s'):             /* string */
142            {
[345]143                char* str = va_arg( *args, char* );
[295]144                while (str[len]) 
145                {
146                    len++;
147                }
148                pbuf = str;
149                break;
150            }
151            default:
152                goto return_error;
[258]153        }
154
[295]155        ret = sys_call(SYSCALL_TTY_WRITE, 
156                       (unsigned int)pbuf,
157                       len,
158                       channel, 
159                       0);
160        if (ret != len)  goto return_error;
161       
162        goto printf_text;
[258]163    }
164
[295]165return_error:
[345]166    return 1;
167} // end __printf()
[295]168
[345]169
170////////////////////////////////////////
171void giet_tty_printf( char* format, ...) 
172{
173    va_list args;
174
175    va_start( args, format );
176    int ret = __printf(format, 0xFFFFFFFF, &args);
[295]177    va_end( args );
[345]178
179    if (ret)
180    {
181        giet_exit("error in giet_tty_printf()");
182    }
[295]183} // end giet_tty_printf()
184
185////////////////////////////////////////
186void giet_shr_printf( char* format, ...) 
[258]187{
[295]188    va_list args;
[345]189    const int channel = 0;
190    volatile unsigned int sr_save;
[258]191
[295]192    sys_call( SYSCALL_TTY_GET_LOCK,
193              channel,
194              (unsigned int)&sr_save,
195              0, 0 );
196
[345]197    va_start( args, format );
198    int ret = __printf(format, channel, &args);
199    va_end( args );
[258]200
[295]201    sys_call( SYSCALL_TTY_RELEASE_LOCK,
202              channel,
203              (unsigned int)&sr_save,
204              0, 0 );
[267]205
[345]206    if (ret)
[258]207    {
[345]208        giet_exit("error in giet_shr_printf()");
[258]209    }
[345]210} // end giet_shr_printf()
[267]211
[295]212/////////////////////////////////
213void giet_tty_getc( char * byte ) 
214{
215    int ret;
216
217    do
[267]218    {
[295]219        ret = sys_call(SYSCALL_TTY_READ, 
220                      (unsigned int)byte,  // buffer address
221                      1,                   // number of characters
222                      0xFFFFFFFF,          // channel index from task context
223                      0);
224        if ( ret < 0 ) giet_exit("error in giet_tty_getc()");
[267]225    }
[295]226    while (ret != 1); 
227}
[267]228
[295]229/////////////////////////////////////
230void giet_tty_gets( char*        buf, 
231                    unsigned int bufsize ) 
232{
233    int           ret;
234    unsigned char byte;
235    unsigned int  index = 0;
236 
237    while (index < (bufsize - 1)) 
238    {
239        do 
240        { 
241            ret = sys_call(SYSCALL_TTY_READ, 
242                           (unsigned int)(&byte),
243                           1,
244                           0xFFFFFFFF,
245                           0);
246            if ( ret < 0 ) giet_exit("error in giet_tty_gets()");
247        } 
248        while (ret != 1);
249
250        if (byte == 0x0A)  /* LF */
251        {
252            break; 
253        }
254        else if ((byte == 0x7F) && (index > 0))  /* DEL */
255        {
256            index--; 
257        }
258        else 
259        {
260            buf[index] = byte;
261            index++;
262        }
263    }
264    buf[index] = 0;
[258]265}
266
[295]267///////////////////////////////////////
268void giet_tty_getw( unsigned int* val ) 
269{
270    unsigned char buf[32];
271    unsigned int  string_byte   = 0x00000000;    // string containing one single byte
272    unsigned int  string_cancel = 0x00082008;    // string containing BS/SPACE/BS
273    unsigned int  save = 0;
274    unsigned int  dec = 0;
275    unsigned int  done = 0;
276    unsigned int  overflow = 0;
277    unsigned int  length = 0;
278    unsigned int  i;
279    unsigned int  channel = 0xFFFFFFFF;
280    int           ret;      // return value from syscalls
281 
282    // get characters
283    while (done == 0) 
284    {
285        // read one character
286        do 
287        { 
288            ret = sys_call( SYSCALL_TTY_READ,
289                            (unsigned int)(&string_byte),
290                            1,
291                            channel, 
292                            0); 
293            if ( ret < 0 ) giet_exit("error in giet_tty_getw()");
294        } 
295        while (ret != 1);
[258]296
[295]297        // analyse character
298        if ((string_byte > 0x2F) && (string_byte < 0x3A))  /* decimal character */
299        {
300            buf[length] = (unsigned char)string_byte;
301            length++;
[258]302
[295]303            // echo
304            ret = sys_call( SYSCALL_TTY_WRITE, 
305                            (unsigned int)(&string_byte),
306                            1, 
307                            channel, 
308                            0 );
309            if ( ret < 0 ) giet_exit("error in giet_tty_gets()");
310        }
311        else if (string_byte == 0x0A)                     /* LF character */
312        {
313            done = 1;
314        }
315        else if ( (string_byte == 0x7F) ||                /* DEL character */
316                  (string_byte == 0x08) )                 /* BS  character */
317        {
318            if ( length > 0 ) 
319            {
320                length--;    // cancel the character
321
322                ret = sys_call( SYSCALL_TTY_WRITE, 
323                                (unsigned int)(&string_cancel),
324                                3, 
325                                channel, 
326                                0 );
[352]327                if ( ret < 0 ) giet_exit("error in giet_tty_getw()");
[295]328            }
329        }
330
331        // test buffer overflow
332        if ( length >= 32 ) 
333        {
334            overflow = 1;
335            done     = 1;
336        }
337    }  // end while characters
338
339    // string to int conversion with overflow detection
340    if ( overflow == 0 )
341    {
342        for (i = 0; (i < length) && (overflow == 0) ; i++) 
343        {
344            dec = dec * 10 + (buf[i] - 0x30);
345            if (dec < save)  overflow = 1; 
346            save = dec;
347        }
348    } 
349
350    // final evaluation
351    if ( overflow == 0 )
352    {
353        // return value
354        *val = dec;
355    }
356    else
357    {
358        // cancel all echo characters
359        for (i = 0; i < length ; i++) 
360        {
361            ret = sys_call( SYSCALL_TTY_WRITE, 
362                            (unsigned int)(&string_cancel),
363                            3, 
364                            channel, 
365                            0 );
[352]366            if ( ret < 0 ) giet_exit("error in giet_tty_getw()");
[295]367        }
368        // echo character '0'
369        string_byte = 0x30;
370        ret = sys_call( SYSCALL_TTY_WRITE, 
371                        (unsigned int)(&string_byte),
372                        1, 
373                        channel, 
374                        0 );
[352]375        if ( ret < 0 ) giet_exit("error in giet_tty_getw()");
[295]376
377        // return 0 value
378        *val = 0;
379    }
380}
381
382
[258]383//////////////////////////////////////////////////////////////////////////////////
384/////////////////////  TIMER related system calls ////////////////////////////////
385//////////////////////////////////////////////////////////////////////////////////
386
[295]387///////////////////////
388void giet_timer_start() 
[258]389{
[295]390    if ( sys_call( SYSCALL_TIMER_START, 0, 0, 0, 0 ) ) 
391       giet_exit("error in giet_timer_start()");
[258]392}
[295]393
394//////////////////////
395void giet_timer_stop() 
[258]396{
[295]397    if ( sys_call( SYSCALL_TIMER_STOP, 0, 0, 0, 0 ) ) 
398        giet_exit("error in giet_timer_stop()");
[258]399}
400
401
402//////////////////////////////////////////////////////////////////////////////////
403///////////////  Frame buffer device related system calls  ///////////////////////
404//////////////////////////////////////////////////////////////////////////////////
405
[295]406////////////////////////////////////////////
407void giet_fb_sync_write( unsigned int offset, 
[258]408                        void *       buffer, 
409                        unsigned int length ) 
410{
[295]411    if ( sys_call( SYSCALL_FB_SYNC_WRITE, 
412                   offset, 
413                   (unsigned int)buffer, 
414                   length, 
415                   0 ) )  giet_exit("error in giet_fb_sync_write()");
[258]416}
[295]417
418///////////////////////////////////////////
419void giet_fb_sync_read( unsigned int offset, 
420                        void *       buffer, 
421                        unsigned int length ) 
[258]422{
[295]423    if ( sys_call( SYSCALL_FB_SYNC_READ, 
424                   offset, 
425                   (unsigned int)buffer, 
426                   length, 
427                   0 ) )   giet_exit("error in giet_fb_sync_read()");
[258]428}
[295]429
430/////////////////////////////////////////
431void giet_fb_cma_init( void *       buf0,
432                       void *       buf1,
433                       unsigned int length )
[258]434{
[295]435    if ( sys_call( SYSCALL_FB_CMA_INIT, 
436                   (unsigned int)buf0, 
437                   (unsigned int)buf1, 
438                   length, 
439                   0 ) )   giet_exit("error in giet_fb_cma_init()");
[258]440}
[295]441
442///////////////////////////////////////////////
443void giet_fb_cma_write( unsigned int buffer_id )
[258]444{
[295]445    if ( sys_call( SYSCALL_FB_CMA_WRITE, 
446                   buffer_id, 
447                   0, 0, 0 ) )   giet_exit("error in giet_fb_cma_write()");
[258]448}
[295]449
450////////////////////////
451void giet_fb_cma_stop()
[258]452{
[295]453    if ( sys_call( SYSCALL_FB_CMA_STOP, 
454                   0, 0, 0, 0 ) )    giet_exit("error in giet_fb_cma_stop()");
[258]455}
456
457
458//////////////////////////////////////////////////////////////////////////////////
459/////////////////////// NIC related system calls /////////////////////////////////
460//////////////////////////////////////////////////////////////////////////////////
461
[295]462/////////////////////////
463void giet_nic_cma_start()
[258]464{
[295]465    if ( sys_call( SYSCALL_NIC_CMA_START, 0, 0, 0, 0 ) ) 
466       giet_exit("error in giet_nic_cma_start()");
[258]467}
[295]468
469/////////////////////////
470void giet_nic_cma_stop()
[258]471{
[295]472    if ( sys_call( SYSCALL_NIC_CMA_STOP, 0, 0, 0, 0 ) ) 
473        giet_exit("error in giet_nic_cma_stop()");
[258]474}
475
[295]476///////////////////////////////////////////////////////////////////////////////////
477///////////////////// FAT related system calls ////////////////////////////////////
478///////////////////////////////////////////////////////////////////////////////////
[258]479
[295]480///////////////////////////////////////////
481int giet_fat_open( const char*   pathname, 
482                   unsigned int  flags )
483{
484    return sys_call( SYSCALL_FAT_OPEN, 
485                     (unsigned int)pathname, 
486                     flags,
487                     0, 0 );
488}
[258]489
[295]490////////////////////////////////////
491void giet_fat_read( unsigned int fd,     
492                    void*        buffer, 
493                    unsigned int count, 
494                    unsigned int offset ) 
495{
496    if ( sys_call( SYSCALL_FAT_READ,
497                   fd, 
498                   (unsigned int)buffer,
499                   count, 
500                   offset ) != count ) giet_exit("in giet_fat_read()");
501}
502
503/////////////////////////////////////
504void giet_fat_write( unsigned int fd,
505                     void*        buffer, 
506                     unsigned int count,
507                     unsigned int offset )
508{
509    if ( sys_call( SYSCALL_FAT_WRITE, 
510                   fd, 
511                   (unsigned int)buffer,
512                   count, 
513                   offset ) != count ) giet_exit("in giet_fat_write()");
514}
515
516/* variant implementing the UNIX spec
[258]517///////////////////////////////////////////////////////////////////////////////////
[295]518// This system call writes to a file identified by the "fd" file descriptor.
519// - "buffer" is the source buffer virtual address (must be word aligned).
520// - "count" is a number of bytes (must be multiple of 4).
521// It uses the implicit "lseek" pointer in file descriptor.
[258]522///////////////////////////////////////////////////////////////////////////////////
[295]523void giet_fat_write( unsigned int fd,
524                    void*        buffer,
525                    unsigned int count )  // number of bytes
[258]526{
[295]527    return sys_call( SYSCALL_FAT_WRITE,
528                     fd,
529                     (unsigned int)buffer,
530                     count, 0 );
[258]531}
[295]532*/
533
534/////////////////////////////////////
535void giet_fat_lseek( unsigned int fd, 
536                    unsigned int offset, 
537                    unsigned int whence )
[258]538{
[295]539    if ( sys_call( SYSCALL_FAT_LSEEK, 
540                   fd, 
541                   offset, 
542                   whence, 
543                   0 ) ) giet_exit("in giet_fat_lseek()");
[258]544}
[295]545
546//////////////////////////////////////
547void giet_fat_fstat( unsigned int fd )
[258]548{
[295]549    if ( sys_call( SYSCALL_FAT_FSTAT,
550                   fd,
551                   0, 0, 0 ) )  giet_exit("in giet_fat_lseek()");
[258]552}
[295]553
554/////////////////////////////////////
555void giet_fat_close( unsigned int fd )
[258]556{
[295]557    if ( sys_call( SYSCALL_FAT_CLOSE,
558                   fd,
559                   0, 0, 0 ) )  giet_exit("in giet_fat_close()");
[258]560}
[295]561
562
[258]563//////////////////////////////////////////////////////////////////////////////////
[295]564///////////////////// Miscellaneous system calls /////////////////////////////////
[258]565//////////////////////////////////////////////////////////////////////////////////
[295]566
567/////////////////
568int giet_procid() 
[258]569{
[295]570    return sys_call( SYSCALL_PROCID,
[258]571                     0, 0, 0, 0 );
572}
[295]573
574////////////////////
575int giet_proctime() 
576{
577    return sys_call( SYSCALL_PROCTIME, 
578                     0, 0, 0, 0 );
579}
580
581///////////////////////
[258]582int giet_proc_task_id() 
583{
584    return sys_call( SYSCALL_LOCAL_TASK_ID, 
585                     0, 0, 0, 0 );
586}
[295]587
588/////////////////////////
[258]589int giet_global_task_id() 
590{
591    return sys_call( SYSCALL_GLOBAL_TASK_ID, 
592                     0, 0, 0, 0 );
593}
594
[295]595////////////////////
[267]596int giet_thread_id() 
597{
598    return sys_call( SYSCALL_THREAD_ID, 
599                     0, 0, 0, 0 );
600}
601
[295]602///////////////
603int giet_rand() 
[258]604{
[295]605    unsigned int x = sys_call(SYSCALL_PROCTIME, 0, 0, 0, 0);
606    if ((x & 0xF) > 7) {
607        return (x*x & 0xFFFF);
608    }
609    else {
610        return (x*x*x & 0xFFFF);
611    }
[258]612}
[295]613
614//////////////////////////////
615void giet_exit( char* string ) 
[258]616{
[295]617    sys_call( SYSCALL_EXIT,
618              (unsigned int)string,
619              0, 0, 0 );
[258]620}
[295]621
622/////////////////////////////////////////
623void giet_assert( unsigned int condition,
624                  char*        string )
[258]625{
[295]626    if ( condition == 0 ) giet_exit( string );
[258]627}
[295]628
629////////////////////////////////////////////////////
630void giet_vobj_get_vbase( char*         vspace_name, 
631                          char*         vobj_name, 
632                          unsigned int* vobj_vaddr ) 
[258]633{
[295]634    if ( sys_call( SYSCALL_VOBJ_GET_VBASE, 
635                   (unsigned int) vspace_name,
636                   (unsigned int) vobj_name,
637                   (unsigned int) vobj_vaddr,
638                   0 ) )  giet_exit("in giet_vobj_get_vbase()");
[258]639}
[260]640
[295]641///////////////////////////////////////////////
642void giet_proc_number( unsigned int  cluster_id, 
[368]643                       unsigned int* buffer ) 
[260]644{
[295]645    if ( sys_call( SYSCALL_PROC_NUMBER, 
646                   cluster_id, 
647                   (unsigned int) buffer, 
648                   0, 0) )  giet_exit("in giet_proc_number()");
[260]649}
650
[295]651//////////////////////////
652void giet_context_switch() 
[258]653{
[295]654    sys_call( SYSCALL_CTX_SWITCH,
655              0, 0, 0, 0 );
[258]656}
657
[295]658/////////////////////////////////////////
659void giet_heap_info( unsigned int* vaddr, 
[368]660                     unsigned int* length,
661                     unsigned int  x,
662                     unsigned int  y ) 
[258]663{
[295]664    if ( sys_call( SYSCALL_HEAP_INFO, 
665                   (unsigned int)vaddr, 
666                   (unsigned int)length, 
[368]667                   x,
668                   y ) )  giet_exit("in giet_heap_info()");
[258]669}
670
671// Local Variables:
672// tab-width: 4
673// c-basic-offset: 4
674// c-file-offsets:((innamespace . 0)(inline-open . 0))
675// indent-tabs-mode: nil
676// End:
677// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
678
Note: See TracBrowser for help on using the repository browser.