35,29 → 35,19 |
#include <arch/ski/ski.h> |
#include <console/console.h> |
#include <console/chardev.h> |
#include <arch/interrupt.h> |
#include <sysinfo/sysinfo.h> |
#include <arch/types.h> |
#include <ddi/device.h> |
#include <ddi/irq.h> |
#include <ipc/irq.h> |
#include <proc/thread.h> |
#include <synch/spinlock.h> |
#include <arch/asm.h> |
#include <arch/drivers/kbd.h> |
#include <arch.h> |
|
#define SKI_KBD_INR 0 |
static indev_t skiin; /**< Ski input device. */ |
static outdev_t skiout; /**< Ski output device. */ |
|
static irq_t ski_kbd_irq; |
static devno_t ski_kbd_devno; |
|
chardev_t ski_console; |
chardev_t ski_uconsole; |
|
static bool kbd_disabled; |
|
static void ski_putchar(chardev_t *d, const char ch); |
static int32_t ski_getchar(void); |
|
/** Display character on debug console |
* |
* Use SSC (Simulator System Call) to |
66,8 → 56,9 |
* @param d Character device. |
* @param ch Character to be printed. |
*/ |
void ski_putchar(chardev_t *d, const char ch) |
static void ski_putchar(outdev_t *d, const char ch, bool silent) |
{ |
if (!silent) { |
asm volatile ( |
"mov r15 = %0\n" |
"mov r32 = %1\n" /* r32 is in0 */ |
78,9 → 69,18 |
); |
|
if (ch == '\n') |
ski_putchar(d, '\r'); |
ski_putchar(d, '\r', false); |
} |
} |
|
static indev_operations_t skiin_ops = { |
.poll = NULL |
}; |
|
static outdev_operations_t skiout_ops = { |
.write = ski_putchar |
}; |
|
/** Ask debug console if a key was pressed. |
* |
* Use SSC (Simulator System Call) to |
90,7 → 90,7 |
* |
* @return ASCII code of pressed key or 0 if no key pressed. |
*/ |
int32_t ski_getchar(void) |
static int32_t ski_getchar(void) |
{ |
uint64_t ch; |
|
107,102 → 107,47 |
return (int32_t) ch; |
} |
|
/** |
* This is a blocking wrapper for ski_getchar(). |
* To be used when the kernel crashes. |
*/ |
static char ski_getchar_blocking(chardev_t *d) |
{ |
int ch; |
|
while(!(ch = ski_getchar())) |
; |
if(ch == '\r') |
ch = '\n'; |
return (char) ch; |
} |
|
/** Ask keyboard if a key was pressed. */ |
static void poll_keyboard(void) |
{ |
char ch; |
static char last; |
ipl_t ipl; |
|
ipl = interrupts_disable(); |
|
if (kbd_disabled) { |
interrupts_restore(ipl); |
if (kbd_disabled) |
return; |
} |
|
spinlock_lock(&ski_kbd_irq.lock); |
|
ch = ski_getchar(); |
if(ch == '\r') |
ch = '\n'; |
if (ch) { |
if (ski_kbd_irq.notif_cfg.notify && ski_kbd_irq.notif_cfg.answerbox) { |
chardev_push_character(&ski_uconsole, ch); |
ipc_irq_send_notif(&ski_kbd_irq); |
} else { |
chardev_push_character(&ski_console, ch); |
} |
last = ch; |
spinlock_unlock(&ski_kbd_irq.lock); |
interrupts_restore(ipl); |
indev_push_character(&skiin, ch); |
return; |
} |
|
if (last) { |
if (ski_kbd_irq.notif_cfg.notify && ski_kbd_irq.notif_cfg.answerbox) { |
chardev_push_character(&ski_uconsole, 0); |
ipc_irq_send_notif(&ski_kbd_irq); |
} |
last = 0; |
} |
|
spinlock_unlock(&ski_kbd_irq.lock); |
interrupts_restore(ipl); |
} |
#define POLL_INTERVAL 10000 /* 10 ms */ |
|
/* Called from getc(). */ |
static void ski_kbd_enable(chardev_t *d) |
/** Kernel thread for polling keyboard. */ |
static void kkbdpoll(void *arg) |
{ |
kbd_disabled = false; |
while (1) { |
if (!silent) { |
poll_keyboard(); |
} |
|
/* Called from getc(). */ |
static void ski_kbd_disable(chardev_t *d) |
{ |
kbd_disabled = true; |
thread_usleep(POLL_INTERVAL); |
} |
|
/** Decline to service hardware IRQ. |
* |
* This is only a virtual IRQ, so always decline. |
* |
* @return Always IRQ_DECLINE. |
*/ |
static irq_ownership_t ski_kbd_claim(void) |
{ |
return IRQ_DECLINE; |
} |
|
static chardev_operations_t ski_ops = { |
.resume = ski_kbd_enable, |
.suspend = ski_kbd_disable, |
.write = ski_putchar, |
.read = ski_getchar_blocking |
}; |
|
/** Initialize debug console |
* |
* Issue SSC (Simulator System Call) to |
* to open debug console. |
*/ |
void ski_init_console(void) |
static void ski_init(void) |
{ |
static bool initialized; |
|
if (initialized) |
return; |
|
asm volatile ( |
"mov r15 = %0\n" |
"break 0x80000\n" |
211,54 → 156,46 |
: "r15", "r8" |
); |
|
chardev_initialize("ski_console", &ski_console, &ski_ops); |
chardev_initialize("ski_uconsole", &ski_uconsole, &ski_ops); |
stdin = &ski_console; |
stdout = &ski_console; |
initialized = true; |
} |
|
ski_kbd_devno = device_assign_devno(); |
indev_t *skiin_init(void) |
{ |
ski_init(); |
|
irq_initialize(&ski_kbd_irq); |
ski_kbd_irq.inr = SKI_KBD_INR; |
ski_kbd_irq.devno = ski_kbd_devno; |
ski_kbd_irq.claim = ski_kbd_claim; |
irq_register(&ski_kbd_irq); |
indev_initialize("skiin", &skiin, &skiin_ops); |
thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true); |
if (t) |
thread_ready(t); |
else |
return NULL; |
|
sysinfo_set_item_val("kbd", NULL, true); |
sysinfo_set_item_val("kbd.inr", NULL, SKI_KBD_INR); |
sysinfo_set_item_val("kbd.devno", NULL, ski_kbd_devno); |
sysinfo_set_item_val("kbd.type", NULL, KBD_SKI); |
|
return &skiin; |
} |
|
void ski_kbd_grab(void) |
|
void skiout_init(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&ski_kbd_irq.lock); |
ski_kbd_irq.notif_cfg.notify = false; |
spinlock_unlock(&ski_kbd_irq.lock); |
interrupts_restore(ipl); |
ski_init(); |
|
outdev_initialize("skiout", &skiout, &skiout_ops); |
stdout = &skiout; |
|
sysinfo_set_item_val("fb", NULL, false); |
} |
|
void ski_kbd_release(void) |
void ski_kbd_grab(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&ski_kbd_irq.lock); |
if (ski_kbd_irq.notif_cfg.answerbox) |
ski_kbd_irq.notif_cfg.notify = true; |
spinlock_unlock(&ski_kbd_irq.lock); |
interrupts_restore(ipl); |
kbd_disabled = true; |
} |
|
|
#define POLL_INTERVAL 50000 /* 50 ms */ |
|
/** Kernel thread for polling keyboard. */ |
void kkbdpoll(void *arg) |
void ski_kbd_release(void) |
{ |
while (1) { |
poll_keyboard(); |
thread_usleep(POLL_INTERVAL); |
kbd_disabled = false; |
} |
} |
|
/** @} |
*/ |