source: soft/giet_vm/giet_common/tty0.c @ 609

Last change on this file since 609 was 594, checked in by alain, 9 years ago

1) Fix a bug in the _free() function in kernel_malloc.c
2) Introduce a strlen() function in utils.c

File size: 8.8 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : tty0.c
3// Date     : 02/12/2014
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The tty0.c and tty0.h files are part of the GIET-VM nano-kernel.
8///////////////////////////////////////////////////////////////////////////////////
9
10#include <hard_config.h>
11#include <tty0.h>
12#include <stdarg.h>
13#include <tty_driver.h>
14#include <utils.h>
15#include <kernel_locks.h>
16
17/////////////////////////////////////////////////////////////////////////////
18// The global variable tty0_boot_mode define the type of lock used,
19// and must be defined in both kernel_init.c and boot.c files.
20// - the boot code must use a spin_lock because the kernel heap is not set.
21// - the kernel code can use a sqt_lock when the kernel heap is set.
22/////////////////////////////////////////////////////////////////////////////
23
24extern unsigned int  _tty0_boot_mode;
25
26__attribute__((section(".kdata")))
27sqt_lock_t           _tty0_sqt_lock  __attribute__((aligned(64))); 
28
29__attribute__((section(".kdata")))
30spin_lock_t          _tty0_spin_lock  __attribute__((aligned(64)));
31
32//////////////////////////////////////////////
33unsigned int _tty0_write( char*        buffer,
34                          unsigned int nbytes )
35{
36    unsigned int n;
37    unsigned int k;
38
39    for ( n = 0 ; n < nbytes ; n++ ) 
40    {
41        // test TTY_TX buffer full
42        if ( (_tty_get_register( 0, TTY_STATUS ) & 0x2) ) // buffer full
43        {
44            // retry if full
45            for( k = 0 ; k < 10000 ; k++ )
46            {
47                if ( (_tty_get_register( 0, TTY_STATUS ) & 0x2) == 0) break;
48            }
49            // return error if full after 10000 retry
50            return 1;
51        }
52
53        // write one byte
54        if (buffer[n] == '\n') _tty_set_register( 0, TTY_WRITE, (unsigned int)'\r' );
55        _tty_set_register( 0, TTY_WRITE, (unsigned int)buffer[n] );
56    }
57    return 0;
58}
59
60//////////////////////////
61void _puts( char* string ) 
62{
63    unsigned int n = 0;
64
65    while ( string[n] > 0 ) n++;
66
67    _tty0_write( string, n );
68}
69
70
71//////////////////////////////
72void _putx( unsigned int val )
73{
74    static const char HexaTab[] = "0123456789ABCDEF";
75    char buf[10];
76    unsigned int c;
77
78    buf[0] = '0';
79    buf[1] = 'x';
80
81    for (c = 0; c < 8; c++) 
82    { 
83        buf[9 - c] = HexaTab[val & 0xF];
84        val = val >> 4;
85    }
86    _tty0_write( buf, 10 );
87}
88
89////////////////////////////////////
90void _putl( unsigned long long val )
91{
92    static const char HexaTab[] = "0123456789ABCDEF";
93    char buf[18];
94    unsigned int c;
95
96    buf[0] = '0';
97    buf[1] = 'x';
98
99    for (c = 0; c < 16; c++) 
100    { 
101        buf[17 - c] = HexaTab[(unsigned int)val & 0xF];
102        val = val >> 4;
103    }
104    _tty0_write( buf, 18 );
105}
106
107//////////////////////////////
108void _putd( unsigned int val ) 
109{
110    static const char DecTab[] = "0123456789";
111    char buf[10];
112    unsigned int i;
113    unsigned int first = 0;
114
115    for (i = 0; i < 10; i++) 
116    {
117        if ((val != 0) || (i == 0)) 
118        {
119            buf[9 - i] = DecTab[val % 10];
120            first = 9 - i;
121        }
122        else 
123        {
124            break;
125        }
126        val /= 10;
127    }
128    _tty0_write( &buf[first], 10 - first );
129}
130
131/////////////////////////
132void _getc( char*  byte )
133{
134    // test status register
135    while ( _tty_get_register( 0 , TTY_STATUS ) == 0 );
136
137    // read one byte
138    *byte = (char)_tty_get_register( 0 , TTY_READ );
139}
140
141//////////////////////////////////////////////////////////
142static void _kernel_printf( char * format, va_list* args ) 
143{
144
145printf_text:
146
147    while (*format) 
148    {
149        unsigned int i;
150        for (i = 0 ; format[i] && (format[i] != '%') ; i++);
151        if (i) 
152        {
153            if ( _tty0_write( format, i ) ) goto return_error;
154            format += i;
155        }
156        if (*format == '%') 
157        {
158            format++;
159            goto printf_arguments;
160        }
161    }
162
163    return;
164
165printf_arguments:
166
167    {
168        char buf[20];
169        char * pbuf;
170        unsigned int len = 0;
171        static const char HexaTab[] = "0123456789ABCDEF";
172        unsigned int i;
173
174        switch (*format++) 
175        {
176            case ('c'):             /* char conversion */
177            {
178                int val = va_arg( *args , int );
179                len = 1;
180                buf[0] = val;
181                pbuf = &buf[0];
182                break;
183            }
184            case ('d'):             /* 32 bits decimal signed  */
185            {
186                int val = va_arg( *args , int );
187                if (val < 0) 
188                {
189                    val = -val;
190                    if ( _tty0_write( "-" , 1 ) ) goto return_error;
191                }
192                for(i = 0; i < 10; i++) 
193                {
194                    buf[9 - i] = HexaTab[val % 10];
195                    if (!(val /= 10)) break;
196                }
197                len =  i + 1;
198                pbuf = &buf[9 - i];
199                break;
200            }
201            case ('u'):             /* 32 bits decimal unsigned  */
202            {
203                unsigned int val = va_arg( *args , unsigned int );
204                for(i = 0; i < 10; i++) 
205                {
206                    buf[9 - i] = HexaTab[val % 10];
207                    if (!(val /= 10)) break;
208                }
209                len =  i + 1;
210                pbuf = &buf[9 - i];
211                break;
212            }
213            case ('x'):             /* 32 bits hexadecimal unsigned */
214            {
215                unsigned int val = va_arg( *args , unsigned int );
216                if ( _tty0_write( "0x" , 2 ) ) goto return_error;
217                for(i = 0; i < 8; i++) 
218                {
219                    buf[7 - i] = HexaTab[val % 16];
220                    if (!(val = (val>>4)))  break;
221                }
222                len =  i + 1;
223                pbuf = &buf[7 - i];
224                break;
225            }
226            case ('X'):             /* 32 bits hexadecimal unsigned  on 10 char*/
227            {
228                unsigned int val = va_arg( *args , unsigned int );
229                if ( _tty0_write( "0x" , 2 ) ) goto return_error;
230                for(i = 0; i < 8; i++) 
231                {
232                    buf[7 - i] = HexaTab[val % 16];
233                    val = (val>>4);
234                }
235                len =  8;
236                pbuf = buf;
237                break;
238            }
239            case ('l'):            /* 64 bits hexadecimal unsigned */
240            {
241                unsigned long long val = va_arg( *args , unsigned long long );
242                if ( _tty0_write( "0x" , 2 ) ) goto return_error;
243                for(i = 0; i < 16; i++) 
244                {
245                    buf[15 - i] = HexaTab[val % 16];
246                    if (!(val /= 16))  break;
247                }
248                len =  i + 1;
249                pbuf = &buf[15 - i];
250                break;
251            }
252            case ('s'):             /* string */
253            {
254                char* str = va_arg( *args , char* );
255                while (str[len]) 
256                {
257                    len++;
258                }
259                pbuf = str;
260                break;
261            }
262            default:
263                goto return_error;
264        }
265
266        if ( _tty0_write( pbuf, len ) ) goto return_error;
267       
268        goto printf_text;
269    }
270
271return_error:
272
273    {
274        // try to print an error message and exit...
275        unsigned int procid     = _get_procid();
276        unsigned int x          = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
277        unsigned int y          = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
278        unsigned int lpid       = procid & ((1<<P_WIDTH)-1);
279        _puts("\n\n[GIET ERROR] in _printf() for processor[");
280        _putd( x ); 
281        _puts(",");
282        _putd( y );
283        _puts(",");
284        _putd( lpid );
285        _puts("]\n");
286
287        _exit();
288    }
289}  // end _kernel_printf()
290
291///////////////////////////////////////
292void _nolock_printf( char* format, ...)
293{
294    va_list   args;
295
296    va_start( args , format );
297    _kernel_printf( format , &args );
298    va_end( args );
299}
300////////////////////////////////
301void _printf( char* format, ...)
302{
303    va_list       args;
304    unsigned int  save_sr;
305
306    // get TTY0 lock
307    _it_disable( &save_sr );
308    if ( _tty0_boot_mode ) _spin_lock_acquire( &_tty0_spin_lock );
309    else                   _sqt_lock_acquire( &_tty0_sqt_lock );
310
311    va_start( args , format );
312    _kernel_printf( format , &args );
313    va_end( args );
314
315    // release TTY0 lock
316    if ( _tty0_boot_mode ) _spin_lock_release( &_tty0_spin_lock );
317    else                   _sqt_lock_release( &_tty0_sqt_lock );
318    _it_restore( &save_sr );
319}
320
321
322// Local Variables:
323// tab-width: 4
324// c-basic-offset: 4
325// c-file-offsets:((innamespace . 0)(inline-open . 0))
326// indent-tabs-mode: nil
327// End:
328// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
329
Note: See TracBrowser for help on using the repository browser.