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

Last change on this file since 5 was 5, checked in by alain, 7 years ago

Introduce the chdev_t structure in place of the device_t structure.

File size: 8.2 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 <printk.h>
31
32///////////////////////////////////////////////////////////////////////////////////
33// This static function is called by kernel_printf() to display a string on the
34// TXT channel defined by the <channel> argument.
35// The access mode is defined by the <busy> argument:
36// - if <busy> is true, it uses the dev_txt_sync_write() function, that takes the
37//   TXT lock, and call directly the relevant TXT driver, without descheduling.
38// - if <busy is false, it uses the dev_txt_write() function, that register the
39//   write buffer in the relevant TXT chdev queue, and uses a descheduling policy.
40///////////////////////////////////////////////////////////////////////////////////
41// @ channel  : TXT channel.
42// @ busy     : TXT device acces mode.
43// @ buf      : buffer containing the characters.
44// @ nc       : number of characters.
45// return 0 if success / return -1 if TTY0 busy after 10000 retries.
46///////////////////////////////////////////////////////////////////////////////////
47static error_t txt_write( uint32_t  channel,
48                          uint32_t  busy,
49                          char    * buffer,
50                          uint32_t  count )
51{
52    if( busy ) return dev_txt_sync_write( channel , buffer , count );
53    else       return dev_txt_write( channel , buffer , count );
54} 
55
56//////////////////////////////////////////////////////////////////////////////////////
57// This static function is called by printk() and user_printk() to build
58// a formated string.
59//////////////////////////////////////////////////////////////////////////////////////
60// @ channel   : channel index.
61// @ busy      : TXT device access mode.
62// @ format    : printf like format.
63// @ args      : format arguments.
64//////////////////////////////////////////////////////////////////////////////////////
65static void kernel_printf( uint32_t   channel,
66                           uint32_t   busy,
67                           char     * format, 
68                           va_list  * args ) 
69{
70
71printf_text:
72
73    while (*format) 
74    {
75        uint32_t i;
76        for (i = 0 ; format[i] && (format[i] != '%') ; i++);
77        if (i) 
78        {
79            txt_write( channel, busy, format, i );
80            format += i;
81        }
82        if (*format == '%') 
83        {
84            format++;
85            goto printf_arguments;
86        }
87    }
88
89    return;
90
91printf_arguments:
92
93    {
94        char      buf[20];
95        char    * pbuf = NULL;
96        uint32_t  len  = 0;
97        static const char HexaTab[] = "0123456789ABCDEF";
98        uint32_t i;
99
100        switch (*format++) 
101        {
102            case ('c'):             /* char conversion */
103            {
104                int val = va_arg( *args , int );
105                len = 1;
106                buf[0] = val;
107                pbuf = &buf[0];
108                break;
109            }
110            case ('d'):             /* 32 bits decimal signed  */
111            {
112                int val = va_arg( *args , int );
113                if (val < 0) 
114                {
115                    val = -val;
116                    txt_write( channel, busy, "-" , 1 );
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;
126            }
127            case ('u'):             /* 32 bits decimal unsigned  */
128            {
129                uint32_t val = va_arg( *args , uint32_t );
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 unsigned */
140            {
141                uint32_t val = va_arg( *args , uint32_t );
142                txt_write( channel, busy, "0x" , 2 );
143                for(i = 0; i < 8; i++) 
144                {
145                    buf[7 - i] = HexaTab[val & 0xF];
146                    if (!(val = (val>>4)))  break;
147                }
148                len =  i + 1;
149                pbuf = &buf[7 - i];
150                break;
151            }
152            case ('X'):             /* 32 bits hexadecimal unsigned  on 10 char */
153            {
154                uint32_t val = va_arg( *args , uint32_t );
155                txt_write( channel, busy, "0x" , 2 );
156                for(i = 0; i < 8; i++) 
157                {
158                    buf[7 - i] = HexaTab[val & 0xF];
159                    val = (val>>4);
160                }
161                len =  8;
162                pbuf = buf;
163                break;
164            }
165            case ('l'):            /* 64 bits hexadecimal unsigned */
166            {
167                uint64_t val = va_arg( *args , uint64_t );
168                txt_write( channel, busy, "0x" , 2 );
169                for(i = 0; i < 16; i++) 
170                {
171                    buf[15 - i] = HexaTab[val & 0xF];
172                    if (!(val = (val>>4)))  break;
173                }
174                len =  i + 1;
175                pbuf = &buf[15 - i];
176                break;
177            }
178            case ('L'):           /* 64 bits hexadecimal unsigned on 18 char */ 
179            {
180                uint64_t val = va_arg( *args , uint64_t );
181                txt_write( channel, busy, "0x" , 2 );
182                for(i = 0; i < 16; i++) 
183                {
184                    buf[15 - i] = HexaTab[val & 0xF];
185                    val = (val>>4);
186                }
187                len =  16;
188                pbuf = buf;
189                break;
190            }
191            case ('s'):             /* string */
192            {
193                char* str = va_arg( *args , char* );
194                while (str[len]) 
195                {
196                    len++;
197                }
198                pbuf = str;
199                break;
200            }
201            default:
202            {
203                txt_write( channel , busy,
204                           "\n[PANIC] in kernel_printf() : illegal format\n", 45 );
205            }
206        }
207
208        if( pbuf != NULL ) txt_write( channel, busy, pbuf, len );
209       
210        goto printf_text;
211    }
212
213}  // end kernel_printf()
214
215////////////////////////////////
216void printk( char * format, ...)
217{
218    va_list       args;
219
220    // call kernel_printf
221    va_start( args , format );
222    kernel_printf( 0 , 1 , format , &args );
223    va_end( args );
224}
225
226/////////////////////////////////////
227void user_printk( char* format, ...)
228{
229    va_list   args;
230
231    // get calling thread TXT channel TODO
232    uint32_t channel = 0;
233
234    // call kernel_printf
235    va_start( args , format );
236    kernel_printf( channel, 0 , format , &args );
237    va_end( args );
238}
239
240///////////////////////////////////////////
241inline void assert( bool_t       condition,
242                    const char * function_name,
243                    char       * string )
244{
245    if( condition == false )
246    {
247        printk("\n[PANIC] in %s : %s\n" , function_name , string );
248        hal_core_sleep();
249    }
250}
251
252// Local Variables:
253// tab-width: 4
254// c-basic-offset: 4
255// c-file-offsets:((innamespace . 0)(inline-open . 0))
256// indent-tabs-mode: nil
257// End:
258// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
259
Note: See TracBrowser for help on using the repository browser.