Slighly better terminal stuff
This commit is contained in:
parent
5b585e5b70
commit
08b4fa927d
|
@ -77,7 +77,7 @@ noreturn void __assert_handler(const char *, const char *, int, const char *);
|
||||||
// When debugging //
|
// When debugging //
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
#if !defined(_NO_DEBUG) && !defined(NDEBUG) && !defined(KalAssert)
|
#if /*!defined(_NO_DEBUG) && !defined(NDEBUG) &&*/ !defined(KalAssert)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check whether (x) holds, if not call __assert_handler
|
// Check whether (x) holds, if not call __assert_handler
|
||||||
|
|
|
@ -51,7 +51,7 @@ enum LockType_t
|
||||||
// Mutex-type lock
|
// Mutex-type lock
|
||||||
//
|
//
|
||||||
// WARNING
|
// WARNING
|
||||||
// AquireLock() panics when used on a mutex while not running a process
|
// AcquireLock() panics when used on a mutex while not running a process
|
||||||
KLOCK_MUTEX,
|
KLOCK_MUTEX,
|
||||||
|
|
||||||
// Spinlock-type lock
|
// Spinlock-type lock
|
||||||
|
@ -121,18 +121,18 @@ void DestroyLock(Lock_t *lock)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Aquire the lock
|
// Acquire the lock
|
||||||
// Panic on double aquisition since that should never happen
|
// Panic on double acquisition since that should never happen
|
||||||
// until we have at least a basic scheduler
|
// until we have at least a basic scheduler
|
||||||
//
|
//
|
||||||
static inline
|
static inline
|
||||||
void AquireLock(Lock_t *lock)
|
void AcquireLock(Lock_t *lock)
|
||||||
{
|
{
|
||||||
KalAssert(lock->initDone == INITOK);
|
KalAssert(lock->initDone == INITOK);
|
||||||
|
|
||||||
while (!__sync_bool_compare_and_swap(&lock->locked, 0, 1)) {
|
while (!__sync_bool_compare_and_swap(&lock->locked, 0, 1)) {
|
||||||
#ifdef _KALEID_KERNEL
|
#ifdef _KALEID_KERNEL
|
||||||
StartPanic("AquireLock on an already locked object");
|
StartPanic("AcquireLock on an already locked object");
|
||||||
#else
|
#else
|
||||||
if likely (lock->type == KLOCK_SPINLOCK) continue;
|
if likely (lock->type == KLOCK_SPINLOCK) continue;
|
||||||
#ifdef _OSK_SOURCE
|
#ifdef _OSK_SOURCE
|
||||||
|
@ -146,8 +146,8 @@ void AquireLock(Lock_t *lock)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release an already aquired lock
|
// Release an already acquired lock
|
||||||
// Panic if the lock was never aquired
|
// Panic if the lock was never acquired
|
||||||
//
|
//
|
||||||
static inline
|
static inline
|
||||||
void ReleaseLock(Lock_t *lock)
|
void ReleaseLock(Lock_t *lock)
|
||||||
|
@ -161,7 +161,7 @@ void ReleaseLock(Lock_t *lock)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Tries to aquire lock
|
// Tries to acquire lock
|
||||||
//
|
//
|
||||||
static inline
|
static inline
|
||||||
bool AttemptLock(Lock_t *lock)
|
bool AttemptLock(Lock_t *lock)
|
||||||
|
|
|
@ -31,9 +31,7 @@
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
// Can't use the macro because panicStr is an array
|
extern volatile char *PanicStr;
|
||||||
static inline char *GetPanicStr(void)
|
|
||||||
{ return GetCurCPU().panicStr; }
|
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
|
|
|
@ -80,46 +80,35 @@ struct Terminal_t
|
||||||
TermColor_t bgColor;
|
TermColor_t bgColor;
|
||||||
|
|
||||||
// Defined in driver
|
// Defined in driver
|
||||||
error_t (*ClearTermUnlocked)(Terminal_t *);
|
error_t (*clear)(Terminal_t *);
|
||||||
error_t (*PutOnTermUnlocked)(Terminal_t *, char);
|
error_t (*putchar)(Terminal_t *, char);
|
||||||
error_t (*PrintOnTermUnlocked)(Terminal_t *, const char *);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
void InitTerms(void);
|
void InitTerms(void);
|
||||||
error_t ClearTerm(Terminal_t *);
|
error_t ClearTerm(Terminal_t *);
|
||||||
error_t PutOnTerm(Terminal_t *, char);
|
|
||||||
error_t PrintOnTerm(Terminal_t *, const char *);
|
|
||||||
error_t ChTermColor(Terminal_t *, TermColor_t, TermColor_t);
|
error_t ChTermColor(Terminal_t *, TermColor_t, TermColor_t);
|
||||||
|
|
||||||
|
error_t PutOnTerm(Terminal_t *, char);
|
||||||
|
error_t PutOnTermUnlocked(Terminal_t *, char);
|
||||||
|
|
||||||
|
error_t PrintOnTerm(Terminal_t *, const char *);
|
||||||
|
error_t PrintOnTermUnlocked(Terminal_t *, const char *);
|
||||||
|
|
||||||
error_t KernLog(const char *, ...);
|
error_t KernLog(const char *, ...);
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
extern Terminal_t *stdOut;
|
extern Terminal_t *StdOut;
|
||||||
#define GetStdOut() (stdOut)
|
extern Terminal_t *StdDbg;
|
||||||
#define SetStdOut(x) (stdOut = (x))
|
|
||||||
|
|
||||||
// Debug purposes
|
|
||||||
volatile ushort *vga;
|
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
||||||
#ifndef _NO_DEBUG
|
#ifndef _NO_DEBUG
|
||||||
|
|
||||||
extern Terminal_t *stdDbg;
|
|
||||||
#define GetStdDbg() (stdDbg)
|
|
||||||
#define SetStdDbg(x) (stdDbg = (x))
|
|
||||||
|
|
||||||
error_t DebugLog(const char *, ...);
|
error_t DebugLog(const char *, ...);
|
||||||
|
|
||||||
#else // _NO_DEBUG
|
#else // _NO_DEBUG
|
||||||
|
|
||||||
#define GetStdDbg() NULL
|
|
||||||
#define SetStdDbg(x) ((void)0)
|
|
||||||
#define DebugLog(fmt, ...) EOK
|
#define DebugLog(fmt, ...) EOK
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//------------------------------------------//
|
//------------------------------------------//
|
||||||
|
|
|
@ -27,5 +27,6 @@
|
||||||
int cpuCount = 1;
|
int cpuCount = 1;
|
||||||
Processor_t cpuTable[NCPUS] = {0};
|
Processor_t cpuTable[NCPUS] = {0};
|
||||||
|
|
||||||
Terminal_t *stdOut = 0, *stdDbg = 0;
|
Terminal_t *StdOut = 0, *StdDbg = 0;
|
||||||
|
volatile char *PanicStr = 0;
|
||||||
|
|
||||||
|
|
|
@ -32,14 +32,14 @@ extern Terminal_t VGA_Terminal;
|
||||||
//
|
//
|
||||||
void InitTerms(void)
|
void InitTerms(void)
|
||||||
{
|
{
|
||||||
KalAssert(!GetStdOut() && !GetStdDbg());
|
KalAssert(!StdOut && !StdDbg);
|
||||||
|
|
||||||
VGA_Init();
|
VGA_Init();
|
||||||
|
|
||||||
SetStdDbg(&VGA_Terminal);
|
StdDbg = &VGA_Terminal;
|
||||||
SetStdOut(&VGA_Terminal);
|
StdOut = &VGA_Terminal;
|
||||||
|
|
||||||
ClearTerm(GetStdOut());
|
ClearTerm(StdOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -52,8 +52,8 @@ error_t ClearTerm(Terminal_t *term)
|
||||||
if (term == NULL) return EINVAL;
|
if (term == NULL) return EINVAL;
|
||||||
KalAssert(term->initDone == INITOK);
|
KalAssert(term->initDone == INITOK);
|
||||||
|
|
||||||
AquireLock(&term->lock);
|
AcquireLock(&term->lock);
|
||||||
retcode = term->ClearTermUnlocked(term);
|
retcode = term->clear(term);
|
||||||
ReleaseLock(&term->lock);
|
ReleaseLock(&term->lock);
|
||||||
|
|
||||||
return retcode;
|
return retcode;
|
||||||
|
@ -70,7 +70,7 @@ error_t ChTermColor(Terminal_t *term, TermColor_t fgColor, TermColor_t bgColor)
|
||||||
if (term == NULL)
|
if (term == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
AquireLock(&term->lock);
|
AcquireLock(&term->lock);
|
||||||
|
|
||||||
term->fgColor = fgColor;
|
term->fgColor = fgColor;
|
||||||
term->bgColor = bgColor;
|
term->bgColor = bgColor;
|
||||||
|
@ -81,39 +81,99 @@ error_t ChTermColor(Terminal_t *term, TermColor_t fgColor, TermColor_t bgColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Writes a single character on the terminal
|
// Writes a single character on the terminal (UNLOCKED version)
|
||||||
|
//
|
||||||
|
error_t PutOnTermUnlocked(Terminal_t *term, char ch)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
size_t prevY;
|
||||||
|
error_t rc = EOK;
|
||||||
|
|
||||||
|
if (ch == '\r') {
|
||||||
|
term->currentX = 0;
|
||||||
|
return EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Line feed first takes us to the very end of the line
|
||||||
|
// Later in this function we actually do the line feed
|
||||||
|
else if (ch == '\n') {
|
||||||
|
term->currentX = term->width - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tabulations account for "term->tabSize" spaces
|
||||||
|
else if (ch == '\t') {
|
||||||
|
prevY = term->currentX;
|
||||||
|
for (i = 0; i < term->tabSize; i++) {
|
||||||
|
// Make sure tabulations can't spread over two lines
|
||||||
|
if (term->currentX == prevY) {
|
||||||
|
rc = term->putchar(term, ' ');
|
||||||
|
if (rc) return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else rc = term->putchar(term, ch);
|
||||||
|
|
||||||
|
// Did we reach the end of line?
|
||||||
|
if (!rc && ++term->currentX == term->width) {
|
||||||
|
term->currentX = 0;
|
||||||
|
|
||||||
|
// Did we reach the buffer's end?
|
||||||
|
if (++term->currentY == term->height) {
|
||||||
|
term->currentY = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Writes a single character on the terminal (LOCKED version)
|
||||||
//
|
//
|
||||||
error_t PutOnTerm(Terminal_t *term, char ch)
|
error_t PutOnTerm(Terminal_t *term, char ch)
|
||||||
{
|
{
|
||||||
error_t retcode;
|
error_t rc;
|
||||||
|
|
||||||
if (term == NULL) return EINVAL;
|
if (term == NULL) return EINVAL;
|
||||||
KalAssert(term->initDone == INITOK);
|
KalAssert(term->initDone == INITOK);
|
||||||
|
|
||||||
AquireLock(&term->lock);
|
AcquireLock(&term->lock);
|
||||||
retcode = term->PutOnTermUnlocked(term, ch);
|
rc = PutOnTermUnlocked(term, ch);
|
||||||
ReleaseLock(&term->lock);
|
ReleaseLock(&term->lock);
|
||||||
|
|
||||||
return retcode;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Prints string on terminal
|
// Prints string on terminal (UNLOCKED version)
|
||||||
|
//
|
||||||
|
error_t PrintOnTermUnlocked(Terminal_t *term, const char *str)
|
||||||
|
{
|
||||||
|
error_t rc = EOK;
|
||||||
|
|
||||||
|
while (*str && rc == EOK) {
|
||||||
|
rc = PutOnTermUnlocked(term, *str++);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Prints string on terminal (LOCKED version)
|
||||||
//
|
//
|
||||||
error_t PrintOnTerm(Terminal_t *term, const char *str)
|
error_t PrintOnTerm(Terminal_t *term, const char *str)
|
||||||
{
|
{
|
||||||
error_t retcode = EOK;
|
error_t rc = EOK;
|
||||||
|
|
||||||
if (term == NULL) return EINVAL;
|
if (term == NULL) return EINVAL;
|
||||||
KalAssert(term->initDone == INITOK);
|
KalAssert(term->initDone == INITOK);
|
||||||
|
|
||||||
AquireLock(&term->lock);
|
AcquireLock(&term->lock);
|
||||||
while (*str && retcode == EOK) {
|
rc = PrintOnTermUnlocked(term, str);
|
||||||
retcode = term->PutOnTermUnlocked(term, *str++);
|
|
||||||
}
|
|
||||||
ReleaseLock(&term->lock);
|
ReleaseLock(&term->lock);
|
||||||
|
|
||||||
return retcode;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -130,7 +190,7 @@ error_t KernLog(const char *fmt, ...)
|
||||||
vsnprintf(logbuf, KLOG_MAX_BUFSIZE, fmt, ap);
|
vsnprintf(logbuf, KLOG_MAX_BUFSIZE, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return PrintOnTerm(GetStdOut(), logbuf);
|
return PrintOnTerm(StdOut, logbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _NO_DEBUG
|
#ifndef _NO_DEBUG
|
||||||
|
@ -148,7 +208,7 @@ error_t DebugLog(const char *fmt, ...)
|
||||||
vsnprintf(logbuf, KLOG_MAX_BUFSIZE, fmt, ap);
|
vsnprintf(logbuf, KLOG_MAX_BUFSIZE, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return PrintOnTerm(GetStdDbg(), logbuf);
|
return PrintOnTerm(StdDbg, logbuf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -59,69 +59,15 @@ error_t VGA_ClearTermUnlocked(Terminal_t *term)
|
||||||
//
|
//
|
||||||
error_t VGA_PutOnTermUnlocked(Terminal_t *term, char ch)
|
error_t VGA_PutOnTermUnlocked(Terminal_t *term, char ch)
|
||||||
{
|
{
|
||||||
uint i;
|
ushort *buffer = (ushort *)term->data;
|
||||||
size_t prevY;
|
const size_t offset = VGA_ComputeOffset(term, term->currentX, term->currentY);
|
||||||
|
buffer[offset] = VGA_ComputeEntry(ch, VGA_ComputeColorCode(term->fgColor, term->bgColor));
|
||||||
|
|
||||||
if (ch == '\r') {
|
|
||||||
term->currentX = 0;
|
|
||||||
return EOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line feed first takes us to the very end of the line
|
|
||||||
// Later in this function we actually do the line feed
|
|
||||||
else if (ch == '\n') {
|
|
||||||
term->currentX = term->width - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tabulations account for "term->tabSize" spaces
|
|
||||||
else if (ch == '\t') {
|
|
||||||
prevY = term->currentX;
|
|
||||||
for (i = 0; i < term->tabSize; i++) {
|
|
||||||
// Make sure tabulations can't spread over two lines
|
|
||||||
if (term->currentX == prevY) {
|
|
||||||
VGA_PutOnTermUnlocked(term, ' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
ushort *buffer = (ushort *)term->data;
|
|
||||||
const size_t offset = VGA_ComputeOffset(term, term->currentX, term->currentY);
|
|
||||||
buffer[offset] = VGA_ComputeEntry(ch, VGA_ComputeColorCode(term->fgColor, term->bgColor));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Did we reach the end of line?
|
|
||||||
if (++term->currentX == term->width) {
|
|
||||||
term->currentX = 0;
|
|
||||||
|
|
||||||
// Did we reach the buffer's end?
|
|
||||||
if (++term->currentY == term->height) {
|
|
||||||
// XXX scroll up
|
|
||||||
term->currentY = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing can go wrong
|
|
||||||
return EOK;
|
return EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Prints string on terminal
|
|
||||||
//
|
|
||||||
error_t VGA_PrintOnTermUnlocked(Terminal_t *term, const char *str)
|
|
||||||
{
|
|
||||||
error_t retcode = EOK;
|
|
||||||
|
|
||||||
while (*str && retcode == EOK) {
|
|
||||||
retcode = term->PutOnTermUnlocked(term, *str++);
|
|
||||||
}
|
|
||||||
|
|
||||||
return retcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// VGA output
|
// VGA output
|
||||||
// XXX custom sizes
|
|
||||||
//
|
//
|
||||||
Terminal_t VGA_Terminal = {
|
Terminal_t VGA_Terminal = {
|
||||||
.initDone = FALSE,
|
.initDone = FALSE,
|
||||||
|
@ -140,9 +86,8 @@ Terminal_t VGA_Terminal = {
|
||||||
.fgColor = KTERM_COLOR_LGREY,
|
.fgColor = KTERM_COLOR_LGREY,
|
||||||
.bgColor = KTERM_COLOR_BLACK,
|
.bgColor = KTERM_COLOR_BLACK,
|
||||||
|
|
||||||
.ClearTermUnlocked = VGA_ClearTermUnlocked,
|
.clear = VGA_ClearTermUnlocked,
|
||||||
.PutOnTermUnlocked = VGA_PutOnTermUnlocked,
|
.putchar = VGA_PutOnTermUnlocked,
|
||||||
.PrintOnTermUnlocked = VGA_PrintOnTermUnlocked,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ noreturn void __assert_handler(const char *msg,
|
||||||
|
|
||||||
(void)file; (void)line; (void)func;
|
(void)file; (void)line; (void)func;
|
||||||
|
|
||||||
StartPanic("cpu%d: In function '%s', from %s line %d - assert() failed: '%s'",
|
StartPanic("cpu%d: In function '%s', from %s line %d - assertion failed: '%s'",
|
||||||
_GetCurCPU(), func, file, line, msg);
|
_GetCurCPU(), func, file, line, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,25 +52,23 @@ noreturn void StartPanic(const char *fmt, ...)
|
||||||
DisableIRQs();
|
DisableIRQs();
|
||||||
|
|
||||||
if (GetCurProc()) _SetCurProc(NULL);
|
if (GetCurProc()) _SetCurProc(NULL);
|
||||||
if (GetStdOut() == NULL) CrashSystem();
|
if (StdOut == NULL) CrashSystem();
|
||||||
|
|
||||||
GetStdOut()->ClearTermUnlocked(GetStdOut());
|
|
||||||
|
|
||||||
if (fmt == NULL) {
|
if (fmt == NULL) {
|
||||||
fmt = "(no message given)";
|
fmt = "(no message given)";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*GetPanicStr()) {
|
if (PanicStr[0] != 0) {
|
||||||
GetStdOut()->PrintOnTermUnlocked(GetStdOut(), "\nDouble panic!");
|
PrintOnTermUnlocked(StdOut, "\nDouble panic!");
|
||||||
HaltCPU();
|
HaltCPU();
|
||||||
}
|
}
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vsnprintf(GetPanicStr(), PANICSTR_SIZE, fmt, ap);
|
vsnprintf(PanicStr, PANICSTR_SIZE, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
GetStdOut()->PrintOnTermUnlocked(GetStdOut(), "\nPanic!\n\n");
|
PrintOnTermUnlocked(StdOut, "\nPanic!\n\n");
|
||||||
GetStdOut()->PrintOnTermUnlocked(GetStdOut(), GetPanicStr());
|
PrintOnTermUnlocked(StdOut, PanicStr);
|
||||||
|
|
||||||
HaltCPU();
|
HaltCPU();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,11 +47,11 @@ void InitHeap(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Aquires control of the heap's lock
|
// Acquires control of the heap's lock
|
||||||
//
|
//
|
||||||
void LockHeap(void)
|
void LockHeap(void)
|
||||||
{
|
{
|
||||||
AquireLock(&_heap_lock);
|
AcquireLock(&_heap_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -46,7 +46,7 @@ error_t KalAllocMemory(void **ptr, size_t req, int flags, size_t align)
|
||||||
UnlockHeap();
|
UnlockHeap();
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if ((flags & M_CANFAIL) == 0)
|
if ((flags & M_CANFAIL) != 0)
|
||||||
return rc;
|
return rc;
|
||||||
StartPanic("Out of memory");
|
StartPanic("Out of memory");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue