Avoid hardware specific code in output.c. This will reduce the amount of change needed to output.c as support for more serial hardware is added.
This patch also renames some functions to improve the naming scheme.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- Makefile | 2 +- src/boot.c | 4 +-- src/fw/coreboot.c | 2 +- src/fw/xen.c | 1 + src/hw/serialio.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++ src/hw/serialio.h | 8 +++++ src/optionroms.c | 2 +- src/output.c | 101 ++++++++++++++++-------------------------------------- src/output.h | 3 +- src/post.c | 2 +- src/resume.c | 2 +- src/util.h | 2 +- 12 files changed, 137 insertions(+), 81 deletions(-) create mode 100644 src/hw/serialio.c
diff --git a/Makefile b/Makefile index 855fdf4..3aefbe6 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ IASL:=iasl SRCBOTH=misc.c stacks.c output.c string.c x86.c block.c cdrom.c mouse.c kbd.c \ serial.c clock.c resume.c pnpbios.c vgahooks.c pcibios.c apm.c \ fw/smp.c \ - hw/pci.c hw/timer.c hw/rtc.c hw/dma.c hw/pic.c hw/ps2port.c \ + hw/pci.c hw/timer.c hw/rtc.c hw/dma.c hw/pic.c hw/ps2port.c hw/serialio.c \ hw/usb.c hw/usb-uhci.c hw/usb-ohci.c hw/usb-ehci.c hw/usb-xhci.c \ hw/usb-hid.c hw/usb-msc.c hw/usb-uas.c \ hw/blockcmd.c hw/floppy.c hw/ata.c hw/ramdisk.c \ diff --git a/src/boot.c b/src/boot.c index b14ced9..1c74d57 100644 --- a/src/boot.c +++ b/src/boot.c @@ -743,7 +743,7 @@ int BootSequence VARLOW = -1; void VISIBLE32FLAT handle_18(void) { - debug_serial_preinit(); + debug_preinit(); debug_enter(NULL, DEBUG_HDL_18); int seq = BootSequence + 1; BootSequence = seq; @@ -754,7 +754,7 @@ handle_18(void) void VISIBLE32FLAT handle_19(void) { - debug_serial_preinit(); + debug_preinit(); debug_enter(NULL, DEBUG_HDL_19); BootSequence = 0; do_boot(0); diff --git a/src/fw/coreboot.c b/src/fw/coreboot.c index 70a99a0..5b7e77a 100644 --- a/src/fw/coreboot.c +++ b/src/fw/coreboot.c @@ -202,7 +202,7 @@ fail: return; }
-void debug_cbmem(char c) +void coreboot_debug_putc(char c) { if (!CONFIG_DEBUG_COREBOOT) return; diff --git a/src/fw/xen.c b/src/fw/xen.c index 9b00030..d5f5ed3 100644 --- a/src/fw/xen.c +++ b/src/fw/xen.c @@ -5,6 +5,7 @@ // This file may be distributed under the terms of the GNU LGPLv3 license.
#include "config.h" +#include "hw/serialio.h" // DebugOutputPort #include "malloc.h" // memalign_high #include "memmap.h" // add_e820 #include "output.h" // dprintf diff --git a/src/hw/serialio.c b/src/hw/serialio.c new file mode 100644 index 0000000..6486fc0 --- /dev/null +++ b/src/hw/serialio.c @@ -0,0 +1,89 @@ +// Low-level serial (and serial-like) device access. +// +// Copyright (C) 2008-1013 Kevin O'Connor kevin@koconnor.net +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_DEBUG_SERIAL +#include "fw/paravirt.h" // RunningOnQEMU +#include "output.h" // dprintf +#include "serialio.h" // serial_debug_preinit +#include "x86.h" // outb + + +/**************************************************************** + * Serial port debug output + ****************************************************************/ + +#define DEBUG_TIMEOUT 100000 + +// Setup the debug serial port for output. +void +serial_debug_preinit(void) +{ + if (!CONFIG_DEBUG_SERIAL) + return; + // setup for serial logging: 8N1 + u8 oldparam, newparam = 0x03; + oldparam = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LCR); + outb(newparam, CONFIG_DEBUG_SERIAL_PORT+SEROFF_LCR); + // Disable irqs + u8 oldier, newier = 0; + oldier = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER); + outb(newier, CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER); + + if (oldparam != newparam || oldier != newier) + dprintf(1, "Changing serial settings was %x/%x now %x/%x\n" + , oldparam, oldier, newparam, newier); +} + +// Write a character to the serial port. +static void +serial_debug(char c) +{ + if (!CONFIG_DEBUG_SERIAL) + return; + int timeout = DEBUG_TIMEOUT; + while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x20) != 0x20) + if (!timeout--) + // Ran out of time. + return; + outb(c, CONFIG_DEBUG_SERIAL_PORT+SEROFF_DATA); +} + +void +serial_debug_putc(char c) +{ + if (c == '\n') + serial_debug('\r'); + serial_debug(c); +} + +// Make sure all serial port writes have been completely sent. +void +serial_debug_flush(void) +{ + if (!CONFIG_DEBUG_SERIAL) + return; + int timeout = DEBUG_TIMEOUT; + while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x60) != 0x60) + if (!timeout--) + // Ran out of time. + return; +} + + +/**************************************************************** + * QEMU debug port + ****************************************************************/ + +u16 DebugOutputPort VARFSEG = 0x402; + +// Write a character to the special debugging port. +void +qemu_debug_putc(char c) +{ + if (CONFIG_DEBUG_IO && runningOnQEMU()) + // Send character to debug port. + outb(c, GET_GLOBAL(DebugOutputPort)); +} diff --git a/src/hw/serialio.h b/src/hw/serialio.h index 883fc9c..88296fe 100644 --- a/src/hw/serialio.h +++ b/src/hw/serialio.h @@ -1,6 +1,8 @@ #ifndef __SERIALIO_H #define __SERIALIO_H
+#include "types.h" // u16 + #define PORT_LPT2 0x0278 #define PORT_SERIAL4 0x02e8 #define PORT_SERIAL2 0x02f8 @@ -18,4 +20,10 @@ #define SEROFF_LSR 5 #define SEROFF_MSR 6
+void serial_debug_preinit(void); +void serial_debug_putc(char c); +void serial_debug_flush(void); +extern u16 DebugOutputPort; +void qemu_debug_putc(char c); + #endif // serialio.h diff --git a/src/optionroms.c b/src/optionroms.c index d7c8aef..1ff73c4 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -45,7 +45,7 @@ __callrom(struct rom_header *rom, u16 offset, u16 bdf) farcall16big(&br); finish_preempt();
- debug_serial_preinit(); + debug_preinit(); }
// Execute a given option rom at the standard entry vector. diff --git a/src/output.c b/src/output.c index b47625f..1d882fa 100644 --- a/src/output.c +++ b/src/output.c @@ -1,6 +1,6 @@ // Raw screen writing and debug output code. // -// Copyright (C) 2008,2009 Kevin O'Connor kevin@koconnor.net +// Copyright (C) 2008-2013 Kevin O'Connor kevin@koconnor.net // // This file may be distributed under the terms of the GNU LGPLv3 license.
@@ -10,8 +10,7 @@ #include "bregs.h" // struct bregs #include "config.h" // CONFIG_* #include "biosvar.h" // GET_GLOBAL -#include "fw/paravirt.h" // PlatformRunningOn -#include "hw/serialio.h" // SEROFF_IER +#include "hw/serialio.h" // serial_debug_putc #include "malloc.h" // malloc_tmp #include "output.h" // dprintf #include "stacks.h" // call16_int @@ -27,81 +26,41 @@ struct putcinfo { * Debug output ****************************************************************/
-#define DEBUG_TIMEOUT 100000 - -u16 DebugOutputPort VARFSEG = 0x402; - +// Setup debugging port(s). void -debug_serial_preinit(void) +debug_preinit(void) { - if (!CONFIG_DEBUG_SERIAL) - return; - // setup for serial logging: 8N1 - u8 oldparam, newparam = 0x03; - oldparam = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LCR); - outb(newparam, CONFIG_DEBUG_SERIAL_PORT+SEROFF_LCR); - // Disable irqs - u8 oldier, newier = 0; - oldier = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER); - outb(newier, CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER); - - if (oldparam != newparam || oldier != newier) - dprintf(1, "Changing serial settings was %x/%x now %x/%x\n" - , oldparam, oldier, newparam, newier); -} - -// Write a character to the serial port. -static void -debug_serial(char c) -{ - if (!CONFIG_DEBUG_SERIAL) - return; - int timeout = DEBUG_TIMEOUT; - while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x20) != 0x20) - if (!timeout--) - // Ran out of time. - return; - outb(c, CONFIG_DEBUG_SERIAL_PORT+SEROFF_DATA); + serial_debug_preinit(); }
-// Make sure all serial port writes have been completely sent. +// Write a character to debug port(s). static void -debug_serial_flush(void) +debug_putc(struct putcinfo *action, char c) { - if (!CONFIG_DEBUG_SERIAL) + if (! CONFIG_DEBUG_LEVEL) return; - int timeout = DEBUG_TIMEOUT; - while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x60) != 0x60) - if (!timeout--) - // Ran out of time. - return; + qemu_debug_putc(c); + if (!MODESEGMENT) + coreboot_debug_putc(c); + serial_debug_putc(c); }
-// Write a character to debug port(s). +// Flush any pending output to debug port(s). static void -putc_debug(struct putcinfo *action, char c) +debug_flush(void) { - if (! CONFIG_DEBUG_LEVEL) - return; - if (CONFIG_DEBUG_IO && runningOnQEMU()) - // Send character to debug port. - outb(c, GET_GLOBAL(DebugOutputPort)); - if (!MODESEGMENT) - debug_cbmem(c); - if (c == '\n') - debug_serial('\r'); - debug_serial(c); + serial_debug_flush(); }
-// In segmented mode just need a dummy variable (putc_debug is always +// In segmented mode just need a dummy variable (debug_putc is always // used anyway), and in 32bit flat mode need a pointer to the 32bit -// instance of putc_debug(). +// instance of debug_putc(). #if MODE16 static struct putcinfo debuginfo VAR16; #elif MODESEGMENT static struct putcinfo debuginfo VAR32SEG; #else -static struct putcinfo debuginfo = { putc_debug }; +static struct putcinfo debuginfo = { debug_putc }; #endif
@@ -123,16 +82,16 @@ screenc(char c)
// Handle a character from a printf request. static void -putc_screen(struct putcinfo *action, char c) +screen_putc(struct putcinfo *action, char c) { if (ScreenAndDebug) - putc_debug(&debuginfo, c); + debug_putc(&debuginfo, c); if (c == '\n') screenc('\r'); screenc(c); }
-static struct putcinfo screeninfo = { putc_screen }; +static struct putcinfo screeninfo = { screen_putc };
/**************************************************************** @@ -145,7 +104,7 @@ putc(struct putcinfo *action, char c) { if (MODESEGMENT) { // Only debugging output supported in segmented mode. - putc_debug(action, c); + debug_putc(action, c); return; }
@@ -348,7 +307,7 @@ panic(const char *fmt, ...) va_start(args, fmt); bvprintf(&debuginfo, fmt, args); va_end(args); - debug_serial_flush(); + debug_flush(); }
// XXX - use PANIC PORT. @@ -365,10 +324,10 @@ __dprintf(const char *fmt, ...) struct thread_info *cur = getCurThread(); if (cur != &MainThread) { // Show "thread id" for this debug message. - putc_debug(&debuginfo, '|'); + debug_putc(&debuginfo, '|'); puthex(&debuginfo, (u32)cur, 8); - putc_debug(&debuginfo, '|'); - putc_debug(&debuginfo, ' '); + debug_putc(&debuginfo, '|'); + debug_putc(&debuginfo, ' '); } }
@@ -376,7 +335,7 @@ __dprintf(const char *fmt, ...) va_start(args, fmt); bvprintf(&debuginfo, fmt, args); va_end(args); - debug_serial_flush(); + debug_flush(); }
void @@ -388,7 +347,7 @@ printf(const char *fmt, ...) bvprintf(&screeninfo, fmt, args); va_end(args); if (ScreenAndDebug) - debug_serial_flush(); + debug_flush(); }
@@ -479,7 +438,7 @@ hexdump(const void *d, int len) d+=4; } putc(&debuginfo, '\n'); - debug_serial_flush(); + debug_flush(); }
static void @@ -503,7 +462,7 @@ __debug_isr(const char *fname) { puts_cs(&debuginfo, fname); putc(&debuginfo, '\n'); - debug_serial_flush(); + debug_flush(); }
// Function called on handler startup. diff --git a/src/output.h b/src/output.h index bdfdd63..a13d55b 100644 --- a/src/output.h +++ b/src/output.h @@ -4,8 +4,7 @@ #include "types.h" // u32
// output.c -extern u16 DebugOutputPort; -void debug_serial_preinit(void); +void debug_preinit(void); void panic(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) __noreturn; void printf(const char *fmt, ...) diff --git a/src/post.c b/src/post.c index b634686..ace6f4c 100644 --- a/src/post.c +++ b/src/post.c @@ -317,7 +317,7 @@ handle_post(void) if (!CONFIG_QEMU && !CONFIG_COREBOOT) return;
- debug_serial_preinit(); + debug_preinit(); dprintf(1, "Start bios (version %s)\n", VERSION);
// Check if we are running under Xen. diff --git a/src/resume.c b/src/resume.c index fc2fee9..d69429c 100644 --- a/src/resume.c +++ b/src/resume.c @@ -25,7 +25,7 @@ void VISIBLE16 handle_resume(void) { ASSERT16(); - debug_serial_preinit(); + debug_preinit(); int status = rtc_read(CMOS_RESET_CODE); rtc_write(CMOS_RESET_CODE, 0); dprintf(1, "In resume (status=%d)\n", status); diff --git a/src/util.h b/src/util.h index e6a6cb5..1b7d525 100644 --- a/src/util.h +++ b/src/util.h @@ -78,7 +78,7 @@ void *find_acpi_rsdp(void); // fw/coreboot.c extern const char *CBvendor, *CBpart; struct cbfs_file; -void debug_cbmem(char c); +void coreboot_debug_putc(char c); void cbfs_run_payload(struct cbfs_file *file); void coreboot_platform_setup(void); void cbfs_payload_setup(void);