[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