summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-11-09 21:18:03 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-11-09 21:18:03 +0100
commit3e3de67f025f427b557403193b0514ff19958c92 (patch)
tree0f5f08f9d5374cf453db07b3045be5bb5008d9a9 /Kernel
parent8a865c11ec25c1d313146c055f5efaea862e7a8d (diff)
downloadserenity-3e3de67f025f427b557403193b0514ff19958c92.zip
Use the VGA start address for fast VirtualConsole scrolling.
Instead of memcpy'ing the entire screen every time we press enter at the bottom, use the VGA start address register to make a "view" onto the underlying memory that moves downward as we scroll. Eventually we run out of memory and have to reset to the start of the buffer. That's when we memcpy everything. It would be cool if there was some way to get the hardware to act like a ring buffer with automatic wrapping here but I don't know how to do that.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/.bochsrc2
-rw-r--r--Kernel/Process.cpp2
-rw-r--r--Kernel/VGA.cpp34
-rw-r--r--Kernel/VGA.h3
-rw-r--r--Kernel/VirtualConsole.cpp55
-rw-r--r--Kernel/VirtualConsole.h6
6 files changed, 76 insertions, 26 deletions
diff --git a/Kernel/.bochsrc b/Kernel/.bochsrc
index 03643f30f3..a061866f39 100644
--- a/Kernel/.bochsrc
+++ b/Kernel/.bochsrc
@@ -26,7 +26,7 @@ optramimage2: file=none
optramimage3: file=none
optramimage4: file=none
pci: enabled=1, chipset=i440fx
-vga: extension=vbe, update_freq=5, realtime=1
+vga: extension=vbe, update_freq=25, realtime=1
cpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
cpuid: level=6, stepping=3, model=3, family=6, vendor_string="GenuineIntel", brand_string=" Intel(R) Pentium(R) 4 CPU "
cpuid: mmx=true, apic=xapic, simd=sse2, sse4a=false, misaligned_sse=false, sep=true
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index 54e0bde6e7..c1f0d69c4c 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -592,7 +592,7 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t ppid, RingLevel ring
if (!fork_parent->m_file_descriptors[i])
continue;
#ifdef FORK_DEBUG
- dbgprintf("fork: cloning fd %u... (%p) istty? %um\n", i, fork_parent->m_file_descriptors[i].ptr(), fork_parent->m_file_descriptors[i]->isTTY());
+ dbgprintf("fork: cloning fd %u... (%p) istty? %u\n", i, fork_parent->m_file_descriptors[i].ptr(), fork_parent->m_file_descriptors[i]->isTTY());
#endif
m_file_descriptors[i] = fork_parent->m_file_descriptors[i]->clone();
}
diff --git a/Kernel/VGA.cpp b/Kernel/VGA.cpp
index 4c65b7d9cb..f927abed54 100644
--- a/Kernel/VGA.cpp
+++ b/Kernel/VGA.cpp
@@ -7,13 +7,6 @@
static byte* vga_mem = nullptr;
-void vga_scroll_up()
-{
- InterruptDisabler disabler;
- memcpy(vga_mem, vga_mem + 160, 160 * 24);
- vga_clear_row(24);
-}
-
void vga_clear_row(word line)
{
InterruptDisabler disabler;
@@ -37,6 +30,24 @@ void vga_putch_at(byte row, byte column, byte ch, byte attr)
vga_mem[cur + 1] = attr;
}
+word vga_get_start_address()
+{
+ word value;
+ IO::out8(0x3d4, 0x0d);
+ value = IO::in8(0x3d5) << 8;
+ IO::out8(0x3d4, 0x0c);
+ value |= IO::in8(0x3d5);
+ return value;
+}
+
+void vga_set_start_address(word value)
+{
+ IO::out8(0x3d4, 0x0c);
+ IO::out8(0x3d5, MSB(value));
+ IO::out8(0x3d4, 0x0d);
+ IO::out8(0x3d5, LSB(value));
+}
+
void vga_init()
{
vga_mem = (byte*)0xb8000;
@@ -61,10 +72,6 @@ WORD vga_get_cursor()
void vga_set_cursor(WORD value)
{
- if (value >= (80 * 25)) {
- vga_set_cursor(0);
- return;
- }
IO::out8(0x3d4, 0x0e);
IO::out8(0x3d5, MSB(value));
IO::out8(0x3d4, 0x0f);
@@ -75,3 +82,8 @@ void vga_set_cursor(BYTE row, BYTE column)
{
vga_set_cursor(row * 80 + column);
}
+
+void vga_set_cursor(byte row, byte column, word start_address)
+{
+ vga_set_cursor((start_address) + (row * 80 + column));
+}
diff --git a/Kernel/VGA.h b/Kernel/VGA.h
index f477a61090..b34bbd1075 100644
--- a/Kernel/VGA.h
+++ b/Kernel/VGA.h
@@ -4,9 +4,12 @@
void vga_init();
void vga_set_cursor(WORD);
+void vga_set_cursor(byte row, byte column, word start_address);
void vga_set_cursor(BYTE row, BYTE column);
WORD vga_get_cursor();
void vga_putch_at(byte row, byte column, byte ch, byte attr);
void vga_scroll_up();
void vga_clear();
void vga_clear_row(word);
+word vga_get_start_address();
+void vga_set_start_address(word);
diff --git a/Kernel/VirtualConsole.cpp b/Kernel/VirtualConsole.cpp
index d77fb06888..2199cc509a 100644
--- a/Kernel/VirtualConsole.cpp
+++ b/Kernel/VirtualConsole.cpp
@@ -63,12 +63,13 @@ void VirtualConsole::set_active(bool b)
m_active = b;
if (!m_active) {
- memcpy(m_buffer, s_vga_buffer, 80 * 25 * 2);
+ memcpy(m_buffer, m_current_vga_window, 80 * 25 * 2);
return;
}
memcpy(s_vga_buffer, m_buffer, 80 * 25 * 2);
- vga_set_cursor(m_cursor_row, m_cursor_column);
+ set_vga_start_row(0);
+ vga_set_cursor(m_cursor_row, m_cursor_column, m_current_vga_start_address);
Keyboard::the().setClient(this);
}
@@ -282,15 +283,31 @@ void VirtualConsole::execute_escape_sequence(byte final)
m_intermediates.clear();
}
+void VirtualConsole::clear_vga_row(word row)
+{
+ word* linemem = (word*)&m_current_vga_window[row * 160];
+ for (word i = 0; i < 80; ++i)
+ linemem[i] = 0x0720;
+}
+
void VirtualConsole::scroll_up()
{
if (m_cursor_row == (m_rows - 1)) {
- memcpy(m_buffer, m_buffer + 160, 160 * 24);
- word* linemem = (word*)&m_buffer[24 * 160];
- for (word i = 0; i < 80; ++i)
- linemem[i] = 0x0720;
- if (m_active)
- vga_scroll_up();
+ if (m_active) {
+ if (m_vga_start_row >= 160) {
+ memcpy(s_vga_buffer, m_current_vga_window + 160, 80 * 24 * 2);
+ set_vga_start_row(0);
+ clear_vga_row(24);
+ } else {
+ set_vga_start_row(m_vga_start_row + 1);
+ clear_vga_row(24);
+ }
+ } else {
+ memcpy(m_buffer, m_buffer + 160, 160 * 24);
+ word* linemem = (word*)&m_buffer[24 * 160];
+ for (word i = 0; i < 80; ++i)
+ linemem[i] = 0x0720;
+ }
} else {
++m_cursor_row;
}
@@ -304,7 +321,7 @@ void VirtualConsole::set_cursor(unsigned row, unsigned column)
m_cursor_row = row;
m_cursor_column = column;
if (m_active)
- vga_set_cursor(m_cursor_row, m_cursor_column);
+ vga_set_cursor(m_cursor_row, m_cursor_column, m_current_vga_start_address);
}
void VirtualConsole::put_character_at(unsigned row, unsigned column, byte ch)
@@ -312,10 +329,14 @@ void VirtualConsole::put_character_at(unsigned row, unsigned column, byte ch)
ASSERT(row < m_rows);
ASSERT(column < m_columns);
word cur = (row * 160) + (column * 2);
- m_buffer[cur] = ch;
- m_buffer[cur + 1] = m_current_attribute;
- if (m_active)
- vga_putch_at(row, column, ch, m_current_attribute);
+ if (m_active) {
+ word cur = (row * 160) + (column * 2);
+ m_current_vga_window[cur] = ch;
+ m_current_vga_window[cur + 1] = m_current_attribute;
+ } else {
+ m_buffer[cur] = ch;
+ m_buffer[cur + 1] = m_current_attribute;
+ }
}
void VirtualConsole::on_char(byte ch, bool shouldEmit)
@@ -416,3 +437,11 @@ String VirtualConsole::ttyName() const
ksprintf(buf, "/dev/tty%u", m_index);
return String(buf);
}
+
+void VirtualConsole::set_vga_start_row(word row)
+{
+ m_vga_start_row = row;
+ m_current_vga_start_address = row * 80;
+ m_current_vga_window = s_vga_buffer + row * 160;
+ vga_set_start_address(m_current_vga_start_address);
+}
diff --git a/Kernel/VirtualConsole.h b/Kernel/VirtualConsole.h
index 6ef8ec7927..1af03699b5 100644
--- a/Kernel/VirtualConsole.h
+++ b/Kernel/VirtualConsole.h
@@ -51,6 +51,12 @@ private:
byte m_saved_cursor_column { 0 };
byte m_current_attribute { 0x07 };
+ void clear_vga_row(word row);
+ void set_vga_start_row(word row);
+ word m_vga_start_row { 0 };
+ word m_current_vga_start_address { 0 };
+ byte* m_current_vga_window { nullptr };
+
void execute_escape_sequence(byte final);
enum EscapeState {