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

Last change on this file since 345 was 345, checked in by cfuguet, 10 years ago

giet_vm optimizations:

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