[SeaBIOS] [PATCH 3/3] sercon: Support "split output" mode

Kevin O'Connor kevin at koconnor.net
Thu Oct 27 02:34:57 CEST 2016


Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 vgasrc/sercon.c   | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 vgasrc/vgabios.c  |  2 +-
 vgasrc/vgabios.h  |  5 +++++
 vgasrc/vgaentry.S |  7 ++++++
 vgasrc/vgainit.c  |  9 +++++---
 5 files changed, 84 insertions(+), 4 deletions(-)

diff --git a/vgasrc/sercon.c b/vgasrc/sercon.c
index 11df1dc..609a05e 100644
--- a/vgasrc/sercon.c
+++ b/vgasrc/sercon.c
@@ -7,6 +7,7 @@
 #include <stdarg.h> // va_list
 
 #include "biosvar.h" // GET_GLOBAL
+#include "bregs.h" // struct bregs
 #include "output.h" // dprintf
 #include "vgabios.h" // struct vgamode_s
 #include "vgafb.h" // struct cursorpos
@@ -146,6 +147,61 @@ sercon_check_event(void)
 
 
 /****************************************************************
+ * Hooked 0x10 handling
+ ****************************************************************/
+
+struct segoff_s sercon_entry_hook_resume VAR16 VISIBLE16;
+
+static void
+sercon_1000(struct bregs *regs)
+{
+    if (!(regs->al & 0x80))
+        sercon_clear_screen();
+}
+
+static void
+sercon_100e(struct bregs *regs)
+{
+    // Just like handle_100e, but don't update the cursor position
+    struct carattr ca = {regs->al, regs->bl, 0};
+    struct cursorpos cp = get_cursor_pos(GET_BDA(video_page));
+    write_teletype(&cp, ca);
+}
+
+static void
+sercon_1013(struct bregs *regs)
+{
+    // Use the main handle_10 routine, but don't update the cursor position
+    u8 oldal = regs->al;
+    regs->al &= ~0x01;
+    handle_10(regs);
+    regs->al = oldal;
+}
+
+void VISIBLE16
+sercon_10(struct bregs *regs)
+{
+    if (!CONFIG_VGA_SERCON)
+        return;
+
+    switch (regs->ah) {
+    case 0x00: sercon_1000(regs); break;
+    case 0x0e: sercon_100e(regs); break;
+    case 0x13: sercon_1013(regs); break;
+
+    case 0x06:
+    case 0x07:
+    case 0x09:
+    case 0x0a:
+        handle_10(regs);
+        break;
+    default:
+        break;
+    }
+}
+
+
+/****************************************************************
  * Interface functions
  ****************************************************************/
 
@@ -287,5 +343,14 @@ sercon_setup(void)
 {
     outb(0x03, SERCON_PORT + SEROFF_LCR); // 8N1
     outb(0x01, SERCON_PORT + 0x02);       // enable fifo
+
+    struct segoff_s cur_entry = GET_IVT(0x10);
+    if (cur_entry.seg != SEG_BIOS) {
+        // Looks like a VGA BIOS has already been installed - hook it.
+        SET_VGA(sercon_entry_hook_resume, cur_entry);
+        extern void entry_sercon_10(void);
+        SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_sercon_10));
+    }
+
     return 0;
 }
diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c
index 5b08022..dc7ea9c 100644
--- a/vgasrc/vgabios.c
+++ b/vgasrc/vgabios.c
@@ -168,7 +168,7 @@ write_char(struct cursorpos *pcp, struct carattr ca)
 
 // Write a character to the screen at a given position.  Implement
 // special characters and scroll the screen if necessary.
-static void
+void
 write_teletype(struct cursorpos *pcp, struct carattr ca)
 {
     switch (ca.car) {
diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h
index 3d5bbfe..5e727bb 100644
--- a/vgasrc/vgabios.h
+++ b/vgasrc/vgabios.h
@@ -84,5 +84,10 @@ int bda_save_restore(int cmd, u16 seg, void *data);
 struct vgamode_s *get_current_mode(void);
 int vga_set_mode(int mode, int flags);
 extern struct video_func_static static_functionality;
+struct cursorpos;
+struct carattr;
+void write_teletype(struct cursorpos *pcp, struct carattr ca);
+struct bregs;
+void handle_10(struct bregs *regs);
 
 #endif // vgabios.h
diff --git a/vgasrc/vgaentry.S b/vgasrc/vgaentry.S
index 53be2b3..f064681 100644
--- a/vgasrc/vgaentry.S
+++ b/vgasrc/vgaentry.S
@@ -159,3 +159,10 @@ entry_timer_hook_extrastack:
         movl PUSHBREGS_size(%eax), %esp
         RESTOREBREGS_DSEAX
         ljmpw *%cs:Timer_Hook_Resume
+
+        // Serial console irq hooking
+        DECLFUNC entry_sercon_10
+entry_sercon_10:
+        ENTRY_ARG sercon_10
+        ljmpw *%cs:sercon_entry_hook_resume
+        // XXX - support extra stack on sercon entry?
diff --git a/vgasrc/vgainit.c b/vgasrc/vgainit.c
index ec3996f..3df1824 100644
--- a/vgasrc/vgainit.c
+++ b/vgasrc/vgainit.c
@@ -155,6 +155,7 @@ vga_post(struct bregs *regs)
             SET_VGA(VgaBDF, bdf);
     }
 
+    struct segoff_s orig_entry = GET_IVT(0x10);
     int ret = vgahw_setup();
     if (ret) {
         dprintf(1, "Failed to initialize VGA hardware.  Exiting.\n");
@@ -169,10 +170,12 @@ vga_post(struct bregs *regs)
     if (CONFIG_VGA_STDVGA_PORTS)
         stdvga_build_video_param();
 
-    extern void entry_10(void);
-    SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10));
+    if (orig_entry.segoff == GET_IVT(0x10).segoff) {
+        extern void entry_10(void);
+        SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10));
 
-    allocate_extra_stack();
+        allocate_extra_stack();
+    }
 
     hook_timer_irq();
 
-- 
2.5.5




More information about the SeaBIOS mailing list