diff --git a/libmaxsi/include/libmaxsi/sortix-vga.h b/libmaxsi/include/libmaxsi/sortix-vga.h index 8d5daa6d..18f486ad 100644 --- a/libmaxsi/include/libmaxsi/sortix-vga.h +++ b/libmaxsi/include/libmaxsi/sortix-vga.h @@ -26,27 +26,12 @@ #ifndef LIBMAXSI_SORTIX_VGA_H #define LIBMAXSI_SORTIX_VGA_H +#include + namespace System { namespace VGA { - // TODO: Move these to a better place - #define COLOR8_BLACK 0 - #define COLOR8_BLUE 1 - #define COLOR8_GREEN 2 - #define COLOR8_CYAN 3 - #define COLOR8_RED 4 - #define COLOR8_MAGENTA 5 - #define COLOR8_BROWN 6 - #define COLOR8_LIGHT_GREY 7 - #define COLOR8_DARK_GREY 8 - #define COLOR8_LIGHT_BLUE 9 - #define COLOR8_LIGHT_GREEN 10 - #define COLOR8_LIGHT_CYAN 11 - #define COLOR8_LIGHT_RED 12 - #define COLOR8_LIGHT_MAGENTA 13 - #define COLOR8_LIGHT_BROWN 14 - #define COLOR8_WHITE 15 } } diff --git a/sortix/include/sortix/vga.h b/sortix/include/sortix/vga.h new file mode 100644 index 00000000..2c0dcf19 --- /dev/null +++ b/sortix/include/sortix/vga.h @@ -0,0 +1,52 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + + This file is part of Sortix. + + Sortix 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, either version 3 of the License, or (at your option) any later + version. + + Sortix 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 + Sortix. If not, see . + + sortix/vga.h + Standard symbolic constants and types for Sortix. + +*******************************************************************************/ + +#ifndef INC_SORTIX_VGA_H +#define INC_SORTIX_VGA_H + +#include + +__BEGIN_DECLS + +#define COLOR8_BLACK 0 +#define COLOR8_BLUE 1 +#define COLOR8_GREEN 2 +#define COLOR8_CYAN 3 +#define COLOR8_RED 4 +#define COLOR8_MAGENTA 5 +#define COLOR8_BROWN 6 +#define COLOR8_LIGHT_GREY 7 +#define COLOR8_DARK_GREY 8 +#define COLOR8_LIGHT_BLUE 9 +#define COLOR8_LIGHT_GREEN 10 +#define COLOR8_LIGHT_CYAN 11 +#define COLOR8_LIGHT_RED 12 +#define COLOR8_LIGHT_MAGENTA 13 +#define COLOR8_LIGHT_BROWN 14 +#define COLOR8_WHITE 15 + +__END_DECLS + +#endif + diff --git a/sortix/vga.cpp b/sortix/vga.cpp index 0fc71a8d..11297bae 100644 --- a/sortix/vga.cpp +++ b/sortix/vga.cpp @@ -35,193 +35,194 @@ using namespace Maxsi; -namespace Sortix +namespace Sortix { +namespace VGA { + +uint8_t* const VGA = (byte* const) 0xB8000; +const unsigned WIDTH = 80; +const unsigned HEIGHT = 25; +const size_t VGA_SIZE = sizeof(uint16_t) * WIDTH * HEIGHT; +size_t vgafontsize; +uint8_t* vgafont; + +static void WriteIndex(uint16_t port, uint8_t index, uint8_t value) { - namespace VGA + CPU::OutPortB(port, index); + CPU::OutPortB(port+1, value); +} + +static uint8_t ReadIndex(uint16_t port, uint8_t index) +{ + CPU::OutPortB(port, index); + return CPU::InPortB(port+1); +} + +static uint8_t ReplaceIndex(uint16_t port, uint8_t index, uint8_t value) +{ + uint8_t ret = ReadIndex(port, index); + WriteIndex(port, index, value); + return ret; +} + +static void FetchVGAFont(uint8_t* font) +{ + // TODO: I just got these magic constants off the net. + // Select plane 2 for reading. + uint8_t old_03ce_04 = ReplaceIndex(0x03CE, 0x04, 0x02); + // Clear even/odd mode. + uint8_t old_03ce_05 = ReplaceIndex(0x03CE, 0x05, 0x04); + // Map VGA Memory to 0xA0000 (Select 0xA0000-0xAFFFF). + uint8_t old_03ce_06 = ReplaceIndex(0x03CE, 0x06, 0x04); + // Set bitplane 2. + uint8_t old_03c4_02 = ReplaceIndex(0x03C4, 0x02, 0x04); + // Clear even/odd mode (the other way, don't ask why). + uint8_t old_03c4_04 = ReplaceIndex(0x03C4, 0x04, 0x07); + // The font data is now at 0xA0000, so fetch it. Note that there is + // reserved room for a 8x32 resolution but we are using 8x16. + const uint8_t* data = (const uint8_t*) 0xA0000UL; + for ( size_t i = 0; i < VGA_FONT_NUMCHARS; i++ ) { - byte* const VGA = (byte* const) 0xB8000; - const unsigned WIDTH = 80; - const unsigned HEIGHT = 25; - const size_t VGA_SIZE = sizeof(uint16_t) * WIDTH * HEIGHT; - size_t vgafontsize; - uint8_t* vgafont; - - static void WriteIndex(uint16_t port, uint8_t index, uint8_t value) - { - CPU::OutPortB(port, index); - CPU::OutPortB(port+1, value); - } - - static uint8_t ReadIndex(uint16_t port, uint8_t index) - { - CPU::OutPortB(port, index); - return CPU::InPortB(port+1); - } - - static uint8_t ReplaceIndex(uint16_t port, uint8_t index, uint8_t value) - { - uint8_t ret = ReadIndex(port, index); - WriteIndex(port, index, value); - return ret; - } - - static void FetchVGAFont(uint8_t* font) - { - // TODO: I just got these magic constants off the net. - // Select plane 2 for reading. - uint8_t old_03ce_04 = ReplaceIndex(0x03CE, 0x04, 0x02); - // Clear even/odd mode. - uint8_t old_03ce_05 = ReplaceIndex(0x03CE, 0x05, 0x04); - // Map VGA Memory to 0xA0000 (Select 0xA0000-0xAFFFF). - uint8_t old_03ce_06 = ReplaceIndex(0x03CE, 0x06, 0x04); - // Set bitplane 2. - uint8_t old_03c4_02 = ReplaceIndex(0x03C4, 0x02, 0x04); - // Clear even/odd mode (the other way, don't ask why). - uint8_t old_03c4_04 = ReplaceIndex(0x03C4, 0x04, 0x07); - // The font data is now at 0xA0000, so fetch it. Note that there is - // reserved room for a 8x32 resolution but we are using 8x16. - const uint8_t* data = (const uint8_t*) 0xA0000UL; - for ( size_t i = 0; i < VGA_FONT_NUMCHARS; i++ ) - { - const uint8_t* src = data + (32*8)/8 * i; - uint8_t* dest = font + VGA_FONT_CHARSIZE * i; - Memory::Copy(dest, src, VGA_FONT_CHARSIZE); - } - // Restore the VGA state. - WriteIndex(0x03C4, 0x02, old_03c4_02); - WriteIndex(0x03C4, 0x04, old_03c4_04); - WriteIndex(0x03CE, 0x05, old_03ce_05); - WriteIndex(0x03CE, 0x06, old_03ce_06); - WriteIndex(0x03CE, 0x04, old_03ce_04); - } + const uint8_t* src = data + (32*8)/8 * i; + uint8_t* dest = font + VGA_FONT_CHARSIZE * i; + Memory::Copy(dest, src, VGA_FONT_CHARSIZE); + } + // Restore the VGA state. + WriteIndex(0x03C4, 0x02, old_03c4_02); + WriteIndex(0x03C4, 0x04, old_03c4_04); + WriteIndex(0x03CE, 0x05, old_03ce_05); + WriteIndex(0x03CE, 0x06, old_03ce_06); + WriteIndex(0x03CE, 0x04, old_03ce_04); +} #if TEST_VGAFONT - static void PrintFontChar(const uint8_t* font, unsigned char c) +static void PrintFontChar(const uint8_t* font, unsigned char c) +{ + const uint8_t* glyph = font + VGA_FONT_CHARSIZE * (size_t) c; + for ( size_t y = 0; y < VGA_FONT_HEIGHT; y++ ) + { + for ( size_t x = 0; x < VGA_FONT_WIDTH; x++ ) { - const uint8_t* glyph = font + VGA_FONT_CHARSIZE * (size_t) c; - for ( size_t y = 0; y < VGA_FONT_HEIGHT; y++ ) - { - for ( size_t x = 0; x < VGA_FONT_WIDTH; x++ ) - { - size_t bitindex = y * VGA_FONT_WIDTH + x; - uint8_t bitmap = glyph[bitindex/8UL]; - uint8_t bitmod = bitindex % 8UL; - uint8_t bitmask = 1U << bitmod; - const char* toprint = (bitmap & bitmask) ? "X" : " "; - Log::Print(toprint); - } - Log::Print("\n"); - } + size_t bitindex = y * VGA_FONT_WIDTH + x; + uint8_t bitmap = glyph[bitindex/8UL]; + uint8_t bitmod = bitindex % 8UL; + uint8_t bitmask = 1U << bitmod; + const char* toprint = (bitmap & bitmask) ? "X" : " "; + Log::Print(toprint); } -#endif - - const uint8_t* GetFont() - { - return vgafont; - } - - void Init() - { - vgafontsize = VGA_FONT_NUMCHARS * VGA_FONT_CHARSIZE; - if ( !(vgafont = new uint8_t[vgafontsize]) ) - Panic("Unable to allocate vga font buffer"); - FetchVGAFont(vgafont); -#if TEST_VGAFONT - PrintFontChar(vgafont, 'A'); - PrintFontChar(vgafont, 'S'); -#endif - } - - // Changes the position of the hardware cursor. - void SetCursor(nat x, nat y) - { - nat value = x + y * WIDTH; - - // This sends a command to indicies 14 and 15 in the - // CRT Control Register of the VGA controller. These - // are the high and low bytes of the index that show - // where the hardware cursor is to be 'blinking'. - CPU::OutPortB(0x3D4, 14); - CPU::OutPortB(0x3D5, (value >> 8) & 0xFF); - CPU::OutPortB(0x3D4, 15); - CPU::OutPortB(0x3D5, (value >> 0) & 0xFF); - } - } - - DevVGA::DevVGA() - { - offset = 0; - } - - DevVGA::~DevVGA() - { -#ifdef PLATFORM_SERIAL - // TODO: HACK: This is a hack that is unrelated to this file. - // This is a hack to make the cursor a proper color after the vga buffer - // has been radically modified. The best solution would be for the VGA - // to ANSI Escape Codes converter to keep track of colors and restoring - // them, but this will do for now. - Log::PrintF("\e[m"); -#endif - } - - ssize_t DevVGA::Read(byte* dest, size_t count) - { - if ( VGA::VGA_SIZE - offset < count ) { count = VGA::VGA_SIZE - offset; } - Maxsi::Memory::Copy(dest, VGA::VGA + offset, count); - offset += count; - return count; - } - - ssize_t DevVGA::Write(const byte* src, size_t count) - { - if ( offset == VGA::VGA_SIZE && count ) { Error::Set(ENOSPC); return -1; } - if ( VGA::VGA_SIZE - offset < count ) { count = VGA::VGA_SIZE - offset; } - Maxsi::Memory::Copy(VGA::VGA + offset, src, count); - offset = (offset + count) % VGA::VGA_SIZE; - VGA::SetCursor(VGA::WIDTH, VGA::HEIGHT-1); -#ifdef PLATFORM_SERIAL - SerialTerminal::OnVGAModified(); -#endif - return count; - } - - bool DevVGA::IsReadable() - { - return true; - } - - bool DevVGA::IsWritable() - { - return true; - } - - size_t DevVGA::BlockSize() - { - return 1; - } - - uintmax_t DevVGA::Size() - { - return VGA::VGA_SIZE; - } - - uintmax_t DevVGA::Position() - { - return offset; - } - - bool DevVGA::Seek(uintmax_t position) - { - if ( VGA::VGA_SIZE < position ) { Error::Set(EINVAL); return false; } - offset = position; - return true; - } - - bool DevVGA::Resize(uintmax_t size) - { - if ( size == VGA::VGA_SIZE ) { return false; } - Error::Set(ENOSPC); - return false; + Log::Print("\n"); } } +#endif + +const uint8_t* GetFont() +{ + return vgafont; +} + +void Init() +{ + vgafontsize = VGA_FONT_NUMCHARS * VGA_FONT_CHARSIZE; + if ( !(vgafont = new uint8_t[vgafontsize]) ) + Panic("Unable to allocate vga font buffer"); + FetchVGAFont(vgafont); +#if TEST_VGAFONT + PrintFontChar(vgafont, 'A'); + PrintFontChar(vgafont, 'S'); +#endif +} + +// Changes the position of the hardware cursor. +void SetCursor(unsigned x, unsigned y) +{ + nat value = x + y * WIDTH; + + // This sends a command to indicies 14 and 15 in the + // CRT Control Register of the VGA controller. These + // are the high and low bytes of the index that show + // where the hardware cursor is to be 'blinking'. + CPU::OutPortB(0x3D4, 14); + CPU::OutPortB(0x3D5, (value >> 8) & 0xFF); + CPU::OutPortB(0x3D4, 15); + CPU::OutPortB(0x3D5, (value >> 0) & 0xFF); +} + +} // namespace VGA + +DevVGA::DevVGA() +{ + offset = 0; +} + +DevVGA::~DevVGA() +{ +#ifdef PLATFORM_SERIAL + // TODO: HACK: This is a hack that is unrelated to this file. + // This is a hack to make the cursor a proper color after the vga buffer + // has been radically modified. The best solution would be for the VGA + // to ANSI Escape Codes converter to keep track of colors and restoring + // them, but this will do for now. + Log::PrintF("\e[m"); +#endif +} + +ssize_t DevVGA::Read(byte* dest, size_t count) +{ + if ( VGA::VGA_SIZE - offset < count ) { count = VGA::VGA_SIZE - offset; } + Maxsi::Memory::Copy(dest, VGA::VGA + offset, count); + offset += count; + return count; +} + +ssize_t DevVGA::Write(const byte* src, size_t count) +{ + if ( offset == VGA::VGA_SIZE && count ) { Error::Set(ENOSPC); return -1; } + if ( VGA::VGA_SIZE - offset < count ) { count = VGA::VGA_SIZE - offset; } + Maxsi::Memory::Copy(VGA::VGA + offset, src, count); + offset = (offset + count) % VGA::VGA_SIZE; + VGA::SetCursor(VGA::WIDTH, VGA::HEIGHT-1); +#ifdef PLATFORM_SERIAL + SerialTerminal::OnVGAModified(); +#endif + return count; +} + +bool DevVGA::IsReadable() +{ + return true; +} + +bool DevVGA::IsWritable() +{ + return true; +} + +size_t DevVGA::BlockSize() +{ + return 1; +} + +uintmax_t DevVGA::Size() +{ + return VGA::VGA_SIZE; +} + +uintmax_t DevVGA::Position() +{ + return offset; +} + +bool DevVGA::Seek(uintmax_t position) +{ + if ( VGA::VGA_SIZE < position ) { Error::Set(EINVAL); return false; } + offset = position; + return true; +} + +bool DevVGA::Resize(uintmax_t size) +{ + if ( size == VGA::VGA_SIZE ) { return false; } + Error::Set(ENOSPC); + return false; +} + +} // namespace Sortix diff --git a/sortix/vga.h b/sortix/vga.h index efdcfee5..74ae90bd 100644 --- a/sortix/vga.h +++ b/sortix/vga.h @@ -28,63 +28,49 @@ #include "device.h" #include "stream.h" -namespace Sortix +namespace Sortix { + +const size_t VGA_FONT_WIDTH = 8UL; +const size_t VGA_FONT_HEIGHT = 16UL; +const size_t VGA_FONT_NUMCHARS = 256UL; +const size_t VGA_FONT_CHARSIZE = VGA_FONT_WIDTH * VGA_FONT_HEIGHT / 8UL; + +namespace VGA { + +void Init(); +void SetCursor(unsigned x, unsigned y); +const uint8_t* GetFont(); + +} // namespace VGA + +// TODO: This class shouldn't be exposed publicly; it is used in a hack in the +// /dev filesystem. However, vga.cpp should register /dev/vga instead. +class DevVGA : public DevBuffer { - const size_t VGA_FONT_WIDTH = 8UL; - const size_t VGA_FONT_HEIGHT = 16UL; - const size_t VGA_FONT_NUMCHARS = 256UL; - const size_t VGA_FONT_CHARSIZE = VGA_FONT_WIDTH * VGA_FONT_HEIGHT / 8UL; +public: + typedef DevBuffer BaseClass; - namespace VGA - { - // TODO: Move these to a better place - #define COLOR8_BLACK 0 - #define COLOR8_BLUE 1 - #define COLOR8_GREEN 2 - #define COLOR8_CYAN 3 - #define COLOR8_RED 4 - #define COLOR8_MAGENTA 5 - #define COLOR8_BROWN 6 - #define COLOR8_LIGHT_GREY 7 - #define COLOR8_DARK_GREY 8 - #define COLOR8_LIGHT_BLUE 9 - #define COLOR8_LIGHT_GREEN 10 - #define COLOR8_LIGHT_CYAN 11 - #define COLOR8_LIGHT_RED 12 - #define COLOR8_LIGHT_MAGENTA 13 - #define COLOR8_LIGHT_BROWN 14 - #define COLOR8_WHITE 15 +public: + DevVGA(); + virtual ~DevVGA(); - void Init(); - void SetCursor(nat x, nat y); - const uint8_t* GetFont(); - } +private: + size_t offset; - class DevVGA : public DevBuffer - { - public: - typedef DevBuffer BaseClass; +public: + virtual ssize_t Read(byte* dest, size_t count); + virtual ssize_t Write(const byte* src, size_t count); + virtual bool IsReadable(); + virtual bool IsWritable(); + virtual size_t BlockSize(); + virtual uintmax_t Size(); + virtual uintmax_t Position(); + virtual bool Seek(uintmax_t position); + virtual bool Resize(uintmax_t size); - public: - DevVGA(); - virtual ~DevVGA(); +}; - private: - size_t offset; - - public: - virtual ssize_t Read(byte* dest, size_t count); - virtual ssize_t Write(const byte* src, size_t count); - virtual bool IsReadable(); - virtual bool IsWritable(); - virtual size_t BlockSize(); - virtual uintmax_t Size(); - virtual uintmax_t Position(); - virtual bool Seek(uintmax_t position); - virtual bool Resize(uintmax_t size); - - }; -} +} // namespace Sortix #endif diff --git a/sortix/vgaterminal.cpp b/sortix/vgaterminal.cpp index 7d791ff5..cb463162 100644 --- a/sortix/vgaterminal.cpp +++ b/sortix/vgaterminal.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include "vga.h" #include "vgaterminal.h"