summaryrefslogtreecommitdiff
path: root/Kernel/VGA.cpp
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-10-16 11:01:38 +0200
committerAndreas Kling <awesomekling@gmail.com>2018-10-16 11:02:00 +0200
commit9396108034acd4bdd91532e13528f0b94af16653 (patch)
tree26d7870743b3276555db4f2408a4ce9c3f8ced9a /Kernel/VGA.cpp
parentf6086297047b639ede6fc0e058e4efcfc09ea46f (diff)
downloadserenity-9396108034acd4bdd91532e13528f0b94af16653.zip
Import the "gerbert" kernel I worked on earlier this year.
It's a lot crappier than I remembered it. It's gonna need a lot of work.
Diffstat (limited to 'Kernel/VGA.cpp')
-rw-r--r--Kernel/VGA.cpp237
1 files changed, 237 insertions, 0 deletions
diff --git a/Kernel/VGA.cpp b/Kernel/VGA.cpp
new file mode 100644
index 0000000000..c9916a3b79
--- /dev/null
+++ b/Kernel/VGA.cpp
@@ -0,0 +1,237 @@
+#include "types.h"
+#include "VGA.h"
+#include "i386.h"
+#include "IO.h"
+#include "StdLib.h"
+#include "Task.h"
+#include <stdarg.h>
+
+PRIVATE BYTE *vga_mem = 0L;
+PRIVATE BYTE current_attr = 0x07;
+
+PRIVATE volatile WORD soft_cursor;
+
+PRIVATE void print_num( DWORD );
+PRIVATE void print_hex( DWORD, BYTE fields );
+static void printSignedNumber(int);
+
+PRIVATE void
+putch( char ch )
+{
+ WORD row;
+
+ switch( ch )
+ {
+ case '\n':
+ row = soft_cursor / 80;
+ if( row == 23 )
+ {
+ memcpy( vga_mem, vga_mem + 160, 160 * 23 );
+ memset( vga_mem + (160 * 23), 0, 160 );
+ soft_cursor = row * 80;
+ }
+ else
+ soft_cursor = (row + 1) * 80;
+ return;
+ default:
+ vga_mem[soft_cursor * 2] = ch;
+ vga_mem[soft_cursor * 2 + 1] = current_attr;
+ soft_cursor++;
+ }
+ row = soft_cursor / 80;
+ if ((row >= 24 && current->handle() != IPC::Handle::PanelTask)) {
+ memcpy( vga_mem, vga_mem + 160, 160 * 23 );
+ memset( vga_mem + (160 * 23), 0, 160 );
+ soft_cursor = 23 * 80;
+ }
+}
+
+PUBLIC void
+kprintf( const char *fmt, ... )
+{
+ const char *p;
+ va_list ap;
+
+ soft_cursor = vga_get_cursor();
+
+ va_start( ap, fmt );
+
+ for( p = fmt; *p; ++p )
+ {
+ if( *p == '%' && *(p + 1) )
+ {
+ ++p;
+ switch( *p )
+ {
+ case 's':
+ {
+ const char* sp = va_arg(ap, const char*);
+ //ASSERT(sp != nullptr);
+ if (!sp) {
+ putch('<');
+ putch('N');
+ putch('u');
+ putch('L');
+ putch('>');
+ } else {
+ for (; *sp; ++sp)
+ putch(*sp);
+ }
+ }
+ break;
+
+ case 'd':
+ printSignedNumber(va_arg(ap, int));
+ break;
+
+ case 'u':
+ print_num( va_arg( ap, DWORD ));
+ break;
+
+ case 'x':
+ print_hex( va_arg( ap, DWORD ), 8 );
+ break;
+
+ case 'b':
+ print_hex( va_arg( ap, int ), 2 );
+ break;
+
+ case 'c':
+ putch( (char)va_arg( ap, int ));
+ break;
+
+ case 'p':
+ putch( '0' );
+ putch( 'x' );
+ print_hex( va_arg( ap, DWORD ), 8 );
+ break;
+ }
+ }
+ else
+ {
+ putch( *p );
+ }
+ }
+
+ /* va_arg( ap, type ); */
+ va_end( ap );
+
+ vga_set_cursor( soft_cursor );
+}
+
+PRIVATE void
+print_hex( DWORD number, BYTE fields )
+{
+ static const char h[] = {
+ '0','1','2','3','4','5','6','7',
+ '8','9','a','b','c','d','e','f'
+ };
+
+ BYTE shr_count = fields * 4;
+ while( shr_count )
+ {
+ shr_count -= 4;
+ putch( h[(number >> shr_count) & 0x0F] );
+ }
+}
+
+PRIVATE void
+print_num( DWORD number )
+{
+ DWORD divisor = 1000000000;
+ char ch;
+ char padding = 1;
+
+ for( ;; )
+ {
+ ch = '0' + (number / divisor);
+ number %= divisor;
+
+ if( ch != '0' )
+ padding = 0;
+
+ if( !padding || divisor == 1 )
+ putch( ch );
+
+ if( divisor == 1 )
+ break;
+ divisor /= 10;
+ }
+}
+
+static void printSignedNumber(int number)
+{
+ if (number < 0) {
+ putch('-');
+ print_num(0 - number);
+ } else {
+ print_num(number);
+ }
+}
+
+PUBLIC void
+vga_set_attr( BYTE attr )
+{
+ current_attr = attr;
+}
+
+PUBLIC BYTE
+vga_get_attr()
+{
+ return current_attr;
+}
+
+PUBLIC void
+vga_init()
+{
+ DWORD i;
+
+ current_attr = 0x07;
+ vga_mem = (BYTE *)0xb8000;
+
+ for( i = 0; i < (80 * 24); ++i )
+ {
+ vga_mem[i*2] = ' ';
+ vga_mem[i*2 + 1] = 0x07;
+ }
+
+ /* Fill the bottom line with blue. */
+ for( i = (80 * 24); i < (80 * 25); ++i )
+ {
+ vga_mem[i*2] = ' ';
+ vga_mem[i*2 + 1] = 0x17;
+ }
+ vga_set_cursor( 0 );
+}
+
+PUBLIC WORD
+vga_get_cursor()
+{
+ WORD value;
+ IO::out8(0x3d4, 0x0e);
+ value = IO::in8(0x3d5) << 8;
+ IO::out8(0x3d4, 0x0f);
+ value |= IO::in8(0x3d5);
+ return value;
+}
+
+PUBLIC void
+vga_set_cursor( WORD value )
+{
+ if( value >= (80 * 25) )
+ {
+ /* XXX: If you try to move the cursor off the screen, I will go reddish pink! */
+ vga_set_cursor( 0 );
+ current_attr = 0x0C;
+ return;
+ }
+ IO::out8(0x3d4, 0x0e);
+ IO::out8(0x3d5, MSB(value));
+ IO::out8(0x3d4, 0x0f);
+ IO::out8(0x3d5, LSB(value));
+}
+
+void vga_set_cursor(BYTE row, BYTE column)
+{
+ vga_set_cursor(row * 80 + column);
+}