diff options
Diffstat (limited to '')
-rw-r--r-- | bsps/x86_64/amd64/console/outch.c | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/bsps/x86_64/amd64/console/outch.c b/bsps/x86_64/amd64/console/outch.c new file mode 100644 index 0000000000..3627cc57d8 --- /dev/null +++ b/bsps/x86_64/amd64/console/outch.c @@ -0,0 +1,461 @@ +/** + * @file + * + * @ingroup amd64 + * + * @brief displaying characters on the console + * + * NOTE: This file is copied from arm/raspberrypi BSP. + * It is only slightly changed to work with EFI GOP. + * Obvious idea is to refactor whole framebuffer console + * business shared between various BSPs and move that + * properly to bsps/shared and reuse. + */ + +/** + * + * Copyright (c) 2015 Yang Qiao + * based on work by: + * Copyright (C) 1998 Eric Valette (valette@crf.canon.fr) + * Canon Centre Recherche France. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * Till Straumann <strauman@slac.stanford.edu>, 2003/9: + * - added handling of basic escape sequences (cursor movement + * and erasing; just enough for the line editor 'libtecla' to + * work...) + * + */ + +#include <bsp.h> +#include <rtems/fb.h> + +#include <efigop.h> + +#include <stdlib.h> +#include <string.h> +#include "font_data.h" + +static void wr_cursor( + int r, + int c +) +{ + /* dummy function for now */ +} + +#define TAB_SPACE 4 +#define CONSOLE_BG_COL 0xff +#define CONSOLE_FG_COL 0x00 + +static void *fb_mem = NULL; +static unsigned short maxCol; +static unsigned short maxRow; +static unsigned short bytes_per_pixel; +static unsigned int bytes_per_line; +static unsigned int bytes_per_char_line; +static unsigned char row; +static unsigned char column; +static unsigned int nLines; +static uint32_t fgx, bgx, eorx; +static int rpi_video_initialized; + +static const int video_font_draw_table32[ 16 ][ 4 ] = { + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00000000, 0x00000000, 0x00000000, 0x00ffffff }, + { 0x00000000, 0x00000000, 0x00ffffff, 0x00000000 }, + { 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff }, + { 0x00000000, 0x00ffffff, 0x00000000, 0x00000000 }, + { 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff }, + { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000 }, + { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff }, + { 0x00ffffff, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff }, + { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000 }, + { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff }, + { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000 }, + { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff }, + { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000 }, + { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff } +}; + +void +rpi_fb_outch( char c ); + +void +rpi_video_init( void ); + +static void scroll( void ) +{ + int i, j; /* Counters */ + uint8_t *pt_scroll, *pt_bitmap; /* Pointers on the bit-map */ + + pt_bitmap = fb_mem; + j = 0; + pt_bitmap = pt_bitmap + j; + pt_scroll = pt_bitmap + bytes_per_char_line; + + for ( i = j; i < maxRow - 1; i++ ) { + memcpy( pt_bitmap, pt_scroll, bytes_per_char_line ); + pt_bitmap = pt_bitmap + bytes_per_char_line; + pt_scroll = pt_bitmap + bytes_per_char_line; + } + + /* + * Blank characters are displayed on the last line. + */ + memset( pt_bitmap, CONSOLE_BG_COL, bytes_per_char_line ); +} + +static void doCRNL( + int cr, + int nl +) +{ + if ( nl ) { + if ( ++row == maxRow ) { + scroll(); /* Scroll the screen now */ + row = maxRow - 1; + } + + nLines++; + } + + if ( cr ) + column = 0; + + /* Move cursor on the next location */ + if ( cr || nl ) { + wr_cursor( row, column ); + } +} + +static void advanceCursor( void ) +{ + if ( ++column == maxCol ) + doCRNL( 1, 1 ); + else + wr_cursor( row, column ); +} + +static void gotorc( + int r, + int c +) +{ + column = c; + row = r; + wr_cursor( row, column ); +} + +static void video_drawchars( + int r, + int c, + unsigned char ch +) +{ + if ( fb_mem == NULL ) { + return; + } + + uint8_t *cdat, *dest, *dest0; + int rows, offset; + + offset = r * bytes_per_char_line + c * bytes_per_pixel * RPI_FONT_WIDTH; + dest0 = fb_mem + offset; + + /* + * only 32-bit per pixel format is supported for now + */ + cdat = rpi_font + ch * RPI_FONT_HEIGHT; + + for ( rows = RPI_FONT_HEIGHT, dest = dest0; + rows--; dest += bytes_per_line ) { + uint8_t bits = *cdat++; + + ( (uint32_t *) dest )[ 0 ] = + ( video_font_draw_table32 + [ bits >> 4 ][ 0 ] & eorx ) ^ bgx; + ( (uint32_t *) dest )[ 1 ] = + ( video_font_draw_table32 + [ bits >> 4 ][ 1 ] & eorx ) ^ bgx; + ( (uint32_t *) dest )[ 2 ] = + ( video_font_draw_table32 + [ bits >> 4 ][ 2 ] & eorx ) ^ bgx; + ( (uint32_t *) dest )[ 3 ] = + ( video_font_draw_table32 + [ bits >> 4 ][ 3 ] & eorx ) ^ bgx; + + ( (uint32_t *) dest )[ 4 ] = + ( video_font_draw_table32 + [ bits & 15 ][ 0 ] & eorx ) ^ bgx; + ( (uint32_t *) dest )[ 5 ] = + ( video_font_draw_table32 + [ bits & 15 ][ 1 ] & eorx ) ^ bgx; + ( (uint32_t *) dest )[ 6 ] = + ( video_font_draw_table32 + [ bits & 15 ][ 2 ] & eorx ) ^ bgx; + ( (uint32_t *) dest )[ 7 ] = + ( video_font_draw_table32 + [ bits & 15 ][ 3 ] & eorx ) ^ bgx; + } +} + +#define ESC ( (char) 27 ) +/* erase current location without moving the cursor */ +#define BLANK ( (char) 0x7f ) + +static void videoPutChar( char ch ) +{ + switch ( ch ) { + case '\b': { + if ( column ) + column--; + + /* Move cursor on the previous location */ + wr_cursor( row, column ); + return; + } + case '\t': { + int i; + + i = TAB_SPACE - ( column & ( TAB_SPACE - 1 ) ); + + while ( i-- ) { + + video_drawchars( row, column, ' ' ); + column += 1; + + if ( column >= maxCol ) { + doCRNL( 1, 1 ); + return; + } + } + + wr_cursor( row, column ); + + return; + } + case '\n': { + doCRNL( 0, 1 ); + return; + } + case 7: { /* Bell code must be inserted here */ + return; + } + case '\r': { + doCRNL( 1, 0 ); + return; + } + case BLANK: { + video_drawchars( row, column, ' ' ); + + wr_cursor( row, column ); + + return; + } + default: { + // *pt_bitmap = (unsigned char)ch | attribute; + video_drawchars( row, column, ch ); + advanceCursor(); + return; + } + } +} + +/* trivial state machine to handle escape sequences: + * + * --------------------------------- + * | | + * | | + * KEY: esc V [ DCABHKJ esc | + * STATE: 0 -----> 27 -----> '[' ----------> -1 ----- + * ^\ \ \ \ + * KEY: | \other \ other \ other \ other + * <------------------------------------- + * + * in state '-1', the DCABHKJ cases are handled + * + * (cursor motion and screen clearing) + */ + +#define DONE ( -1 ) + +static int handleEscape( + int oldState, + char ch +) +{ + int rval = 0; + int ro, co; + + switch ( oldState ) { + case DONE: /* means the previous char terminated an ESC sequence... */ + case 0: + + if ( 27 == ch ) { + rval = 27; /* START of an ESC sequence */ + } + + break; + + case 27: + + if ( '[' == ch ) { + rval = ch; /* received ESC '[', so far */ + } else { + /* dump suppressed 'ESC'; outch will append the char */ + videoPutChar( ESC ); + } + + break; + + case '[': + /* handle 'ESC' '[' sequences here */ + ro = row; + co = column; + rval = DONE; /* done */ + + switch ( ch ) { + case 'D': /* left */ + + if ( co > 0 ) + co--; + + break; + case 'C': /* right */ + + if ( co < maxCol ) + co++; + + break; + case 'A': /* up */ + + if ( ro > 0 ) + ro--; + + break; + case 'B': /* down */ + + if ( ro < maxRow ) + ro++; + + break; + case 'H': /* home */ + ro = co = 0; + break; + case 'K': /* clear to end of line */ + + while ( column < maxCol - 1 ) + videoPutChar( ' ' ); + + videoPutChar( BLANK ); + break; + case 'J': /* clear to end of screen */ + + while ( ( ( row < maxRow - 1 ) || ( column < maxCol - 1 ) ) ) + videoPutChar( ' ' ); + + videoPutChar( BLANK ); + break; + default: + videoPutChar( ESC ); + videoPutChar( '[' ); + /* DONT move the cursor */ + ro = -1; + rval = 0; + break; + } + + // /* reset cursor */ + if ( ro >= 0 ) + gotorc( ro, co ); + + default: + break; + } + + return rval; +} + +static void clear_screen( void ) +{ + int i, j; + + for ( j = 0; j < maxRow; j++ ) { + for ( i = 0; i < maxCol; i++ ) { + videoPutChar( ' ' ); + } + } + + column = 0; + row = 0; +} + +void rpi_fb_outch( char c ) +{ + static int escaped = 0; + + if ( !( escaped = handleEscape( escaped, c ) ) ) { + if ( '\n' == c ) + videoPutChar( '\r' ); + + videoPutChar( c ); + } +} + +void rpi_video_init( void ) +{ + struct fb_var_screeninfo fb_var_info; + struct fb_fix_screeninfo fb_fix_info; + rpi_get_var_screen_info( &fb_var_info ); + rpi_get_fix_screen_info( &fb_fix_info ); + maxCol = fb_var_info.xres / RPI_FONT_WIDTH; + maxRow = fb_var_info.yres / RPI_FONT_HEIGHT; + bytes_per_pixel = fb_var_info.bits_per_pixel / 8; + bytes_per_line = bytes_per_pixel * fb_var_info.xres; + bytes_per_char_line = RPI_FONT_HEIGHT * bytes_per_line; + fb_mem = RTEMS_DEVOLATILE( void *, fb_fix_info.smem_start ); + column = 0; + row = 0; + nLines = 0; + fgx = ( CONSOLE_FG_COL << 24 ) | + ( CONSOLE_FG_COL << 16 ) | + ( CONSOLE_FG_COL << 8 ) | + CONSOLE_FG_COL; + bgx = ( CONSOLE_BG_COL << 24 ) | + ( CONSOLE_BG_COL << 16 ) | + ( CONSOLE_BG_COL << 8 ) | + CONSOLE_BG_COL; + eorx = fgx ^ bgx; + clear_screen(); + rpi_video_initialized = 1; +} +/* for old DOS compatibility n-curses type of applications */ +void gotoxy( + int x, + int y +); +int whereX( void ); +int whereY( void ); + +void gotoxy( + int x, + int y +) +{ + gotorc( y, x ); +} + +int whereX( void ) +{ + return row; +} + +int whereY( void ) +{ + return column; +} |