* AcessOS Microkernel Version
* debug.c
*/
-#include <common.h>
+#include <acess.h>
#include <stdarg.h>
-// === MACROS ===
-#define E9(ch) __asm__ __volatile__ ("outb %%al, $0xe9"::"a"(((Uint8)ch)))
+#define DEBUG_TO_E9 1
+#define DEBUG_TO_SERIAL 1
+#define SERIAL_PORT 0x3F8
+#define GDB_SERIAL_PORT 0x2F8
// === IMPORTS ===
extern void Threads_Dump();
// === GLOBALS ===
int gDebug_Level = 0;
+ int giDebug_KTerm = -1;
+ int gbDebug_SerialSetup = 0;
+ int gbGDB_SerialSetup = 0;
// === CODE ===
+int putDebugChar(char ch)
+{
+ if(!gbGDB_SerialSetup) {
+ outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts
+ outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(GDB_SERIAL_PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
+ outb(GDB_SERIAL_PORT + 1, 0x00); // (hi byte)
+ outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
+ outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ gbDebug_SerialSetup = 1;
+ }
+ while( (inb(GDB_SERIAL_PORT + 5) & 0x20) == 0 );
+ outb(GDB_SERIAL_PORT, ch);
+ return 0;
+}
+int getDebugChar()
+{
+ if(!gbGDB_SerialSetup) {
+ outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts
+ outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(GDB_SERIAL_PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
+ outb(GDB_SERIAL_PORT + 1, 0x00); // (hi byte)
+ outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
+ outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ gbDebug_SerialSetup = 1;
+ }
+ while( (inb(GDB_SERIAL_PORT + 5) & 1) == 0) ;
+ return inb(GDB_SERIAL_PORT);
+}
+
+static void E9(char ch)
+{
+ if(giDebug_KTerm != -1)
+ VFS_Write(giDebug_KTerm, 1, &ch);
+
+ #if DEBUG_TO_SERIAL
+ if(!gbDebug_SerialSetup) {
+ outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts
+ outb(SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(SERIAL_PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
+ outb(SERIAL_PORT + 1, 0x00); // (hi byte)
+ outb(SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
+ outb(SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ gbDebug_SerialSetup = 1;
+ }
+ while( (inb(SERIAL_PORT + 5) & 0x20) == 0 );
+ outb(SERIAL_PORT, ch);
+ #endif
+
+ #if DEBUG_TO_E9
+ __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) );
+ #endif
+}
+
static void E9_Str(char *Str)
{
while(*Str) E9(*Str++);
char *p = NULL;
int isLongLong = 0;
Uint64 arg;
-
+
while((c = *format++) != 0)
{
// Non control character
E9(c);
continue;
}
-
+
c = *format++;
-
+
// Literal %
if(c == '%') {
E9('%');
continue;
}
-
+
// Pointer
if(c == 'p') {
Uint ptr = va_arg(*args, Uint);
itoa(p, ptr, 16, BITS/4, '0');
goto printString;
}
-
+
// Get Argument
arg = va_arg(*args, Uint);
-
+
// Padding
if(c == '0') {
pad = '0';
c = *format++;
} else
pad = ' ';
-
+
// Minimum length
minSize = 1;
if('1' <= c && c <= '9')
c = *format++;
}
}
-
+
// Long (default)
isLongLong = 0;
if(c == 'l') {
isLongLong = 1;
}
}
-
+
p = tmpBuf;
switch (c) {
case 'd':
if(arg) E9_Str("True");
else E9_Str("False");
break;
-
+
case 's':
p = (char*)(Uint)arg;
printString:
if(!p) p = "(null)";
while(*p) E9(*p++);
break;
-
+
+ // Single Character / Array
+ case 'c':
+ if(minSize == 1) {
+ E9(arg);
+ break;
+ }
+ p = (char*)(Uint)arg;
+ if(!p) goto printString;
+ while(minSize--) E9(*p++);
+ break;
+
default: E9(arg); break;
}
}
void LogF(char *Fmt, ...)
{
va_list args;
-
+
va_start(args, Fmt);
-
+
E9_Fmt(Fmt, &args);
-
+
va_end(args);
}
/**
void Log(char *Fmt, ...)
{
va_list args;
-
+
E9_Str("Log: ");
va_start(args, Fmt);
E9_Fmt(Fmt, &args);
E9_Fmt(Fmt, &args);
va_end(args);
E9('\n');
-
+
Threads_Dump();
-
+
__asm__ __volatile__ ("xchg %bx, %bx");
__asm__ __volatile__ ("cli;\n\thlt");
for(;;) __asm__ __volatile__ ("hlt");
}
+void Debug_SetKTerminal(char *File)
+{
+ if(giDebug_KTerm != -1)
+ VFS_Close(giDebug_KTerm);
+ giDebug_KTerm = VFS_Open(File, VFS_OPENFLAG_WRITE);
+ Log("Opened '%s' as 0x%x", File, giDebug_KTerm);
+}
+
void Debug_Enter(char *FuncName, char *ArgTypes, ...)
{
va_list args;
int i = gDebug_Level ++;
int pos;
-
+
va_start(args, ArgTypes);
-
+
while(i--) E9(' ');
-
+
E9_Str(FuncName); E9_Str(": (");
-
+
while(*ArgTypes)
{
pos = strpos(ArgTypes, ' ');
if(pos != -1) {
E9(','); E9(' ');
}
-
+
if(pos == -1) break;
ArgTypes = &ArgTypes[pos+1];
}
-
+
va_end(args);
E9(')'); E9('\n');
}
{
va_list args;
int i = gDebug_Level;
-
+
va_start(args, Fmt);
-
+
while(i--) E9(' ');
-
+
E9_Str(FuncName); E9_Str(": ");
E9_Fmt(Fmt, &args);
-
+
va_end(args);
E9('\n');
}
{
va_list args;
int i = --gDebug_Level;
-
+
va_start(args, RetType);
-
+
+ if( i == -1 ) {
+ gDebug_Level = 0;
+ i = 0;
+ }
// Indenting
while(i--) E9(' ');
-
+
E9_Str(FuncName); E9_Str(": RETURN");
-
+
// No Return
if(RetType == '-') {
E9('\n');
return;
}
-
+
E9(' ');
switch(RetType)
{
case 'X': E9_Fmt("0x%llx", &args); break;
}
E9('\n');
-
+
va_end(args);
}
Uint pos = 0;
E9_Str(Header);
LogF(" (Hexdump of %p)\n", Data);
-
+
while(Length >= 16)
{
- Log("%04x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
+ #define CH(n) ((' '<=cdat[(n)]&&cdat[(n)]<=0x7F) ? cdat[(n)] : '.')
+ Log("%04x: %02x %02x %02x %02x %02x %02x %02x %02x"
+ " %02x %02x %02x %02x %02x %02x %02x %02x"
+ " %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
pos,
cdat[0], cdat[1], cdat[2], cdat[3], cdat[4], cdat[5], cdat[6], cdat[7],
- cdat[8], cdat[9], cdat[10], cdat[11], cdat[12], cdat[13], cdat[14], cdat[15]
+ cdat[8], cdat[9], cdat[10], cdat[11], cdat[12], cdat[13], cdat[14], cdat[15],
+ CH(0), CH(1), CH(2), CH(3), CH(4), CH(5), CH(6), CH(7),
+ CH(8), CH(9), CH(10), CH(11), CH(12), CH(13), CH(14), CH(15)
);
Length -= 16;
cdat += 16;
pos += 16;
}
-
+
LogF("Log: %04x: ", pos);
while(Length)
{
}
// --- EXPORTS ---
+EXPORT(Log);
EXPORT(Warning);
EXPORT(Debug_Enter);
EXPORT(Debug_Log);