summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2011-04-27 09:43:00 -0700
committerRichard Henderson <rth@twiddle.net>2011-04-27 09:43:00 -0700
commitea0e38f6bc1e458b34b11b40c1092036db34f548 (patch)
tree78a8757d7a5d6bc16cce2c63beb652b78dd520a6
parent331e6b4c75dd8095a29ed2991e32a862dc40074b (diff)
downloadqemu-palcode-ea0e38f6bc1e458b34b11b40c1092036db34f548.tar.gz
Re-org for Clipper system.
-rw-r--r--Makefile23
-rw-r--r--core-cia.h (renamed from cia.h)99
-rw-r--r--core-typhoon.h163
-rw-r--r--init.c28
-rw-r--r--io.h18
-rw-r--r--osf.h1
-rw-r--r--pal.S312
-rw-r--r--pal.h134
-rw-r--r--protos.h42
-rw-r--r--sys-clipper.S90
-rw-r--r--sys-clipper.h10
-rw-r--r--sys-sx164.h25
-rw-r--r--uart.c2
13 files changed, 637 insertions, 310 deletions
diff --git a/Makefile b/Makefile
index ea2eac2..f62888f 100644
--- a/Makefile
+++ b/Makefile
@@ -2,25 +2,28 @@ CROSS = alphaev67-linux-
CC = $(CROSS)gcc
LD = $(CROSS)ld
+CORE = typhoon
+SYSTEM = clipper
+
+ASFLAGS = -Wa,-m21264 -Wa,--noexecstack
CFLAGS = -Os -g -Wall -fvisibility=hidden -fno-strict-aliasing \
-msmall-text -msmall-data -mno-fp-regs -mbuild-constants
+CPPFLAGS = -DSYSTEM_H='"sys-$(SYSTEM).h"'
-CFLAGS += -mcpu=pca56
+CFLAGS += -mcpu=ev67
-OBJS = pal.o init.o uart.o memset.o printf.o
+OBJS = pal.o sys-$(SYSTEM).o init.o uart.o memset.o printf.o
-all: palcode-sx164
+all: palcode-$(SYSTEM)
-palcode-sx164: palcode.ld $(OBJS)
+palcode-$(SYSTEM): palcode.ld $(OBJS)
$(LD) -relax -o $@ -T palcode.ld -Map $@.map $(OBJS)
clean:
rm -f *.o
- rm -f palcode palcode.map
-
-pal.o: pal.S osf.h uart.h
- $(CC) $(CFLAGS) -c -Wa,-m21264 -Wa,--noexecstack -o $@ $<
+ rm -f palcode-*
-init.o: init.c hwrpb.h osf.h uart.h
+pal.o: pal.S osf.h sys-$(SYSTEM).h core-$(CORE).h
+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 io.h cia.h
+uart.o: uart.c uart.h protos.h
diff --git a/cia.h b/core-cia.h
index cea81b6..a42cea0 100644
--- a/cia.h
+++ b/core-cia.h
@@ -1,63 +1,8 @@
-#ifndef __ALPHA_CIA__H__
-#define __ALPHA_CIA__H__
+#ifndef CIA_H
+#define CIA_H
#define IDENT_ADDR 0xfffffc0000000000UL
-/*
- * CIA is the internal name for the 21171 chipset which provides
- * memory controller and PCI access for the 21164 chip based systems.
- * Also supported here is the 21172 (CIA-2) and 21174 (PYXIS).
- *
- * The lineage is a bit confused, since the 21174 was reportedly started
- * from the 21171 Pass 1 mask, and so is missing bug fixes that appear
- * in 21171 Pass 2 and 21172, but it also contains additional features.
- *
- * This file is based on:
- *
- * DECchip 21171 Core Logic Chipset
- * Technical Reference Manual
- *
- * EC-QE18B-TE
- *
- * david.rusling@reo.mts.dec.com Initial Version.
- *
- */
-
-/*
- * CIA ADDRESS BIT DEFINITIONS
- *
- * 3333 3333 3322 2222 2222 1111 1111 11
- * 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210
- * ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
- * 1 000
- * ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
- * | |\|
- * | Byte Enable --+ |
- * | Transfer Length --+
- * +-- IO space, not cached
- *
- * Byte Transfer
- * Enable Length Transfer Byte Address
- * adr<6:5> adr<4:3> Length Enable Adder
- * ---------------------------------------------
- * 00 00 Byte 1110 0x000
- * 01 00 Byte 1101 0x020
- * 10 00 Byte 1011 0x040
- * 11 00 Byte 0111 0x060
- *
- * 00 01 Word 1100 0x008
- * 01 01 Word 1001 0x028 <= Not supported in this code.
- * 10 01 Word 0011 0x048
- *
- * 00 10 Tribyte 1000 0x010
- * 01 10 Tribyte 0001 0x030
- *
- * 10 11 Longword 0000 0x058
- *
- * Note that byte enables are asserted low.
- *
- */
-
#define CIA_MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */
#define CIA_MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */
#define CIA_MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */
@@ -265,4 +210,42 @@
/* Offset between ram physical addresses and pci64 DAC bus addresses. */
#define PYXIS_DAC_OFFSET (1UL << 40)
-#endif /* __ALPHA_CIA__H__ */
+#ifdef __ASSEMBLER__
+
+/* Unfortunately, GAS doesn't attempt any interesting constructions of
+ 64-bit constants, dropping them all into the .lit8 section. It is
+ better for us to build these by hand. */
+.macro LOAD_PHYS_PYXIS_INT ret
+ lda \ret, 0x87a
+ sll \ret, 28, \ret
+.endm
+
+.macro LOAD_KSEG_PCI_IO ret
+ lda \ret, -887
+ sll \ret, 32, \ret
+.endm
+
+.macro SYS_WHAMI ret
+ mov 0, \ret
+.endm
+
+.macro SYS_ACK_SMP t0, t1, t2
+ br MchkBugCheck
+.endm
+
+#else
+
+static inline unsigned long inb(unsigned long port)
+{
+ return *(volatile unsigned char *)(CIA_BW_IO + port);
+}
+
+static inline void outb(unsigned long port, unsigned char val)
+{
+ *(volatile unsigned char *)(CIA_BW_IO + port) = val;
+}
+
+
+#endif
+
+#endif /* CIA_H */
diff --git a/core-typhoon.h b/core-typhoon.h
new file mode 100644
index 0000000..70d85af
--- /dev/null
+++ b/core-typhoon.h
@@ -0,0 +1,163 @@
+#ifndef TYPHOON_H
+#define TYPHOON_H 1
+
+/* Assume a 43-bit KSEG for now. */
+#define PIO_PHYS_ADDR 0x80000000000
+#define PIO_KSEG_ADDR (0xfffffc0000000000 + 0x10000000000)
+
+/* CCHIP REGISTERS */
+
+#define TYPHOON_CCHIP 0x1a0000000
+
+#define TYPHOON_CCHIP_CSC 0x0000
+#define TYPHOON_CCHIP_MTR 0x0040
+#define TYPHOON_CCHIP_MISC 0x0080
+#define TYPHOON_CCHIP_MPD 0x00c0
+#define TYPHOON_CCHIP_AAR0 0x0100
+#define TYPHOON_CCHIP_AAR1 0x0140
+#define TYPHOON_CCHIP_AAR2 0x0180
+#define TYPHOON_CCHIP_AAR3 0x01c0
+#define TYPHOON_CCHIP_DIM0 0x0200
+#define TYPHOON_CCHIP_DIM1 0x0240
+#define TYPHOON_CCHIP_DIR0 0x0280
+#define TYPHOON_CCHIP_DIR1 0x02c0
+#define TYPHOON_CCHIP_DRIR 0x0300
+#define TYPHOON_CCHIP_PRBEN 0x0340
+#define TYPHOON_CCHIP_IIC0 0x0380
+#define TYPHOON_CCHIP_IIC1 0x03c0
+#define TYPHOON_CCHIP_MPR0 0x0400
+#define TYPHOON_CCHIP_MPR1 0x0440
+#define TYPHOON_CCHIP_MPR2 0x0480
+#define TYPHOON_CCHIP_MPR3 0x04c0
+#define TYPHOON_CCHIP_TTR 0x0580
+#define TYPHOON_CCHIP_TDR 0x05c0
+#define TYPHOON_CCHIP_DIM2 0x0600
+#define TYPHOON_CCHIP_DIM3 0x0640
+#define TYPHOON_CCHIP_DIR2 0x0680
+#define TYPHOON_CCHIP_DIR3 0x06c0
+#define TYPHOON_CCHIP_IIC2 0x0700
+#define TYPHOON_CCHIP_IIC3 0x0740
+#define TYPHOON_CCHIP_PWR 0x0780
+#define TYPHOON_CCHIP_CMONCTLA 0x0c00
+#define TYPHOON_CCHIP_CMONCTLB 0x0c40
+#define TYPHOON_CCHIP_CMONCNT01 0x0c80
+#define TYPHOON_CCHIP_CMONCNT23 0x0cc0
+
+/* DCHIP REGISTERS */
+
+#define TYPHOON_DCHIP 0x1b0000000
+
+#define TYPHOON_DCHIP_DSC 0x0800
+#define TYPHOON_DCHIP_STR 0x0840
+#define TYPHOON_DCHIP_DREV 0x0880
+#define TYPHOON_DCHIP_DSC2 0x08c0
+
+/* PCHIP REGISTERS */
+
+#define TYPHOON_PCHIP0 0x180000000
+#define TYPHOON_PCHIP1 0x380000000
+
+#define TYPHOON_PCHIP_WSBA0 0x0000
+#define TYPHOON_PCHIP_WSBA1 0x0040
+#define TYPHOON_PCHIP_WSBA2 0x0080
+#define TYPHOON_PCHIP_WSBA3 0x00c0
+#define TYPHOON_PCHIP_WSM0 0x0100
+#define TYPHOON_PCHIP_WSM1 0x0140
+#define TYPHOON_PCHIP_WSM2 0x0180
+#define TYPHOON_PCHIP_WSM3 0x01c0
+#define TYPHOON_PCHIP_TBA0 0x0200
+#define TYPHOON_PCHIP_TBA1 0x0240
+#define TYPHOON_PCHIP_TBA2 0x0280
+#define TYPHOON_PCHIP_TBA3 0x02c0
+#define TYPHOON_PCHIP_PCTL 0x0300
+#define TYPHOON_PCHIP_PLAT 0x0340
+#define TYPHOON_PCHIP_PERROR 0x03c0
+#define TYPHOON_PCHIP_PERRMASK 0x0400
+#define TYPHOON_PCHIP_PERRSET 0x0440
+#define TYPHOON_PCHIP_TLBIV 0x0480
+#define TYPHOON_PCHIP_TLBIA 0x04c0
+#define TYPHOON_PCHIP_PMONCTL 0x0500
+#define TYPHOON_PCHIP_PMONCNT 0x0540
+#define TYPHOON_PCHIP_SPRST 0x0800
+
+/* PCI ADDRESSES */
+
+#define TYPHOON_PCHIP0_PCI_MEM 0
+#define TYPHOON_PCHIP0_PCI_IO 0x1fc000000
+#define TYPHOON_PCHIP0_PCI_CONF 0x1fe000000
+
+#ifdef __ASSEMBLER__
+
+#include "pal.h"
+
+#define ptCpuDIR ptSys0
+#define ptCpuIIC ptSys1
+
+/* Unfortunately, GAS doesn't attempt any interesting constructions of
+ 64-bit constants, dropping them all into the .lit8 section. It is
+ better for us to build these by hand. */
+.macro LOAD_PHYS_CCHIP ret
+ lda \ret, 0x400d
+ sll \ret, 29, \ret
+.endm
+
+.macro LOAD_PHYS_PCHIP0 ret
+ lda \ret, 0x400c
+ sll \ret, 29, \ret
+.endm
+
+.macro LOAD_KSEG_PCI_IO ret
+ ldah \ret, -48
+ lda \ret, 0x1fc0(\ret)
+ sll \ret, 20, \ret
+.endm
+
+.macro SYS_WHAMI ret
+ LOAD_PHYS_CCHIP \ret
+ ldq_p \ret, TYPHOON_CCHIP_MISC(\ret)
+ and \ret, 3, \ret
+.endm
+
+/* ACK the Interprocessor Interrupt. */
+.macro SYS_ACK_SMP t0, t1, t2
+ LOAD_PHYS_CCHIP \t0
+ ldq_p \t1, TYPHOON_CCHIP_MISC(\t0)
+ and \t1, 3, \t1
+ addq \t1, 8, \t1
+ lda \t2, 1
+ sll \t2, \t1, \t2
+ stq_p \t2, TYPHOON_CCHIP_MISC(\t0)
+.endm
+
+/* ACK the Clock Interrupt. */
+.macro SYS_ACK_CLK t0, t1, t2
+ LOAD_PHYS_CCHIP \t0
+ ldq_p \t1, TYPHOON_CCHIP_MISC(\t0)
+ and \t1, 3, \t1
+ addq \t1, 4, \t1
+ lda \t2, 1
+ sll \t2, \t1, \t2
+ stq_p \t2, TYPHOON_CCHIP_MISC(\t0)
+.endm
+
+/* Load the device interrupt vector. */
+.macro SYS_DEV_VECTOR ret
+ mfpr \ret, ptCpuDIR
+ ldq_p \ret, 0(\ret)
+ cttz \ret, \ret
+ sll \ret, 4, \ret
+ lda \ret, 0x800(\ret)
+.endm
+
+/* Interrupt another CPU. */
+.macro SYS_WRIPIR target, t0, t1, t2
+ LOAD_PHYS_CCHIP \t0
+ mov 1, \t1
+ and \target, 3, \t2
+ addq \t2, 12, \t2
+ sll \t1, \t2, \t1
+ stq_p \t1, TYPHOON_CCHIP_MISC(\t0)
+.endm
+
+#endif /* ASSEMBLER */
+#endif /* TYPHOON_H */
diff --git a/init.c b/init.c
index 169ae07..535f92b 100644
--- a/init.c
+++ b/init.c
@@ -3,6 +3,7 @@
#include "hwrpb.h"
#include "osf.h"
#include "uart.h"
+#include SYSTEM_H
#define PAGE_SHIFT 13
#define PAGE_SIZE (1ul << PAGE_SHIFT)
@@ -141,6 +142,7 @@ static void
init_hwrpb (unsigned long memsize)
{
unsigned long pal_pages;
+ unsigned long cpu_type;
hwrpb.hwrpb.phys_addr = PA(&hwrpb);
@@ -167,14 +169,15 @@ init_hwrpb (unsigned long memsize)
((int *)hwrpb.hwrpb.ssn)[2] = ( 'U' << 0);
/* For now, hard-code emulation of sx164. */
- hwrpb.hwrpb.cpuid = PCA56_CPU;
+ cpu_type = init_cpuid();
+ hwrpb.hwrpb.cpuid = cpu_type;
hwrpb.hwrpb.pagesize = PAGE_SIZE;
hwrpb.hwrpb.pa_bits = 40;
hwrpb.hwrpb.max_asn = 127;
- hwrpb.hwrpb.sys_type = ST_DEC_EB164;
- hwrpb.hwrpb.sys_variation = 15 << 10;
- hwrpb.hwrpb.sys_revision = 0;
- hwrpb.processor.type = PCA56_CPU;
+ hwrpb.hwrpb.sys_type = SYS_TYPE;
+ hwrpb.hwrpb.sys_variation = SYS_VARIATION;
+ hwrpb.hwrpb.sys_revision = SYS_REVISION;
+ hwrpb.processor.type = cpu_type;
hwrpb.hwrpb.intr_freq = HZ * 4096;
hwrpb.hwrpb.cycle_freq = 250000000; /* QEMU architects 250MHz. */
@@ -220,7 +223,7 @@ do_hello(void)
}
void
-do_start(unsigned long memsize, void (*kernel_entry)(void))
+do_start(unsigned long memsize, void (*kernel_entry)(void), long cpus)
{
last_alloc = _end;
@@ -242,3 +245,16 @@ do_start(unsigned long memsize, void (*kernel_entry)(void))
}
__builtin_unreachable ();
}
+
+void
+do_start_wait(void)
+{
+ while (1)
+ {
+ // WtInt with interrupts off. Rely on the fact that QEMU will
+ // un-halt the CPU when an interrupt arrives.
+ asm("lda $16,-1\n\tcall_pal 0x3e" : : : "$0", "$16");
+
+ // FIXME do something with the IPI.
+ }
+}
diff --git a/io.h b/io.h
deleted file mode 100644
index c58c271..0000000
--- a/io.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef IO_H
-#define IO_H
-
-#include "cia.h"
-
-static inline unsigned long
-inb(unsigned long port)
-{
- return *(volatile unsigned char *)(CIA_BW_IO + port);
-}
-
-static inline void
-outb(unsigned char val, unsigned long port)
-{
- *(volatile unsigned char *)(CIA_BW_IO + port) = val;
-}
-
-#endif
diff --git a/osf.h b/osf.h
index c7e18c8..78e2e70 100644
--- a/osf.h
+++ b/osf.h
@@ -59,6 +59,7 @@
#define IPL_K_DEV0 0x3
#define IPL_K_DEV1 0x4
#define IPL_K_CLK 0x5
+#define IPL_K_IP 0x6
#define IPL_K_RT 0x6
#define IPL_K_PERF 0x6
#define IPL_K_PFAIL 0x6
diff --git a/pal.S b/pal.S
index d604666..124763a 100644
--- a/pal.S
+++ b/pal.S
@@ -2,129 +2,9 @@
.set nomacro
.text
+#include "pal.h"
#include "osf.h"
-#include "uart.h"
-
-/* General Purpose Registers. */
-#define v0 $0
-#define t0 $1
-#define t1 $2
-#define t2 $3
-#define t3 $4
-#define t4 $5
-#define t5 $6
-#define a0 $16
-#define a1 $17
-#define a2 $18
-#define a3 $19
-#define a4 $20
-#define a5 $21
-#define t8 $22
-#define t9 $23
-#define t10 $24
-
-/* PALcode Shadow Registers. These registers are swapped out when
- QEMU is in PALmode. Unlike real hardware, there is no enable bit.
- However, also unlike real hardware, the originals can be accessed
- via MTPR/MFPR. */
-#define p0 $8
-#define p1 $9
-#define p2 $10
-#define p3 $11
-#define p4 $12
-#define p5 $13
-#define p6 $14 // Used to save exc_addr for machine check
-#define p7 $25
-
-/* QEMU Processor Registers. */
-#define qemu_ps 0
-#define qemu_fen 1
-#define qemu_pcc_ofs 2
-#define qemu_trap_arg0 3
-#define qemu_trap_arg1 4
-#define qemu_trap_arg2 5
-#define qemu_exc_addr 6
-#define qemu_palbr 7
-#define qemu_ptbr 8
-#define qemu_vptptr 9
-#define qemu_unique 10
-#define qemu_sysval 11
-#define qemu_usp 12
-
-#define qemu_shadow0 32
-#define qemu_shadow1 33
-#define qemu_shadow2 34
-#define qemu_shadow3 35
-#define qemu_shadow4 36
-#define qemu_shadow5 37
-#define qemu_shadow6 38
-#define qemu_shadow7 39
-
-/* PALcode Processor Register Private Storage. */
-#define pt0 40
-#define pt1 41
-#define pt2 42
-#define pt3 43
-#define pt4 44
-#define pt5 45
-#define pt6 46
-#define pt7 47
-#define pt8 48
-#define pt9 49
-#define pt10 50
-#define pt11 51
-#define pt12 52
-#define pt13 53
-#define pt14 54
-#define pt15 55
-#define pt16 56
-#define pt17 57
-#define pt18 58
-#define pt19 59
-#define pt20 60
-#define pt21 61
-#define pt22 62
-#define pt23 63
-
-/* QEMU function calls, via mtpr. */
-#define qemu_tbia 255
-#define qemu_tbis 254
-#define qemu_wait 253
-
-/* PALcode uses of the private storage slots. */
-#define ptEntUna pt0
-#define ptEntIF pt1
-#define ptEntSys pt2
-#define ptEntInt pt3
-#define ptEntArith pt4
-#define ptEntMM pt5
-#define ptMces pt6
-#define ptKsp pt7
-#define ptKgp pt8
-#define ptPcbb pt9
-#define ptPgp pt10
-#define ptMisc pt11
-#define ptMchk0 pt12
-#define ptMchk1 pt13
-#define ptMchk2 pt14
-#define ptMchk3 pt15
-#define ptMchk4 pt16
-#define ptMchk5 pt17
-
-/*
- * Shortcuts for various PALmode instructions.
- */
-#define mtpr hw_mtpr
-#define mfpr hw_mfpr
-#define stq_p hw_stq/p
-#define stl_p hw_stl/p
-#define ldl_p hw_ldl/p
-#define ldq_p hw_ldq/p
-
-/* QEMU recognizes the EV4/EV5 HW_REI instruction as a special case of
- the EV6 HW_RET instruction. This pulls the destination address from
- the EXC_ADDR processor register. */
-#define hw_rei hw_ret ($31)
+#include SYSTEM_H
/*
* Create a standard kernel entry stack frame.
@@ -158,11 +38,6 @@
stq a2, FRM_Q_A2($sp)
.endm
-.macro ENDFN function
- .type \function, @function
- .size \function, . - \function
-.endm
-
/*
* Allocate a 1 page stack for use by the console.
*/
@@ -183,26 +58,30 @@
.org 0x0000
.globl __start
__start:
- // Initialize GP and stack.
+ // Initialize GP.
br $gp, .+4
ldah $gp, 0($gp) !gpdisp!1
lda $gp, 0($gp) !gpdisp!1
mtpr $gp, ptPgp
- lda $sp, stack+STACK_SIZE($gp) !gprel
-
// Disable interrupts; kernel mode
lda t0, IPL_K_HIGH
mtpr t0, qemu_ps
- // Make sure kernel entry points are invalid.
- lda t0, -1
- mtpr t0, ptEntUna
- mtpr t0, ptEntIF
- mtpr t0, ptEntSys
- mtpr t0, ptEntInt
- mtpr t0, ptEntArith
- mtpr t0, ptEntMM
+ // Initialize Stack.
+ SYS_WHAMI a0
+ lda t0, STACK_SIZE
+ mull t0, a0, t0
+ ldah t1, stack($gp) !gprelhigh
+ lda t1, stack(t1) !gprellow
+ addq t0, t1, $sp
+
+ // Do any necessary system setup required for PALmode,
+ // e.g. setting up ptSys[01].
+ bsr $26, Sys_Setup
+
+ // Non-boot CPUs can go wait now.
+ bne a0, 1f
// Load boot arguments
mfpr a0, qemu_trap_arg0
@@ -213,6 +92,10 @@ __start:
ldah $27, do_start($gp) !gprelhigh
lda $27, do_start($27) !gprellow
hw_ret ($27)
+
+1: ldah $27, do_start_wait($gp) !gprelhigh
+ lda $27, do_start_wait($27) !gprellow
+ hw_ret ($27)
ENDFN __start
/*
@@ -242,7 +125,7 @@ Pal_Mchk:
ENDFN Pal_Mchk
/*
- * Clock Interrupt
+ * Interprocessor Interrupt
*
* INPUT PARAMETERS:
*
@@ -250,26 +133,48 @@ ENDFN Pal_Mchk
* trap_arg1 =
* trap_arg2 =
*
- * The clock interrupt is special, in that PALcode is supposed
+ * The interprocessor interrupt is special, in that PALcode is supposed
* to clear the interupt and not wait for the OS to do it.
*/
.org 0x0100
-Pal_Clk_Interrupt:
+Pal_Smp_Interrupt:
mfpr p6, qemu_exc_addr
- // Load CIA_BW_IO. Note that this is the KSEG address,
- // since there is no hw_stb with physical address access.
- lda p0, -887
- sll p0, 32, p0
+ SYS_ACK_SMP p0, p1, p2
+
+ mfpr p0, qemu_ps
+
+ STACK_FRAME p0, p6, p2, 0
+
+ mov IPL_K_IP, p0 // Raise IPL
+ mtpr p0, qemu_ps
- mov 0xc, p1 // Set RTCADD (0x70) to index register 0xC
- stb p1, 0x70(p0)
- ldbu p1, 0x71(p0) // Read RTCDAT to clear interrupt.
+ mfpr p6, ptEntInt
+ mfpr $gp, ptKgp
+ lda a0, INT_K_IP
+ lda a1, 0
+ lda a2, 0
+
+ hw_ret (p6)
+ENDFN Pal_Smp_Interrupt
+
+/*
+ * Clock Interrupt
+ *
+ * INPUT PARAMETERS:
+ *
+ * trap_arg0 =
+ * trap_arg1 =
+ * trap_arg2 =
+ *
+ * The clock interrupt is special, in that PALcode is supposed
+ * to clear the interupt and not wait for the OS to do it.
+ */
+ .org 0x0180
+Pal_Clk_Interrupt:
+ mfpr p6, qemu_exc_addr
-#if 0
- and p1, 0x40, p1 // Check for real interrupt.
- bne p1, 9f // If not, exit now, no stack frame.
-#endif
+ SYS_ACK_CLK p0, p1, p2
mfpr p0, qemu_ps
@@ -296,7 +201,7 @@ ENDFN Pal_Clk_Interrupt
* trap_arg1 =
* trap_arg2 =
*/
- .org 0x0180
+ .org 0x0200
Pal_Dev_Interrupt:
mfpr p6, qemu_exc_addr
mfpr p0, qemu_ps
@@ -308,9 +213,12 @@ Pal_Dev_Interrupt:
mfpr p7, ptEntInt
mfpr $gp, ptKgp
+
lda a0, INT_K_DEV
- lda a1, 0x800
lda a2, 0
+
+ SYS_DEV_VECTOR a1
+
hw_ret (p7)
ENDFN Pal_Dev_Interrupt
@@ -323,7 +231,7 @@ ENDFN Pal_Dev_Interrupt
* trap_arg1 = fault type (TNV, ACV, FOR, FOW, FOE)
* trap_arg2 = access type (exec=-1, read=0, write=1)
*/
- .org 0x0200
+ .org 0x0280
Pal_MMFault:
mfpr p0, qemu_ps
mfpr p6, qemu_exc_addr
@@ -348,7 +256,7 @@ ENDFN Pal_MMFault
* trap_arg1 = opcode of faulting insn
* trap_arg2 = src/dst register number
*/
- .org 0x0280
+ .org 0x0300
Pal_Unalign:
mfpr p0, qemu_ps
mfpr p6, qemu_exc_addr
@@ -380,7 +288,7 @@ ENDFN Pal_Unalign
* r17 (a1) = UNPREDICTABLE
* r18 (a2) = UNPREDICTABLE
*/
- .org 0x0300
+ .org 0x0380
Pal_OpcDec:
mfpr p0, qemu_ps
mfpr p6, qemu_exc_addr
@@ -404,7 +312,7 @@ ENDFN Pal_OpcDec
* trap_arg1 = register modification mask
* trap_arg2 = UNDEFINED
*/
- .org 0x0380
+ .org 0x0400
Pal_Arith:
mfpr p0, qemu_ps
mfpr p6, qemu_exc_addr
@@ -434,7 +342,7 @@ ENDFN Pal_Arith
* r17 (a1) = UNPREDICTABLE
* r18 (a2) = UNPREDICTABLE
*/
- .org 0x0400
+ .org 0x0480
Pal_Fen:
mfpr p0, qemu_ps
mfpr p6, qemu_exc_addr
@@ -466,14 +374,9 @@ ENDFN Pal_Fen
ORG_CALL_PAL_PRIV(0x00)
CallPal_Halt:
bsr p7, UpdatePCB // Save kernel data
- lda v0, HLT_K_SW_HALT
+ lda v0, HLT_K_SW_HALT // FIXME store this somewhere.
- ldah p0, 1 // Store 0xdead into CIA RESET reg
- lda p0, -(0x10000 - 0xdead)(p0)
- lda p1, 0x878
- sll p1, 28, p1
- lda p1, 0x900(p1)
- stl_p p0, 0(p1)
+ mtpr $31, qemu_halt
br Sys_EnterConsole
ENDFN CallPal_Halt
@@ -535,69 +438,40 @@ ENDFN CallPal_OpcDec08
*
* r16 (a0) = Option selector
* r17..r21 (a1..a5) = Implementation specific entry parameters
- *
+ *
* SIDE EFFECTS:
*
* Registers a0..a5, and v0 are UNPREDICTABLE upon return.
*/
ORG_CALL_PAL_PRIV(0x09)
CallPal_Cserve:
- cmpeq a0, 15, v0
- bne v0, Cserve_putc
+ // ??? For SRM compatibility, use 52/53 for these. Anyone know what
+ // other "standard" SRM Cserve entry points are? Certainly we don't
+ // want to be compatible with MILO, which puts the selector at A2.
cmpeq a0, 52, v0
- bne v0, Cserve_ena
+ bne v0, Cserve_Ena
cmpeq a0, 53, v0
- bne v0, Cserve_dis
+ bne v0, Cserve_Dis
+
+ // All the rest of the Cserve entry points are compressed from 1.
+ cmpeq a0, 1, v0
+ bne v0, Cserve_Ldqp
+ cmpeq a0, 2, v0
+ bne v0, Cserve_Stqp
+
hw_rei
ENDFN CallPal_Cserve
.text 1
-Cserve_putc:
- // Load CIA_BW_IO. Note that this is the KSEG address,
- // since there is no hw_stb with physical address access.
- lda p0, -887
- sll p0, 32, p0
-
- ldbu v0, com1Lsr(p0) // Get Transmit Holding Register Empty
- and v0, 0x20, v0
- beq v0, 1f
-
- stb a1, com1Thr(p0) // Output the byte
- mov 1, v0
-1: hw_rei
-ENDFN Cserve_putc
-
-Cserve_ena:
- lda p0, 0x87a // Load PYXIS INT REG base.
- sll p0, 28, p0
-
- lda p1, 1 // Shift the interrupt line in place.
- sll p1, a1, p1
-
- ldq_p p2, 0x40(p0) // Load PYXIS_INT_MASK
- sll p2, a1, v0 // Return the current setting
- and v0, 1, v0
- andnot p2, p1, p2 // Clear the bit
- stq_p p2, 0x40(p0) // Store PYXIS_INT_MASK
-
+Cserve_Ldqp:
+ ldq_p v0, 0(a1)
hw_rei
-ENDFN Cserve_ena
-
-Cserve_dis:
- lda p0, 0x87a // Load PYXIS INT REG base.
- sll p0, 28, p0
-
- lda p1, 1 // Shift the interrupt line in place.
- sll p1, a1, p1
-
- ldq_p p2, 0x40(p0) // Load PYXIS_INT_MASK
- sll p2, a1, v0 // Return the current setting
- and v0, 1, v0
- or p2, p1, p2 // Set the bit
- stq_p p2, 0x40(p0) // Store PYXIS_INT_MASK
+ENDFN Cserve_Ldqp
+Cserve_Stqp:
+ stq_p a2, 0(a1)
hw_rei
-ENDFN Cserve_dis
+ENDFN Cserve_Stqp
.previous
/*
@@ -717,7 +591,11 @@ ENDFN CallPal_OpcDec0C
*/
ORG_CALL_PAL_PRIV(0x0D)
CallPal_WrIpir:
- // We do not currently support more cpus
+ // Save a copy of the return address in case of machine check.
+ mfpr p6, qemu_exc_addr
+
+ SYS_WRIPIR a0, p0, p1, p2
+
hw_rei
ENDFN CallPal_WrIpir
@@ -1266,8 +1144,7 @@ ENDFN CallPal_OpcDec3B
*/
ORG_CALL_PAL_PRIV(0x3C)
CallPal_Whami:
- // We do not currently support more cpus
- mov 0, v0
+ SYS_WHAMI v0
hw_rei
ENDFN CallPal_Whami
@@ -2177,6 +2054,7 @@ laf_q_pci_err2: .quad 0
$laf_size = . - laf_base
.size laf_base, . - laf_base
+ .section .bss
.align 3
.globl stack
.type stack,@object
diff --git a/pal.h b/pal.h
new file mode 100644
index 0000000..a2ee6cf
--- /dev/null
+++ b/pal.h
@@ -0,0 +1,134 @@
+#ifndef PAL_H
+#define PAL_H 1
+
+/* General Purpose Registers. */
+#define v0 $0
+#define t0 $1
+#define t1 $2
+#define t2 $3
+#define t3 $4
+#define t4 $5
+#define t5 $6
+#define a0 $16
+#define a1 $17
+#define a2 $18
+#define a3 $19
+#define a4 $20
+#define a5 $21
+#define t8 $22
+#define t9 $23
+#define t10 $24
+
+/* PALcode Shadow Registers. These registers are swapped out when
+ QEMU is in PALmode. Unlike real hardware, there is no enable bit.
+ However, also unlike real hardware, the originals can be accessed
+ via MTPR/MFPR. */
+#define p0 $8
+#define p1 $9
+#define p2 $10
+#define p3 $11
+#define p4 $12
+#define p5 $13
+#define p6 $14 // Used to save exc_addr for machine check
+#define p7 $25
+
+/* QEMU Processor Registers. */
+#define qemu_ps 0
+#define qemu_fen 1
+#define qemu_pcc_ofs 2
+#define qemu_trap_arg0 3
+#define qemu_trap_arg1 4
+#define qemu_trap_arg2 5
+#define qemu_exc_addr 6
+#define qemu_palbr 7
+#define qemu_ptbr 8
+#define qemu_vptptr 9
+#define qemu_unique 10
+#define qemu_sysval 11
+#define qemu_usp 12
+
+#define qemu_shadow0 32
+#define qemu_shadow1 33
+#define qemu_shadow2 34
+#define qemu_shadow3 35
+#define qemu_shadow4 36
+#define qemu_shadow5 37
+#define qemu_shadow6 38
+#define qemu_shadow7 39
+
+/* PALcode Processor Register Private Storage. */
+#define pt0 40
+#define pt1 41
+#define pt2 42
+#define pt3 43
+#define pt4 44
+#define pt5 45
+#define pt6 46
+#define pt7 47
+#define pt8 48
+#define pt9 49
+#define pt10 50
+#define pt11 51
+#define pt12 52
+#define pt13 53
+#define pt14 54
+#define pt15 55
+#define pt16 56
+#define pt17 57
+#define pt18 58
+#define pt19 59
+#define pt20 60
+#define pt21 61
+#define pt22 62
+#define pt23 63
+
+/* QEMU function calls, via mtpr. */
+#define qemu_tbia 255
+#define qemu_tbis 254
+#define qemu_wait 253
+#define qemu_halt 252
+
+/* PALcode uses of the private storage slots. */
+#define ptEntUna pt0
+#define ptEntIF pt1
+#define ptEntSys pt2
+#define ptEntInt pt3
+#define ptEntArith pt4
+#define ptEntMM pt5
+#define ptMces pt6
+#define ptKsp pt7
+#define ptKgp pt8
+#define ptPcbb pt9
+#define ptPgp pt10
+#define ptMisc pt11
+#define ptMchk0 pt12
+#define ptMchk1 pt13
+#define ptMchk2 pt14
+#define ptMchk3 pt15
+#define ptMchk4 pt16
+#define ptMchk5 pt17
+#define ptSys0 pt18
+#define ptSys1 pt19
+
+/*
+ * Shortcuts for various PALmode instructions.
+ */
+#define mtpr hw_mtpr
+#define mfpr hw_mfpr
+#define stq_p hw_stq/p
+#define stl_p hw_stl/p
+#define ldl_p hw_ldl/p
+#define ldq_p hw_ldq/p
+
+/* QEMU recognizes the EV4/EV5 HW_REI instruction as a special case of
+ the EV6 HW_RET instruction. This pulls the destination address from
+ the EXC_ADDR processor register. */
+#define hw_rei hw_ret ($31)
+
+
+.macro ENDFN function
+ .type \function, @function
+ .size \function, . - \function
+.endm
+
+#endif /* PAL_H */
diff --git a/protos.h b/protos.h
new file mode 100644
index 0000000..6bff767
--- /dev/null
+++ b/protos.h
@@ -0,0 +1,42 @@
+#ifndef PROTOS_H
+#define PROTOS_H 1
+
+/*
+ * Cserve functions.
+ */
+
+static inline unsigned long ldq_p(unsigned long addr)
+{
+ register unsigned long v0 __asm__("$0");
+ register unsigned long a0 __asm__("$16") = 1;
+ register unsigned long a1 __asm__("$17") = addr;
+
+ asm volatile ("call_pal 9"
+ : "=r"(v0), "+r"(a0), "+r"(a1) :
+ : "$18", "$19", "$20", "$21");
+
+ return v0;
+}
+
+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 a1 __asm__("$17") = port;
+ register unsigned long a2 __asm__("$18") = val;
+
+ asm volatile ("call_pal 9"
+ : "=r"(v0), "+r"(a0), "+r"(a1), "+r"(a2) :
+ : "$19", "$20", "$21");
+
+ return v0;
+}
+
+/*
+ * I/O functions
+ */
+
+extern unsigned long inb(unsigned long port);
+extern unsigned long outb(unsigned char val, unsigned long port);
+
+#endif /* PROTOS_H */
diff --git a/sys-clipper.S b/sys-clipper.S
new file mode 100644
index 0000000..e3fc6f5
--- /dev/null
+++ b/sys-clipper.S
@@ -0,0 +1,90 @@
+#include "pal.h"
+#include SYSTEM_H
+
+/*
+ * Sys_Setup
+ *
+ * Do any system specific setup necessary.
+ *
+ * INPUT PARAMETERS
+ *
+ * r16 (a0) = whami
+ * r26 (ra) = return address
+ */
+ .globl Sys_Setup
+ .ent Sys_Setup
+Sys_Setup:
+ .frame $sp, 0, p7, 0
+ lda t0, TYPHOON_CCHIP_DIM0
+ lda t1, TYPHOON_CCHIP_DIM2
+ lda t2, TYPHOON_CCHIP_IIC0
+ lda t3, TYPHOON_CCHIP_IIC2
+ and a0, 2, t4
+ cmovne t4, t1, t0
+ cmovne t4, t3, t2
+ and a0, 1, t4
+ sll t4, 6, t4
+ addq t0, t4, t0
+ addq t2, t4, t2
+ LOAD_PHYS_CCHIP t4
+ addq t0, t4, t0
+ addq t2, t4, t2
+ mtpr t0, ptCpuDIR
+ mtpr t2, ptCpuIIC
+ ret
+ .end Sys_Setup
+
+/*
+ * Cserve_Ena
+ *
+ * Unmask a PCI interrupt
+ */
+ .globl Cserve_Ena
+Cserve_Ena:
+ // FIXME
+ hw_rei
+ENDFN Cserve_Ena
+
+/*
+ * Cserve_Dis
+ *
+ * Mask a PCI interrupt
+ */
+ .globl Cserve_Dis
+Cserve_Dis:
+ // FIXME
+ hw_rei
+ENDFN Cserve_Dis
+
+/*
+ * inb
+ *
+ * Read a byte from the PCI I/O bus.
+ */
+ .globl inb
+ .ent inb
+inb:
+ .frame $sp, 0, $26, 0
+ .prologue 0
+ LOAD_KSEG_PCI_IO v0
+ addq v0, a0, v0
+ ldbu v0, 0(v0)
+ ret
+ .end inb
+
+/*
+ * outb
+ *
+ * Write a byte to the PCI I/O bus.
+ */
+ .globl outb
+ .ent outb
+outb:
+ .frame $sp, 0, $26, 0
+ .prologue 0
+ LOAD_KSEG_PCI_IO p0
+ addq p0, a1, p0
+ stb a0, 0(p0)
+ ret
+ .end outb
+
diff --git a/sys-clipper.h b/sys-clipper.h
new file mode 100644
index 0000000..beea346
--- /dev/null
+++ b/sys-clipper.h
@@ -0,0 +1,10 @@
+#ifndef SYS_CLIPPER_H
+#define SYS_CLIPPER_H 1
+
+#include "core-typhoon.h"
+
+#define SYS_TYPE ST_DEC_TSUNAMI
+#define SYS_VARIATION (5 << 10)
+#define SYS_REVISION 0
+
+#endif
diff --git a/sys-sx164.h b/sys-sx164.h
new file mode 100644
index 0000000..8198ae8
--- /dev/null
+++ b/sys-sx164.h
@@ -0,0 +1,25 @@
+#ifndef SYS_SX164_H
+#define SYS_SX164_H 1
+
+#include "core_cia.h"
+
+#ifdef __ASSEMBLER__
+
+.macro SYS_ACK_CLK t0, t1, t2
+ LOAD_KSEG_PCI_IO \t0 // Set RTCADD (0x70) to index reg 0xC
+ mov 0xc, \t1
+ stb \t1, 0x70(\t0)
+ ldbu \t1, 0x71(\t0) // Read RTCDAT to clear interrupt
+.endm
+
+.macro SYS_DEV_VECTOR ret
+ FIXME
+.endm
+
+#endif /* ASSEMBLER */
+
+#define SYS_TYPE ST_DEC_EB164
+#define SYS_VARIATION (15 << 10)
+#define SYS_REVISION 0
+
+#endif /* SYS_SX164_H */
diff --git a/uart.c b/uart.c
index d3fd848..2e93482 100644
--- a/uart.c
+++ b/uart.c
@@ -30,7 +30,7 @@ your own risk.
* Modified for QEMU PALcode by rth@twiddle.net.
*/
-#include "io.h"
+#include "protos.h"
#include "uart.h"
#ifndef SERIAL_SPEED