POK(kernelpart)
/home/jaouen/pok_official/pok/trunk/kernel/arch/x86/x86-qemu/cons.c
Go to the documentation of this file.
00001 /*
00002  *                               POK header
00003  * 
00004  * The following file is a part of the POK project. Any modification should
00005  * made according to the POK licence. You CANNOT use this file or a part of
00006  * this file is this part of a file for your own project
00007  *
00008  * For more information on the POK licence, please see our LICENCE FILE
00009  *
00010  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
00011  *
00012  *                                      Copyright (c) 2007-2009 POK team 
00013  *
00014  * Created by julien on Thu Jan 15 23:34:13 2009 
00015  */
00016 
00017 
00018 #include <errno.h>
00019 
00020 #include <arch/x86/ioports.h>
00021 #include <libc.h>
00022 #include <core/debug.h>
00023 #include <core/cons.h>
00024 
00025 #include "cons.h"
00026 
00027 #if defined (POK_NEEDS_DEBUG) || defined (POK_NEEDS_CONSOLE) || defined (POK_NEEDS_INSTRUMENTATION) || defined (POK_NEEDS_COVERAGE_INFOS)
00028 
00029 static const int     screen_w = 80;
00030 static const int     screen_h = 25;
00031 static const int     tab_size = 8;
00032 static char *const   vga_base = (char *)0xb8000;
00033 struct s_cons        g_cons;
00034 
00035 #if defined (POK_NEEDS_DEBUG) || defined (POK_NEEDS_INSTRUMENTATION) || defined (POK_NEEDS_COVERAGE_INFOS)
00036 #define  COM1      0x3F8
00037 
00038 int is_transmit_empty() {
00039    return inb(COM1 + 5) & 0x20;
00040 }
00041 
00042 void write_serial(char a) {
00043    while (is_transmit_empty() == 0);
00044 
00045    outb(COM1,a);
00046 }
00047 #endif
00048 
00049 
00050 
00051 void pok_cons_print_char (const char c)
00052 {
00053 #ifdef POK_NEEDS_CONSOLE
00054    char*                ptr;
00055    static struct s_cons local_curs; /* Local copy of the curent cursor position */
00056    int                  i;
00057 #endif
00058 
00059 #if defined (POK_NEEDS_DEBUG) || defined (POK_NEEDS_INSTRUMENTATION) || defined (POK_NEEDS_COVERAGE_INFOS)
00060    write_serial (c);
00061 #endif
00062 
00063 #ifdef POK_NEEDS_CONSOLE
00064    local_curs = g_cons;
00065 
00066    if (c == '\r')
00067    {
00068       local_curs.col = 0;
00069    }
00070 
00071    if (c == '\n')
00072    {
00073       local_curs.col = 0;
00074       ++local_curs.row;
00075    }
00076 
00077    if (c == '\t')
00078    {
00079       local_curs.col += tab_size - local_curs.col % tab_size;
00080    }
00081 
00082    if (c != '\r' && c != '\n' && c != '\t')
00083    {
00084       ptr = vga_base + 2 * screen_w * local_curs.row + 2 * local_curs.col++;
00085       *ptr = c;
00086       ++ptr;
00087       *ptr = local_curs.cur_attr;
00088    }
00089 
00090    if (local_curs.col >= screen_w)
00091    {
00092       local_curs.col = 0;
00093       ++local_curs.row;
00094    }
00095 
00096    if (local_curs.row >= screen_h)
00097    {
00098       memcpy (vga_base, vga_base + 2 * screen_w, (screen_h - 1) * screen_w * 2);
00099       for (i = 0; i < screen_w; ++i)
00100       {
00101          *(vga_base + 2 * screen_w * (screen_h - 1) + 2 * i) = 0;
00102          *(vga_base + 2 * screen_w * (screen_h - 1) + 2 * i + 1) = local_curs.cur_attr;
00103       }
00104       local_curs.row = screen_h - 1;
00105    }
00106 
00107    // Reset the global cursor to the new position
00108    g_cons = local_curs;
00109 #endif
00110 }
00111 
00112 void pok_cons_attr (uint8_t attr)
00113 {
00114    g_cons.cur_attr = attr;
00115 }
00116 
00117 void pok_cons_clear (void)
00118 {
00119    int   i;
00120    int   j;
00121    char  *ptr;
00122    static struct s_cons         local_curs; /* local copy of the current cursor position */
00123 
00124    ptr = vga_base;
00125    local_curs = g_cons;
00126 
00127    for (i = 0 ; i < screen_h ; ++i)
00128    {
00129       for (j = 0 ; j < screen_w ; ++j)
00130       {
00131          *ptr = 0;
00132          ++ptr;
00133          *ptr = g_cons.cur_attr;
00134          ++ptr;
00135       }
00136    }
00137 
00138    local_curs.row = 0;
00139    local_curs.col = 0;
00140 
00141    g_cons = local_curs; /* reset the global cursor to the new position */
00142 }
00143 
00144 
00145 pok_bool_t pok_cons_write (const char *s, size_t length)
00146 {
00147    int    res;
00148    size_t i;
00149 
00150    res = 0;
00151    i   = 0;
00152 
00153    while (i < length)
00154    {
00155       if ((const unsigned char)s[i] == CONS_ESCAPE)
00156       {
00157          ++i;
00158          switch (s[i])
00159          {
00160             case CONS_CLEAR:
00161                pok_cons_clear();
00162                break;
00163             case CONS_COLOR:
00164                ++i;
00165                pok_cons_attr((const unsigned char)s[i]);
00166                break;
00167             case CONS_SETY:
00168                ++i;
00169                g_cons.row = (const unsigned char)s[i] % screen_h;
00170                break;
00171             case CONS_SETX:
00172                ++i;
00173                g_cons.col = (const unsigned char)s[i] % screen_w;
00174                break;
00175             default:
00176                pok_cons_print_char(s[i]);
00177                ++res;
00178          }
00179       }
00180       else
00181       {
00182          pok_cons_print_char(s[i]);
00183          ++res;
00184       }
00185       ++i;
00186    }
00187    return res;
00188 }
00189 
00190 #ifdef POK_NEEDS_CONSOLE
00191 void pok_cons_disable_cursor (void)
00192 {
00193    char tmp;
00194    int  base_port;
00195 
00196    if (inb(0x3cc) & 0x01)
00197    {
00198       base_port = 0x3d4;
00199    }
00200    else
00201    {
00202       base_port = 0x3b4;
00203    }
00204 
00205    tmp = inb (base_port);
00206    outb (base_port, 0x0a);
00207    outb (base_port + 1, inb (base_port + 1) | 0x20);
00208    outb (base_port, tmp);
00209 }
00210 #endif
00211 
00212 int pok_cons_init (void)
00213 {
00214 #ifdef POK_NEEDS_CONSOLE
00215    g_cons.cur_attr = CONS_FRONT (CONS_WHITE) | CONS_BACK (CONS_BLACK);
00216    pok_cons_clear ();
00217    pok_cons_disable_cursor ();
00218    pok_print_init (pok_cons_print_char, pok_cons_attr);
00219 #endif
00220 
00221 #if defined (POK_NEEDS_DEBUG) || defined (POK_NEEDS_INSTRUMENTATION) || defined (POK_NEEDS_COVERAGE_INFOS)
00222    /* To be fixed : init serial */
00223    outb(COM1 + 1, 0x00);    // Disable all interrupts
00224    outb(COM1 + 3, 0x80);    // Enable DLAB (set baud rate divisor)
00225    outb(COM1 + 0, 0x03);    // Set divisor to 3 (lo byte) 38400 baud
00226    outb(COM1 + 1, 0x00);    //                  (hi byte)
00227    outb(COM1 + 3, 0x03);    // 8 bits, no parity, one stop bit
00228    outb(COM1 + 2, 0xC7);    // Enable FIFO, clear them, with 14-byte threshold
00229    outb(COM1 + 4, 0x0B);    // IRQs enabled, RTS/DSR set
00230 #endif
00231 
00232    return 0;
00233 }
00234 #else
00235 int pok_cons_init (void)
00236 {
00237    return 0;
00238 }
00239 #endif
00240 
00241