summaryrefslogtreecommitdiffstats
path: root/bsps/x86_64/amd64/console/outch.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bsps/x86_64/amd64/console/outch.c461
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;
+}