source: trunk/kernel/kern/printk.c @ 15

Last change on this file since 15 was 14, checked in by alain, 8 years ago

Bugs fix.

File size: 8.8 KB
Line 
1/*
2 * printk.c - Kernel Log & debug messages API implementation.
3 *
4 * authors  Alain Greiner (2016)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH..
9 *
10 * ALMOS-MKH. is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH. is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_types.h>
25#include <hal_irqmask.h>
26#include <hal_special.h>
27#include <dev_txt.h>
28#include <remote_spinlock.h>
29#include <cluster.h>
30#include <chdev.h>
31#include <printk.h>
32
33///////////////////////////////////////////////////////////////////////////////////
34//      Extern variables
35///////////////////////////////////////////////////////////////////////////////////
36
37extern chdev_t            txt0_chdev;        // allocated in kernel_init.c
38
39///////////////////////////////////////////////////////////////////////////////////
40// This static function is called by kernel_printf() to display a string on the
41// TXT channel defined by the <channel> argument.
42// The access mode is defined by the <busy> argument:
43// - if <busy> is true, it uses the dev_txt_sync_write() function, that takes the
44//   TXT lock, and call directly the relevant TXT driver, without descheduling.
45// - if <busy is false, it uses the dev_txt_write() function, that register the
46//   write buffer in the relevant TXT chdev queue, and uses a descheduling policy.
47///////////////////////////////////////////////////////////////////////////////////
48// @ channel  : TXT channel.
49// @ busy     : TXT device acces mode.
50// @ buf      : buffer containing the characters.
51// @ nc       : number of characters.
52// return 0 if success / return -1 if TTY0 busy after 10000 retries.
53///////////////////////////////////////////////////////////////////////////////////
54static error_t txt_write( uint32_t  channel,
55                          uint32_t  busy,
56                          char    * buffer,
57                          uint32_t  count )
58{
59    if( busy ) return dev_txt_sync_write( channel , buffer , count );
60    else       return dev_txt_write( channel , buffer , count );
61} 
62
63//////////////////////////////////////////////////////////////////////////////////////
64// This static function is called by printk() and user_printk() to build
65// a formated string.
66//////////////////////////////////////////////////////////////////////////////////////
67// @ channel   : channel index.
68// @ busy      : TXT device access mode.
69// @ format    : printf like format.
70// @ args      : format arguments.
71//////////////////////////////////////////////////////////////////////////////////////
72static void kernel_printf( uint32_t   channel,
73                           uint32_t   busy,
74                           char     * format, 
75                           va_list  * args ) 
76{
77
78printf_text:
79
80    while (*format) 
81    {
82        uint32_t i;
83        for (i = 0 ; format[i] && (format[i] != '%') ; i++);
84        if (i) 
85        {
86            txt_write( channel, busy, format, i );
87            format += i;
88        }
89        if (*format == '%') 
90        {
91            format++;
92            goto printf_arguments;
93        }
94    }
95
96    return;
97
98printf_arguments:
99
100    {
101        char      buf[20];
102        char    * pbuf = NULL;
103        uint32_t  len  = 0;
104        static const char HexaTab[] = "0123456789ABCDEF";
105        uint32_t i;
106
107        switch (*format++) 
108        {
109            case ('c'):             /* char conversion */
110            {
111                int val = va_arg( *args , int );
112                len = 1;
113                buf[0] = val;
114                pbuf = &buf[0];
115                break;
116            }
117            case ('d'):             /* 32 bits decimal signed  */
118            {
119                int val = va_arg( *args , int );
120                if (val < 0) 
121                {
122                    val = -val;
123                    txt_write( channel, busy, "-" , 1 );
124                }
125                for(i = 0; i < 10; i++) 
126                {
127                    buf[9 - i] = HexaTab[val % 10];
128                    if (!(val /= 10)) break;
129                }
130                len =  i + 1;
131                pbuf = &buf[9 - i];
132                break;
133            }
134            case ('u'):             /* 32 bits decimal unsigned  */
135            {
136                uint32_t val = va_arg( *args , uint32_t );
137                for(i = 0; i < 10; i++) 
138                {
139                    buf[9 - i] = HexaTab[val % 10];
140                    if (!(val /= 10)) break;
141                }
142                len =  i + 1;
143                pbuf = &buf[9 - i];
144                break;
145            }
146            case ('x'):             /* 32 bits hexadecimal unsigned */
147            {
148                uint32_t val = va_arg( *args , uint32_t );
149                txt_write( channel, busy, "0x" , 2 );
150                for(i = 0; i < 8; i++) 
151                {
152                    buf[7 - i] = HexaTab[val & 0xF];
153                    if (!(val = (val>>4)))  break;
154                }
155                len =  i + 1;
156                pbuf = &buf[7 - i];
157                break;
158            }
159            case ('X'):             /* 32 bits hexadecimal unsigned  on 10 char */
160            {
161                uint32_t val = va_arg( *args , uint32_t );
162                txt_write( channel, busy, "0x" , 2 );
163                for(i = 0; i < 8; i++) 
164                {
165                    buf[7 - i] = HexaTab[val & 0xF];
166                    val = (val>>4);
167                }
168                len =  8;
169                pbuf = buf;
170                break;
171            }
172            case ('l'):            /* 64 bits hexadecimal unsigned */
173            {
174                uint64_t val = va_arg( *args , uint64_t );
175                txt_write( channel, busy, "0x" , 2 );
176                for(i = 0; i < 16; i++) 
177                {
178                    buf[15 - i] = HexaTab[val & 0xF];
179                    if (!(val = (val>>4)))  break;
180                }
181                len =  i + 1;
182                pbuf = &buf[15 - i];
183                break;
184            }
185            case ('L'):           /* 64 bits hexadecimal unsigned on 18 char */ 
186            {
187                uint64_t val = va_arg( *args , uint64_t );
188                txt_write( channel, busy, "0x" , 2 );
189                for(i = 0; i < 16; i++) 
190                {
191                    buf[15 - i] = HexaTab[val & 0xF];
192                    val = (val>>4);
193                }
194                len =  16;
195                pbuf = buf;
196                break;
197            }
198            case ('s'):             /* string */
199            {
200                char* str = va_arg( *args , char* );
201                while (str[len]) 
202                {
203                    len++;
204                }
205                pbuf = str;
206                break;
207            }
208            default:
209            {
210                txt_write( channel , busy,
211                           "\n[PANIC] in kernel_printf() : illegal format\n", 45 );
212            }
213        }
214
215        if( pbuf != NULL ) txt_write( channel, busy, pbuf, len );
216       
217        goto printf_text;
218    }
219
220}  // end kernel_printf()
221
222/////////////////////////////////
223void printk( char * format , ...)
224{
225    va_list       args;
226    uint32_t      save_sr;
227
228    // get extended pointer on remote TXT0 chdev lock
229    xptr_t  txt0_lock_xp = XPTR( LOCAL_CLUSTER->io_cxy , &txt0_chdev.wait_lock );
230
231    // get TXT0 lock in busy waiting mode
232    remote_spinlock_lock_busy( txt0_lock_xp , &save_sr );
233
234    // call kernel_printf in busy waiting mode
235    va_start( args , format );
236    kernel_printf( 0 , 1 , format , &args );
237    va_end( args );
238
239    // release lock
240    remote_spinlock_unlock_busy( txt0_lock_xp , save_sr );
241}
242
243//////////////////////////////////////
244void user_printk( char * format , ...)
245{
246    va_list   args;
247
248    // get calling thread TXT channel TODO
249    uint32_t channel = 0;
250
251   // call kernel_printf in descheduling mode
252    va_start( args , format );
253    kernel_printf( channel, 0 , format , &args );
254    va_end( args );
255}
256
257///////////////////////////////////////////
258inline void assert( bool_t       condition,
259                    const char * function_name,
260                    char       * string )
261{
262    if( condition == false )
263    {
264        printk("\n[PANIC] in %s : %s\n" , function_name , string );
265        hal_core_sleep();
266    }
267}
268
269// Local Variables:
270// tab-width: 4
271// c-basic-offset: 4
272// c-file-offsets:((innamespace . 0)(inline-open . 0))
273// indent-tabs-mode: nil
274// End:
275// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
276
Note: See TracBrowser for help on using the repository browser.