//
// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
//
-// This file may be distributed under the terms of the GNU GPLv3 license.
+// This file may be distributed under the terms of the GNU LGPLv3 license.
#include <stdarg.h> // va_list
#include "config.h" // CONFIG_*
#include "biosvar.h" // GET_GLOBAL
-#define DEBUG_PORT 0x03f8
+#define DEBUG_PORT PORT_SERIAL1
#define DEBUG_TIMEOUT 100000
void
return;
// setup for serial logging: 8N1
u8 oldparam, newparam = 0x03;
- oldparam = inb(DEBUG_PORT+3);
- outb(newparam, DEBUG_PORT+3);
+ oldparam = inb(DEBUG_PORT+SEROFF_LCR);
+ outb(newparam, DEBUG_PORT+SEROFF_LCR);
// Disable irqs
u8 oldier, newier = 0;
- oldier = inb(DEBUG_PORT+1);
- outb(newier, DEBUG_PORT+1);
+ oldier = inb(DEBUG_PORT+SEROFF_IER);
+ outb(newier, DEBUG_PORT+SEROFF_IER);
if (oldparam != newparam || oldier != newier)
dprintf(1, "Changing serial settings was %x/%x now %x/%x\n"
static void
debug_serial(char c)
{
+ if (!CONFIG_DEBUG_SERIAL)
+ return;
+ int timeout = DEBUG_TIMEOUT;
+ while ((inb(DEBUG_PORT+SEROFF_LSR) & 0x60) != 0x60)
+ if (!timeout--)
+ // Ran out of time.
+ return;
+ outb(c, DEBUG_PORT+SEROFF_DATA);
+}
+
+// Make sure all serial port writes have been completely sent.
+static void
+debug_serial_flush()
+{
+ if (!CONFIG_DEBUG_SERIAL)
+ return;
int timeout = DEBUG_TIMEOUT;
- while ((inb(DEBUG_PORT+5) & 0x60) != 0x60)
+ while ((inb(DEBUG_PORT+SEROFF_LSR) & 0x40) != 0x40)
if (!timeout--)
// Ran out of time.
return;
- outb(c, DEBUG_PORT);
}
// Show a character on the screen.
static void
putc(u16 action, char c)
{
- if (CONFIG_DEBUG_LEVEL) {
+ if (CONFIG_DEBUG_LEVEL && (CONFIG_SCREEN_AND_DEBUG || !action)) {
if (! CONFIG_COREBOOT)
// Send character to debug port.
outb(c, PORT_BIOS_DEBUG);
- if (CONFIG_DEBUG_SERIAL) {
- // Send character to serial port.
- if (c == '\n')
- debug_serial('\r');
- debug_serial(c);
- }
+ // Send character to serial port.
+ if (c == '\n')
+ debug_serial('\r');
+ debug_serial(c);
}
if (action) {
// Output an integer in hexadecimal.
static void
-puthex(u16 action, u32 val)
+puthex(u16 action, u32 val, int width)
{
- putsinglehex(action, (val >> 28) & 0xf);
- putsinglehex(action, (val >> 24) & 0xf);
- putsinglehex(action, (val >> 20) & 0xf);
- putsinglehex(action, (val >> 16) & 0xf);
- putsinglehex(action, (val >> 12) & 0xf);
- putsinglehex(action, (val >> 8) & 0xf);
- putsinglehex(action, (val >> 4) & 0xf);
- putsinglehex(action, (val >> 0) & 0xf);
+ if (!width) {
+ u32 tmp = val;
+ width = 1;
+ if (tmp > 0xffff) {
+ width += 4;
+ tmp >>= 16;
+ }
+ if (tmp > 0xff) {
+ width += 2;
+ tmp >>= 8;
+ }
+ if (tmp > 0xf)
+ width += 1;
+ }
+
+ switch (width) {
+ default: putsinglehex(action, (val >> 28) & 0xf);
+ case 7: putsinglehex(action, (val >> 24) & 0xf);
+ case 6: putsinglehex(action, (val >> 20) & 0xf);
+ case 5: putsinglehex(action, (val >> 16) & 0xf);
+ case 4: putsinglehex(action, (val >> 12) & 0xf);
+ case 3: putsinglehex(action, (val >> 8) & 0xf);
+ case 2: putsinglehex(action, (val >> 4) & 0xf);
+ case 1: putsinglehex(action, (val >> 0) & 0xf);
+ }
}
static inline int
continue;
}
const char *n = s+1;
+ int field_width = 0;
for (;;) {
c = GET_GLOBAL(*(u8*)n);
if (!isdigit(c))
break;
+ field_width = field_width * 10 + c - '0';
n++;
}
if (c == 'l') {
putuint(action, val);
break;
case 'p':
+ /* %p always has 0x prepended */
+ putc(action, '0');
+ putc(action, 'x');
+ field_width = 8;
case 'x':
val = va_arg(args, s32);
- puthex(action, val);
+ puthex(action, val, field_width);
break;
case 'c':
val = va_arg(args, int);
}
s = n;
}
+ debug_serial_flush();
}
void
-BX_PANIC(const char *fmt, ...)
+panic(const char *fmt, ...)
{
if (CONFIG_DEBUG_LEVEL) {
va_list args;
va_end(args);
}
+void
+hexdump(void *d, int len)
+{
+ int count=0;
+ while (len) {
+ if (count % 8 == 0) {
+ putc(0, '\n');
+ puthex(0, count*4, 8);
+ putc(0, ':');
+ } else {
+ putc(0, ' ');
+ }
+ puthex(0, *(u32*)d, 8);
+ count++;
+ len-=4;
+ d+=4;
+ }
+ putc(0, '\n');
+ debug_serial_flush();
+}
+
static void
dump_regs(struct bregs *regs)
{
dprintf(1, " NULL\n");
return;
}
- dprintf(1, " a=%x b=%x c=%x d=%x si=%x di=%x\n"
+ dprintf(1, " a=%08x b=%08x c=%08x d=%08x ds=%04x es=%04x ss=%04x\n"
, regs->eax, regs->ebx, regs->ecx, regs->edx
- , regs->esi, regs->edi);
- dprintf(1, " ds=%x es=%x ip=%x cs=%x f=%x r=%p\n"
- , regs->ds, regs->es, regs->ip, regs->cs, regs->flags, regs);
+ , regs->ds, regs->es, GET_SEG(SS));
+ dprintf(1, " si=%08x di=%08x bp=%08x sp=%08x cs=%04x ip=%04x f=%04x\n"
+ , regs->esi, regs->edi, regs->ebp, (u32)®s[1]
+ , regs->code.seg, regs->code.offset, regs->flags);
}
// Report entry to an Interrupt Service Routine (ISR).
{
puts_cs(0, fname);
putc(0, '\n');
+ debug_serial_flush();
}
// Function called on handler startup.