summaryrefslogtreecommitdiff
path: root/Source/Kernel/Devices/Display
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Kernel/Devices/Display')
-rw-r--r--Source/Kernel/Devices/Display/Display.proto.h8
-rw-r--r--Source/Kernel/Devices/Display/GraphicDisplay.proto.cpp64
-rw-r--r--Source/Kernel/Devices/Display/GraphicDisplay.proto.h24
-rw-r--r--Source/Kernel/Devices/Display/VESADisplay.class.cpp127
-rw-r--r--Source/Kernel/Devices/Display/VESADisplay.class.h65
-rw-r--r--Source/Kernel/Devices/Display/VGATextOutput.class.cpp16
-rw-r--r--Source/Kernel/Devices/Display/VGATextOutput.class.h6
-rw-r--r--Source/Kernel/Devices/Display/vga-vesa.wtf.asm11
8 files changed, 312 insertions, 9 deletions
diff --git a/Source/Kernel/Devices/Display/Display.proto.h b/Source/Kernel/Devices/Display/Display.proto.h
index e1775bd..8401e0b 100644
--- a/Source/Kernel/Devices/Display/Display.proto.h
+++ b/Source/Kernel/Devices/Display/Display.proto.h
@@ -19,7 +19,13 @@ class Display : public Device {
virtual void putChar(u16int line, u16int col, WChar c, u8int color) = 0; //Color : <bg 4bits><fg 4bits>
virtual void moveCursor(u16int line, u16int col) = 0;
- //Graphic functions
+ //Graphic functions, can stay unimplemented for textual displays
+ virtual void putPix(u16int x, u16int y, u32int color) {}
+ virtual u32int getPix(u16int x, u16int y) { return 0; }
+ //Advanced graphic functions. These have a simple implementation in GraphicDisplay,
+ //and should have an optimized version in each individual driver. This is also the
+ //case of the graphical putChar and moveCursor.
+ //drawLine, drawCircle, ...
};
#endif
diff --git a/Source/Kernel/Devices/Display/GraphicDisplay.proto.cpp b/Source/Kernel/Devices/Display/GraphicDisplay.proto.cpp
new file mode 100644
index 0000000..636a64c
--- /dev/null
+++ b/Source/Kernel/Devices/Display/GraphicDisplay.proto.cpp
@@ -0,0 +1,64 @@
+#include "GraphicDisplay.proto.h"
+
+#include <Ressources/ConsoleFont.cd>
+
+u32int consoleColor[16] = {
+ 0x00000000, // 0 == black
+ 0x00000077, // 1 == dark blue
+ 0x00007700, // 2 == dark green
+ 0x00007777, // 3 == dark cyan
+ 0x00770000, // 4 == dark red
+ 0x00770077, // 5 == dark magenta
+ 0x00777700, // 6 == dark orange
+ 0x00777777, // 7 == light grey
+ 0x00444444, // 8 == dark grey
+ 0x000000FF, // 9 == bright blue
+ 0x0000FF00, // A == bright green
+ 0x0000FFFF, // B == bright cyan
+ 0x00FF0000, // C == bright red
+ 0x00FF00FF, // D == bright yellow
+ 0x00FFFF00, // E == bright orange
+ 0x00FFFFFF, // F == white
+};
+
+void GraphicDisplay::putChar(u16int line, u16int col, WChar c, u8int color) {
+ u8int ch = c.toAscii();
+ if (ch == 0) return;
+
+ u16int sx = col * C_FONT_WIDTH, sy = line * C_FONT_HEIGHT;
+ u32int fgcolor = consoleColor[color & 0xF], bgcolor = consoleColor[(color >> 4) & 0xF];
+
+ for (int y = 0; y < C_FONT_HEIGHT; y++) {
+ u8int pixs = consoleFont[ch][y];
+ for (int x = C_FONT_WIDTH - 1; x >= 0; x--) {
+ putPix(sx + x, sy + y, ((pixs & 1) != 0 ? fgcolor : bgcolor));
+ pixs = pixs >> 1;
+ }
+ }
+}
+
+void GraphicDisplay::moveCursor(u16int line, u16int col) {
+ //If the current cursor position is correct, write there what is supposed to be there
+ if (m_csrbuff.x >= 0 and m_csrbuff.y >= 0) {
+ for (int x = 0; x < C_FONT_WIDTH; x++) {
+ for (int y = 0; y < C_FONT_HEIGHT; y++) {
+ putPix(m_csrbuff.x + x, m_csrbuff.y + y, m_csrbuff.buff[x][y]);
+ }
+ }
+ }
+
+ //Save the current stuff to the buffer
+ m_csrbuff.x = col * C_FONT_WIDTH;
+ m_csrbuff.y = line * C_FONT_HEIGHT;
+ for (int x = 0; x < C_FONT_WIDTH; x++) {
+ for (int y = 0; y < C_FONT_HEIGHT; y++) {
+ m_csrbuff.buff[x][y] = getPix(m_csrbuff.x + x, m_csrbuff.y + y);
+ }
+ }
+
+ //draw some cursor
+ for (int x = 0; x < C_FONT_WIDTH; x++) {
+ putPix(m_csrbuff.x + x, m_csrbuff.y + 14, 0x00FFFFFF);
+ putPix(m_csrbuff.x + x, m_csrbuff.y + 15, 0x00777777);
+ }
+}
diff --git a/Source/Kernel/Devices/Display/GraphicDisplay.proto.h b/Source/Kernel/Devices/Display/GraphicDisplay.proto.h
new file mode 100644
index 0000000..2f4be98
--- /dev/null
+++ b/Source/Kernel/Devices/Display/GraphicDisplay.proto.h
@@ -0,0 +1,24 @@
+#ifndef DEF_GRAPHICDISPLAY_PROTO_H
+#define DEF_GRAPHICDISPLAY_PROTO_H
+
+#include <Devices/Display/Display.proto.h>
+
+extern char consoleFont[256][16];
+extern u32int consoleColor[16];
+
+#define C_FONT_WIDTH 9 //This is width of one character ON SCREEN, real width is 8px (1px padding)
+#define C_FONT_HEIGHT 16
+
+class GraphicDisplay : public Display {
+ struct {
+ int x, y;
+ u32int buff[C_FONT_WIDTH][C_FONT_HEIGHT];
+ } m_csrbuff;
+
+ public:
+ GraphicDisplay() { m_csrbuff.x = -1; m_csrbuff.y = -1; }
+ virtual void putChar(u16int line, u16int col, WChar c, u8int color);
+ virtual void moveCursor(u16int line, u16int col);
+};
+
+#endif
diff --git a/Source/Kernel/Devices/Display/VESADisplay.class.cpp b/Source/Kernel/Devices/Display/VESADisplay.class.cpp
new file mode 100644
index 0000000..a1dc7c1
--- /dev/null
+++ b/Source/Kernel/Devices/Display/VESADisplay.class.cpp
@@ -0,0 +1,127 @@
+#include "VESADisplay.class.h"
+#include <DeviceManager/Disp.ns.h>
+
+extern v86_function_t vesa_int; //in vga-vesa.wtf.asm
+
+using namespace Disp;
+
+String VESADisplay::getClass() {
+ return "display.vesa";
+}
+
+String VESADisplay::getName() {
+ return "Standard VESA display";
+}
+
+vbe_controller_info_t VESADisplay::getCtrlrInfo() {
+ vbe_controller_info_t *info = (vbe_controller_info_t*)V86::alloc(sizeof(vbe_controller_info_t));
+ info->signature[0] = 'V'; info->signature[1] = 'B'; info->signature[2] = 'E'; info->signature[3] = '2';
+ info->videomodes = 0;
+ registers_t regs;
+ regs.eax = 0x00004F00;
+ regs.esi = LIN_SEG(info);
+ regs.edi = LIN_OFF(info);
+ V86::run(vesa_int, regs, 0);
+ if (regs.eax != 0x004F) PANIC("Something went wrong in detecting VBE modes.");
+ if (info->signature[3] != 'A') PANIC("No vesa sinature");
+ return *info;
+}
+
+vbe_mode_info_t VESADisplay::getModeInfo(u16int id) {
+ vbe_mode_info_t *mode = (vbe_mode_info_t*)V86::alloc(sizeof(vbe_mode_info_t));
+ CMem::memset((u8int*)mode, 0, sizeof(vbe_mode_info_t));
+ registers_t regs;
+ regs.eax = 0x00004F01;
+ regs.ecx = id;
+ regs.esi = LIN_SEG(mode);
+ regs.edi = LIN_OFF(mode);
+ V86::run(vesa_int, regs, 0);
+ return *mode;
+}
+
+void VESADisplay::getModes(Vector<mode_t> &to) {
+ vbe_controller_info_t info = getCtrlrInfo();
+
+ u16int *modes = (u16int*)(((info.videomodes & 0xFFFF0000) >> 12) | ((info.videomodes) & 0x0000FFFF));
+ for (int i = 0; i < 64; i++) {
+ if (modes[i] == 0xFFFF) break;
+ vbe_mode_info_t mode = getModeInfo(modes[i]);
+
+ if ((mode.attributes & 0x19) != 0x19) continue;
+ if (mode.planes != 1) continue;
+ mode_t m; m.device = this;
+ m.textCols = mode.Xres / C_FONT_WIDTH; m.textRows = mode.Yres / C_FONT_HEIGHT;
+ m.identifier = modes[i];
+ m.graphWidth = mode.Xres; m.graphHeight = mode.Yres; m.graphDepth = mode.bpp;
+ to.push(m);
+ }
+}
+
+bool VESADisplay::setMode(mode_t &mode) {
+ if (mode.device != this) return false;
+ m_currMode = getModeInfo(mode.identifier);
+ registers_t regs;
+ regs.eax = 0x00004F02;
+ regs.ebx = mode.identifier;
+ V86::run(vesa_int, regs, 0);
+ return true;
+}
+
+u8int* VESADisplay::memPos(u16int x, u16int y) {
+ u32int addr = y * m_currMode.pitch + x * (m_currMode.bpp / 8);
+
+ u8int *base = (u8int*)(((m_currMode.physbase & 0xFFFF0000) >> 12) | (m_currMode.physbase & 0x0000FFFF));
+
+ return base + addr;
+}
+
+void VESADisplay::clear() {
+ for (u16int y = 0; y < m_currMode.Yres; y++) {
+ for (u16int x = 0; x < m_currMode.Xres; x++) {
+ putPix(x, y, 0x77777777);
+ }
+ }
+}
+
+void VESADisplay::putPix(u16int x, u16int y, u32int c) {
+ u32int addr = y * m_currMode.pitch + x * (m_currMode.bpp / 8);
+ int banksize = m_currMode.granularity*1024;
+ int banknumber = addr / banksize;
+ int bankoffset = addr % banksize;
+
+ if (banknumber != b) {
+ registers_t r;
+ r.eax = 0x4F05;
+ r.ebx = 0;
+ r.edx = banknumber;
+ V86::run(vesa_int, r, 0);
+ b = banknumber;
+ }
+
+ u8int* a = (u8int*)(0xA0000 + bankoffset);
+ a[2] = (c >> 16) & 0xFF;
+ a[1] = (c >> 8) & 0xFF;
+ a[0] = c & 0xFF;
+}
+
+u32int VESADisplay::getPix(u16int x, u16int y) {
+ u32int addr = y * m_currMode.pitch + x * (m_currMode.bpp / 8);
+ int banksize = m_currMode.granularity*1024;
+ int banknumber = addr / banksize;
+ int bankoffset = addr % banksize;
+
+ if (banknumber != b) {
+ registers_t r;
+ r.eax = 0x4F05;
+ r.ebx = 0;
+ r.edx = banknumber;
+ V86::run(vesa_int, r, 0);
+ b = banknumber;
+ }
+
+ u32int ret;
+
+ u8int* a = (u8int*)(0xA0000 + bankoffset);
+ ret = (a[2] << 16) | (a[1] << 8) | a[0];
+ return ret;
+}
diff --git a/Source/Kernel/Devices/Display/VESADisplay.class.h b/Source/Kernel/Devices/Display/VESADisplay.class.h
new file mode 100644
index 0000000..9daf1b9
--- /dev/null
+++ b/Source/Kernel/Devices/Display/VESADisplay.class.h
@@ -0,0 +1,65 @@
+#ifndef DEF_VESADISPLAY_CLASS_H
+#define DEF_VESADISPLAY_CLASS_H
+
+#include <Devices/Display/GraphicDisplay.proto.h>
+#include <TaskManager/V86/V86.ns.h>
+
+struct vbe_controller_info_t {
+ char signature[4]; // == "VESA"
+ s16int version; // == 0x0300 for VBE 3.0
+ //s16int oemString[2]; // isa vbeFarPtr
+ FARPTR oemString;
+ u8int capabilities[4];
+ FARPTR videomodes;
+ s16int totalMemory; // as # of 64KB blocks
+} __attribute__((packed));
+
+struct vbe_mode_info_t {
+ u16int attributes;
+ u8int winA, winB;
+ u16int granularity;
+ u16int winsize;
+ u16int segmentA, segmentB;
+ FARPTR realFctPtr;
+ u16int pitch; // bytes per scanline
+
+ u16int Xres, Yres;
+ u8int Wchar, Ychar, planes, bpp, banks;
+ u8int memory_model, bank_size, image_pages;
+ u8int reserved0;
+
+ u8int red_mask, red_position;
+ u8int green_mask, green_position;
+ u8int blue_mask, blue_position;
+ u8int rsv_mask, rsv_position;
+ u8int directcolor_attributes;
+
+ u32int physbase; // your LFB address ;)
+ u32int reserved1;
+ u16int reserved2;
+} __attribute__ ((packed));
+
+class VESADisplay : public GraphicDisplay {
+ private:
+ vbe_controller_info_t getCtrlrInfo();
+ vbe_mode_info_t getModeInfo(u16int mode);
+
+ u8int* memPos(u16int x, u16int y);
+
+ vbe_mode_info_t m_currMode;
+
+ int b;
+
+ public:
+ String getClass();
+ String getName();
+
+ void getModes(Vector<Disp::mode_t> &to);
+ bool setMode(Disp::mode_t& mode);
+
+ void clear();
+ void putPix(u16int x, u16int y, u32int color);
+ u32int getPix(u16int x, u16int y);
+};
+
+#endif
diff --git a/Source/Kernel/Devices/Display/VGATextOutput.class.cpp b/Source/Kernel/Devices/Display/VGATextOutput.class.cpp
index 3265a7d..d307f60 100644
--- a/Source/Kernel/Devices/Display/VGATextOutput.class.cpp
+++ b/Source/Kernel/Devices/Display/VGATextOutput.class.cpp
@@ -21,19 +21,23 @@ String VGATextOutput::getName() {
void VGATextOutput::getModes(Vector<mode_t> &to) {
mode_t m;
- m.textCols = 80;
+ m.textCols = 40;
m.textRows = 25;
- m.identifier = 3;
+ m.identifier = 1;
m.graphWidth = 0;
m.graphHeight = 0;
m.device = this;
to.push(m);
+ m.textCols = 80;
+ m.identifier = 3; //3 = text 80x25 16color, just what we want
+ to.push(m);
}
bool VGATextOutput::setMode(mode_t& mode) {
- if (mode.device == this && mode.identifier == 3) {
+ if (mode.device == this && (mode.identifier == 3 or mode.identifier == 1)) {
registers_t r;
- r.eax = 3; //3 = text 80x25 16color, just what we want
+ r.eax = mode.identifier;
+ m_cols = mode.textCols;
V86::run(setvgamode, r, 0);
clear();
return true;
@@ -43,11 +47,11 @@ bool VGATextOutput::setMode(mode_t& mode) {
void VGATextOutput::putChar(u16int line, u16int col, WChar c, u8int color) {
u16int* where = (u16int*)RAM_ADDR;
- where[(80 * line) + col] = (color << 8) | c.toAscii();
+ where[(m_cols * line) + col] = (color << 8) | c.toAscii();
}
void VGATextOutput::moveCursor(u16int line, u16int col) {
- u16int csrLoc = (line * 80) + col;
+ u16int csrLoc = (line * m_cols) + col;
outb(0x3D4, 14);
outb(0x3D5, csrLoc >> 8);
outb(0x3D4, 15);
diff --git a/Source/Kernel/Devices/Display/VGATextOutput.class.h b/Source/Kernel/Devices/Display/VGATextOutput.class.h
index 1ced227..2c72d40 100644
--- a/Source/Kernel/Devices/Display/VGATextOutput.class.h
+++ b/Source/Kernel/Devices/Display/VGATextOutput.class.h
@@ -4,15 +4,17 @@
#include <Devices/Display/Display.proto.h>
class VGATextOutput : public Display {
+ int m_cols;
+
public:
+ VGATextOutput() : m_cols(80) {}
+
String getClass();
String getName();
void getModes(Vector<Disp::mode_t> &to);
bool setMode(Disp::mode_t& mode);
- u16int textCols();
- u16int textRows();
void putChar(u16int line, u16int col, WChar c, u8int color);
void moveCursor(u16int line, u16int col);
void clear();
diff --git a/Source/Kernel/Devices/Display/vga-vesa.wtf.asm b/Source/Kernel/Devices/Display/vga-vesa.wtf.asm
index c7b6bb5..4a6a1d6 100644
--- a/Source/Kernel/Devices/Display/vga-vesa.wtf.asm
+++ b/Source/Kernel/Devices/Display/vga-vesa.wtf.asm
@@ -9,3 +9,14 @@ setvgamode_start:
int 3
setvgamode_end:
db 0
+
+[GLOBAL vesa_int]
+vesa_int:
+ dw vesa_int_end - vesa_int_start
+vesa_int_start:
+ int 60
+ mov es, si
+ int 10h
+ int 3
+vesa_int_end:
+ db 0