From 369d1d9a68527fe2659f4a21dc4c0aa52533dbc3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 5 May 2011 13:06:24 -0700 Subject: Beginnings of the SRM console prompt. --- Makefile | 3 +- console-low.S | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ console.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ init.c | 10 +---- protos.h | 102 ++++++++++++++++++++++++++++++++++++++++++++- uart.c | 13 +++++- 6 files changed, 373 insertions(+), 13 deletions(-) create mode 100644 console-low.S create mode 100644 console.c 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 + . */ + + .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 + . */ + +#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); } -- cgit v1.1