Merge branch 'shell' into 'master'

Shell : scroll, new keyboard layout, history

See merge request os-k-team/os-k!74
This commit is contained in:
Adrien Bourmault 2020-02-02 13:37:26 +01:00
commit 1b59decd0f
17 changed files with 402 additions and 173 deletions

View File

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

View File

@ -36,17 +36,25 @@ void IoChangeCodePage(char *);
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#define KEY_ESC 27 #define K_BACKSPACE 8
#define KEY_BS 8 #define K_BELL 7
#define KEY_BEL 7
#define KEY_DC1 17 // Arrow Up #define K_ARRW_UP 17
#define KEY_DC2 18 // Arrow Down #define K_ARRW_DOWN 18
#define KEY_DC3 19 // Arrow Left #define K_ARRW_LEFT 19
#define KEY_DC4 20 // Arrow Right #define K_ARRW_RIGHT 20
#define KEY_DC5 17 // Page Up #define K_PAGE_UP 21
#define KEY_DC6 18 // Page Down #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); void IoChangeTermColor(int, int);
int IoGetCursorOffset(void);
void IoSetCursorOffset(int);
error_t IoInitVGABuffer(void); error_t IoInitVGABuffer(void);
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//

View File

@ -26,6 +26,10 @@
#include <kernel.h> #include <kernel.h>
#endif #endif
#ifndef _LIB_LIST_H
#include <lib/list.h>
#endif
#ifndef _KALKERN_PROC_H #ifndef _KALKERN_PROC_H
#define _KALKERN_PROC_H #define _KALKERN_PROC_H
@ -44,6 +48,9 @@ enum ProcState_t
// //
struct Process_t struct Process_t
{ {
// Scheduler internals
ListNode_t schedNode;
// Identifier // Identifier
int pid; int pid;
@ -67,9 +74,6 @@ struct Process_t
// Default time-slice // Default time-slice
ulong defTimeSlice; 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))) \ while(_vga<(volatile ushort*)(0xB8000+(80*25*2))) \
*_vga++=(c|(0xf<<8)); \ *_vga++=(c|(0xf<<8)); \
asm volatile("cli\nhlt"); \ asm volatile("cli\nhlt"); \
}while(0) }while(1)
#define BUG() XBUG('B') #define BUG() XBUG('B')
#define BUGON(x) if(x)BUG() #define BUGON(x) if(x)BUG()

View File

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

View File

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

View File

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

View File

@ -25,6 +25,8 @@
#include <init/boot.h> #include <init/boot.h>
#include <io/cursor.h> #include <io/cursor.h>
static int _curX = 0, _curY = 0;
void IoEnableCursor(void) void IoEnableCursor(void)
{ {
IoWriteByteOnPort(0x3D4, 0xA); IoWriteByteOnPort(0x3D4, 0xA);
@ -42,6 +44,9 @@ void IoDisableCursor(void)
void IoUpdateCursor(int x, int y) void IoUpdateCursor(int x, int y)
{ {
_curX = x;
_curY = y;
const ushort pos = y * BtVideoInfo.framebufferWidth + x; const ushort pos = y * BtVideoInfo.framebufferWidth + x;
IoWriteByteOnPort(0x3D4, 0x0F); IoWriteByteOnPort(0x3D4, 0x0F);
@ -49,3 +54,7 @@ void IoUpdateCursor(int x, int y)
IoWriteByteOnPort(0x3D4, 0x0E); IoWriteByteOnPort(0x3D4, 0x0E);
IoWriteByteOnPort(0x3D5, ((pos >> 8) & 0xFF)); 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]) #define FLAGS(code) (table[2*(code)+1])
static bool capsLockActive = 0; static bool capsLockActive = 0;
static bool e0received = 0;
static bool altPressed = 0; static bool altPressed = 0;
static bool altGrPressed = 0;
static bool shiftPressed = 0; static bool shiftPressed = 0;
static bool controlPressed = 0; static bool controlPressed = 0;
@ -40,11 +43,18 @@ static void KeybPrint(uchar _code)
{ {
uint code = (uint)_code; uint code = (uint)_code;
const uint *table = const uint *table;
(altPressed ? LeftAltScanCodes
: (controlPressed ? LeftControlScanCodes if (!e0received) {
: (shiftPressed ? LeftShiftScanCodes table = (altPressed ? LeftAltScanCodes
: RegularScanCodes))); : (controlPressed ? LeftControlScanCodes
: (shiftPressed ? LeftShiftScanCodes
: (altGrPressed ? AltGrScanCodes
: RegularScanCodes))));
} else {
table = E0ScanCodes;
e0received = 0;
}
if ((capsLockActive && (FLAGS(code) & CAPSLOCK)) if ((capsLockActive && (FLAGS(code) & CAPSLOCK))
&& !(altPressed || controlPressed)) { && !(altPressed || controlPressed)) {
@ -58,8 +68,14 @@ static void KeybPrint(uchar _code)
if (!ch) { if (!ch) {
switch (code) { switch (code) {
case 0x38: altPressed = 1; break; case 0xE0: e0received = 1; break;
case 0xB8: altPressed = 0; 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 0x36: case 0x2A: shiftPressed = 1; break;
case 0xB6: case 0xAA: shiftPressed = 0; break; case 0xB6: case 0xAA: shiftPressed = 0; break;
@ -73,10 +89,6 @@ static void KeybPrint(uchar _code)
} }
bputc(BStdIn, ch); bputc(BStdIn, ch);
if (code && (FLAGS(code) & INVISIBLE) == 0) {
bputc(BStdOut, table[2 * code]);
BStdOut->flusher(BStdOut);
}
} }
static void KeybHandler(ISRFrame_t *regs) static void KeybHandler(ISRFrame_t *regs)

View File

@ -22,8 +22,6 @@
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. // // along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
#define WANT_AZERTY 1
#define NONE 0 #define NONE 0
#define INVISIBLE 1 #define INVISIBLE 1
#define CAPSLOCK 2 #define CAPSLOCK 2
@ -35,7 +33,7 @@
const uint RegularScanCodes[2 * 256] = const uint RegularScanCodes[2 * 256] =
{ {
ENTRY (0x00, 0, INVISIBLE|INVALID), ENTRY (0x00, 0, INVISIBLE|INVALID),
ENTRY (0x01, KEY_ESC, INVISIBLE), ENTRY (0x01, K_ESCAPE, INVISIBLE),
ENTRY (0x02, '&', NONE), ENTRY (0x02, '&', NONE),
ENTRY (0x03, 'e', NONE), ENTRY (0x03, 'e', NONE),
@ -49,7 +47,7 @@ const uint RegularScanCodes[2 * 256] =
ENTRY (0x0B, 'a', NONE), ENTRY (0x0B, 'a', NONE),
ENTRY (0x0C, ')', NONE), ENTRY (0x0C, ')', NONE),
ENTRY (0x0D, '=', NONE), ENTRY (0x0D, '=', NONE),
ENTRY (0x0E, KEY_BS, NONE), // Backspace ENTRY (0x0E, '\b', NONE),
ENTRY (0x0F, '\t', NONE), ENTRY (0x0F, '\t', NONE),
ENTRY (0x10, 'a', CAPSLOCK), ENTRY (0x10, 'a', CAPSLOCK),
@ -97,16 +95,31 @@ const uint RegularScanCodes[2 * 256] =
ENTRY (0x39, ' ', NONE), ENTRY (0x39, ' ', NONE),
ENTRY (0x48, KEY_DC1, INVISIBLE), // UP arrow ENTRY (0x40, '\a', INVISIBLE), // F6
ENTRY (0x4B, KEY_DC3, INVISIBLE), // LEFT arrow
ENTRY (0x4D, KEY_DC4, INVISIBLE), // RIGHT arrow // Numpad keys
ENTRY (0x50, KEY_DC2, INVISIBLE), // DOWN arrow 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] = const uint LeftShiftScanCodes[2 * 256] =
{ {
ENTRY (0x00, 0, INVISIBLE|INVALID), ENTRY (0x00, 0, INVISIBLE|INVALID),
ENTRY (0x01, KEY_ESC, INVISIBLE), ENTRY (0x01, K_ESCAPE, INVISIBLE),
ENTRY (0x02, '1', NONE), ENTRY (0x02, '1', NONE),
ENTRY (0x03, '2', NONE), ENTRY (0x03, '2', NONE),
@ -120,7 +133,7 @@ const uint LeftShiftScanCodes[2 * 256] =
ENTRY (0x0B, '0', NONE), ENTRY (0x0B, '0', NONE),
ENTRY (0x0C, 'o', NONE), ENTRY (0x0C, 'o', NONE),
ENTRY (0x0D, '+', NONE), ENTRY (0x0D, '+', NONE),
ENTRY (0x0E, KEY_BS, NONE), // Backspace ENTRY (0x0E, '\b', NONE),
ENTRY (0x0F, '\t', NONE), ENTRY (0x0F, '\t', NONE),
ENTRY (0x10, 'A', CAPSLOCK), ENTRY (0x10, 'A', CAPSLOCK),
@ -167,8 +180,54 @@ const uint LeftShiftScanCodes[2 * 256] =
ENTRY (0x35, '!', NONE), ENTRY (0x35, '!', NONE),
ENTRY (0x39, ' ', 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 AltGrScanCodes[2 * 256] = {
const uint LeftControlScanCodes[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 bfg = VGA_COLOR_LIGHT_GREY;
static int bbg = VGA_COLOR_BLACK; static int bbg = VGA_COLOR_BLACK;
static int cursorOffset = 0;
// //
// VGA Buffer Flusher // VGA Buffer Flusher
// //
@ -86,11 +88,12 @@ error_t bvgaflusher(Buffer_t *buf)
} }
} }
} }
// Update the cursor // Update the cursor
size_t curX = ((size_t)ptr - (size_t)bufStart - cols) % buf->lineLen; size_t curX = ((size_t)ptr - (size_t)bufStart - cols) % buf->lineLen;
size_t curY = ((size_t)ptr - (size_t)bufStart) / 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 // Empty the rest of the buffer
@ -108,6 +111,14 @@ error_t bvgaflusher(Buffer_t *buf)
return EOK; return EOK;
} }
int IoGetCursorOffset(void) {
return cursorOffset;
}
void IoSetCursorOffset(int ins) {
cursorOffset = ins;
}
uint IoGetScroll(void) uint IoGetScroll(void)
{ {
return bscroll; return bscroll;

View File

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

View File

@ -29,6 +29,7 @@
#include <sh/argv.h> #include <sh/argv.h>
#include <sh/shell.h> #include <sh/shell.h>
#include <po/shtdwn.h> #include <po/shtdwn.h>
#include <io/cursor.h>
int shargc = 0; int shargc = 0;
char **shargv = 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) void ShStartShell(void)
{ {
uchar ch; uchar ch;
error_t rc; error_t rc;
char *ptr; // temp
// Current line - beginning & current pos
char *cmdbuf = malloc(CMDBUFSIZE); char *cmdbuf = malloc(CMDBUFSIZE);
char *bufptr = cmdbuf; 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); argvbuf = malloc(ARG_MAX * 2);
memzero(argvbuf, ARG_MAX * 2); memzero(argvbuf, ARG_MAX * 2);
@ -98,57 +113,179 @@ void ShStartShell(void)
switch (ch) { switch (ch) {
case KEY_BS: // Backspace character
*bufptr = 0; case K_BACKSPACE:
if (bufptr > cmdbuf) { if (bufptr == cmdbuf)
bufptr--; break;
memmove(bufptr-1, bufptr, bufend-bufptr+1);
bufptr--;
bufend--;
goto print_current_line;
// DEL character
case K_DEL:
if (bufptr == bufend)
break;
memmove(bufptr, bufptr+1, bufend-bufptr+1);
IoSetCursorOffset(IoGetCursorOffset()+1);
bufend--;
goto print_current_line;
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;
case K_END:
if (bufptr == bufend)
break;
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--;
} }
break;
case KEY_BEL: else if (historyScroll < historyIndex-1) {
if (rand() % 16 == 0) { historyScroll++;
IoDoStarWars(); memmove(cmdbuf, &history[historyScroll*CMDBUFSIZE], CMDBUFSIZE);
} }
else IoDoBeep();
break;
case KEY_DC1: else
IoScrollUp(); break;
break;
case KEY_DC2: for (bufend = cmdbuf; *bufend && bufend < cmdbuf+CMDBUFSIZE; bufend++);
IoScrollDown(); bufptr = bufend;
break;
case KEY_ESC: IoSetCursorOffset(0);
PoShutdown(); goto print_current_line;
break;
// Regular character
default: default:
IoSetScroll(1); if (bufptr >= bufend) {
IoScrollDown(); *bufptr++ = (char)ch;
*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? // End of buffer?
if (bufptr != cmdbuf+CMDBUFSIZE-1) { if (bufend != cmdbuf+CMDBUFSIZE-1) {
break; // No break; // No
} }
KernLog("\n"); // Else, *FALLTHROUGH* to case '\n'
// Else, fallthrough to case '\n'
case '\n': case '\n':
BPutOnBuf(BStdOut, '\n');
while (IoGetScroll() > 0) { while (IoGetScroll() > 0) {
IoScrollDown(); IoScrollDown();
} }
*bufptr = 0; IoSetCursorOffset(0);
bufptr = cmdbuf;
ExecuteCommand(cmdbuf, shcmdtable); 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); KernLog("%Cshell> %C", VGA_COLOR_WHITE, shcol);
BFlushBuf(BStdIn); BFlushBuf(BStdIn);
BFlushBuf(BStdOut); BFlushBuf(BStdOut);
@ -157,5 +294,4 @@ void ShStartShell(void)
KePauseCPU(); KePauseCPU();
} }
KernLog("[EOI]\n");
} }

View File

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

View File

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

View File

@ -25,6 +25,8 @@
#include <lib/buf.h> #include <lib/buf.h>
#include <io/spkr.h> #include <io/spkr.h>
#include <io/keyb.h>
// //
// Writes a character on a buffer // Writes a character on a buffer
// //
@ -78,10 +80,6 @@ error_t bputc(Buffer_t *buf, uchar ch)
if (buf->flusher) buf->flusher(buf); if (buf->flusher) buf->flusher(buf);
} }
else if (ch == '\a') {
IoDoBeep();
}
// Deal with carriage returns // Deal with carriage returns
else if (ch == '\r') { else if (ch == '\r') {
buf->wp -= buf->lastLF; buf->wp -= buf->lastLF;
@ -89,7 +87,7 @@ error_t bputc(Buffer_t *buf, uchar ch)
assert(buf->wp >= buf->buf); 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 // We assume tabs are 4 characters long for now
else if (ch == '\t') { else if (ch == '\t') {
rc = bputc(buf, ' '); rc = bputc(buf, ' ');
@ -99,25 +97,6 @@ error_t bputc(Buffer_t *buf, uchar ch)
} }
} }
// 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 // Just a regular character
else { else {
if (buf->wp == buf->buf + buf->size) { if (buf->wp == buf->buf + buf->size) {