on risc-v, emulate keyboard input using an alarm
authorAndrew Waterman <waterman@eecs.berkeley.edu>
Sat, 12 May 2012 00:56:25 +0000 (17:56 -0700)
committerAndrew Waterman <waterman@eecs.berkeley.edu>
Sat, 12 May 2012 00:56:25 +0000 (17:56 -0700)
kern/arch/riscv/console.c
kern/arch/riscv/console.h
kern/arch/riscv/init.c
kern/arch/riscv/time.c

index b3fadcc..00431cb 100644 (file)
 #include <arch/console.h>
+#include <console.h>
 #include <pmap.h>
 #include <atomic.h>
+#include <smp.h>
 
-long
-fesvr_syscall(long n, long a0, long a1, long a2, long a3)
+static volatile uint64_t magic_mem[MAX_NUM_CPUS][8] __attribute__((aligned(64)));
+
+static bool fesvr_busy()
+{
+       if (mfpcr(PCR_TOHOST))
+               return true;
+       
+       volatile uint64_t* mm = magic_mem[core_id()];
+       if (mfpcr(PCR_FROMHOST) && mm[6])
+       {
+               void (*func)(void*, uint64_t*) = (void*)(uintptr_t)mm[6];
+               void* farg = (void*)(uintptr_t)mm[7];
+               func(farg, (uint64_t*)mm);
+       }
+
+       return false;
+}
+
+int fesvr_syscall(long n, long a0, long a1, long a2, long a3,
+                  void (*continuation)(void*, uint64_t*), void* arg)
 {
-  volatile uint64_t magic_mem[8];
+       int ret = -1;
+       uintptr_t irq_state = disable_irq();
 
-  magic_mem[0] = n;
-  magic_mem[1] = a0;
-  magic_mem[2] = a1;
-  magic_mem[3] = a2;
-  magic_mem[4] = a3;
+       if (fesvr_busy())
+               goto out;
 
-  mb();
-  mtpcr(PCR_TOHOST, PADDR(magic_mem));
-  while(mfpcr(PCR_FROMHOST) == 0);
-  mb();
+       volatile uint64_t* mm = magic_mem[core_id()];
+       mm[0] = n;
+       mm[1] = a0;
+       mm[2] = a1;
+       mm[3] = a2;
+       mm[4] = a3;
+       mm[6] = (uintptr_t)continuation;
+       mm[7] = (uintptr_t)arg;
 
-  return magic_mem[0];
+       mb();
+       mtpcr(PCR_TOHOST, PADDR(mm));
+  
+       ret = 0;
+out:
+       restore_irq(irq_state);
+       return ret;
 }
 
 void
 fesvr_die()
 {
-       fesvr_syscall(FESVR_SYS_exit, 0, 0, 0, 0);
+       while (fesvr_syscall(FESVR_SYS_exit, 0, 0, 0, 0, 0, 0) < 0);
 }
 
-void
-cons_init(void)
+static void cons_polled(void* null, uint64_t* magic_mem)
 {
+       for (int i = 0; i < (int)magic_mem[0]; i++)
+       {
+               char c = ((char*)KADDR(magic_mem[2]))[i];
+               if (c == 'G')
+                       send_kernel_message(core_id(), __run_mon, 0, 0, 0, KMSG_ROUTINE);
+               else
+                       send_kernel_message(core_id(), __cons_add_char, (long)&cons_buf,
+                                           (long)c, 0, KMSG_ROUTINE);
+       }
 }
 
-// `High'-level console I/O.  Used by readline and cprintf.
+static struct alarm_waiter keyboard_waiter;
+
+static void cons_poll(struct alarm_waiter* awaiter)
+{
+       static char buf[64] __attribute__((aligned(64)));
+       fesvr_syscall(FESVR_SYS_read, 0, PADDR(buf), sizeof(buf), 0, cons_polled, 0);
+
+       set_awaiter_rel(&keyboard_waiter, 10);
+       set_alarm(&per_cpu_info[core_id()].tchain, &keyboard_waiter);
+}
+
+// emulate keyboard input with an alarm
+void keyboard_alarm_init()
+{
+       init_awaiter(&keyboard_waiter, cons_poll);
+       set_awaiter_rel(&keyboard_waiter, 1);
+       set_alarm(&per_cpu_info[core_id()].tchain, &keyboard_waiter);
+}
+
+int cons_get_any_char(void)
+{
+       assert(0);
+}
 
 void
-cputbuf(const char* buf, int len)
+cons_init(void)
 {
-       fesvr_syscall(FESVR_SYS_write, 1, PADDR((uintptr_t)buf), len, 0);
 }
 
-// Low-level console I/O
+// `High'-level console I/O.  Used by readline and cprintf.
 
 void
-cons_putc(int c)
+cputbuf(const char* str, int len)
 {
-       if(c == '\b' || c == 0x7F)
-       {
-       #ifdef __CONFIG_PRINTK_NO_BACKSPACE__
-               char buf[2] = {'^', 'H'};
-               cputbuf(buf, 2);
-       #else
-               char buf[3] = {'\b', ' ', '\b'};
-               cputbuf(buf, 3);
-       #endif /* __CONFIG_PRINTK_NO_BACKSPACE__ */
-       }
-       else
-       {
-               char ch = c;
-               cputbuf(&ch,1);
-       }
+       static char bufs[MAX_NUM_CPUS][1024] __attribute__((aligned(64)));
+       assert(len <= sizeof(bufs[0]));
+
+       char* buf = bufs[core_id()];
+       while (fesvr_busy());
+       memcpy(buf, str, len);
+       while (fesvr_syscall(FESVR_SYS_write, 1, PADDR(buf), len, 0, 0, 0) < 0);
 }
 
+// Low-level console I/O
+
 void
 cputchar(int c)
 {
@@ -70,23 +121,10 @@ cputchar(int c)
 }
 
 int
-cons_getc()
-{
-       char ch;
-       uintptr_t paddr = PADDR((uintptr_t)&ch);
-       long ret = fesvr_syscall(FESVR_SYS_read, 0, paddr, 1, 0);
-       if(ch == 0x7F)
-               ch = '\b';
-       return ret <= 0 ? 0 : ch;
-}
-
-int
 getchar(void)
 {
-       int c;
-
-       while ((c = cons_getc()) == 0)
-               /* do nothing */;
+       char c;
+       kb_get_from_buf(&cons_buf, &c, 1);
        return c;
 }
 
index 3d54d5b..a50560c 100644 (file)
@@ -13,8 +13,9 @@
 #define CRT_SIZE       (CRT_ROWS * CRT_COLS)
 
 void cons_init(void);
-void cons_putc(int c);
-int cons_getc(void);
+void keyboard_alarm_init();
+/* Returns any available character, or 0 for none (legacy helper) */
+int cons_get_any_char(void);
 
 #define        FESVR_SYS_exit  1
 #define        FESVR_SYS_getpid        20
@@ -35,7 +36,6 @@ int cons_getc(void);
 #define        FESVR_SYS_pwrite 181
 #define FESVR_SYS_getmainvars 201
 
-long fesvr_syscall(long n, long a0, long a1, long a2, long a3);
 void fesvr_die();
 
 #endif /* _CONSOLE_H_ */
index cade583..d664167 100644 (file)
@@ -2,9 +2,11 @@
 
 #include <smp.h>
 #include <arch/init.h>
+#include <arch/console.h>
 
 void arch_init()
 {              
        smp_boot();
        proc_init();
+       keyboard_alarm_init();
 }
index bc5bde2..da9b215 100644 (file)
@@ -23,20 +23,20 @@ set_core_timer(uint32_t usec, bool periodic)
 
        if (usec)
        {
-         uint32_t clocks =  (uint64_t)usec*TSC_HZ/1000000;
+               uint32_t clocks =  (uint64_t)usec*TSC_HZ/1000000;
 
-         int8_t irq_state = 0;
-         disable_irqsave(&irq_state);
+               int8_t irq_state = 0;
+               disable_irqsave(&irq_state);
 
-         mtpcr(PCR_COUNT, 0);
-         mtpcr(PCR_COMPARE, clocks);
-         mtpcr(PCR_SR, mfpcr(PCR_SR) | (1 << (IRQ_TIMER+SR_IM_SHIFT)));
+               mtpcr(PCR_COUNT, 0);
+               mtpcr(PCR_COMPARE, clocks);
+               mtpcr(PCR_SR, mfpcr(PCR_SR) | (1 << (IRQ_TIMER+SR_IM_SHIFT)));
 
-         enable_irqsave(&irq_state);
+               enable_irqsave(&irq_state);
        }
        else
        {
-         mtpcr(PCR_SR, mfpcr(PCR_SR) & ~(1 << (IRQ_TIMER+SR_IM_SHIFT)));
+               mtpcr(PCR_SR, mfpcr(PCR_SR) & ~(1 << (IRQ_TIMER+SR_IM_SHIFT)));
        }
 }