Shell : scroll, new keyboard layout, history
This commit is contained in:
parent
f69383330f
commit
589ce20818
|
@ -34,6 +34,8 @@
|
|||
void IoEnableCursor(void);
|
||||
void IoDisableCursor(void);
|
||||
void IoUpdateCursor(int, int);
|
||||
int IoGetCursorX(void);
|
||||
int IoGetCursorY(void);
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
|
|
@ -65,6 +65,10 @@ void IoScrollDown(void);
|
|||
|
||||
void IoChangeTermColor(int, int);
|
||||
|
||||
|
||||
int IoGetCursorOffset(void);
|
||||
void IoSetCursorOffset(int);
|
||||
|
||||
error_t IoInitVGABuffer(void);
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define CMDBUFSIZE 256
|
||||
|
||||
typedef struct Command_t Command_t;
|
||||
|
||||
struct Command_t
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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" },
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue