Shell : scroll, new keyboard layout, history

This commit is contained in:
Adrien Bourmault 2020-02-02 13:37:26 +01:00
parent f69383330f
commit 589ce20818
17 changed files with 402 additions and 173 deletions

View File

@ -34,6 +34,8 @@
void IoEnableCursor(void);
void IoDisableCursor(void);
void IoUpdateCursor(int, int);
int IoGetCursorX(void);
int IoGetCursorY(void);
//----------------------------------------------------------------------------//

View File

@ -36,17 +36,25 @@ void IoChangeCodePage(char *);
//----------------------------------------------------------------------------//
#define KEY_ESC 27
#define KEY_BS 8
#define KEY_BEL 7
#define K_BACKSPACE 8
#define K_BELL 7
#define KEY_DC1 17 // Arrow Up
#define KEY_DC2 18 // Arrow Down
#define KEY_DC3 19 // Arrow Left
#define KEY_DC4 20 // Arrow Right
#define K_ARRW_UP 17
#define K_ARRW_DOWN 18
#define K_ARRW_LEFT 19
#define K_ARRW_RIGHT 20
#define KEY_DC5 17 // Page Up
#define KEY_DC6 18 // Page Down
#define K_PAGE_UP 21
#define K_PAGE_DOWN 22
#define K_INSERT 23
#define K_HOME 24
#define K_END 25
#define K_ESCAPE 27
#define K_DEL 127
//----------------------------------------------------------------------------//

View File

@ -65,6 +65,10 @@ void IoScrollDown(void);
void IoChangeTermColor(int, int);
int IoGetCursorOffset(void);
void IoSetCursorOffset(int);
error_t IoInitVGABuffer(void);
//----------------------------------------------------------------------------//

View File

@ -26,6 +26,10 @@
#include <kernel.h>
#endif
#ifndef _LIB_LIST_H
#include <lib/list.h>
#endif
#ifndef _KALKERN_PROC_H
#define _KALKERN_PROC_H
@ -44,6 +48,9 @@ enum ProcState_t
//
struct Process_t
{
// Scheduler internals
ListNode_t schedNode;
// Identifier
int pid;
@ -67,9 +74,6 @@ struct Process_t
// Default time-slice
ulong defTimeSlice;
// Scheduler internals
ListNode_t *schedNode;
};
//----------------------------------------------------------------------------//

View File

@ -211,7 +211,7 @@ noreturn void KeStartPanic(const char *, ...);
while(_vga<(volatile ushort*)(0xB8000+(80*25*2))) \
*_vga++=(c|(0xf<<8)); \
asm volatile("cli\nhlt"); \
}while(0)
}while(1)
#define BUG() XBUG('B')
#define BUGON(x) if(x)BUG()

View File

@ -57,8 +57,8 @@ struct ListNode_t
//
// Create a list head with an extern lock
//
static inline ListHead_t
*ExCreateListHead(Lock_t *lock)
static inline
ListHead_t *ExCreateListHead()
{
ListHead_t *head = malloc(sizeof(ListHead_t));
@ -70,11 +70,24 @@ static inline ListHead_t
return head;
}
static inline
ListNode_t *ExCreateNode()
{
ListNode_t *node = malloc(sizeof(ListNode_t));
if (node == NULL) return NULL;
node->prev = node->next = NULL;
node->head = NULL;
return node;
}
//
// Prepend node at beginning of list
//
static inline ListHead_t
*ExPrependNode(ListHead_t *head, ListNode_t *node)
static inline
ListHead_t *ExPrependNode(ListHead_t *head, ListNode_t *node)
{
assert(head && node);
@ -101,8 +114,8 @@ static inline ListHead_t
//
// Append node at end of list
//
static inline ListHead_t
*ExAppendNode(ListHead_t *head, ListNode_t *node)
static inline
ListHead_t *ExAppendNode(ListHead_t *head, ListNode_t *node)
{
assert(head && node);
@ -182,6 +195,9 @@ static inline ListHead_t
static inline ListHead_t
*ExRemoveNode(ListHead_t *head, ListNode_t *node)
{
assert(head);
assert(node);
assert(head->length > 0);
assert(head && node && head->length > 0 && node->head == head);
if (head->length == 1) {
@ -221,6 +237,8 @@ ExDestroyListHead(ListHead_t *head)
free(head);
}
#define ExGetNodeData(list, type) ((type)list)
//------------------------------------------//
#ifdef __cplusplus

View File

@ -31,8 +31,6 @@
//----------------------------------------------------------------------------//
#define CMDBUFSIZE 256
typedef struct Command_t Command_t;
struct Command_t

View File

@ -29,6 +29,7 @@
#include <ke/idt.h>
#include <ke/time.h>
#include <ke/cpuid.h>
#include <ke/sched.h>
#include <sh/shell.h>
#include <io/vga.h>
#include <io/keyb.h>

View File

@ -25,6 +25,8 @@
#include <init/boot.h>
#include <io/cursor.h>
static int _curX = 0, _curY = 0;
void IoEnableCursor(void)
{
IoWriteByteOnPort(0x3D4, 0xA);
@ -42,6 +44,9 @@ void IoDisableCursor(void)
void IoUpdateCursor(int x, int y)
{
_curX = x;
_curY = y;
const ushort pos = y * BtVideoInfo.framebufferWidth + x;
IoWriteByteOnPort(0x3D4, 0x0F);
@ -49,3 +54,7 @@ void IoUpdateCursor(int x, int y)
IoWriteByteOnPort(0x3D4, 0x0E);
IoWriteByteOnPort(0x3D5, ((pos >> 8) & 0xFF));
}
int IoGetCursorX(void) { return _curX; }
int IoGetCursorY(void) { return _curY; }

View File

@ -32,7 +32,10 @@
#define FLAGS(code) (table[2*(code)+1])
static bool capsLockActive = 0;
static bool e0received = 0;
static bool altPressed = 0;
static bool altGrPressed = 0;
static bool shiftPressed = 0;
static bool controlPressed = 0;
@ -40,11 +43,18 @@ static void KeybPrint(uchar _code)
{
uint code = (uint)_code;
const uint *table =
(altPressed ? LeftAltScanCodes
: (controlPressed ? LeftControlScanCodes
: (shiftPressed ? LeftShiftScanCodes
: RegularScanCodes)));
const uint *table;
if (!e0received) {
table = (altPressed ? LeftAltScanCodes
: (controlPressed ? LeftControlScanCodes
: (shiftPressed ? LeftShiftScanCodes
: (altGrPressed ? AltGrScanCodes
: RegularScanCodes))));
} else {
table = E0ScanCodes;
e0received = 0;
}
if ((capsLockActive && (FLAGS(code) & CAPSLOCK))
&& !(altPressed || controlPressed)) {
@ -58,8 +68,14 @@ static void KeybPrint(uchar _code)
if (!ch) {
switch (code) {
case 0x38: altPressed = 1; break;
case 0xB8: altPressed = 0; break;
case 0xE0: e0received = 1; break;
case 0x38: if (table == E0ScanCodes) altGrPressed = 1;
else altPressed = 1;
break;
case 0xB8: if (table == E0ScanCodes) altGrPressed = 0;
else altPressed = 0;
break;
case 0x36: case 0x2A: shiftPressed = 1; break;
case 0xB6: case 0xAA: shiftPressed = 0; break;
@ -73,10 +89,6 @@ static void KeybPrint(uchar _code)
}
bputc(BStdIn, ch);
if (code && (FLAGS(code) & INVISIBLE) == 0) {
bputc(BStdOut, table[2 * code]);
BStdOut->flusher(BStdOut);
}
}
static void KeybHandler(ISRFrame_t *regs)

View File

@ -22,8 +22,6 @@
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
//----------------------------------------------------------------------------//
#define WANT_AZERTY 1
#define NONE 0
#define INVISIBLE 1
#define CAPSLOCK 2
@ -35,7 +33,7 @@
const uint RegularScanCodes[2 * 256] =
{
ENTRY (0x00, 0, INVISIBLE|INVALID),
ENTRY (0x01, KEY_ESC, INVISIBLE),
ENTRY (0x01, K_ESCAPE, INVISIBLE),
ENTRY (0x02, '&', NONE),
ENTRY (0x03, 'e', NONE),
@ -49,7 +47,7 @@ const uint RegularScanCodes[2 * 256] =
ENTRY (0x0B, 'a', NONE),
ENTRY (0x0C, ')', NONE),
ENTRY (0x0D, '=', NONE),
ENTRY (0x0E, KEY_BS, NONE), // Backspace
ENTRY (0x0E, '\b', NONE),
ENTRY (0x0F, '\t', NONE),
ENTRY (0x10, 'a', CAPSLOCK),
@ -96,17 +94,32 @@ const uint RegularScanCodes[2 * 256] =
ENTRY (0x35, '!', CAPSLOCK),
ENTRY (0x39, ' ', NONE),
ENTRY (0x48, KEY_DC1, INVISIBLE), // UP arrow
ENTRY (0x4B, KEY_DC3, INVISIBLE), // LEFT arrow
ENTRY (0x4D, KEY_DC4, INVISIBLE), // RIGHT arrow
ENTRY (0x50, KEY_DC2, INVISIBLE), // DOWN arrow
ENTRY (0x40, '\a', INVISIBLE), // F6
// Numpad keys
ENTRY (0x37, '*', NONE),
ENTRY (0x47, '7', NONE),
ENTRY (0x48, '8', NONE),
ENTRY (0x49, '9', NONE),
ENTRY (0x4A, '-', NONE),
ENTRY (0x4B, '4', NONE),
ENTRY (0x4C, '5', NONE),
ENTRY (0x4D, '6', NONE),
ENTRY (0x4E, '+', NONE),
ENTRY (0x4F, '1', NONE),
ENTRY (0x50, '2', NONE),
ENTRY (0x51, '3', NONE),
ENTRY (0x52, '0', NONE),
ENTRY (0x53, '.', NONE),
ENTRY (0xE0, 0, INVISIBLE),
};
const uint LeftShiftScanCodes[2 * 256] =
{
ENTRY (0x00, 0, INVISIBLE|INVALID),
ENTRY (0x01, KEY_ESC, INVISIBLE),
ENTRY (0x01, K_ESCAPE, INVISIBLE),
ENTRY (0x02, '1', NONE),
ENTRY (0x03, '2', NONE),
@ -120,7 +133,7 @@ const uint LeftShiftScanCodes[2 * 256] =
ENTRY (0x0B, '0', NONE),
ENTRY (0x0C, 'o', NONE),
ENTRY (0x0D, '+', NONE),
ENTRY (0x0E, KEY_BS, NONE), // Backspace
ENTRY (0x0E, '\b', NONE),
ENTRY (0x0F, '\t', NONE),
ENTRY (0x10, 'A', CAPSLOCK),
@ -167,8 +180,54 @@ const uint LeftShiftScanCodes[2 * 256] =
ENTRY (0x35, '!', NONE),
ENTRY (0x39, ' ', NONE),
// Numpad keys
ENTRY (0x47, K_HOME, INVISIBLE),
ENTRY (0x48, K_ARRW_UP, INVISIBLE),
ENTRY (0x49, K_PAGE_UP, INVISIBLE),
ENTRY (0x4B, K_ARRW_LEFT, INVISIBLE),
ENTRY (0x4D, K_ARRW_RIGHT, INVISIBLE),
ENTRY (0x4F, K_END, INVISIBLE),
ENTRY (0x50, K_ARRW_DOWN, INVISIBLE),
ENTRY (0x51, K_PAGE_DOWN, INVISIBLE),
ENTRY (0x52, K_INSERT, INVISIBLE),
ENTRY (0x53, K_DEL, INVISIBLE),
ENTRY (0xE0, 0, INVISIBLE),
};
const uint LeftAltScanCodes[2 * 256];
const uint LeftControlScanCodes[2 * 256];
const uint AltGrScanCodes[2 * 256] = {
ENTRY (0x03, '~', NONE),
ENTRY (0x04, '#', NONE),
ENTRY (0x05, '{', NONE),
ENTRY (0x06, '[', NONE),
ENTRY (0x07, '|', NONE),
ENTRY (0x08, '`', NONE),
ENTRY (0x09, '\\', NONE),
ENTRY (0x0A, '^', NONE),
ENTRY (0x0B, '@', NONE),
ENTRY (0x0C, ']', NONE),
ENTRY (0x0D, '}', NONE),
};
const uint LeftAltScanCodes[2 * 256] = { 0 };
const uint LeftControlScanCodes[2 * 256] = {
ENTRY (0x2E, K_ESCAPE, INVISIBLE), // Ctrl+C
};
const uint E0ScanCodes[2 * 256] = {
ENTRY (0x1C, '\n', NONE), // Numpad Enter
ENTRY (0x35, '/', NONE), // Numpad Slash
ENTRY (0x47, K_HOME, INVISIBLE), // Home key
ENTRY (0x48, K_ARRW_UP, INVISIBLE), // Cursor UP
ENTRY (0x49, K_PAGE_UP, INVISIBLE), // Page UP
ENTRY (0x4B, K_ARRW_LEFT, INVISIBLE), // Cursor LEFT
ENTRY (0x4D, K_ARRW_RIGHT, INVISIBLE), // Cursor RIGHT
ENTRY (0x4F, K_END, INVISIBLE), // End key
ENTRY (0x50, K_ARRW_DOWN, INVISIBLE), // Cursor DOWN
ENTRY (0x51, K_PAGE_DOWN, INVISIBLE), // Page DOWN
ENTRY (0x52, K_INSERT, INVISIBLE), // Insert mode
ENTRY (0x53, K_DEL, INVISIBLE), // Delete key
};

View File

@ -46,6 +46,8 @@ static uint bscroll = 0;
static int bfg = VGA_COLOR_LIGHT_GREY;
static int bbg = VGA_COLOR_BLACK;
static int cursorOffset = 0;
//
// VGA Buffer Flusher
//
@ -86,11 +88,12 @@ error_t bvgaflusher(Buffer_t *buf)
}
}
}
// Update the cursor
size_t curX = ((size_t)ptr - (size_t)bufStart - cols) % buf->lineLen;
size_t curY = ((size_t)ptr - (size_t)bufStart) / buf->lineLen;
IoUpdateCursor(curX, curY);
IoUpdateCursor(max(min(curX + cursorOffset, buf->lineLen), 0), curY);
// Empty the rest of the buffer
@ -108,6 +111,14 @@ error_t bvgaflusher(Buffer_t *buf)
return EOK;
}
int IoGetCursorOffset(void) {
return cursorOffset;
}
void IoSetCursorOffset(int ins) {
cursorOffset = ins;
}
uint IoGetScroll(void)
{
return bscroll;

View File

@ -27,25 +27,21 @@
#include <ke/sched.h>
#include <lib/list.h>
// XXX not ready
#if 0
//
// For test purpose only
//
int procslen = 10;
Process_t procs[] = {
{ 0, 0, 0, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
{ 1, 2, 2, 16, 16, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
{ 2, 3, 3, 31, 31, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
{ 3, 2, 2, 1, 1, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
{ 4, 3, 3, 5, 5, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
{ 5, 0, 0, 30, 30, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
{ 6, 1, 1, 19, 19, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
{ 7, 1, 1, 0, 0, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
{ 8, 3, 3, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
{ 9, 2, 2, 21, 21, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE, NULL },
{ {0}, 0, 0, 0, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
{ {0}, 1, 2, 2, 16, 16, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
{ {0}, 2, 3, 3, 31, 31, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
{ {0}, 3, 2, 2, 1, 1, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
{ {0}, 4, 3, 3, 5, 5, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
{ {0}, 5, 0, 0, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
{ {0}, 6, 1, 1, 19, 19, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
{ {0}, 7, 1, 1, 0, 0, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
{ {0}, 8, 3, 3, 12, 12, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
{ {0}, 9, 2, 2, 21, 21, STATE_RUNNABLE, DEF_PROC_TSLICE, DEF_PROC_TSLICE },
};
//------------------------------------------//
@ -65,8 +61,8 @@ Process_t procs[] = {
//
static void SetCurProc(Process_t *proc)
{
PsCurProc = proc;
if (PsCurProc) PsCurProc->procState = STATE_RUNNING;
KeCurProc = proc;
if (KeCurProc) KeCurProc->procState = STATE_RUNNING;
}
//
@ -80,7 +76,7 @@ void PsLockSched(void) {
static inline
void PsUnlockSched(void) {
//KeEnableIRQs();
KeEnableIRQs();
}
//
@ -104,7 +100,7 @@ static ListHead_t *GetPrioClassHead(int prioClass)
case SERV_PRIO_PROC: return ServPrioProcs;
case REGL_PRIO_PROC: return ReglPrioProcs;
case IDLE_PRIO_PROC: return IdlePrioProcs;
default: KalAssert(FALSE && "Unknown priority class");
default: assert(!"Unknown priority class");
}
return NULL;
@ -116,7 +112,7 @@ static ListHead_t *GetPrioClassHead(int prioClass)
//
static Process_t *CompareProcs(Process_t *proc1, Process_t *proc2)
{
KalAssert(proc1 && proc2);
assert(proc1 && proc2);
if (proc1->prioClass < proc2->prioClass) return proc1;
if (proc1->prioClass > proc2->prioClass) return proc2;
@ -132,26 +128,21 @@ static Process_t *CompareProcs(Process_t *proc1, Process_t *proc2)
//
static void SchedThisProcUnlocked(Process_t *proc)
{
KalAssert(proc && proc->procState == STATE_RUNNABLE && !proc->schedNode);
assert(proc && proc->procState == STATE_RUNNABLE);
bool found = 0;
ListNode_t *iterNode = NULL;
ListNode_t *procNode = ExCreateNode(proc);
ListHead_t *head = GetPrioClassHead(proc->prioClass);
KalAssert(head);
KalAssert(procNode);
proc->schedNode = procNode;
assert(head);
// Find a process with lesser priority
for (iterNode = head->first; iterNode; iterNode = iterNode->next) {
if (proc->prioLevel > ExGetNodeData(iterNode, Process_t *)->prioLevel) {
// Detect double insertions
KalAssert(proc->pid != ExGetNodeData(iterNode, Process_t *)->pid);
assert(proc->pid != ExGetNodeData(iterNode, Process_t *)->pid);
// Add process to schedule
ExAddNodeBefore(head, iterNode, procNode);
ExAddNodeBefore(head, iterNode, &proc->schedNode);
found = true;
break;
}
@ -159,7 +150,7 @@ static void SchedThisProcUnlocked(Process_t *proc)
// Didn't find any process with lesser priority
if (found == false) {
ExAppendNode(head, procNode);
ExAppendNode(head, &proc->schedNode);
}
}
@ -201,36 +192,29 @@ static Process_t *SelectSchedNext(void)
//
void PsBlockCurProc(void)
{
KalAssert(PsCurProc && PsCurProc->procState == STATE_RUNNING);
assert(KeCurProc && KeCurProc->procState == STATE_RUNNING);
ListNode_t *procNode = PsCurProc->schedNode;
KeCurProc->procState = STATE_BLOCKED;
ExRemoveNode(KeCurProc->schedNode.head, &KeCurProc->schedNode);
KalAssert(procNode && "Blocking non-scheduled process");
PsCurProc->procState = STATE_BLOCKED;
ExRemoveNode(procNode->head, procNode);
PsCurProc->schedNode = NULL;
SetCurProc(SelectSchedNext());
}
static void ReSchedCurProc(void)
{
KalAssert(PsCurProc && PsCurProc->procState == STATE_RUNNING);
KalAssert(PsCurProc->schedNode);
assert(KeCurProc && KeCurProc->procState == STATE_RUNNING);
// Restore default attributes, cancelling boosts
PsCurProc->prioClass = PsCurProc->defPrioClass;
PsCurProc->prioLevel = PsCurProc->defPrioLevel;
PsCurProc->timeSlice = PsCurProc->defTimeSlice;
PsCurProc->procState = STATE_RUNNABLE;
KeCurProc->prioClass = KeCurProc->defPrioClass;
KeCurProc->prioLevel = KeCurProc->defPrioLevel;
KeCurProc->timeSlice = KeCurProc->defTimeSlice;
KeCurProc->procState = STATE_RUNNABLE;
// Remove from list
ExRemoveNode(PsCurProc->schedNode->head, PsCurProc->schedNode);
PsCurProc->schedNode = NULL;
ExRemoveNode(KeCurProc->schedNode.head, &KeCurProc->schedNode);
// Schedule again, with default attributes now
SchedThisProcUnlocked(PsCurProc);
SchedThisProcUnlocked(KeCurProc);
}
//
@ -241,30 +225,30 @@ void PsSchedOnTick(void)
{
PsLockSched();
Process_t *procNext, *winner, *previous = PsCurProc;
Process_t *procNext, *winner, *previous = KeCurProc;
// We're either idle or running something
KalAssert(PsCurProc == NULL || PsCurProc->procState == STATE_RUNNING);
assert(KeCurProc == NULL || KeCurProc->procState == STATE_RUNNING);
// Have the current process spent its timeslice?
// Has the current process spent its timeslice?
// (To be handled in CPU decisions function)
if (PsCurProc != NULL) {
if (PsCurProc->timeSlice <= 1) {
if (KeCurProc != NULL) {
if (KeCurProc->timeSlice <= 1) {
// Re-schedule
ReSchedCurProc();
// See next 'if' statement
PsCurProc = NULL;
KeCurProc = NULL;
}
// Otherwise, make it lose a tick
else {
PsCurProc->timeSlice--;
KeCurProc->timeSlice--;
}
}
// Are we idle, or scheduling next process?
if (PsCurProc == NULL) {
if (KeCurProc == NULL) {
SetCurProc(SelectSchedNext());
goto leave;
}
@ -274,7 +258,7 @@ void PsSchedOnTick(void)
// Is there a higher priority process that is runnable?
procNext = SelectSchedNext();
winner = CompareProcs(PsCurProc, procNext);
winner = CompareProcs(KeCurProc, procNext);
// Yes, procNext should preempt current process
if (winner == procNext) {
@ -290,7 +274,7 @@ void PsSchedOnTick(void)
leave:
PsUnlockSched();
if (PsCurProc != NULL && PsCurProc != previous) {
if (KeCurProc != NULL && KeCurProc != previous) {
// dispatch & context switch
}
}
@ -309,7 +293,7 @@ void PsInitSched(void)
ReglPrioProcs = ExCreateListHead();
IdlePrioProcs = ExCreateListHead();
KalAssert(IdlePrioProcs && ReglPrioProcs && ServPrioProcs && TimeCritProcs);
assert(IdlePrioProcs && ReglPrioProcs && ServPrioProcs && TimeCritProcs);
for (pid = 0; pid < procslen; pid++) {
if (procs[pid].procState == STATE_RUNNABLE) {
@ -325,7 +309,7 @@ void PsInitSched(void)
//
void PsFiniSched(void)
{
KalAssert(IdlePrioProcs && ReglPrioProcs && ServPrioProcs && TimeCritProcs);
assert(IdlePrioProcs && ReglPrioProcs && ServPrioProcs && TimeCritProcs);
PsLockSched();
@ -356,12 +340,12 @@ void PsFiniSched(void)
//
void PrintList(ListHead_t *head)
{
KalAssert(head);
assert(head);
Process_t *proc;
ListNode_t *node = head->first;
KernLog("len: %lu\n", head->length);
KernLog("len %lu\n", head->length);
while (node) {
proc = ExGetNodeData(node, Process_t *);
@ -394,7 +378,7 @@ void pstest(void)
while (tick < 100) {
//if (tick%25==0)ClearTerm(StdOut);
if (tick > 0 && tick != 50 && tick % 10 == 0 && PsCurProc) {
if (tick > 0 && tick != 50 && tick % 10 == 0 && KeCurProc) {
KernLog("Blocking current process\n");
PsBlockCurProc();
}
@ -406,12 +390,12 @@ void pstest(void)
KernLog("Tick %d - Running: ", tick);
if (PsCurProc == NULL) {
if (KeCurProc == NULL) {
KernLog("IDLE\n");
}
else {
PrintProc(PsCurProc);
PrintProc(KeCurProc);
}
PsSchedOnTick();
@ -423,5 +407,3 @@ void pstest(void)
}
}
#endif

View File

@ -29,6 +29,7 @@
#include <sh/argv.h>
#include <sh/shell.h>
#include <po/shtdwn.h>
#include <io/cursor.h>
int shargc = 0;
char **shargv = 0;
@ -65,13 +66,27 @@ void ExecuteCommand(char *cmdbuf, Command_t *cmdtable)
}
}
#define CMDBUFSIZE (BStdOut->lineLen - 9) // strlen("%Cshell> %C" = 9
void ShStartShell(void)
{
uchar ch;
error_t rc;
char *ptr; // temp
// Current line - beginning & current pos
char *cmdbuf = malloc(CMDBUFSIZE);
char *bufptr = cmdbuf;
char *bufend = cmdbuf;
// History...
// We use a basic N-entries command history
#define N 10 // must be >1
char *history = malloc(CMDBUFSIZE * N);
int historyIndex = 0;
int historyScroll = 0;
bool insertMode = 0;
argvbuf = malloc(ARG_MAX * 2);
memzero(argvbuf, ARG_MAX * 2);
@ -98,57 +113,179 @@ void ShStartShell(void)
switch (ch) {
case KEY_BS:
*bufptr = 0;
if (bufptr > cmdbuf) {
bufptr--;
}
break;
// Backspace character
case K_BACKSPACE:
if (bufptr == cmdbuf)
break;
case KEY_BEL:
if (rand() % 16 == 0) {
IoDoStarWars();
}
else IoDoBeep();
break;
memmove(bufptr-1, bufptr, bufend-bufptr+1);
bufptr--;
bufend--;
goto print_current_line;
case KEY_DC1:
IoScrollUp();
break;
// DEL character
case K_DEL:
if (bufptr == bufend)
break;
case KEY_DC2:
IoScrollDown();
break;
memmove(bufptr, bufptr+1, bufend-bufptr+1);
IoSetCursorOffset(IoGetCursorOffset()+1);
bufend--;
goto print_current_line;
case KEY_ESC:
PoShutdown();
case K_BELL: IoDoBeep(); break;
case K_ESCAPE: PoShutdown(); break;
case K_PAGE_UP: IoScrollUp(); break;
case K_PAGE_DOWN: IoScrollDown(); break;
case K_INSERT:
insertMode = 1 - insertMode;
break;
// Move within buffer
case K_ARRW_LEFT:
if (!(bufptr > cmdbuf))
break;
bufptr--;
IoSetCursorOffset(IoGetCursorOffset()-1);
BFlushBuf(BStdOut);
break;
case K_ARRW_RIGHT:
if (bufptr == bufend)
break;
bufptr++;
IoSetCursorOffset(IoGetCursorOffset()+1);
BFlushBuf(BStdOut);
break;
case K_HOME:
if (bufptr == cmdbuf)
break;
IoSetCursorOffset(IoGetCursorOffset()-(int)(bufptr-cmdbuf));
bufptr = cmdbuf;
BFlushBuf(BStdOut);
break;
default:
IoSetScroll(1);
IoScrollDown();
case K_END:
if (bufptr == bufend)
break;
*bufptr++ = (char)ch;
IoSetCursorOffset(IoGetCursorOffset()+(int)(bufend-bufptr));
bufptr = bufend;
BFlushBuf(BStdOut);
break;
// Handle history scroll up/down
case K_ARRW_UP:
case K_ARRW_DOWN:
if (historyIndex == 0)
break; // No history yet
if (ch == K_ARRW_UP) {
memmove(cmdbuf, &history[historyScroll*CMDBUFSIZE], CMDBUFSIZE);
if (historyScroll > 0)
historyScroll--;
}
else if (historyScroll < historyIndex-1) {
historyScroll++;
memmove(cmdbuf, &history[historyScroll*CMDBUFSIZE], CMDBUFSIZE);
}
else
break;
for (bufend = cmdbuf; *bufend && bufend < cmdbuf+CMDBUFSIZE; bufend++);
bufptr = bufend;
IoSetCursorOffset(0);
goto print_current_line;
// Regular character
default:
if (bufptr >= bufend) {
*bufptr++ = (char)ch;
bufend = bufptr;
*bufptr = 0;
// Advance cursor
if (IoGetCursorOffset() < 0)
IoSetCursorOffset(IoGetCursorOffset() + 1);
}
else {
if (!insertMode) {
*++bufend = 0;
for (ptr = bufend-1; ptr != bufptr; ptr--)
*ptr = *(ptr - 1);
}
else { // insertMode
// Advance cursor
if (IoGetCursorOffset() < 0)
IoSetCursorOffset(IoGetCursorOffset() + 1);
}
*bufptr++ = (char)ch;
}
print_current_line:
BLockBuf(BStdOut);
BStdOut->wp -= BStdOut->lastLF;
BStdOut->size -= BStdOut->lastLF;
BStdOut->lastLF = 0;
bprintf(BStdOut, "%Cshell> %C%s", VGA_COLOR_WHITE, shcol, cmdbuf);
BUnlockBuf(BStdOut);
IoSetScroll(1);
IoScrollDown(); // This calls the flusher
// End of buffer?
if (bufptr != cmdbuf+CMDBUFSIZE-1) {
if (bufend != cmdbuf+CMDBUFSIZE-1) {
break; // No
}
KernLog("\n");
// Else, fallthrough to case '\n'
// Else, *FALLTHROUGH* to case '\n'
case '\n':
BPutOnBuf(BStdOut, '\n');
while (IoGetScroll() > 0) {
IoScrollDown();
}
*bufptr = 0;
bufptr = cmdbuf;
ExecuteCommand(cmdbuf, shcmdtable);
IoSetCursorOffset(0);
bufptr = cmdbuf; // Reset bufptr
bufend = cmdbuf;
if (cmdbuf[0] && !isspace(cmdbuf[0])) {
// Forget old commands
if (historyIndex >= N) {
assert(historyIndex == N);
memmove(history, history+CMDBUFSIZE, CMDBUFSIZE * (N-1));
historyIndex = historyScroll = N-1;
}
// Update history
memmove(&history[historyIndex*CMDBUFSIZE], cmdbuf, CMDBUFSIZE);
historyScroll = historyIndex;
historyIndex++;
// Execute & reset
ExecuteCommand(cmdbuf, shcmdtable);
memzero(cmdbuf, CMDBUFSIZE);
}
memzero(cmdbuf, CMDBUFSIZE);
KernLog("%Cshell> %C", VGA_COLOR_WHITE, shcol);
BFlushBuf(BStdIn);
BFlushBuf(BStdOut);
@ -157,5 +294,4 @@ void ShStartShell(void)
KePauseCPU();
}
KernLog("[EOI]\n");
}

View File

@ -303,6 +303,14 @@ error_t CmdPF(int argc, char **argv, char *cmdline)
return EOK;
}
extern void pstest(void);
error_t CmdPS(int argc, char **argv, char *cmdline)
{
pstest();
return EOK;
}
error_t CmdShell(int argc, char **argv, char *cmdline)
{
ShStartShell();
@ -358,6 +366,7 @@ static Command_t testcmdtable[] =
"with z flags"},
{ "pfree", CmdPageFree, "Free a page block of id x" },
{ "pf", CmdPF, "Provoke a PF. Usage: pfault <address>"},
{ "ps", CmdPS, "Scheduler algorithm test" },
{ "shell", CmdShell, "Start a new shell (nested)", },
{ "stkov", CmdStackOverflow, "Provoke a stack overflow" },
{ "stkun", CmdStackUnderflow, "Provoke a stack underflow" },

View File

@ -43,9 +43,6 @@ error_t BGetFromBuf(Buffer_t *buf, uchar *ch)
ExReleaseLock(&buf->lock);
return rc;
}
// XXX for now, at most 4096 characters can be inputed in BStdIn
error_t bgetc(Buffer_t *buf, uchar *ch)
{
error_t rc = EOK;
@ -72,7 +69,7 @@ error_t bgetc(Buffer_t *buf, uchar *ch)
// (so that BStdIn works; don't make anything else)
while (buf->rp >= buf->wp) {
#ifdef _KALEID_KERNEL
KeSleep(1);
KeSleep(1); // XXX synchronization with keyboard driver
#endif
}

View File

@ -25,6 +25,8 @@
#include <lib/buf.h>
#include <io/spkr.h>
#include <io/keyb.h>
//
// Writes a character on a buffer
//
@ -78,10 +80,6 @@ error_t bputc(Buffer_t *buf, uchar ch)
if (buf->flusher) buf->flusher(buf);
}
else if (ch == '\a') {
IoDoBeep();
}
// Deal with carriage returns
else if (ch == '\r') {
buf->wp -= buf->lastLF;
@ -89,7 +87,7 @@ error_t bputc(Buffer_t *buf, uchar ch)
assert(buf->wp >= buf->buf);
}
// Deal with tabs... we need a tabSize field
// Deal with tabs... should be dealt with elsewhere tho
// We assume tabs are 4 characters long for now
else if (ch == '\t') {
rc = bputc(buf, ' ');
@ -98,25 +96,6 @@ error_t bputc(Buffer_t *buf, uchar ch)
rc = bputc(buf, ' ');
}
}
// Backspace
else if (ch == 8) {
if (buf->wp > buf->buf && buf->lastLF > 0) {
buf->wp--;
buf->lastLF--;
rc = bputc(buf, ' ');
if (!rc) {
buf->wp--;
buf->lastLF--;
}
}
}
// DEL character, XXX lastLF
else if (ch == 127) {
rc = bputc(buf, ' ');
if (!rc) buf->wp--;
}
// Just a regular character
else {