summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2011-05-05 13:06:24 -0700
committerRichard Henderson <rth@twiddle.net>2011-05-05 13:12:49 -0700
commit369d1d9a68527fe2659f4a21dc4c0aa52533dbc3 (patch)
treee348726a048cecbb036ba7b9a80cd1bf7bfcff21
parent9e75c89f005e07e059c80317904fefaffe6fde7f (diff)
downloadqemu-palcode-369d1d9a68527fe2659f4a21dc4c0aa52533dbc3.tar.gz
Beginnings of the SRM console prompt.
-rw-r--r--Makefile3
-rw-r--r--console-low.S126
-rw-r--r--console.c132
-rw-r--r--init.c10
-rw-r--r--protos.h102
-rw-r--r--uart.c13
6 files changed, 373 insertions, 13 deletions
diff --git a/Makefile b/Makefile
index 71ce4ae..315d932 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ CPPFLAGS = -DSYSTEM_H='"sys-$(SYSTEM).h"'
CFLAGS += -mcpu=ev67
-OBJS = pal.o sys-$(SYSTEM).o init.o crb.o uart.o memset.o printf.o
+OBJS = pal.o sys-$(SYSTEM).o init.o crb.o uart.o console.o console-low.o memset.o printf.o
all: palcode-$(SYSTEM)
@@ -28,3 +28,4 @@ init.o: init.c hwrpb.h osf.h uart.h sys-$(SYSTEM).h core-$(CORE).h
printf.o: printf.c uart.h
uart.o: uart.c uart.h protos.h
crb.o: crb.c hwrpb.h protos.h console.h uart.h
+console.o: console.c console.h protos.h
diff --git a/console-low.S b/console-low.S
new file mode 100644
index 0000000..a03f4ed
--- /dev/null
+++ b/console-low.S
@@ -0,0 +1,126 @@
+/* Assembly helper routines for the emulation SRM console.
+
+ Copyright (C) 2011 Richard Henderson
+
+ This file is part of QEMU PALcode.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text
+ of the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>. */
+
+ .set nomacro
+ .set noat
+ .text
+ .cfi_sections .debug_frame
+
+#define SAVE_ALL_SIZE (18*8)
+
+ .globl entInt
+ .type entInt, @function
+ .cfi_startproc simple
+entInt:
+ .cfi_return_column 64
+ .cfi_def_cfa $sp, 48
+ .cfi_rel_offset 64, 8
+ .cfi_rel_offset $gp, 16
+ .cfi_rel_offset $16, 24
+ .cfi_rel_offset $17, 32
+ .cfi_rel_offset $18, 40
+ lda $sp, -SAVE_ALL_SIZE($sp)
+ .cfi_adjust_cfa_offset SAVE_ALL_SIZE
+ stq $0, 0*8($sp)
+ stq $1, 1*8($sp)
+ stq $2, 2*8($sp)
+ stq $3, 3*8($sp)
+ stq $4, 4*8($sp)
+ stq $5, 5*8($sp)
+ stq $6, 6*8($sp)
+ stq $7, 7*8($sp)
+ stq $8, 9*8($sp)
+ stq $19, 9*8($sp)
+ stq $20, 10*8($sp)
+ stq $21, 11*8($sp)
+ stq $22, 12*8($sp)
+ stq $23, 13*8($sp)
+ stq $24, 14*8($sp)
+ stq $25, 15*8($sp)
+ stq $26, 16*8($sp)
+ stq $27, 17*8($sp)
+ stq $28, 18*8($sp)
+ .cfi_rel_offset $0, 0*8
+ .cfi_rel_offset $1, 1*8
+ .cfi_rel_offset $2, 2*8
+ .cfi_rel_offset $3, 3*8
+ .cfi_rel_offset $4, 4*8
+ .cfi_rel_offset $5, 5*8
+ .cfi_rel_offset $6, 6*8
+ .cfi_rel_offset $7, 7*8
+ .cfi_rel_offset $8, 8*8
+ .cfi_rel_offset $19, 9*8
+ .cfi_rel_offset $20, 10*8
+ .cfi_rel_offset $21, 11*8
+ .cfi_rel_offset $22, 12*8
+ .cfi_rel_offset $23, 13*8
+ .cfi_rel_offset $24, 14*8
+ .cfi_rel_offset $25, 15*8
+ .cfi_rel_offset $26, 16*8
+ .cfi_rel_offset $27, 17*8
+ .cfi_rel_offset $28, 18*8
+
+ bsr $26, do_entInt !samegp
+
+ ldq $0, 0*8($sp)
+ ldq $1, 1*8($sp)
+ ldq $2, 2*8($sp)
+ ldq $3, 3*8($sp)
+ ldq $4, 4*8($sp)
+ ldq $5, 5*8($sp)
+ ldq $6, 6*8($sp)
+ ldq $7, 7*8($sp)
+ ldq $8, 9*8($sp)
+ ldq $19, 9*8($sp)
+ ldq $20, 10*8($sp)
+ ldq $21, 11*8($sp)
+ ldq $22, 12*8($sp)
+ ldq $23, 13*8($sp)
+ ldq $24, 14*8($sp)
+ ldq $25, 15*8($sp)
+ ldq $26, 16*8($sp)
+ ldq $27, 17*8($sp)
+ ldq $28, 18*8($sp)
+ lda $sp, SAVE_ALL_SIZE($sp)
+ .cfi_adjust_cfa_offset -SAVE_ALL_SIZE
+ .cfi_restore $0
+ .cfi_restore $1
+ .cfi_restore $2
+ .cfi_restore $3
+ .cfi_restore $4
+ .cfi_restore $5
+ .cfi_restore $6
+ .cfi_restore $7
+ .cfi_restore $8
+ .cfi_restore $19
+ .cfi_restore $20
+ .cfi_restore $21
+ .cfi_restore $22
+ .cfi_restore $23
+ .cfi_restore $24
+ .cfi_restore $25
+ .cfi_restore $26
+ .cfi_restore $27
+ .cfi_restore $28
+
+ call_pal 0x3f // rti
+
+ .cfi_endproc
+ .size entInt, . - entInt
diff --git a/console.c b/console.c
new file mode 100644
index 0000000..b1eb91b
--- /dev/null
+++ b/console.c
@@ -0,0 +1,132 @@
+/* The SRM console prompt.
+
+ Copyright (C) 2011 Richard Henderson
+
+ This file is part of QEMU PALcode.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text
+ of the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "protos.h"
+#include "console.h"
+
+
+static void
+output_crnl(void)
+{
+ crb_puts(0, "\r\n", 2);
+}
+
+static void
+output_bell(void)
+{
+ crb_puts(0, "\a", 1);
+}
+
+static void
+backspace_and_erase(void)
+{
+ crb_puts(0, "\b \b", 3);
+}
+
+static unsigned long
+getline(char *buf, unsigned long bufsize)
+{
+ unsigned long len = 0;
+ long c;
+
+ while (1)
+ {
+ c = crb_getc(0);
+ if (c < 0)
+ continue;
+ switch ((int)c)
+ {
+ case '\r':
+ case '\n':
+ output_crnl();
+ buf[len] = 0;
+ return len;
+
+ case '\b':
+ case 0x7f: /* Delete */
+ if (len > 0)
+ {
+ backspace_and_erase();
+ len--;
+ }
+ else
+ output_bell();
+ break;
+
+ default:
+ if (len + 1 < bufsize)
+ {
+ buf[len] = c;
+ crb_puts(0, buf+len, 1);
+ len++;
+ }
+ else
+ output_bell();
+ break;
+ }
+ }
+}
+
+static inline void set_console_alarm(void)
+{
+ /* Just set a new timeout for 10ms = 10M ns. */
+ set_alarm_rel(10 * 1000 * 1000);
+}
+
+void
+do_entInt(unsigned long type, unsigned long vector)
+{
+ switch (type)
+ {
+ case 0:
+ /* ??? SMP interrupt. We're going to need this for starting up
+ secondary cpus. */
+ break;
+ case 1:
+ /* Timer interrupt. */
+ set_console_alarm();
+ break;
+ case 2:
+ /* ??? Device interrupt. We're going to need this for virtio disk
+ operations at minimum. */
+ break;
+ }
+}
+
+void
+do_console(void)
+{
+ char line[256];
+ unsigned long len;
+
+ wrkgp();
+ wrent(entInt, 0);
+ set_console_alarm();
+ swpipl(0);
+
+ while (1)
+ {
+ crb_puts(0, ">>> ", 4);
+ len = getline(line, sizeof(line));
+ crb_puts(0, "got: ", 5);
+ crb_puts(0, line, len);
+ output_crnl();
+ }
+}
diff --git a/init.c b/init.c
index 59da517..0a92f97 100644
--- a/init.c
+++ b/init.c
@@ -231,14 +231,6 @@ init_pcb (void)
}
void
-do_hello(void)
-{
- uart_puts(COM1, "Hello, World!\n");
- asm ("halt");
- __builtin_unreachable ();
-}
-
-void
do_start(unsigned long memsize, void (*kernel_entry)(void), long cpus)
{
last_alloc = _end;
@@ -254,7 +246,7 @@ do_start(unsigned long memsize, void (*kernel_entry)(void), long cpus)
register unsigned long pa_pcb __asm__("$18");
register unsigned long vptptr __asm__("$19");
- pc = (kernel_entry ? kernel_entry : do_hello);
+ pc = (kernel_entry ? kernel_entry : do_console);
pa_pcb = PA(&pcb);
vptptr = VPTPTR;
asm("call_pal 0x0a" : : "r"(variant), "r"(pc), "r"(pa_pcb), "r"(vptptr));
diff --git a/protos.h b/protos.h
index 901fe3a..53bf401 100644
--- a/protos.h
+++ b/protos.h
@@ -21,6 +21,60 @@
#ifndef PROTOS_H
#define PROTOS_H 1
+/*
+ * Call_Pal functions.
+ */
+
+static inline void wrent(void *cb, unsigned long which)
+{
+ register void *a0 __asm__("$16") = cb;
+ register unsigned long a1 __asm__("$17") = which;
+
+ asm volatile ("call_pal 0x34"
+ : "+r"(a0), "+r"(a1)
+ : : "$1", "$22", "$23", "$24", "$25");
+}
+
+static inline unsigned long swpipl(unsigned long newipl)
+{
+ register unsigned long v0 __asm__("$0");
+ register unsigned long a0 __asm__("$16") = newipl;
+
+ asm volatile ("call_pal 0x35"
+ : "=r"(v0), "+r"(a0)
+ : : "$1", "$22", "$23", "$24", "$25");
+
+ return v0;
+}
+
+static inline unsigned long rdps(void)
+{
+ register unsigned long v0 __asm__("$0");
+
+ asm volatile ("call_pal 0x36"
+ : "=r"(v0) : : "$1", "$22", "$23", "$24", "$25");
+
+ return v0;
+}
+
+static inline void wrkgp(void)
+{
+ asm volatile ("mov $29, $16\n\tcall_pal 0x37"
+ : : : "$16", "$1", "$22", "$23", "$24", "$25");
+}
+
+static inline unsigned long wtint(unsigned long skip)
+{
+ register unsigned long v0 __asm__("$0");
+ register unsigned long a0 __asm__("$16") = skip;
+
+ asm volatile ("call_pal 0x3e"
+ : "=r"(v0), "+r"(a0)
+ : : "$1", "$22", "$23", "$24", "$25");
+
+ return v0;
+}
+
/*
* Cserve functions.
*/
@@ -41,7 +95,7 @@ static inline unsigned long ldq_p(unsigned long addr)
static inline unsigned long stq_p(unsigned long port, unsigned long val)
{
register unsigned long v0 __asm__("$0");
- register unsigned long a0 __asm__("$16") = 4;
+ register unsigned long a0 __asm__("$16") = 2;
register unsigned long a1 __asm__("$17") = port;
register unsigned long a2 __asm__("$18") = val;
@@ -52,6 +106,46 @@ static inline unsigned long stq_p(unsigned long port, unsigned long val)
return v0;
}
+static inline unsigned long get_wall_time(void)
+{
+ register unsigned long v0 __asm__("$0");
+ register unsigned long a0 __asm__("$16") = 3;
+
+ asm("call_pal 9" : "=r"(v0), "+r"(a0) : : "$17", "$18", "$19", "$20", "$21");
+
+ return v0;
+}
+
+static inline unsigned long get_alarm(void)
+{
+ register unsigned long v0 __asm__("$0");
+ register unsigned long a0 __asm__("$16") = 4;
+
+ asm("call_pal 9" : "=r"(v0), "+r"(a0) : : "$17", "$18", "$19", "$20", "$21");
+
+ return v0;
+}
+
+static inline void set_alarm_rel(unsigned long nsec)
+{
+ register unsigned long a0 __asm__("$16") = 5;
+ register unsigned long a1 __asm__("$17") = nsec;
+
+ asm volatile ("call_pal 9"
+ : "+r"(a0), "+r"(a1)
+ : : "$0", "$18", "$19", "$20", "$21");
+}
+
+static inline void set_alarm_abs(unsigned long nsec)
+{
+ register unsigned long a0 __asm__("$16") = 6;
+ register unsigned long a1 __asm__("$17") = nsec;
+
+ asm volatile ("call_pal 9"
+ : "+r"(a0), "+r"(a1)
+ : : "$0", "$18", "$19", "$20", "$21");
+}
+
/*
* I/O functions
*/
@@ -67,4 +161,10 @@ extern unsigned long crb_dispatch(long select, long a1, long a2,
long a3, long a4);
extern unsigned long crb_fixup(unsigned long vptptr, unsigned long hwrpb);
+/*
+ * The Console
+ */
+extern void do_console(void);
+extern void entInt(void);
+
#endif /* PROTOS_H */
diff --git a/uart.c b/uart.c
index 56e1cc7..cf2615e 100644
--- a/uart.c
+++ b/uart.c
@@ -46,8 +46,17 @@ uart_charav(int offset)
int
uart_getchar(int offset)
{
- while (!uart_charav(offset))
- continue;
+ /* If interrupts are enabled, use wtint assuming that either the
+ device itself will wake us, or that a clock interrupt will. */
+ if ((rdps() & 7) == 0) {
+ while (!uart_charav(offset)) {
+ wtint(0);
+ }
+ } else {
+ while (!uart_charav(offset))
+ continue;
+ }
+
return inb(com2Rbr + offset);
}