Handout
This commit is contained in:
78
kernel/arch/cga.cc
Normal file
78
kernel/arch/cga.cc
Normal file
@@ -0,0 +1,78 @@
|
||||
#include "cga.h"
|
||||
|
||||
#include "../utils/math.h"
|
||||
#include "ioport.h"
|
||||
|
||||
namespace CGA {
|
||||
// I/O Ports required for hardware cursor
|
||||
constexpr IOPort index_port(0x3d4); ///< Graphic card register selection
|
||||
constexpr IOPort data_port(0x3d5); ///< Read/Write selected register
|
||||
|
||||
/*! \brief Helper structure for the hardware cursor
|
||||
*/
|
||||
union Cursor {
|
||||
uint16_t value;
|
||||
struct {
|
||||
uint16_t low : 8;
|
||||
uint16_t high : 6;
|
||||
uint16_t : 2;
|
||||
} __attribute__((packed));
|
||||
} __attribute__((packed));
|
||||
|
||||
/*! \brief Register (for index_port)
|
||||
*/
|
||||
enum RegisterIndex {
|
||||
CURSOR_START =
|
||||
10, ///< Control the cursor (blink timing and start scanline)
|
||||
CURSOR_END = 11, ///< Control the cursors end scanline
|
||||
START_ADDRESS_HIGH = 12, ///< Base offset address for output (high)
|
||||
START_ADDRESS_LOW = 13, ///< Base offset address for output (low)
|
||||
CURSOR_HIGH = 14, ///< Cursor offset address (high)
|
||||
CURSOR_LOW = 15, ///< Cursor offset address (low)
|
||||
};
|
||||
|
||||
void setCursor(unsigned abs_x, unsigned abs_y) {
|
||||
// Using the hardware cursor is quite important:
|
||||
// The access to the IO Ports is rather slow and -- if interrupted by
|
||||
// another output -- it will result in a strange word jumble.
|
||||
// Hence this helps in a quite visible manner to understand the
|
||||
// necessity of correct synchronization (and its performance impact).
|
||||
if (abs_x < COLUMNS && abs_y < ROWS) {
|
||||
Cursor pos = {static_cast<uint16_t>((abs_y * COLUMNS) + abs_x)};
|
||||
|
||||
// Select index 14 / CURSOR_HIGH register
|
||||
index_port.outb(CURSOR_HIGH);
|
||||
// Write high part of value to selected register (cursor high)
|
||||
data_port.outb(pos.high);
|
||||
// Select index 15 / CURSOR_LOW register
|
||||
index_port.outb(CURSOR_LOW);
|
||||
// Write low part of value to selected register (cursor low)
|
||||
data_port.outb(pos.low);
|
||||
}
|
||||
}
|
||||
|
||||
void getCursor(unsigned& abs_x, unsigned& abs_y) {
|
||||
Cursor pos = {.value = 0};
|
||||
|
||||
// Select index 14 / CURSOR_HIGH register
|
||||
index_port.outb(CURSOR_HIGH);
|
||||
// Read high part part of value from selected register (cursor high)
|
||||
pos.high = data_port.inb();
|
||||
// Select index 15 / CURSOR_LOW register
|
||||
index_port.outb(CURSOR_LOW);
|
||||
// Read low part of value from selected register (cursor low)
|
||||
pos.low = data_port.inb();
|
||||
|
||||
// Calculate absolute position
|
||||
abs_x = pos.value % COLUMNS;
|
||||
abs_y = Math::min(pos.value / COLUMNS, ROWS - 1);
|
||||
}
|
||||
|
||||
void show(unsigned abs_x, unsigned abs_y, char character, Attribute attrib) {
|
||||
// Output only on current page
|
||||
if (abs_x < COLUMNS && abs_y < ROWS) {
|
||||
Cell cell(character, attrib);
|
||||
TEXT_BUFFER_BASE[(abs_y * COLUMNS) + abs_x] = cell;
|
||||
}
|
||||
}
|
||||
}; // namespace CGA
|
||||
Reference in New Issue
Block a user