/* * printk.c - Kernel Log & debug messages API implementation. * * authors Alain Greiner (2016) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH.. * * ALMOS-MKH. is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH. is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH.; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////////// // This static function is called by printk(), nolock_printk() and user_printk() /////////////////////////////////////////////////////////////////////////////////// static void kernel_printf( uint32_t channel, char * format, va_list * args ) { printf_text: while (*format) { uint32_t i; for (i = 0 ; format[i] && (format[i] != '%') ; i++); if (i) { dev_txt_sync_write( channel, format, i ); format += i; } if (*format == '%') { format++; goto printf_arguments; } } return; printf_arguments: { char buf[20]; char * pbuf = NULL; uint32_t len = 0; static const char HexaTab[] = "0123456789ABCDEF"; uint32_t i; switch (*format++) { case ('c'): /* char conversion */ { int val = va_arg( *args , int ); len = 1; buf[0] = val; pbuf = &buf[0]; break; } case ('d'): /* 32 bits decimal signed */ { int val = va_arg( *args , int ); if (val < 0) { val = -val; dev_txt_sync_write( channel, "-" , 1 ); } for(i = 0; i < 10; i++) { buf[9 - i] = HexaTab[val % 10]; if (!(val /= 10)) break; } len = i + 1; pbuf = &buf[9 - i]; break; } case ('u'): /* 32 bits decimal unsigned */ { uint32_t val = va_arg( *args , uint32_t ); for(i = 0; i < 10; i++) { buf[9 - i] = HexaTab[val % 10]; if (!(val /= 10)) break; } len = i + 1; pbuf = &buf[9 - i]; break; } case ('x'): /* 32 bits hexadecimal unsigned */ { uint32_t val = va_arg( *args , uint32_t ); dev_txt_sync_write( channel, "0x" , 2 ); for(i = 0; i < 8; i++) { buf[7 - i] = HexaTab[val % 16]; if (!(val = (val>>4))) break; } len = i + 1; pbuf = &buf[7 - i]; break; } case ('X'): /* 32 bits hexadecimal unsigned on 10 char*/ { uint32_t val = va_arg( *args , uint32_t ); dev_txt_sync_write( channel, "0x" , 2 ); for(i = 0; i < 8; i++) { buf[7 - i] = HexaTab[val % 16]; val = (val>>4); } len = 8; pbuf = buf; break; } case ('l'): /* 64 bits hexadecimal unsigned */ { uint64_t val = va_arg( *args , uint64_t ); dev_txt_sync_write( channel, "0x" , 2 ); for(i = 0; i < 16; i++) { buf[15 - i] = HexaTab[val % 16]; if (!(val /= 16)) break; } len = i + 1; pbuf = &buf[15 - i]; break; } case ('s'): /* string */ { char* str = va_arg( *args , char* ); while (str[len]) { len++; } pbuf = str; break; } default: { dev_txt_sync_write( channel , "\n[PANIC] in kernel_printf() : illegal format\n", 45 ); } } if( pbuf != NULL ) dev_txt_sync_write( channel, pbuf, len ); goto printf_text; } } // end kernel_printf() /////////////////////////////////////// void nolock_printk( char* format, ...) { va_list args; // call kernel_printf va_start( args , format ); kernel_printf( 0, format , &args ); va_end( args ); } //////////////////////////////// void printk( char* format, ...) { va_list args; uint32_t save_sr; // disable IRQs hal_disable_irq( &save_sr ); // get TXT0 lock cluster_t * cluster = LOCAL_CLUSTER; remote_spinlock_lock( XPTR( cluster->io_cxy , &cluster->txt0_lock ) ); // call kernel_printf va_start( args , format ); kernel_printf( 0, format , &args ); va_end( args ); // release TXT0 lock remote_spinlock_unlock( XPTR( cluster->io_cxy , &cluster->txt0_lock ) ); // restore IRQs hal_restore_irq( save_sr ); } ///////////////////////////////////// void user_printk( char* format, ...) { va_list args; // get calling thread TXT channel TODO uint32_t channel = 0; // call kernel_printf va_start( args , format ); kernel_printf( channel, format , &args ); va_end( args ); } // Local Variables: // tab-width: 4 // c-basic-offset: 4 // c-file-offsets:((innamespace . 0)(inline-open . 0)) // indent-tabs-mode: nil // End: // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4