summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2011-04-10 19:20:18 -0700
committerRichard Henderson <rth@twiddle.net>2011-04-10 19:20:18 -0700
commit0c0f711f60fec844964c99b141508e7343a41501 (patch)
tree696a34d7ae26fe75c4d42415aea4e9697395fadb
parent0ea286dc681fe3690fc4bb8007144190e03b8d51 (diff)
downloadqemu-palcode-0c0f711f60fec844964c99b141508e7343a41501.zip
qemu-palcode-0c0f711f60fec844964c99b141508e7343a41501.tar.gz
qemu-palcode-0c0f711f60fec844964c99b141508e7343a41501.tar.bz2
Add uart printing support.
-rw-r--r--.gitignore2
-rw-r--r--Makefile2
-rw-r--r--cia.h268
-rw-r--r--impure.h339
-rw-r--r--init.c4
-rw-r--r--io.h18
-rw-r--r--osf.h14
-rw-r--r--pal.S242
-rw-r--r--uart.c134
-rw-r--r--uart.h62
10 files changed, 676 insertions, 409 deletions
diff --git a/.gitignore b/.gitignore
index 5761abc..867dbf2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
*.o
+palcode
+palcode.map
diff --git a/Makefile b/Makefile
index 462046a..fabb6ee 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ CC = /home/rth/work/gcc/run-axp/bin/alphaev6-linux-gcc
LD = /home/rth/work/gcc/run-axp/bin/alphaev6-linux-ld
CFLAGS = -O2 -g -msmall-text -msmall-data -fvisibility=hidden
-OBJS = pal.o init.o memset.o
+OBJS = pal.o init.o uart.o memset.o
all: palcode
diff --git a/cia.h b/cia.h
new file mode 100644
index 0000000..cea81b6
--- /dev/null
+++ b/cia.h
@@ -0,0 +1,268 @@
+#ifndef __ALPHA_CIA__H__
+#define __ALPHA_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 */
+
+/*
+ * 21171-CA Control and Status Registers
+ */
+#define CIA_IOC_CIA_REV (IDENT_ADDR + 0x8740000080UL)
+# define CIA_REV_MASK 0xff
+#define CIA_IOC_PCI_LAT (IDENT_ADDR + 0x87400000C0UL)
+#define CIA_IOC_CIA_CTRL (IDENT_ADDR + 0x8740000100UL)
+# define CIA_CTRL_PCI_EN (1 << 0)
+# define CIA_CTRL_PCI_LOCK_EN (1 << 1)
+# define CIA_CTRL_PCI_LOOP_EN (1 << 2)
+# define CIA_CTRL_FST_BB_EN (1 << 3)
+# define CIA_CTRL_PCI_MST_EN (1 << 4)
+# define CIA_CTRL_PCI_MEM_EN (1 << 5)
+# define CIA_CTRL_PCI_REQ64_EN (1 << 6)
+# define CIA_CTRL_PCI_ACK64_EN (1 << 7)
+# define CIA_CTRL_ADDR_PE_EN (1 << 8)
+# define CIA_CTRL_PERR_EN (1 << 9)
+# define CIA_CTRL_FILL_ERR_EN (1 << 10)
+# define CIA_CTRL_MCHK_ERR_EN (1 << 11)
+# define CIA_CTRL_ECC_CHK_EN (1 << 12)
+# define CIA_CTRL_ASSERT_IDLE_BC (1 << 13)
+# define CIA_CTRL_COM_IDLE_BC (1 << 14)
+# define CIA_CTRL_CSR_IOA_BYPASS (1 << 15)
+# define CIA_CTRL_IO_FLUSHREQ_EN (1 << 16)
+# define CIA_CTRL_CPU_FLUSHREQ_EN (1 << 17)
+# define CIA_CTRL_ARB_CPU_EN (1 << 18)
+# define CIA_CTRL_EN_ARB_LINK (1 << 19)
+# define CIA_CTRL_RD_TYPE_SHIFT 20
+# define CIA_CTRL_RL_TYPE_SHIFT 24
+# define CIA_CTRL_RM_TYPE_SHIFT 28
+# define CIA_CTRL_EN_DMA_RD_PERF (1 << 31)
+#define CIA_IOC_CIA_CNFG (IDENT_ADDR + 0x8740000140UL)
+# define CIA_CNFG_IOA_BWEN (1 << 0)
+# define CIA_CNFG_PCI_MWEN (1 << 4)
+# define CIA_CNFG_PCI_DWEN (1 << 5)
+# define CIA_CNFG_PCI_WLEN (1 << 8)
+#define CIA_IOC_FLASH_CTRL (IDENT_ADDR + 0x8740000200UL)
+#define CIA_IOC_HAE_MEM (IDENT_ADDR + 0x8740000400UL)
+#define CIA_IOC_HAE_IO (IDENT_ADDR + 0x8740000440UL)
+#define CIA_IOC_CFG (IDENT_ADDR + 0x8740000480UL)
+#define CIA_IOC_CACK_EN (IDENT_ADDR + 0x8740000600UL)
+# define CIA_CACK_EN_LOCK_EN (1 << 0)
+# define CIA_CACK_EN_MB_EN (1 << 1)
+# define CIA_CACK_EN_SET_DIRTY_EN (1 << 2)
+# define CIA_CACK_EN_BC_VICTIM_EN (1 << 3)
+
+
+/*
+ * 21171-CA Diagnostic Registers
+ */
+#define CIA_IOC_CIA_DIAG (IDENT_ADDR + 0x8740002000UL)
+#define CIA_IOC_DIAG_CHECK (IDENT_ADDR + 0x8740003000UL)
+
+/*
+ * 21171-CA Performance Monitor registers
+ */
+#define CIA_IOC_PERF_MONITOR (IDENT_ADDR + 0x8740004000UL)
+#define CIA_IOC_PERF_CONTROL (IDENT_ADDR + 0x8740004040UL)
+
+/*
+ * 21171-CA Error registers
+ */
+#define CIA_IOC_CPU_ERR0 (IDENT_ADDR + 0x8740008000UL)
+#define CIA_IOC_CPU_ERR1 (IDENT_ADDR + 0x8740008040UL)
+#define CIA_IOC_CIA_ERR (IDENT_ADDR + 0x8740008200UL)
+# define CIA_ERR_COR_ERR (1 << 0)
+# define CIA_ERR_UN_COR_ERR (1 << 1)
+# define CIA_ERR_CPU_PE (1 << 2)
+# define CIA_ERR_MEM_NEM (1 << 3)
+# define CIA_ERR_PCI_SERR (1 << 4)
+# define CIA_ERR_PERR (1 << 5)
+# define CIA_ERR_PCI_ADDR_PE (1 << 6)
+# define CIA_ERR_RCVD_MAS_ABT (1 << 7)
+# define CIA_ERR_RCVD_TAR_ABT (1 << 8)
+# define CIA_ERR_PA_PTE_INV (1 << 9)
+# define CIA_ERR_FROM_WRT_ERR (1 << 10)
+# define CIA_ERR_IOA_TIMEOUT (1 << 11)
+# define CIA_ERR_LOST_CORR_ERR (1 << 16)
+# define CIA_ERR_LOST_UN_CORR_ERR (1 << 17)
+# define CIA_ERR_LOST_CPU_PE (1 << 18)
+# define CIA_ERR_LOST_MEM_NEM (1 << 19)
+# define CIA_ERR_LOST_PERR (1 << 21)
+# define CIA_ERR_LOST_PCI_ADDR_PE (1 << 22)
+# define CIA_ERR_LOST_RCVD_MAS_ABT (1 << 23)
+# define CIA_ERR_LOST_RCVD_TAR_ABT (1 << 24)
+# define CIA_ERR_LOST_PA_PTE_INV (1 << 25)
+# define CIA_ERR_LOST_FROM_WRT_ERR (1 << 26)
+# define CIA_ERR_LOST_IOA_TIMEOUT (1 << 27)
+# define CIA_ERR_VALID (1 << 31)
+#define CIA_IOC_CIA_STAT (IDENT_ADDR + 0x8740008240UL)
+#define CIA_IOC_ERR_MASK (IDENT_ADDR + 0x8740008280UL)
+#define CIA_IOC_CIA_SYN (IDENT_ADDR + 0x8740008300UL)
+#define CIA_IOC_MEM_ERR0 (IDENT_ADDR + 0x8740008400UL)
+#define CIA_IOC_MEM_ERR1 (IDENT_ADDR + 0x8740008440UL)
+#define CIA_IOC_PCI_ERR0 (IDENT_ADDR + 0x8740008800UL)
+#define CIA_IOC_PCI_ERR1 (IDENT_ADDR + 0x8740008840UL)
+#define CIA_IOC_PCI_ERR3 (IDENT_ADDR + 0x8740008880UL)
+
+/*
+ * 21171-CA System configuration registers
+ */
+#define CIA_IOC_MCR (IDENT_ADDR + 0x8750000000UL)
+#define CIA_IOC_MBA0 (IDENT_ADDR + 0x8750000600UL)
+#define CIA_IOC_MBA2 (IDENT_ADDR + 0x8750000680UL)
+#define CIA_IOC_MBA4 (IDENT_ADDR + 0x8750000700UL)
+#define CIA_IOC_MBA6 (IDENT_ADDR + 0x8750000780UL)
+#define CIA_IOC_MBA8 (IDENT_ADDR + 0x8750000800UL)
+#define CIA_IOC_MBAA (IDENT_ADDR + 0x8750000880UL)
+#define CIA_IOC_MBAC (IDENT_ADDR + 0x8750000900UL)
+#define CIA_IOC_MBAE (IDENT_ADDR + 0x8750000980UL)
+#define CIA_IOC_TMG0 (IDENT_ADDR + 0x8750000B00UL)
+#define CIA_IOC_TMG1 (IDENT_ADDR + 0x8750000B40UL)
+#define CIA_IOC_TMG2 (IDENT_ADDR + 0x8750000B80UL)
+
+/*
+ * 2117A-CA PCI Address and Scatter-Gather Registers.
+ */
+#define CIA_IOC_PCI_TBIA (IDENT_ADDR + 0x8760000100UL)
+
+#define CIA_IOC_PCI_W0_BASE (IDENT_ADDR + 0x8760000400UL)
+#define CIA_IOC_PCI_W0_MASK (IDENT_ADDR + 0x8760000440UL)
+#define CIA_IOC_PCI_T0_BASE (IDENT_ADDR + 0x8760000480UL)
+
+#define CIA_IOC_PCI_W1_BASE (IDENT_ADDR + 0x8760000500UL)
+#define CIA_IOC_PCI_W1_MASK (IDENT_ADDR + 0x8760000540UL)
+#define CIA_IOC_PCI_T1_BASE (IDENT_ADDR + 0x8760000580UL)
+
+#define CIA_IOC_PCI_W2_BASE (IDENT_ADDR + 0x8760000600UL)
+#define CIA_IOC_PCI_W2_MASK (IDENT_ADDR + 0x8760000640UL)
+#define CIA_IOC_PCI_T2_BASE (IDENT_ADDR + 0x8760000680UL)
+
+#define CIA_IOC_PCI_W3_BASE (IDENT_ADDR + 0x8760000700UL)
+#define CIA_IOC_PCI_W3_MASK (IDENT_ADDR + 0x8760000740UL)
+#define CIA_IOC_PCI_T3_BASE (IDENT_ADDR + 0x8760000780UL)
+
+#define CIA_IOC_PCI_Wn_BASE(N) (IDENT_ADDR + 0x8760000400UL + (N)*0x100)
+#define CIA_IOC_PCI_Wn_MASK(N) (IDENT_ADDR + 0x8760000440UL + (N)*0x100)
+#define CIA_IOC_PCI_Tn_BASE(N) (IDENT_ADDR + 0x8760000480UL + (N)*0x100)
+
+#define CIA_IOC_PCI_W_DAC (IDENT_ADDR + 0x87600007C0UL)
+
+/*
+ * 2117A-CA Address Translation Registers.
+ */
+
+/* 8 tag registers, the first 4 of which are lockable. */
+#define CIA_IOC_TB_TAGn(n) \
+ (IDENT_ADDR + 0x8760000800UL + (n)*0x40)
+
+/* 4 page registers per tag register. */
+#define CIA_IOC_TBn_PAGEm(n,m) \
+ (IDENT_ADDR + 0x8760001000UL + (n)*0x100 + (m)*0x40)
+
+/*
+ * Memory spaces:
+ */
+#define CIA_IACK_SC (IDENT_ADDR + 0x8720000000UL)
+#define CIA_CONF (IDENT_ADDR + 0x8700000000UL)
+#define CIA_IO (IDENT_ADDR + 0x8580000000UL)
+#define CIA_SPARSE_MEM (IDENT_ADDR + 0x8000000000UL)
+#define CIA_SPARSE_MEM_R2 (IDENT_ADDR + 0x8400000000UL)
+#define CIA_SPARSE_MEM_R3 (IDENT_ADDR + 0x8500000000UL)
+#define CIA_DENSE_MEM (IDENT_ADDR + 0x8600000000UL)
+#define CIA_BW_MEM (IDENT_ADDR + 0x8800000000UL)
+#define CIA_BW_IO (IDENT_ADDR + 0x8900000000UL)
+#define CIA_BW_CFG_0 (IDENT_ADDR + 0x8a00000000UL)
+#define CIA_BW_CFG_1 (IDENT_ADDR + 0x8b00000000UL)
+
+/*
+ * ALCOR's GRU ASIC registers
+ */
+#define GRU_INT_REQ (IDENT_ADDR + 0x8780000000UL)
+#define GRU_INT_MASK (IDENT_ADDR + 0x8780000040UL)
+#define GRU_INT_EDGE (IDENT_ADDR + 0x8780000080UL)
+#define GRU_INT_HILO (IDENT_ADDR + 0x87800000C0UL)
+#define GRU_INT_CLEAR (IDENT_ADDR + 0x8780000100UL)
+
+#define GRU_CACHE_CNFG (IDENT_ADDR + 0x8780000200UL)
+#define GRU_SCR (IDENT_ADDR + 0x8780000300UL)
+#define GRU_LED (IDENT_ADDR + 0x8780000800UL)
+#define GRU_RESET (IDENT_ADDR + 0x8780000900UL)
+
+#define ALCOR_GRU_INT_REQ_BITS 0x800fffffUL
+#define XLT_GRU_INT_REQ_BITS 0x80003fffUL
+#define GRU_INT_REQ_BITS (alpha_mv.sys.cia.gru_int_req_bits+0)
+
+/*
+ * PYXIS interrupt control registers
+ */
+#define PYXIS_INT_REQ (IDENT_ADDR + 0x87A0000000UL)
+#define PYXIS_INT_MASK (IDENT_ADDR + 0x87A0000040UL)
+#define PYXIS_INT_HILO (IDENT_ADDR + 0x87A00000C0UL)
+#define PYXIS_INT_ROUTE (IDENT_ADDR + 0x87A0000140UL)
+#define PYXIS_GPO (IDENT_ADDR + 0x87A0000180UL)
+#define PYXIS_INT_CNFG (IDENT_ADDR + 0x87A00001C0UL)
+#define PYXIS_RT_COUNT (IDENT_ADDR + 0x87A0000200UL)
+#define PYXIS_INT_TIME (IDENT_ADDR + 0x87A0000240UL)
+#define PYXIS_IIC_CTRL (IDENT_ADDR + 0x87A00002C0UL)
+#define PYXIS_RESET (IDENT_ADDR + 0x8780000900UL)
+
+/* Offset between ram physical addresses and pci64 DAC bus addresses. */
+#define PYXIS_DAC_OFFSET (1UL << 40)
+
+#endif /* __ALPHA_CIA__H__ */
diff --git a/impure.h b/impure.h
deleted file mode 100644
index 230ad14..0000000
--- a/impure.h
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
-** Commmon area Offset Definitions:
-*/
-
-#define CNS_Q_RCS_ID 0x0
-#define CNS_Q_SCRATCH 0xA0
-
-/*
-** Processor Saved State Area Offset Definitions:
-**
-** These offsets are relative to the base of the impure area.
-*/
-
-#define CNS_Q_BASE 0x000 /* Define base for debug monitor compatibility */
-#define CNS_Q_FLAG 0x100
-#define CNS_Q_HALT 0x108
-#define CNS_Q_GPR 0x110 /* Offset to base of saved GPR area */
-#define CNS_Q_FPR 0x210 /* Offset to base of saved FPR area */
-#define CNS_Q_MCHK 0x310
-#define CNS_Q_PT 0x318 /* Offset to base of saved PALtemp area */
-#define CNS_Q_SHADOW 0x3D8 /* Offset to base of saved PALshadow area */
-#define CNS_Q_IPR 0x418 /* Offset to base of saved IPR area */
-
-/*
-** Offsets to saved internal processor registers
-*/
-
-#define CNS_Q_EXC_ADDR 0x418
-#define CNS_Q_PAL_BASE 0x420
-#define CNS_Q_MM_STAT 0x428
-#define CNS_Q_VA 0x430
-#define CNS_Q_ICSR 0x438
-#define CNS_Q_IPL 0x440
-#define CNS_Q_IPS 0x448
-#define CNS_Q_ITB_ASN 0x450
-#define CNS_Q_ASTER 0x458
-#define CNS_Q_ASTRR 0x460
-#define CNS_Q_ISR 0x468
-#define CNS_Q_IVPTBR 0x470
-#define CNS_Q_MCSR 0x478
-#define CNS_Q_DC_MODE 0x480
-#define CNS_Q_MAF_MODE 0x488
-#define CNS_Q_SIRR 0x490
-#define CNS_Q_FPCSR 0x498
-#define CNS_Q_ICPERR_STAT 0x4A0
-#define CNS_Q_PM_CTR 0x4A8
-#define CNS_Q_EXC_SUM 0x4B0
-#define CNS_Q_EXC_MASK 0x4B8
-#define CNS_Q_INT_ID 0x4C0
-#define CNS_Q_DCPERR_STAT 0x4C8
-#define CNS_Q_SC_STAT 0x4D0
-#define CNS_Q_SC_ADDR 0x4D8
-#define CNS_Q_SC_CTL 0x4E0
-#define CNS_Q_BC_TAG_ADDR 0x4E8
-
-#define CNS_Q_BC_STAT 0x4F0
-#define CNS_Q_BC_ADDR 0x4F8
-#define CNS_Q_FILL_SYN 0x500
-#define CNS_Q_LD_LOCK 0x508
-
-#define CNS_Q_BC_CFG 0x510
-#define CNS_Q_BC_CFG2 0x518
-#define CNS_Q_PM_CTL 0x520 /* Performance monitor counter */
-
-#define CNS_Q_SROM_REV 0x528
-#define CNS_Q_PROC_ID 0x530
-#define CNS_Q_MEM_SIZE 0x538
-#define CNS_Q_CYCLE_CNT 0x540
-#define CNS_Q_SIGNATURE 0x548
-#define CNS_Q_PROC_MASK 0x550
-#define CNS_Q_SYSCTX 0x558
-
-#define CNS_Q_BC_CFG_OFF 0x560
-
-#define CNS_K_SIZE 0x568
-
-#if 0
-/*
-** Macros for saving/restoring data to/from the PAL impure scratch
-** area.
-**
-** The console save state area is larger than the addressibility
-** of the HW_LD/ST instructions (10-bit signed byte displacement),
-** so some adjustments to the base offsets, as well as the offsets
-** within each base region, are necessary.
-**
-** The console save state area is divided into two segments; the
-** CPU-specific segment and the platform-specific segment. The
-** state that is saved in the CPU-specific segment includes GPRs,
-** FPRs, IPRs, halt code, MCHK flag, etc. All other state is saved
-** in the platform-specific segment.
-**
-** The impure pointer will need to be adjusted by a different offset
-** value for each region within a given segment. The SAVE and RESTORE
-** macros will auto-magically adjust the offsets accordingly.
-**
-*/
-
-#define SAVE_GPR(reg,offset,base) \
- stq_p reg, ((offset-0x200))(base)
-
-#define RESTORE_GPR(reg,offset,base) \
- ldq_p reg, ((offset-0x200))(base)
-
-#define SAVE_FPR(reg,offset,base) \
- stt reg, ((offset-0x200))(base)
-
-#define RESTORE_FPR(reg,offset,base) \
- ldt reg, ((offset-0x200))(base)
-
-#define SAVE_IPR(reg,offset,base) \
- mfpr v0, reg; \
- stq_p v0, ((offset-CNS_Q_IPR))(base)
-
-#define RESTORE_IPR(reg,offset,base) \
- ldq_p v0, ((offset-CNS_Q_IPR))(base); \
- mtpr v0, reg
-
-#define SAVE_SHADOW(reg,offset,base) \
- stq_p reg, ((offset-CNS_Q_IPR))(base)
-
-#define RESTORE_SHADOW(reg,offset,base)\
- ldq_p reg, ((offset-CNS_Q_IPR))(base)
-
-/*
- * STORE_IPR doesn't compensate for weird
- * offset/base combinations.
- */
-#define STORE_IPR(reg,offset,base) \
- mfpr v0, reg; \
- stq_p v0, ((offset))(base)
-
-/*
-** Macro to save the internal state of the general purpose
-** register file. Note that it switches out of shadow mode
-** to save the registers real registers hidden behind the
-** shadow registers.
-**
-** Register Usage Conventions:
-**
-** pt0 - Saved v0 (r0)
-** pt4 - Saved t0 (r1)
-** t0 - Base address of the save state area.
-** v0 - scratch. Will be trashed.
-*/
-#define SAVE_GPRS \
- lda t0, 0x200(t0); \
- mfpr v0, pt0; \
- SAVE_GPR(v0,CNS_Q_GPR+0x00,t0); \
- mfpr v0, pt4; \
- SAVE_GPR(v0,CNS_Q_GPR+0x08,t0); \
- SAVE_GPR(r2,CNS_Q_GPR+0x10,t0); \
- SAVE_GPR(r3,CNS_Q_GPR+0x18,t0); \
- SAVE_GPR(r4,CNS_Q_GPR+0x20,t0); \
- SAVE_GPR(r5,CNS_Q_GPR+0x28,t0); \
- mfpr r5, icsr; \
- ldah r4, (1<<(ICSR_V_SDE-16))(zero); \
- bic r5, r4, r4; \
- mtpr r4, icsr; \
- STALL; \
- STALL; \
- STALL; \
- NOP; \
- SAVE_GPR(r6,CNS_Q_GPR+0x30,t0); \
- SAVE_GPR(r7,CNS_Q_GPR+0x38,t0); \
- SAVE_GPR(r8,CNS_Q_GPR+0x40,t0); \
- SAVE_GPR(r9,CNS_Q_GPR+0x48,t0); \
- SAVE_GPR(r10,CNS_Q_GPR+0x50,t0); \
- SAVE_GPR(r11,CNS_Q_GPR+0x58,t0); \
- SAVE_GPR(r12,CNS_Q_GPR+0x60,t0); \
- SAVE_GPR(r13,CNS_Q_GPR+0x68,t0); \
- SAVE_GPR(r14,CNS_Q_GPR+0x70,t0); \
- SAVE_GPR(r15,CNS_Q_GPR+0x78,t0); \
- SAVE_GPR(r16,CNS_Q_GPR+0x80,t0); \
- SAVE_GPR(r17,CNS_Q_GPR+0x88,t0); \
- SAVE_GPR(r18,CNS_Q_GPR+0x90,t0); \
- SAVE_GPR(r19,CNS_Q_GPR+0x98,t0); \
- SAVE_GPR(r20,CNS_Q_GPR+0xA0,t0); \
- SAVE_GPR(r21,CNS_Q_GPR+0xA8,t0); \
- SAVE_GPR(r22,CNS_Q_GPR+0xB0,t0); \
- SAVE_GPR(r23,CNS_Q_GPR+0xB8,t0); \
- SAVE_GPR(r24,CNS_Q_GPR+0xC0,t0); \
- SAVE_GPR(r25,CNS_Q_GPR+0xC8,t0); \
- SAVE_GPR(r26,CNS_Q_GPR+0xD0,t0); \
- SAVE_GPR(r27,CNS_Q_GPR+0xD8,t0); \
- SAVE_GPR(r28,CNS_Q_GPR+0xE0,t0); \
- SAVE_GPR(r29,CNS_Q_GPR+0xE8,t0); \
- SAVE_GPR(r30,CNS_Q_GPR+0xF0,t0); \
- SAVE_GPR(r31,CNS_Q_GPR+0xF8,t0); \
- STALL; \
- STALL; \
- mtpr r5, icsr; \
- STALL; \
- STALL; \
- STALL; \
- NOP; \
- lda t0, -0x200(t0)
-
-/*
-** Macro to restore the internal state of the general purpose
-** register file. Note that it switches out of shadow mode
-** to save the registers real registers hidden behind the
-** shadow registers.
-**
-** Register Usage Conventions:
-**
-** t0 - Base address of the save state area.
-** v0 (r0) and t1 (r2) will be used as scratch.
-** Warning: Make sure that the base register t0
-** is not restored before we are done using it.
-*/
-#define RESTORE_GPRS \
- lda t0, 0x200(t0); \
- mfpr v0, icsr; \
- ldah t1, (1<<(ICSR_V_SDE-16))(zero); \
- bic v0, t1, t1; \
- mtpr t1, icsr; \
- STALL; \
- STALL; \
- STALL; \
- NOP; \
- RESTORE_GPR(r2,CNS_Q_GPR+0x10,t0); \
- RESTORE_GPR(r3,CNS_Q_GPR+0x18,t0); \
- RESTORE_GPR(r4,CNS_Q_GPR+0x20,t0); \
- RESTORE_GPR(r5,CNS_Q_GPR+0x28,t0); \
- RESTORE_GPR(r6,CNS_Q_GPR+0x30,t0); \
- RESTORE_GPR(r7,CNS_Q_GPR+0x38,t0); \
- RESTORE_GPR(r8,CNS_Q_GPR+0x40,t0); \
- RESTORE_GPR(r9,CNS_Q_GPR+0x48,t0); \
- RESTORE_GPR(r10,CNS_Q_GPR+0x50,t0); \
- RESTORE_GPR(r11,CNS_Q_GPR+0x58,t0); \
- RESTORE_GPR(r12,CNS_Q_GPR+0x60,t0); \
- RESTORE_GPR(r13,CNS_Q_GPR+0x68,t0); \
- RESTORE_GPR(r14,CNS_Q_GPR+0x70,t0); \
- RESTORE_GPR(r15,CNS_Q_GPR+0x78,t0); \
- RESTORE_GPR(r16,CNS_Q_GPR+0x80,t0); \
- RESTORE_GPR(r17,CNS_Q_GPR+0x88,t0); \
- RESTORE_GPR(r18,CNS_Q_GPR+0x90,t0); \
- RESTORE_GPR(r19,CNS_Q_GPR+0x98,t0); \
- RESTORE_GPR(r20,CNS_Q_GPR+0xA0,t0); \
- RESTORE_GPR(r21,CNS_Q_GPR+0xA8,t0); \
- RESTORE_GPR(r22,CNS_Q_GPR+0xB0,t0); \
- RESTORE_GPR(r23,CNS_Q_GPR+0xB8,t0); \
- RESTORE_GPR(r24,CNS_Q_GPR+0xC0,t0); \
- RESTORE_GPR(r25,CNS_Q_GPR+0xC8,t0); \
- RESTORE_GPR(r26,CNS_Q_GPR+0xD0,t0); \
- RESTORE_GPR(r27,CNS_Q_GPR+0xD8,t0); \
- RESTORE_GPR(r28,CNS_Q_GPR+0xE0,t0); \
- RESTORE_GPR(r29,CNS_Q_GPR+0xE8,t0); \
- RESTORE_GPR(r30,CNS_Q_GPR+0xF0,t0); \
- RESTORE_GPR(r31,CNS_Q_GPR+0xF8,t0); \
- STALL; \
- STALL; \
- mtpr v0, icsr; \
- STALL; \
- STALL; \
- STALL; \
- NOP; \
- RESTORE_GPR(r0,CNS_Q_GPR+0x00,t0); \
- RESTORE_GPR(r1,CNS_Q_GPR+0x08,t0);
-
-#endif /* 0 */
-
-
-
-/*
-** Short Corrected Error Logout Frame
-*/
-
-#define LAS_Q_BASE CNS_K_SIZE
-
-#define LAS_L_SIZE 0x0000
-#define LAS_L_FLAG 0x0004
-
-#define LAS_Q_OFFSET_BASE 0x0008
-
-#define LAS_L_CPU 0x0008
-#define LAS_L_SYS 0x000C
-
-#define LAS_Q_MCHK_CODE 0x0010
-
-#define LAS_Q_CPU_BASE 0x0018
-
-#define LAS_Q_BC_ADDR 0x0018
-#define LAS_Q_FILL_SYNDROME 0x0020
-
-#define LAS_Q_BC_STAT 0x0028
-#define LAS_Q_ISR 0x0030
-
-#define LAS_Q_SYS_BASE 0x0038
-
-#define LAS_K_SIZE 0x0038
-
-/*
-** Long Machine Check Error Logout Frame
-*/
-
-#define LAF_Q_BASE (LAS_Q_BASE+LAS_K_SIZE)
-
-#define LAF_L_SIZE 0x0000
-#define LAF_L_FLAG 0x0004
-
-#define LAF_Q_OFFSET_BASE 0x0008
-
-#define LAF_L_CPU 0x0008
-#define LAF_L_SYS 0x000C
-
-#define LAF_Q_MCHK_CODE 0x0010
-#define LAF_Q_PT 0x0018
-
-#define LAF_Q_CPU_BASE 0x00D8
-
-#define LAF_Q_EXC_ADDR 0x00D8
-#define LAF_Q_EXC_SUM 0x00E0
-#define LAF_Q_EXC_MASK 0x00E8
-#define LAF_Q_PAL_BASE 0x00F0
-#define LAF_Q_ISR 0x00F8
-#define LAF_Q_ICSR 0x0100
-#define LAF_Q_ICPERR 0x0108
-#define LAF_Q_DCPERR 0x0110
-#define LAF_Q_VA 0x0118
-#define LAF_Q_MM_STAT 0x0120
-#define LAF_Q_BC_ADDR 0x0140
-#define LAF_Q_BC_STAT 0x0150
-#define LAF_Q_SYS_BASE 0x0160
-
-#define LAF_Q_CPU_ERR0 0x160
-#define LAF_Q_CPU_ERR1 0x168
-#define LAF_Q_CIA_ERR 0x170
-#define LAF_Q_CIA_STAT 0x178
-#define LAF_Q_ERR_MASK 0x180
-#define LAF_Q_CIA_SYN 0x188
-#define LAF_Q_MEM_ERR0 0x190
-#define LAF_Q_MEM_ERR1 0x198
-#define LAF_Q_PCI_ERR0 0x1A0
-#define LAF_Q_PCI_ERR1 0x1A8
-#define LAF_Q_PCI_ERR2 0x1B0
-
-#define LAF_K_SIZE 0x01B8
diff --git a/init.c b/init.c
index 70b6297..c3ac97a 100644
--- a/init.c
+++ b/init.c
@@ -2,6 +2,7 @@
#include <stddef.h>
#include "hwrpb.h"
#include "osf.h"
+#include "uart.h"
#define PAGE_SHIFT 13
#define PAGE_SIZE (1ul << PAGE_SHIFT)
@@ -202,5 +203,8 @@ do_start(unsigned long memsize)
init_pcb ();
init_page_table (memsize, hwrpb.mc[0].numpages);
+ uart_init ();
+ uart_puts (COM1, "Hello, World!\n");
+
while (1) ;
}
diff --git a/io.h b/io.h
new file mode 100644
index 0000000..c58c271
--- /dev/null
+++ b/io.h
@@ -0,0 +1,18 @@
+#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 ab87955..c7e18c8 100644
--- a/osf.h
+++ b/osf.h
@@ -206,3 +206,17 @@
#define SCB_Q_SYSMCHK 0x0660
#define SCB_Q_PROCMCHK 0x0670
+
+/*
+ * OSF/1 PAL-code-imposed page table bits
+ */
+#define _PAGE_VALID 0x0001
+#define _PAGE_FOR 0x0002 /* used for page protection (fault on read) */
+#define _PAGE_FOW 0x0004 /* used for page protection (fault on write) */
+#define _PAGE_FOE 0x0008 /* used for page protection (fault on exec) */
+#define _PAGE_ASM 0x0010
+#define _PAGE_KRE 0x0100 /* xxx - see below on the "accessed" bit */
+#define _PAGE_URE 0x0200 /* xxx */
+#define _PAGE_KWE 0x1000 /* used to do the dirty bit in software */
+#define _PAGE_UWE 0x2000 /* used to do the dirty bit in software */
+
diff --git a/pal.S b/pal.S
index 0cc8f7c..5dcd7c0 100644
--- a/pal.S
+++ b/pal.S
@@ -1,9 +1,8 @@
- .set noat
- .set nomacro
+ .set noat
+ .set nomacro
.text
#include "osf.h"
-#include "impure.h"
/* General Purpose Registers. */
#define v0 $0
@@ -48,6 +47,8 @@
#define qemu_ptbr 8
#define qemu_vptptr 9
#define qemu_unique 10
+#define qemu_lock_addr 11
+
#define qemu_shadow0 32
#define qemu_shadow1 33
#define qemu_shadow2 34
@@ -84,11 +85,10 @@
#define pt23 63
/* QEMU function calls, via mtpr. */
-#define qemu_tbia 128
-#define qemu_tbis 129
+#define qemu_tbia 255
+#define qemu_tbis 254
/* PALcode uses of the private storage slots. */
-#define ptSuper pt0
#define ptEntUna pt1
#define ptEntIF pt2
#define ptEntSys pt3
@@ -101,7 +101,7 @@
#define ptKsp pt10
#define ptKgp pt11
#define ptPcbb pt12
-#define ptImpure pt13
+#define ptPgp pt13
#define ptMchk0 pt14
#define ptMchk1 pt15
#define ptMisc pt16
@@ -156,6 +156,13 @@
.endm
/*
+ * Allocate a 1 page stack for use by the console.
+ */
+#define STACK_SIZE 8192
+
+ .comm stack, STACK_SIZE, 8
+
+/*
* QEMU emulator "hardware" entry points.
*/
@@ -166,19 +173,39 @@
*
* trap_arg0 = Memory size
* trap_arg1 = Kernel entry (if loaded)
- *
- * Given that we've no CPU state to save, set things up so that we can
- * jump to C to do the real initialization.
*/
.org 0x0000
+ .globl __start
__start:
+ // Initialize GP and stack.
br $gp, .+4
ldah $gp, 0($gp) !gpdisp!1
- lda $gp, 0($gp) !gpdisp!1
- lda $sp, stack_top($gp) !gprel
+ 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
+
+ // Load the initial PCB and page table elements.
+ lda t0, page_dir($gp) !gprel
+ mtpr t0, qemu_ptbr
+
+ lda t0, pal_pcb($gp) !gprel
+ zap t0, 0xf0, t0
+ mtpr t0, ptPcbb
+
+ // Load boot arguments
mfpr a0, qemu_trap_arg0
mfpr a1, qemu_trap_arg1
- br do_start !samegp
+ mfpr a2, qemu_trap_arg2
+
+ // Continue in do_start, outside PALmode.
+ ldah $27, do_start($gp) !gprelhigh
+ lda $27, do_start($27) !gprellow
+ hw_ret ($27)
/*
* Machine Check
@@ -216,8 +243,8 @@ Pal_Mchk:
*/
.org 0x0100
Pal_Interrupt:
- mfpr p0, qemu_ps
mfpr p6, qemu_exc_addr
+ mfpr p0, qemu_ps
STACK_FRAME p0, p6, p2
@@ -766,6 +793,11 @@ CallPal_SwpCtxCont:
ldq_p t10, PCB_Q_USP(v0)
mtpr t10, ptUsp
+ mfpr t10, qemu_unique // Save old unique value
+ stq_p t10, PCB_Q_UNIQUE(v0)
+ ldq_p t10, PCB_Q_UNIQUE(a0) // Install new unique value
+ mtpr t10, qemu_unique
+
ldq_p t8, PCB_Q_FEN(a0) // Install new FEN
and t8, 1, t8
mtpr t8, qemu_fen
@@ -774,7 +806,7 @@ CallPal_SwpCtxCont:
ldq_p t10, PCB_Q_PTBR(a0) // Install new page tables
mtpr t10, qemu_ptbr
- mtpr $31, qemu_tbia // Flush TLB
+ mtpr $31, qemu_tbia // Flush TLB, since we don't do ASNs
hw_rei
.previous
@@ -1634,66 +1666,78 @@ MchkCommon:
.endm
MchkLogOut:
- mfpr p6, ptImpure // Get address of logout frame
- lda p6, LAF_Q_BASE(p6)
-
- lda t3, LAF_K_SIZE(t4) // Combine retry flag and frame size
- stq_p t3, LAF_L_SIZE(p6)
-
- lda t3, LAF_Q_SYS_BASE
- sll t3, 32, t3
- lda t3, LAF_Q_CPU_BASE(t3)
- stq_p t3, LAF_Q_OFFSET_BASE(p6)
-
- stq_p t5, LAF_Q_MCHK_CODE(p6)
-
- // Being virtual, we don't have I/D caches, or cache errors.
- stq_p $31, LAF_Q_ICPERR(p6)
- stq_p $31, LAF_Q_DCPERR(p6)
- stq_p $31, LAF_Q_BC_ADDR(p6)
- stq_p $31, LAF_Q_BC_STAT(p6)
+ mfpr p6, ptPgp // Get address of logout frame
+ lda p6, laf_base(p6) !gprel
+
+ lda t3, $laf_size
+ stl_p t3, laf_l_size - laf_base(p6)
+ stl_p t4, laf_l_flag - laf_base(p6)
+
+ lda t3, laf_cpu_base - laf_base
+ stl_p t3, laf_l_cpu - laf_base(p6)
+ lda t3, laf_sys_base - laf_base
+ stl_p t3, laf_l_sys - laf_base(p6)
+
+ STORE_IPR qemu_shadow0, laf_q_shadow - laf_base + 0x00, p6
+ STORE_IPR qemu_shadow1, laf_q_shadow - laf_base + 0x08, p6
+ STORE_IPR qemu_shadow2, laf_q_shadow - laf_base + 0x10, p6
+ STORE_IPR qemu_shadow3, laf_q_shadow - laf_base + 0x18, p6
+ STORE_IPR qemu_shadow4, laf_q_shadow - laf_base + 0x20, p6
+ STORE_IPR qemu_shadow5, laf_q_shadow - laf_base + 0x28, p6
+ STORE_IPR qemu_shadow6, laf_q_shadow - laf_base + 0x30, p6
+ STORE_IPR qemu_shadow7, laf_q_shadow - laf_base + 0x38, p6
+
+ STORE_IPR pt0, laf_q_pt - laf_base + 0x00, p6
+ STORE_IPR pt1, laf_q_pt - laf_base + 0x08, p6
+ STORE_IPR pt2, laf_q_pt - laf_base + 0x10, p6
+ STORE_IPR pt3, laf_q_pt - laf_base + 0x18, p6
+ STORE_IPR pt4, laf_q_pt - laf_base + 0x20, p6
+ STORE_IPR pt5, laf_q_pt - laf_base + 0x28, p6
+ STORE_IPR pt6, laf_q_pt - laf_base + 0x30, p6
+ STORE_IPR pt7, laf_q_pt - laf_base + 0x38, p6
+ STORE_IPR pt8, laf_q_pt - laf_base + 0x40, p6
+ STORE_IPR pt9, laf_q_pt - laf_base + 0x48, p6
+ STORE_IPR pt10, laf_q_pt - laf_base + 0x50, p6
+ STORE_IPR pt11, laf_q_pt - laf_base + 0x58, p6
+ STORE_IPR pt12, laf_q_pt - laf_base + 0x60, p6
+ STORE_IPR pt13, laf_q_pt - laf_base + 0x68, p6
+ STORE_IPR pt14, laf_q_pt - laf_base + 0x70, p6
+ STORE_IPR pt15, laf_q_pt - laf_base + 0x78, p6
+ STORE_IPR pt16, laf_q_pt - laf_base + 0x80, p6
+ STORE_IPR pt17, laf_q_pt - laf_base + 0x88, p6
+ STORE_IPR pt18, laf_q_pt - laf_base + 0x90, p6
+ STORE_IPR pt19, laf_q_pt - laf_base + 0x98, p6
+ STORE_IPR pt20, laf_q_pt - laf_base + 0xa0, p6
+ STORE_IPR pt21, laf_q_pt - laf_base + 0xa8, p6
+ STORE_IPR pt22, laf_q_pt - laf_base + 0xb0, p6
+ STORE_IPR pt23, laf_q_pt - laf_base + 0xb8, p6
mfpr t0, ptMchk1
mfpr t3, ptMchk2
mfpr t4, ptMchk3
mfpr t5, ptMchk4
mfpr p7, ptMchk5
- stq_p p7, LAF_Q_EXC_ADDR(p6)
-
- stq_p $31, LAF_Q_MM_STAT(p6)
- stq_p $31, LAF_Q_VA(p6)
- stq_p $31, LAF_Q_ISR(p6)
- stq_p $31, LAF_Q_ICSR(p6)
-
- STORE_IPR qemu_palbr, LAF_Q_PAL_BASE, p6
-
- stq_p $31, LAF_Q_EXC_MASK(p6)
- stq_p $31, LAF_Q_EXC_SUM(p6)
-
- STORE_IPR pt0, LAF_Q_PT+0x00, p6
- STORE_IPR pt1, LAF_Q_PT+0x08, p6
- STORE_IPR pt2, LAF_Q_PT+0x10, p6
- STORE_IPR pt3, LAF_Q_PT+0x18, p6
- STORE_IPR pt4, LAF_Q_PT+0x20, p6
- STORE_IPR pt5, LAF_Q_PT+0x28, p6
- STORE_IPR pt6, LAF_Q_PT+0x30, p6
- STORE_IPR pt7, LAF_Q_PT+0x38, p6
- STORE_IPR pt8, LAF_Q_PT+0x40, p6
- STORE_IPR pt9, LAF_Q_PT+0x48, p6
- STORE_IPR pt10, LAF_Q_PT+0x50, p6
- STORE_IPR pt11, LAF_Q_PT+0x58, p6
- STORE_IPR pt12, LAF_Q_PT+0x60, p6
- STORE_IPR pt13, LAF_Q_PT+0x68, p6
- STORE_IPR pt14, LAF_Q_PT+0x70, p6
- STORE_IPR pt15, LAF_Q_PT+0x78, p6
- STORE_IPR pt16, LAF_Q_PT+0x80, p6
- STORE_IPR pt17, LAF_Q_PT+0x88, p6
- STORE_IPR pt18, LAF_Q_PT+0x90, p6
- STORE_IPR pt19, LAF_Q_PT+0x98, p6
- STORE_IPR pt20, LAF_Q_PT+0xa0, p6
- STORE_IPR pt21, LAF_Q_PT+0xa8, p6
- STORE_IPR pt22, LAF_Q_PT+0xb0, p6
- STORE_IPR pt23, LAF_Q_PT+0xb8, p6
+ stq_p p7, laf_q_exc_addr - laf_base(p6)
+
+ stq_p $31, laf_q_exc_sum - laf_base(p6)
+ stq_p $31, laf_q_exc_mask - laf_base(p6)
+
+ STORE_IPR qemu_palbr, laf_q_pal_base - laf_base, p6
+
+ stq_p $31, laf_q_isr - laf_base(p6)
+ stq_p $31, laf_q_icsr - laf_base(p6)
+ stq_p $31, laf_q_icperr - laf_base(p6)
+ stq_p $31, laf_q_dcperr - laf_base(p6)
+ stq_p $31, laf_q_va - laf_base(p6)
+ stq_p $31, laf_q_mm_stat - laf_base(p6)
+ stq_p $31, laf_q_sc_addr - laf_base(p6)
+ stq_p $31, laf_q_sc_stat - laf_base(p6)
+ stq_p $31, laf_q_bc_addr - laf_base(p6)
+ stq_p $31, laf_q_ei_addr - laf_base(p6)
+ stq_p $31, laf_q_fill_syndrome - laf_base(p6)
+ stq_p $31, laf_q_ei_stat - laf_base(p6)
+
+ STORE_IPR qemu_lock_addr, laf_q_ld_lock - laf_base, p6
// bsr v0, Sys_MchkLogOut
@@ -1771,4 +1815,64 @@ UpdatePCB:
addl p5, p3, p3
stl_p p3, PCB_L_PCC(p4) // Store new time
+ mfpr p5, qemu_unique // Save unique
+ stq_p p5, PCB_Q_UNIQUE(p4)
+
ret $31, (p7), 0
+
+/*
+ * FIXME
+ */
+Sys_EnterConsole:
+Sys_Cserve:
+ halt
+
+/*
+ * Allocate the logout frame.
+ */
+ .section .sbss
+ .type laf_base,@object
+laf_base:
+laf_l_size: .long 0
+laf_l_flag: .long 0
+laf_l_cpu: .long 0
+laf_l_sys: .long 0
+laf_q_mchk_code: .quad 0
+
+$las_size = . - laf_base
+
+laf_cpu_base:
+laf_q_shadow: .skip 8*8
+laf_q_pt: .skip 8*24
+laf_q_exc_addr: .quad 0
+laf_q_exc_sum: .quad 0
+laf_q_exc_mask: .quad 0
+laf_q_pal_base: .quad 0
+laf_q_isr: .quad 0
+laf_q_icsr: .quad 0
+laf_q_icperr: .quad 0
+laf_q_dcperr: .quad 0
+laf_q_va: .quad 0
+laf_q_mm_stat: .quad 0
+laf_q_sc_addr: .quad 0
+laf_q_sc_stat: .quad 0
+laf_q_bc_addr: .quad 0
+laf_q_ei_addr: .quad 0
+laf_q_fill_syndrome: .quad 0
+laf_q_ei_stat: .quad 0
+laf_q_ld_lock: .quad 0
+
+laf_sys_base:
+laf_q_cpu_err0: .quad 0
+laf_q_cpu_err1: .quad 0
+laf_q_cia_err: .quad 0
+laf_q_err_mask: .quad 0
+laf_q_cia_syn: .quad 0
+laf_q_mem_err0: .quad 0
+laf_q_mem_err1: .quad 0
+laf_q_pci_err0: .quad 0
+laf_q_pci_err1: .quad 0
+laf_q_pci_err2: .quad 0
+
+$laf_size = . - laf_base
+ .size laf_base, . - laf_base
diff --git a/uart.c b/uart.c
new file mode 100644
index 0000000..d3fd848
--- /dev/null
+++ b/uart.c
@@ -0,0 +1,134 @@
+/*****************************************************************************
+
+ Copyright © 1995, 1996 Digital Equipment Corporation,
+ Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that the copyright notice and this permission notice appear in all copies
+of software and supporting documentation, and that the name of Digital not
+be used in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission. Digital grants this permission
+provided that you prominently mark, as not part of the original, any
+modifications made to this software or documentation.
+
+Digital Equipment Corporation disclaims all warranties and/or guarantees
+with regard to this software, including all implied warranties of fitness for
+a particular purpose and merchantability, and makes no representations
+regarding the use of, or the results of the use of, the software and
+documentation in terms of correctness, accuracy, reliability, currentness or
+otherwise; and you rely on the software, documentation and results solely at
+your own risk.
+
+******************************************************************************/
+
+/*
+ * david.rusling@reo.mts.dec.com
+ *
+ * Modified for QEMU PALcode by rth@twiddle.net.
+ */
+
+#include "io.h"
+#include "uart.h"
+
+#ifndef SERIAL_SPEED
+#define SERIAL_SPEED 9600
+#endif
+
+int
+uart_charav(int offset)
+{
+ return inb(com2Lsr + offset) & 1;
+}
+
+int
+uart_getchar(int offset)
+{
+ while (!uart_charav(offset))
+ continue;
+ return inb(com2Rbr + offset);
+}
+
+static void
+uart_putchar_raw(int offset, char c)
+{
+ while ((inb(com2Lsr + offset) & 0x20) == 0)
+ continue;
+ outb(c, com2Thr + offset);
+}
+
+void
+uart_putchar(int offset, char c)
+{
+ if (c == '\n')
+ uart_putchar_raw(offset, '\r');
+ uart_putchar_raw(offset, c);
+}
+
+void
+uart_puts(int offset, const char *s)
+{
+ while (*s != '\0')
+ uart_putchar(offset, *s++);
+}
+
+static void
+uart_init_line(int offset, int baud)
+{
+ int i;
+ int baudconst;
+
+ switch (baud) {
+ case 56000:
+ baudconst = 2;
+ break;
+ case 38400:
+ baudconst = 3;
+ break;
+ case 19200:
+ baudconst = 6;
+ break;
+ case 9600:
+ baudconst = 12;
+ break;
+ case 4800:
+ baudconst = 24;
+ break;
+ case 2400:
+ baudconst = 48;
+ break;
+ case 1200:
+ baudconst = 96;
+ break;
+ case 300:
+ baudconst = 384;
+ break;
+ case 150:
+ baudconst = 768;
+ break;
+ default:
+ baudconst = 12;
+ break;
+ }
+
+
+ outb(0x87, com2Lcr + offset);
+ outb(0, com2Dlm + offset);
+ outb(baudconst, com2Dll + offset);
+ outb(0x07, com2Lcr + offset);
+ outb(0x0F, com2Mcr + offset);
+
+ for (i = 10; i > 0; i--) {
+ if (inb(com2Lsr + offset) == 0)
+ break;
+ inb(com2Rbr + offset);
+ }
+}
+
+void uart_init(void)
+{
+ uart_init_line(COM1, SERIAL_SPEED);
+ uart_init_line(COM2, SERIAL_SPEED);
+}
diff --git a/uart.h b/uart.h
new file mode 100644
index 0000000..b5f018d
--- /dev/null
+++ b/uart.h
@@ -0,0 +1,62 @@
+#ifndef __UART_H_LOADED
+#define __UART_H_LOADED
+/*****************************************************************************
+
+ Copyright © 1993, 1994 Digital Equipment Corporation,
+ Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that the copyright notice and this permission notice appear in all copies
+of software and supporting documentation, and that the name of Digital not
+be used in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission. Digital grants this permission
+provided that you prominently mark, as not part of the original, any
+modifications made to this software or documentation.
+
+Digital Equipment Corporation disclaims all warranties and/or guarantees
+with regard to this software, including all implied warranties of fitness for
+a particular purpose and merchantability, and makes no representations
+regarding the use of, or the results of the use of, the software and
+documentation in terms of correctness, accuracy, reliability, currentness or
+otherwise; and you rely on the software, documentation and results solely at
+your own risk.
+
+******************************************************************************/
+
+#define com1Rbr 0x3f8
+#define com1Thr 0x3f8
+#define com1Ier 0x3f9
+#define com1Iir 0x3fa
+#define com1Lcr 0x3fb
+#define com1Mcr 0x3fc
+#define com1Lsr 0x3fd
+#define com1Msr 0x3fe
+#define com1Scr 0x3ff
+#define com1Dll 0x3f8
+#define com1Dlm 0x3f9
+
+#define com2Rbr 0x2f8
+#define com2Thr 0x2f8
+#define com2Ier 0x2f9
+#define com2Iir 0x2fa
+#define com2Lcr 0x2fb
+#define com2Mcr 0x2fc
+#define com2Lsr 0x2fd
+#define com2Msr 0x2fe
+#define com2Scr 0x2ff
+#define com2Dll 0x2f8
+#define com2Dlm 0x2f9
+
+#define COM1 (com1Rbr - com2Rbr)
+#define COM2 0
+
+extern int uart_charav(int port);
+extern int uart_getchar(int port);
+extern void uart_putchar(int port, char c);
+extern void uart_puts(int port, const char *s);
+extern void uart_init(void);
+
+#endif /* __UART_H_LOADED */