Inline i/o routines.
diff --git a/core-typhoon.h b/core-typhoon.h
index cee6e95..96a0a90 100644
--- a/core-typhoon.h
+++ b/core-typhoon.h
@@ -143,6 +143,15 @@
 	sll	\ret, 20, \ret
 .endm
 
+.macro	LOAD_KSEG_PCI_CONF ret
+	.set	macro
+	// Note that GAS shifts are logical.  Force arithmetic shift style
+	// results by negating before and after the shift.
+	lda	\ret, -(-(PIO_KSEG_ADDR + TYPHOON_PCHIP0_PCI_CONF) >> 20)
+	.set	nomacro
+	sll	\ret, 20, \ret
+.endm
+
 .macro	SYS_WHAMI	ret
 	LOAD_PHYS_CCHIP	\ret
 	ldq_p		\ret, TYPHOON_CCHIP_MISC(\ret)
diff --git a/protos.h b/protos.h
index bebd50a..96229eb 100644
--- a/protos.h
+++ b/protos.h
@@ -155,8 +155,17 @@
  * I/O functions
  */
 
-extern unsigned long inb(unsigned long port);
-extern unsigned long outb(unsigned char val, unsigned long port);
+extern void *pci_io_base;
+
+static inline uint8_t inb(unsigned long port)
+{
+  return *(volatile uint8_t *)(pci_io_base + port);
+}
+
+static inline void outb(uint8_t val, unsigned long port)
+{
+  *(volatile uint8_t *)(pci_io_base + port) = val;
+}
 
 /*
  * CRB functions
diff --git a/sys-clipper.S b/sys-clipper.S
index 88ca020..81a0939 100644
--- a/sys-clipper.S
+++ b/sys-clipper.S
@@ -113,34 +113,20 @@
 ENDFN	Cserve_Dis
 
 /*
- * inb
- *
- * Read a byte from the PCI I/O bus.
+ * PCI parameters
  */
-	.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
+	.section .sdata
 
+	.align	3
+	.globl	pci_io_base
+	.type	pci_io_base, @object
+	.size	pci_io_base, 8
+pci_io_base:
+	.quad	PIO_KSEG_ADDR + TYPHOON_PCHIP0_PCI_IO
+
+	.globl	pci_conf_base
+	.type	pci_conf_base, @object
+	.size	pci_conf_base, 8
+pci_conf_base:
+	.quad	PIO_KSEG_ADDR + TYPHOON_PCHIP0_PCI_CONF