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

Last change on this file since 432 was 431, checked in by alain, 10 years ago

Introducing fixed format (X_WIDTH / Y_WIDTH / P_WIDTH) for processor index.

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