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

Last change on this file since 454 was 450, checked in by alain, 10 years ago

1) Introducing an explicit channel initialisation function in the MWMR library.
2) Defining new system calls in stdio.c to support user access to the NIC.

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