Implement CallPal_Cserve.

This is just good enough to handle the cserve_ena/dis used by
the Linux kernel for managing interrupts.
diff --git a/Makefile b/Makefile
index 03a78a1..ea2eac2 100644
--- a/Makefile
+++ b/Makefile
@@ -18,5 +18,9 @@
 	rm -f *.o
 	rm -f palcode palcode.map
 
-pal.o: pal.S osf.h
+pal.o: pal.S osf.h uart.h
 	$(CC) $(CFLAGS) -c -Wa,-m21264 -Wa,--noexecstack -o $@ $<
+
+init.o: init.c hwrpb.h osf.h uart.h
+printf.o: printf.c uart.h
+uart.o: uart.c uart.h io.h cia.h
diff --git a/pal.S b/pal.S
index dc4aecf..c3f100d 100644
--- a/pal.S
+++ b/pal.S
@@ -3,6 +3,7 @@
 	.text
 
 #include "osf.h"
+#include "uart.h"
 
 /* General Purpose Registers.  */
 #define	v0	$0
@@ -532,8 +533,8 @@
  * 
  * INPUT PARAMETERS:
  * 
- *	r0 (v0)           = Option selector
- *	r16..r21 (a0..a5) = Implementation specific entry parameters
+ *	r16 (a0)          = Option selector
+ *	r17..r21 (a1..a5) = Implementation specific entry parameters
  * 
  * SIDE EFFECTS:
  *
@@ -541,9 +542,64 @@
  */ 
 	ORG_CALL_PAL_PRIV(0x09)
 CallPal_Cserve:
-	br	Sys_Cserve
+	cmpeq	a0, 15, v0
+	bne	v0, Cserve_putc
+	cmpeq	a0, 52, v0
+	bne	v0, Cserve_ena
+	cmpeq	a0, 53, v0
+	bne	v0, Cserve_dis
+	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
+
+	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
+
+	hw_rei
+ENDFN	Cserve_dis
+	.previous
+
 /*
  * Swap PALcode
  *
@@ -2068,7 +2124,6 @@
  * FIXME
  */
 Sys_EnterConsole:
-Sys_Cserve:
 	halt
 
 /*
diff --git a/uart.h b/uart.h
index b5f018d..48cceef 100644
--- a/uart.h
+++ b/uart.h
@@ -53,10 +53,13 @@
 #define COM1	(com1Rbr - com2Rbr)
 #define COM2	0
 
+#ifndef __ASSEMBLER__
+
 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 */
+#endif /* __ASSEMBLER__ */
+#endif /* __UART_H_LOADED */