Move low-level hardware writing from output.c to new file hw/serialio.c.

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>
This commit is contained in:
Kevin O'Connor 2013-11-29 12:14:34 -05:00
parent 3ecdc492ce
commit 4cd522e673
13 changed files with 140 additions and 84 deletions

View File

@ -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 \
@ -201,7 +201,7 @@ $(OUT)bios.bin.elf: $(OUT)rom.o $(OUT)bios.bin.prep
################ VGA build rules
# VGA src files
SRCVGA=src/output.c src/string.c src/hw/pci.c \
SRCVGA=src/output.c src/string.c src/hw/pci.c src/hw/serialio.c \
vgasrc/vgabios.c vgasrc/vgafb.c vgasrc/vgafonts.c vgasrc/vbe.c \
vgasrc/stdvga.c vgasrc/stdvgamodes.c vgasrc/stdvgaio.c \
vgasrc/clext.c vgasrc/bochsvga.c vgasrc/geodevga.c

View File

@ -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);

View File

@ -202,7 +202,7 @@ fail:
return;
}
void debug_cbmem(char c)
void coreboot_debug_putc(char c)
{
if (!CONFIG_DEBUG_COREBOOT)
return;

View File

@ -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

89
src/hw/serialio.c Normal file
View File

@ -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));
}

View File

@ -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

View File

@ -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.

View File

@ -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);
}
// Make sure all serial port writes have been completely sent.
static void
debug_serial_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;
serial_debug_preinit();
}
// Write a character to debug port(s).
static void
putc_debug(struct putcinfo *action, char c)
debug_putc(struct putcinfo *action, char c)
{
if (! CONFIG_DEBUG_LEVEL)
return;
if (CONFIG_DEBUG_IO && runningOnQEMU())
// Send character to debug port.
outb(c, GET_GLOBAL(DebugOutputPort));
qemu_debug_putc(c);
if (!MODESEGMENT)
debug_cbmem(c);
if (c == '\n')
debug_serial('\r');
debug_serial(c);
coreboot_debug_putc(c);
serial_debug_putc(c);
}
// In segmented mode just need a dummy variable (putc_debug is always
// Flush any pending output to debug port(s).
static void
debug_flush(void)
{
serial_debug_flush();
}
// 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.

View File

@ -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, ...)

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -1283,7 +1283,7 @@ int HaveRunInit VAR16;
void VISIBLE16
vga_post(struct bregs *regs)
{
debug_serial_preinit();
debug_preinit();
dprintf(1, "Start SeaVGABIOS (version %s)\n", VERSION);
debug_enter(regs, DEBUG_VGA_POST);