Signed-off-by: Kevin O'Connor kevin@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();