summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/socppc/conf/GENERIC63
-rw-r--r--sys/arch/socppc/conf/Makefile.socppc189
-rw-r--r--sys/arch/socppc/conf/files.socppc93
-rw-r--r--sys/arch/socppc/dev/com_obio.c69
-rw-r--r--sys/arch/socppc/dev/ehci_obio.c118
-rw-r--r--sys/arch/socppc/dev/ipic.c333
-rw-r--r--sys/arch/socppc/dev/obio.c83
-rw-r--r--sys/arch/socppc/dev/pciide_machdep.c40
-rw-r--r--sys/arch/socppc/dev/sociic.c290
-rw-r--r--sys/arch/socppc/dev/socpcic.c266
-rw-r--r--sys/arch/socppc/include/_types.h3
-rw-r--r--sys/arch/socppc/include/asm.h3
-rw-r--r--sys/arch/socppc/include/atomic.h3
-rw-r--r--sys/arch/socppc/include/autoconf.h45
-rw-r--r--sys/arch/socppc/include/bat.h3
-rw-r--r--sys/arch/socppc/include/bus.h609
-rw-r--r--sys/arch/socppc/include/cdefs.h3
-rw-r--r--sys/arch/socppc/include/conf.h37
-rw-r--r--sys/arch/socppc/include/cpu.h53
-rw-r--r--sys/arch/socppc/include/db_machdep.h3
-rw-r--r--sys/arch/socppc/include/disklabel.h90
-rw-r--r--sys/arch/socppc/include/endian.h3
-rw-r--r--sys/arch/socppc/include/exec.h3
-rw-r--r--sys/arch/socppc/include/fpu.h3
-rw-r--r--sys/arch/socppc/include/frame.h3
-rw-r--r--sys/arch/socppc/include/internal_types.h3
-rw-r--r--sys/arch/socppc/include/intr.h11
-rw-r--r--sys/arch/socppc/include/limits.h3
-rw-r--r--sys/arch/socppc/include/lock.h3
-rw-r--r--sys/arch/socppc/include/mutex.h3
-rw-r--r--sys/arch/socppc/include/param.h51
-rw-r--r--sys/arch/socppc/include/pcb.h3
-rw-r--r--sys/arch/socppc/include/pio.h3
-rw-r--r--sys/arch/socppc/include/pmap.h3
-rw-r--r--sys/arch/socppc/include/powerpc.h94
-rw-r--r--sys/arch/socppc/include/proc.h3
-rw-r--r--sys/arch/socppc/include/psl.h3
-rw-r--r--sys/arch/socppc/include/pte.h3
-rw-r--r--sys/arch/socppc/include/ptrace.h3
-rw-r--r--sys/arch/socppc/include/reg.h3
-rw-r--r--sys/arch/socppc/include/signal.h3
-rw-r--r--sys/arch/socppc/include/spinlock.h3
-rw-r--r--sys/arch/socppc/include/trap.h3
-rw-r--r--sys/arch/socppc/include/vmparam.h114
-rw-r--r--sys/arch/socppc/socppc/autoconf.c69
-rw-r--r--sys/arch/socppc/socppc/clock.c342
-rw-r--r--sys/arch/socppc/socppc/conf.c287
-rw-r--r--sys/arch/socppc/socppc/cpu.c115
-rw-r--r--sys/arch/socppc/socppc/db_interface.c44
-rw-r--r--sys/arch/socppc/socppc/disksubr.c214
-rw-r--r--sys/arch/socppc/socppc/dma.c608
-rw-r--r--sys/arch/socppc/socppc/machdep.c1147
-rw-r--r--sys/arch/socppc/socppc/mainbus.c77
-rw-r--r--sys/arch/socppc/socppc/mem.c179
54 files changed, 5805 insertions, 0 deletions
diff --git a/sys/arch/socppc/conf/GENERIC b/sys/arch/socppc/conf/GENERIC
new file mode 100644
index 00000000000..5021ce57449
--- /dev/null
+++ b/sys/arch/socppc/conf/GENERIC
@@ -0,0 +1,63 @@
+# $OpenBSD: GENERIC,v 1.1 2008/05/10 12:02:20 kettenis Exp $g
+#
+# For further information on compiling OpenBSD kernels, see the config(8)
+# man page.
+#
+# For further information on hardware support for this architecture, see
+# the intro(4) man page. For further information about kernel options
+# for this architecture, see the options(4) man page. For an explanation
+# of each device driver in this file see the section 4 man page for the
+# device.
+
+machine socppc powerpc
+include "../../../conf/GENERIC"
+maxusers 32 # estimated number of users
+
+option USB_DEBUG
+option PCIVERBOSE
+option USBVERBOSE
+
+option USER_PCICONF # user-space PCI configuration
+option APERTURE
+
+config bsd swap generic
+
+mainbus0 at root
+cpu0 at mainbus0
+obio0 at mainbus0
+
+# On-board IPIC
+ipic0 at obio? addr 0x00700
+
+# On-board I2C
+sociic0 at obio? addr 0x03000 ivec 14
+sociic1 at obio? addr 0x03100 ivec 15
+iic* at sociic?
+ricohrtc0 at iic? addr 0x32 # Ricoh RTC
+fintek0 at iic? flags 0x0001 # temp/fan controller
+
+# On-board DUART
+com0 at obio? addr 0x04500 ivec 9
+com1 at obio? addr 0x04600 ivec 10
+
+# On-board PCI
+socpcic0 at obio? addr 0x08300
+socpcic1 at obio? addr 0x08380
+pci* at socpcic?
+
+pciide* at pci?
+wd* at pciide? flags 0x0000
+
+# Ob-board USB
+ehci0 at obio? addr 0x22100 ivec 39
+usb* at ehci?
+
+# USB devices
+uhub* at usb? # USB Hubs
+uhub* at uhub? # USB Hubs
+umass* at uhub? # USB Mass Storage devices
+scsibus* at umass?
+ural* at uhub? # Ralink RT2500USB
+rum* at uhub? # Ralink RT2501USB/RT2601USB
+
+sd* at scsibus?
diff --git a/sys/arch/socppc/conf/Makefile.socppc b/sys/arch/socppc/conf/Makefile.socppc
new file mode 100644
index 00000000000..baa5d9ca8c7
--- /dev/null
+++ b/sys/arch/socppc/conf/Makefile.socppc
@@ -0,0 +1,189 @@
+# $OpenBSD: Makefile.socppc,v 1.1 2008/05/10 12:02:20 kettenis Exp $
+#
+# Makefile for OpenBSD PowerPC
+#
+# This makefile is constructed from a machine description:
+# config machineid
+# Most changes should be made in the machine description
+# /sys/arch/socppc/conf/``machineid''
+# after which you should do
+# config machineid
+# Machine generic makefile changes should be made in
+# /sys/arch/socppc/conf/Makefile.socppc
+# after which config should be rerun for all machines of that type.
+#
+# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE
+# IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING
+#
+# -DTRACE compile in kernel tracing hooks
+# -DQUOTA compile in file system quotas
+#
+.SUFFIXES: .S .c .o
+
+# DEBUG is set to -g if debugging.
+# PROF is set to -pg if profiling.
+
+.include <bsd.own.mk>
+
+MKDEP?= mkdep
+STRIP?= strip
+SIZE?= size
+
+# source tree is located via $S relative to the compilation directory
+.ifndef S
+S!= cd ../../../..; pwd
+.endif
+SOCPPC= $S/arch/socppc
+
+INCLUDES= -I. -I$S -I$S/arch -nostdinc
+CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL \
+ -D__socppc__
+CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \
+ -Wno-uninitialized -Wno-format -Wno-main \
+ -Wstack-larger-than-2047 -Wvariable-decl
+CMACHFLAGS= -msoft-float -Wa,-many -fno-builtin-printf -fno-builtin-log
+.if ${IDENT:M-DNO_PROPOLICE}
+CMACHFLAGS+= -fno-stack-protector
+.endif
+COPTS?= -O2
+CFLAGS= ${DEBUG} ${CWARNFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE}
+AFLAGS= -D_LOCORE -Wa,-many
+LINKFLAGS= -N -Ttext 200000 -e start --warn-common
+STRIPFLAGS= -g -X -x
+
+HOSTCC?= ${CC}
+HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//}
+HOSTED_CFLAGS= ${CFLAGS}
+
+# compile rules: rules are named ${TYPE}_${SUFFIX}${CONFIG_DEP}
+# where TYPE is NORMAL, DRIVER, or PROFILE}; SUFFIX is the file suffix,
+# capitalized (e.g. C for a .c file), and CONFIG_DEP is _C if the file
+# is marked as config-dependent.
+
+NORMAL_C_NOP= ${CC} ${CFLAGS} ${CPPFLAGS} -c $<
+NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+NORMAL_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+DRIVER_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+DRIVER_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $<
+NORMAL_S_C= ${AS} ${COPTS} ${PARAM} $< -o $@
+
+
+%OBJS
+
+%CFILES
+
+%SFILES
+
+# load lines for config "xxx" will be emitted as:
+# xxx: ${SYSTEM_DEP} swapxxx.o
+# ${SYSTEM_LD_HEAD}
+# ${SYSTEM_LD} swapxxx.o
+# ${SYSTEM_LD_TAIL}
+SYSTEM_OBJ= locore.o param.o ioconf.o ${OBJS}
+SYSTEM_DEP= Makefile ${SYSTEM_OBJ}
+SYSTEM_LD_HEAD= rm -f $@
+SYSTEM_LD= @echo ${LD} ${LINKFLAGS} -o $@ '$${SYSTEM_OBJ}' vers.o; \
+ ${LD} ${LINKFLAGS} -o $@ ${SYSTEM_OBJ} vers.o
+SYSTEM_LD_TAIL= @${SIZE} $@; chmod 755 $@
+
+DEBUG?=
+.if ${DEBUG} == "-g"
+LINKFLAGS+= -X
+SYSTEM_LD_TAIL+=; \
+ echo mv $@ $@.gdb; rm -f $@.gdb; mv $@ $@.gdb; \
+ echo ${STRIP} ${STRIPFLAGS} -o $@ $@.gdb; \
+ ${STRIP} ${STRIPFLAGS} -o $@ $@.gdb
+.else
+LINKFLAGS+= -S -x
+.endif
+
+%LOAD
+
+assym.h: $S/kern/genassym.sh ${SOCPPC}/socppc/genassym.cf Makefile
+ sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} \
+ < ${SOCPPC}/socppc/genassym.cf > assym.h.tmp && \
+ mv -f assym.h.tmp assym.h
+
+param.c: $S/conf/param.c
+ rm -f param.c
+ cp $S/conf/param.c .
+
+param.o: param.c Makefile
+ ${NORMAL_C_C}
+
+mcount.o: $S/lib/libkern/mcount.c Makefile
+ ${NORMAL_C_NOP}
+
+ioconf.o: ioconf.c
+ ${NORMAL_C}
+
+newvers: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP}
+ sh $S/conf/newvers.sh
+ ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c
+
+clean::
+ rm -f eddep *bsd bsd.gdb tags *.[io] [a-z]*.s \
+ [Ee]rrs linterrs makelinks genassym genassym.o assym.h
+
+lint:
+ @lint -hbxncez -DGENERIC -Dvolatile= ${CPPFLAGS} -UKGDB ${CFILES} \
+ ioconf.c param.c | \
+ grep -v 'static function .* unused'
+
+tags:
+ @echo "see $S/kern/Makefile for tags"
+
+links:
+ egrep '#if' ${CFILES} | sed -f $S/conf/defines | \
+ sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink
+ echo ${CFILES} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \
+ sort -u | comm -23 - dontlink | \
+ sed 's,../.*/\(.*.o\),rm -f \1; ln -s ../GENERIC/\1 \1,' > makelinks
+ sh makelinks && rm -f dontlink
+
+SRCS= ${SOCPPC}/socppc/locore.S \
+ param.c ioconf.c ${CFILES} ${SFILES}
+depend:: .depend
+.depend: ${SRCS} assym.h param.c
+ ${MKDEP} ${AFLAGS} ${CPPFLAGS} ${SOCPPC}/socppc/locore.S
+ ${MKDEP} -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES}
+.if ${SFILES} != ""
+ ${MKDEP} -a ${AFLAGS} ${CPPFLAGS} ${SFILES}
+.endif
+ sh $S/kern/genassym.sh ${MKDEP} -f assym.dep ${CFLAGS} \
+ ${CPPFLAGS} < ${SOCPPC}/socppc/genassym.cf
+ @sed -e 's/.*\.o:.* /assym.h: /' < assym.dep >> .depend
+ @rm -f assym.dep
+
+# depend on root or device configuration
+autoconf.o conf.o: Makefile
+
+# depend on network or filesystem configuration
+uipc_proto.o vfs_conf.o: Makefile
+
+# depend on maxusers
+genassym.o machdep.o: Makefile
+
+# depend on CPU configuration
+locore.o machdep.o: Makefile
+
+
+locore.o: ${SOCPPC}/socppc/locore.S assym.h
+ ${NORMAL_S}
+
+# The install target can be redefined by putting a
+# install-kernel-${MACHINE_NAME} target into /etc/mk.conf
+MACHINE_NAME!= uname -n
+install: install-kernel-${MACHINE_NAME}
+.if !target(install-kernel-${MACHINE_NAME}})
+install-kernel-${MACHINE_NAME}:
+ rm -f /obsd
+ ln /bsd /obsd
+ cp bsd /nbsd
+ mv /nbsd /bsd
+.endif
+
+%RULES
diff --git a/sys/arch/socppc/conf/files.socppc b/sys/arch/socppc/conf/files.socppc
new file mode 100644
index 00000000000..d22ecf309f2
--- /dev/null
+++ b/sys/arch/socppc/conf/files.socppc
@@ -0,0 +1,93 @@
+# $OpenBSD: files.socppc,v 1.1 2008/05/10 12:02:20 kettenis Exp $
+
+#
+# macppc-specific configuration info
+#
+maxpartitions 16
+
+maxusers 2 8 64
+
+file arch/socppc/socppc/autoconf.c
+file arch/socppc/socppc/clock.c
+file arch/socppc/socppc/conf.c
+file arch/socppc/socppc/disksubr.c disk
+file arch/socppc/socppc/machdep.c
+file arch/socppc/socppc/mem.c
+file arch/socppc/socppc/dma.c
+file dev/cninit.c
+file arch/socppc/socppc/db_interface.c ddb
+
+
+define mainbus {}
+device mainbus
+attach mainbus at root
+file arch/socppc/socppc/mainbus.c mainbus
+
+device cpu
+attach cpu at mainbus
+file arch/socppc/socppc/cpu.c
+
+# MPC8349E on-board devices
+device obio {addr, [ivec = -1]}
+attach obio at mainbus
+file arch/socppc/dev/obio.c
+
+# On-board IPIC
+device ipic
+attach ipic at obio
+file arch/socppc/dev/ipic.c
+
+# On-board I2C
+device sociic: i2cbus
+attach sociic at obio
+file arch/socppc/dev/sociic.c
+
+# On-board DUART
+attach com at obio with com_obio
+file arch/socppc/dev/com_obio.c
+
+#
+# Media Independent Interface (mii)
+#
+include "../../../dev/mii/files.mii"
+
+major {rd = 17}
+major {wd = 0}
+major {sd = 2}
+major {cd = 3}
+
+include "../../../scsi/files.scsi"
+
+#
+# I2O
+#
+include "../../../dev/i2o/files.i2o"
+
+include "dev/pci/files.pci"
+file arch/socppc/dev/pciide_machdep.c pciide
+
+# On-board PCI
+device socpcic: pcibus
+attach socpcic at obio
+file arch/socppc/dev/socpcic.c
+
+#
+# Machine-independent ATAPI drivers
+#
+
+include "../../../dev/atapiscsi/files.atapiscsi"
+include "../../../dev/ata/files.ata"
+
+#
+# Machine-independent USB drivers
+#
+include "dev/usb/files.usb"
+
+# On-board USB
+attach ehci at obio with ehci_obio
+file arch/socppc/dev/ehci_obio.c
+
+#
+# Machine-independent I2C drivers
+#
+include "dev/i2c/files.i2c"
diff --git a/sys/arch/socppc/dev/com_obio.c b/sys/arch/socppc/dev/com_obio.c
new file mode 100644
index 00000000000..c509c800e05
--- /dev/null
+++ b/sys/arch/socppc/dev/com_obio.c
@@ -0,0 +1,69 @@
+/* $OpenBSD: com_obio.c,v 1.1 2008/05/10 12:02:20 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/tty.h>
+
+#include <machine/autoconf.h>
+
+#include <dev/ic/comreg.h>
+#include <dev/ic/comvar.h>
+
+int com_obio_match(struct device *, void *, void *);
+void com_obio_attach(struct device *, struct device *, void *);
+
+struct cfattach com_obio_ca = {
+ sizeof(struct com_softc), com_obio_match, com_obio_attach
+};
+
+struct cfdriver com_obio_cd = {
+ NULL, "com", DV_DULL
+};
+
+int
+com_obio_match(struct device *parent, void *cfdata, void *aux)
+{
+ return (1);
+}
+
+void
+com_obio_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct com_softc *sc = (void *)self;
+ struct obio_attach_args *oa = aux;
+
+ sc->sc_iot = oa->oa_iot;
+ sc->sc_iobase = oa->oa_offset;
+ sc->sc_frequency = 266666666; /* XXX */
+
+ if (sc->sc_iobase != comconsaddr) {
+ if (bus_space_map(sc->sc_iot, sc->sc_iobase,
+ COM_NPORTS, 0, &sc->sc_ioh)) {
+ printf(": can't map registers\n");
+ return;
+ }
+ } else
+ sc->sc_ioh = comconsioh;
+
+ com_attach_subr(sc);
+
+ intr_establish(oa->oa_ivec, IST_LEVEL, IPL_TTY, comintr,
+ sc, sc->sc_dev.dv_xname);
+}
diff --git a/sys/arch/socppc/dev/ehci_obio.c b/sys/arch/socppc/dev/ehci_obio.c
new file mode 100644
index 00000000000..93039e45533
--- /dev/null
+++ b/sys/arch/socppc/dev/ehci_obio.c
@@ -0,0 +1,118 @@
+/* $OpenBSD: ehci_obio.c,v 1.1 2008/05/10 12:02:20 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/rwlock.h>
+#include <sys/timeout.h>
+
+#include <machine/autoconf.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+
+#include <dev/usb/ehcireg.h>
+#include <dev/usb/ehcivar.h>
+
+#include <dev/pci/pcidevs.h>
+
+int ehci_obio_match(struct device *, void *, void *);
+void ehci_obio_attach(struct device *, struct device *, void *);
+
+struct cfattach ehci_obio_ca = {
+ sizeof(struct ehci_softc), ehci_obio_match, ehci_obio_attach
+};
+
+struct cfdriver ehci_obio_cd = {
+ NULL, "ehci", DV_DULL
+};
+
+struct powerpc_bus_dma_tag ehci_bus_dma_tag = {
+ NULL,
+ _dmamap_create,
+ _dmamap_destroy,
+ _dmamap_load,
+ _dmamap_load_mbuf,
+ _dmamap_load_uio,
+ _dmamap_load_raw,
+ _dmamap_unload,
+ _dmamap_sync,
+ _dmamem_alloc,
+ _dmamem_free,
+ _dmamem_map,
+ _dmamem_unmap,
+ _dmamem_mmap
+};
+
+int
+ehci_obio_match(struct device *parent, void *cfdata, void *aux)
+{
+ return (1);
+}
+
+void
+ehci_obio_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct ehci_softc *sc = (void *)self;
+ struct obio_attach_args *oa = aux;
+ usbd_status r;
+ int s;
+
+ sc->iot = oa->oa_iot;
+ sc->sc_size = 1024;
+ if (bus_space_map(sc->iot, oa->oa_offset, sc->sc_size, 0, &sc->ioh)) {
+ printf(": can't map registers\n");
+ return;
+ }
+
+ sc->sc_id_vendor = PCI_VENDOR_FREESCALE;
+ strlcpy(sc->sc_vendor, "Freescale", sizeof sc->sc_vendor);
+
+ sc->sc_bus.dmatag = &ehci_bus_dma_tag;
+
+ bus_space_write_4(sc->iot, sc->ioh, 0x400, 0x04000000);
+ bus_space_write_4(sc->iot, sc->ioh, 0x300, 0x1e000000);
+
+ s = splhardusb();
+ sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH);
+ EOWRITE2(sc, EHCI_USBINTR, 0);
+
+ intr_establish(oa->oa_ivec, IST_LEVEL, IPL_USB, ehci_intr, sc,
+ sc->sc_bus.bdev.dv_xname);
+
+ r = ehci_init(sc);
+ if (r != USBD_NORMAL_COMPLETION) {
+ printf(": init failed, error=%d\n", r);
+ goto unmap_ret;
+ }
+ splx(s);
+
+ printf("\n");
+
+ /* Attach usb device. */
+ sc->sc_child = config_found((void *)sc, &sc->sc_bus, usbctlprint);
+
+ return;
+
+unmap_ret:
+ bus_space_unmap(sc->iot, sc->ioh, sc->sc_size);
+ splx(s);
+}
diff --git a/sys/arch/socppc/dev/ipic.c b/sys/arch/socppc/dev/ipic.c
new file mode 100644
index 00000000000..befc10c43e3
--- /dev/null
+++ b/sys/arch/socppc/dev/ipic.c
@@ -0,0 +1,333 @@
+/* $OpenBSD: ipic.c,v 1.1 2008/05/10 12:02:20 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/autoconf.h>
+#include <machine/intr.h>
+
+#define IPIC_SICFR 0x00
+#define IPIC_SIVCR 0x04
+#define IPIC_SIPNR_H 0x08
+#define IPIC_SIPNR_L 0x0c
+#define IPIC_SIPRR_A 0x10
+#define IPIC_SIPRR_D 0x1c
+#define IPIC_SIMSR_H 0x20
+#define IPIC_SIMSR_L 0x24
+#define IPIC_SICNR 0x28
+#define IPIC_SEPNR 0x2c
+#define IPIC_SMPRR_A 0x30
+#define IPIC_SMPRR_B 0x34
+#define IPIC_SEMSR 0x38
+#define IPIC_SECNR 0x3c
+#define IPIC_SERSR 0x40
+#define IPIC_SERMR 0x44
+#define IPIC_SERCR 0x48
+#define IPIC_SIFCR_H 0x50
+#define IPIC_SIFCR_L 0x54
+#define IPIC_SEFCR 0x58
+#define IPIC_SERFR 0x5c
+#define IPIC_SCVCR 0x60
+#define IPIC_SMVCR 0x64
+
+#define IPIC_NVEC 128
+
+#define IPIC_EXTERNAL(ivec) ((ivec) >= 17 && (ivec) <= 23)
+
+struct ipic_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ uint32_t sc_simsr_h[IPL_NUM];
+ uint32_t sc_simsr_l[IPL_NUM];
+ uint32_t sc_semsr[IPL_NUM];
+};
+
+uint32_t ipic_imask;
+struct intrhand *ipic_intrhand[IPIC_NVEC];
+struct ipic_softc *ipic_sc;
+
+int ipic_match(struct device *, void *, void *);
+void ipic_attach(struct device *, struct device *, void *);
+
+struct cfattach ipic_ca = {
+ sizeof(struct ipic_softc), ipic_match, ipic_attach
+};
+
+struct cfdriver ipic_cd = {
+ NULL, "ipic", DV_DULL
+};
+
+uint32_t ipic_read(struct ipic_softc *, bus_addr_t);
+void ipic_write(struct ipic_softc *, bus_addr_t, uint32_t);
+uint32_t ipic_simsr_h(int);
+uint32_t ipic_simsr_l(int);
+uint32_t ipic_semsr(int);
+
+void ext_intr(void);
+void ipic_do_pending_int(void);
+
+int
+ipic_match(struct device *parent, void *cfdata, void *aux)
+{
+ return (1);
+}
+
+void
+ipic_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct ipic_softc *sc = (void *)self;
+ struct obio_attach_args *oa = aux;
+
+ sc->sc_iot = oa->oa_iot;
+ if (bus_space_map(sc->sc_iot, oa->oa_offset, 128, 0, &sc->sc_ioh)) {
+ printf(": can't map registers\n");
+ return;
+ }
+
+ ipic_sc = sc;
+ printf("\n");
+}
+
+uint32_t
+ipic_read(struct ipic_softc *sc, bus_addr_t addr)
+{
+ return (letoh32(bus_space_read_4(sc->sc_iot, sc->sc_ioh, addr)));
+}
+
+void
+ipic_write(struct ipic_softc *sc, bus_addr_t addr, uint32_t data)
+{
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, addr, htole32(data));
+}
+
+uint32_t
+ipic_simsr_h(int ivec)
+{
+ switch (ivec) {
+ case 9:
+ return 0x00000080;
+ case 10:
+ return 0x00000040;
+ case 39:
+ return 0x01000000;
+ }
+
+ return 0;
+}
+
+uint32_t
+ipic_simsr_l(int ivec)
+{
+ return 0;
+}
+
+uint32_t
+ipic_semsr(int ivec)
+{
+ switch (ivec) {
+ case 17:
+ return 0x40000000;
+ case 18:
+ return 0x20000000;
+ case 19:
+ return 0x10000000;
+ case 20:
+ return 0x08000000;
+ case 21:
+ return 0x04000000;
+ case 22:
+ return 0x02000000;
+ case 23:
+ return 0x01000000;
+ }
+
+ return 0;
+}
+
+static void
+intr_calculatemasks(void)
+{
+ struct ipic_softc *sc = ipic_sc;
+ int level;
+
+ for (level = IPL_NONE; level < IPL_NUM; level++)
+ imask[level] = SINT_MASK | (1 << level);
+
+ /*
+ * There are tty, network and disk drivers that use free() at interrupt
+ * time, so vm > (tty | net | bio).
+ *
+ * Enforce a hierarchy that gives slow devices a better chance at not
+ * dropping data.
+ */
+ imask[IPL_NET] |= imask[IPL_BIO];
+ imask[IPL_TTY] |= imask[IPL_NET];
+ imask[IPL_VM] |= imask[IPL_TTY];
+ imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCK;
+
+ /*
+ * These are pseudo-levels.
+ */
+ imask[IPL_NONE] = 0x00000000;
+ imask[IPL_HIGH] = 0xffffffff;
+
+ sc->sc_simsr_h[IPL_NET] |= sc->sc_simsr_h[IPL_BIO];
+ sc->sc_simsr_h[IPL_TTY] |= sc->sc_simsr_h[IPL_NET];
+ sc->sc_simsr_h[IPL_VM] |= sc->sc_simsr_h[IPL_TTY];
+ sc->sc_simsr_h[IPL_NET] |= sc->sc_simsr_h[IPL_VM];
+ sc->sc_simsr_h[IPL_HIGH] |= sc->sc_simsr_h[IPL_NET];
+
+ sc->sc_simsr_l[IPL_NET] |= sc->sc_simsr_l[IPL_BIO];
+ sc->sc_simsr_l[IPL_TTY] |= sc->sc_simsr_l[IPL_NET];
+ sc->sc_simsr_l[IPL_VM] |= sc->sc_simsr_l[IPL_TTY];
+ sc->sc_simsr_l[IPL_NET] |= sc->sc_simsr_l[IPL_VM];
+ sc->sc_simsr_l[IPL_HIGH] |= sc->sc_simsr_l[IPL_NET];
+
+ sc->sc_semsr[IPL_NET] |= sc->sc_semsr[IPL_BIO];
+ sc->sc_semsr[IPL_TTY] |= sc->sc_semsr[IPL_NET];
+ sc->sc_semsr[IPL_VM] |= sc->sc_semsr[IPL_TTY];
+ sc->sc_semsr[IPL_NET] |= sc->sc_semsr[IPL_VM];
+ sc->sc_semsr[IPL_HIGH] |= sc->sc_semsr[IPL_NET];
+}
+
+void *
+intr_establish(int ivec, int type, int level,
+ int (*ih_fun)(void *), void *ih_arg, const char *name)
+{
+ struct ipic_softc *sc = ipic_sc;
+ struct intrhand **p, *q, *ih;
+ uint32_t mask;
+
+ ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
+ if (ih == NULL)
+ panic("xxx");
+
+ if (ivec < 0 || ivec >= IPIC_NVEC)
+ panic("xxx");
+
+ for (p = &ipic_intrhand[ivec]; (q = *p) != NULL; p = &q->ih_next)
+ ;
+
+ sc->sc_simsr_h[level] |= ipic_simsr_h(ivec);
+ sc->sc_simsr_l[level] |= ipic_simsr_l(ivec);
+ sc->sc_semsr[level] |= ipic_semsr(ivec);
+ intr_calculatemasks();
+
+ ih->ih_fun = ih_fun;
+ ih->ih_arg = ih_arg;
+ ih->ih_next = NULL;
+ ih->ih_level = level;
+ ih->ih_irq = ivec;
+ evcount_attach(&ih->ih_count, name, NULL, &evcount_intr);
+ *p = ih;
+
+ /* Unmask the interrupt. */
+ mask = ipic_read(sc, IPIC_SIMSR_H);
+ mask |= ipic_simsr_h(ivec);
+ ipic_write(sc, IPIC_SIMSR_H, mask);
+ mask = ipic_read(sc, IPIC_SIMSR_L);
+ mask |= ipic_simsr_l(ivec);
+ ipic_write(sc, IPIC_SIMSR_L, mask);
+ mask = ipic_read(sc, IPIC_SEMSR);
+ mask |= ipic_semsr(ivec);
+ ipic_write(sc, IPIC_SEMSR, mask);
+
+ return (ih);
+}
+
+void
+ext_intr(void)
+{
+ struct cpu_info *ci = curcpu();
+ struct ipic_softc *sc = ipic_sc;
+ struct intrhand *ih;
+ uint32_t simsr_h, simsr_l, semsr;
+ int pcpl, ocpl;
+ int ivec;
+
+ pcpl = ci->ci_cpl;
+ ivec = ipic_read(sc, IPIC_SIVCR) & 0x7f;
+
+ simsr_h = ipic_read(sc, IPIC_SIMSR_H);
+ simsr_l = ipic_read(sc, IPIC_SIMSR_L);
+ semsr = ipic_read(sc, IPIC_SEMSR);
+ ipic_write(sc, IPIC_SIMSR_H, simsr_h & ~ipic_simsr_h(ivec));
+ ipic_write(sc, IPIC_SIMSR_L, simsr_l & ~ipic_simsr_l(ivec));
+ ipic_write(sc, IPIC_SEMSR, semsr & ~ipic_semsr(ivec));
+
+ ih = ipic_intrhand[ivec];
+ while (ih) {
+ if (ci->ci_cpl & (1 << ih->ih_level)) {
+ ci->ci_ipending |= (1 << ih->ih_level);
+ return;
+ }
+
+ ipic_write(sc, IPIC_SIMSR_H, sc->sc_simsr_h[ih->ih_level]);
+ ipic_write(sc, IPIC_SIMSR_L, sc->sc_simsr_l[ih->ih_level]);
+ ipic_write(sc, IPIC_SEMSR, sc->sc_semsr[ih->ih_level]);
+ ocpl = splraise(imask[ih->ih_level]);
+ ppc_intr_enable(1);
+
+ KERNEL_LOCK();
+ if ((*ih->ih_fun)(ih->ih_arg))
+ ih->ih_count.ec_count++;
+ KERNEL_UNLOCK();
+
+ ppc_intr_disable();
+ ci->ci_cpl = ocpl;
+ ih = ih->ih_next;
+ }
+
+ ipic_write(sc, IPIC_SIMSR_H, simsr_h);
+ ipic_write(sc, IPIC_SIMSR_L, simsr_l);
+ ipic_write(sc, IPIC_SEMSR, semsr);
+ splx(pcpl);
+}
+
+static __inline int
+cntlzw(int x)
+{
+ int a;
+
+ __asm __volatile("cntlzw %0,%1" : "=r"(a) : "r"(x));
+
+ return a;
+}
+
+void
+ipic_do_pending_int(void)
+{
+ struct cpu_info *ci = curcpu();
+ struct ipic_softc *sc = ipic_sc;
+ uint32_t mask;
+ int level;
+
+ ci->ci_ipending &= SINT_MASK;
+ level = cntlzw(31 - (ci->ci_cpl & ~(SPL_CLOCK|SINT_MASK)));
+ mask = sc->sc_simsr_h[IPL_HIGH] & ~sc->sc_simsr_h[level];
+ ipic_write(sc, IPIC_SIMSR_H, mask);
+ mask = sc->sc_simsr_l[IPL_HIGH] & ~sc->sc_simsr_l[level];
+ ipic_write(sc, IPIC_SIMSR_L, mask);
+ mask = sc->sc_semsr[IPL_HIGH] & ~sc->sc_semsr[level];
+ ipic_write(sc, IPIC_SEMSR, mask);
+}
diff --git a/sys/arch/socppc/dev/obio.c b/sys/arch/socppc/dev/obio.c
new file mode 100644
index 00000000000..036564fc8a4
--- /dev/null
+++ b/sys/arch/socppc/dev/obio.c
@@ -0,0 +1,83 @@
+/* $OpenBSD: obio.c,v 1.1 2008/05/10 12:02:20 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+
+int obio_match(struct device *, void *, void *);
+void obio_attach(struct device *, struct device *, void *);
+
+struct cfattach obio_ca = {
+ sizeof(struct device), obio_match, obio_attach
+};
+
+struct cfdriver obio_cd = {
+ NULL, "obio", DV_DULL
+};
+
+int obio_search(struct device *, void *, void *);
+int obio_print(void *, const char *);
+
+int
+obio_match(struct device *parent, void *cfdata, void *aux)
+{
+ return (1);
+}
+
+void
+obio_attach(struct device *parent, struct device *self, void *aux)
+{
+ printf("\n");
+
+ config_search(obio_search, self, aux);
+}
+
+int
+obio_search(struct device *parent, void *cfdata, void *aux)
+{
+ struct mainbus_attach_args *ma = aux;
+ struct obio_attach_args oa;
+ struct cfdata *cf = cfdata;
+
+ bzero(&oa, sizeof oa);
+ oa.oa_iot = ma->ma_iot;
+ oa.oa_name = cf->cf_driver->cd_name;
+ oa.oa_offset = cf->cf_offset;
+ oa.oa_ivec = cf->cf_ivec;
+ config_found(parent, &oa, obio_print);
+
+ return (1);
+}
+
+int
+obio_print(void *aux, const char *name)
+{
+ struct obio_attach_args *oa = aux;
+
+ if (name)
+ printf("%s at %s", oa->oa_name, name);
+ if (oa->oa_offset)
+ printf(" offset 0x%05x", oa->oa_offset);
+ if (oa->oa_ivec != -1)
+ printf(" ivec %d", oa->oa_ivec);
+
+ return (UNCONF);
+}
diff --git a/sys/arch/socppc/dev/pciide_machdep.c b/sys/arch/socppc/dev/pciide_machdep.c
new file mode 100644
index 00000000000..b9b3ab8a9c9
--- /dev/null
+++ b/sys/arch/socppc/dev/pciide_machdep.c
@@ -0,0 +1,40 @@
+/* $OpenBSD: pciide_machdep.c,v 1.1 2008/05/10 12:02:20 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pciidereg.h>
+#include <dev/pci/pciidevar.h>
+
+#include <machine/autoconf.h>
+
+void *
+pciide_machdep_compat_intr_establish(struct device *dev,
+ struct pci_attach_args *pa, int chan, int (*func)(void *), void *arg)
+{
+ return (NULL);
+}
+
+void
+pciide_machdep_compat_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
+{
+}
diff --git a/sys/arch/socppc/dev/sociic.c b/sys/arch/socppc/dev/sociic.c
new file mode 100644
index 00000000000..b35c0397963
--- /dev/null
+++ b/sys/arch/socppc/dev/sociic.c
@@ -0,0 +1,290 @@
+/* $OpenBSD: sociic.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver for the I2C interface on the MPC8349E processors.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/rwlock.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+
+#include <dev/i2c/i2cvar.h>
+
+#define I2C_ADR 0x00 /* Address Register */
+#define I2C_FDR 0x04 /* Fequency Divider Register */
+#define I2C_CR 0x08 /* Control Register */
+#define I2C_CR_MEN 0x80
+#define I2C_CR_MIEN 0x40
+#define I2C_CR_MSTA 0x20
+#define I2C_CR_MTX 0x10
+#define I2C_CR_TXAK 0x08
+#define I2C_CR_RSTA 0x04
+#define I2C_CR_BCST 0x01
+#define I2C_SR 0x0c /* Status Register */
+#define I2C_SR_MCF 0x80
+#define I2C_SR_MAAS 0x40
+#define I2C_SR_MBB 0x20
+#define I2C_SR_MAL 0x10
+#define I2C_SR_BCSTM 0x08
+#define I2C_SR_SRW 0x04
+#define I2C_SR_MIF 0x02
+#define I2C_SR_RXAK 0x01
+#define I2C_DR 0x10 /* Data Register */
+#define I2C_DFSRR 0x14 /* Digital Filter Sampling Rate Register */
+
+struct sociic_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ struct i2c_controller sc_i2c;
+ struct rwlock sc_lock;
+};
+
+int sociic_match(struct device *, void *, void *);
+void sociic_attach(struct device *, struct device *, void *);
+
+struct cfattach sociic_ca = {
+ sizeof(struct sociic_softc), sociic_match, sociic_attach
+};
+
+struct cfdriver sociic_cd = {
+ NULL, "sociic", DV_DULL
+};
+
+void sociic_write(struct sociic_softc *, bus_addr_t, uint8_t);
+uint8_t sociic_read(struct sociic_softc *, bus_addr_t);
+int sociic_wait(struct sociic_softc *, int);
+int sociic_wait_bus(struct sociic_softc *);
+int sociic_i2c_acquire_bus(void *, int);
+void sociic_i2c_release_bus(void *, int);
+int sociic_i2c_exec(void *, i2c_op_t, i2c_addr_t,
+ const void *, size_t, void *, size_t, int);
+
+int
+sociic_match(struct device *parent, void *cfdata, void *aux)
+{
+ return (1);
+}
+
+void
+sociic_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct sociic_softc *sc = (void *)self;
+ struct obio_attach_args *oa = aux;
+ struct i2cbus_attach_args iba;
+
+ sc->sc_iot = oa->oa_iot;
+ if (bus_space_map(sc->sc_iot, oa->oa_offset, 24, 0, &sc->sc_ioh)) {
+ printf(": can't map registers\n");
+ return;
+ }
+
+ printf("\n");
+
+ rw_init(&sc->sc_lock, "iiclk");
+ sc->sc_i2c.ic_cookie = sc;
+ sc->sc_i2c.ic_acquire_bus = sociic_i2c_acquire_bus;
+ sc->sc_i2c.ic_release_bus = sociic_i2c_release_bus;
+ sc->sc_i2c.ic_exec = sociic_i2c_exec;
+
+ bzero(&iba, sizeof iba);
+ iba.iba_name = "iic";
+ iba.iba_tag = &sc->sc_i2c;
+ config_found(&sc->sc_dev, &iba, iicbus_print);
+}
+
+void
+sociic_write(struct sociic_softc *sc, bus_addr_t addr, uint8_t data)
+{
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, addr, data);
+}
+
+uint8_t
+sociic_read(struct sociic_softc *sc, bus_addr_t addr)
+{
+ return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, addr));
+}
+
+int
+sociic_wait(struct sociic_softc *sc, int flags)
+{
+ uint8_t sr;
+ int i;
+
+ for (i = 0; i < 1000; i++) {
+ sr = sociic_read(sc, I2C_SR);
+ if (sr & I2C_SR_MIF) {
+ sociic_write(sc, I2C_SR, 0);
+
+ if (sr & I2C_SR_MAL)
+ return (EIO);
+
+ if ((sr & I2C_SR_MCF) == 0)
+ return (EIO);
+
+ if ((flags & I2C_F_READ) == 0 && (sr & I2C_SR_RXAK))
+ return (EIO);
+
+ return (0);
+ }
+ delay(100);
+ }
+
+ return (ETIMEDOUT);
+}
+
+int
+sociic_wait_bus(struct sociic_softc *sc)
+{
+ uint8_t sr;
+ int i;
+
+ for (i = 0; i < 1000; i++) {
+ sr = sociic_read(sc, I2C_SR);
+ if ((sr & I2C_SR_MBB) == 0)
+ return (0);
+ delay(1000);
+ }
+
+ return (ETIMEDOUT);
+}
+
+int
+sociic_i2c_acquire_bus(void *arg, int flags)
+{
+ struct sociic_softc *sc = arg;
+
+ if (cold || (flags & I2C_F_POLL))
+ return (0);
+
+ return (rw_enter(&sc->sc_lock, RW_WRITE | RW_INTR));
+}
+
+void
+sociic_i2c_release_bus(void *arg, int flags)
+{
+ struct sociic_softc *sc = arg;
+
+ if (cold || (flags & I2C_F_POLL))
+ return;
+
+ rw_exit(&sc->sc_lock);
+}
+
+int
+sociic_i2c_exec(void *arg, i2c_op_t op, i2c_addr_t addr,
+ const void *vcmdbuf, size_t cmdlen, void *vbuf, size_t buflen, int flags)
+{
+ struct sociic_softc *sc = arg;
+ const uint8_t *cmdbuf = vcmdbuf;
+ uint8_t *buf = vbuf;
+ int err = 0;
+ size_t len;
+ uint8_t val;
+
+ /* Clear the bus. */
+ sociic_write(sc, I2C_SR, 0);
+ sociic_write(sc, I2C_CR, I2C_CR_MEN);
+ err = sociic_wait_bus(sc);
+ if (err)
+ return (err);
+
+ if (cmdlen > 0) {
+ sociic_write(sc, I2C_CR, I2C_CR_MEN|I2C_CR_MSTA|I2C_CR_MTX);
+ sociic_write(sc, I2C_DR, addr << 1);
+ err = sociic_wait(sc, I2C_F_WRITE);
+ if (err)
+ goto out;
+
+ len = cmdlen;
+ while (len--) {
+ sociic_write(sc, I2C_DR, *cmdbuf++);
+ err = sociic_wait(sc, I2C_F_WRITE);
+ if (err)
+ goto out;
+ }
+ }
+
+ if (I2C_OP_READ_P(op) && buflen > 0) {
+ /* RESTART if we did write a command above. */
+ val = I2C_CR_MEN|I2C_CR_MSTA|I2C_CR_MTX;
+ if (cmdlen > 0)
+ val |= I2C_CR_RSTA;
+ sociic_write(sc, I2C_CR, val);
+ sociic_write(sc, I2C_DR, (addr << 1) | 1);
+ err = sociic_wait(sc, I2C_F_WRITE);
+ if (err)
+ goto out;
+
+ /* NACK if we're only sending one byte. */
+ val = I2C_CR_MEN|I2C_CR_MSTA;
+ if (buflen == 1)
+ val |= I2C_CR_TXAK;
+ sociic_write(sc, I2C_CR, val);
+
+ /* Dummy read. */
+ sociic_read(sc, I2C_DR);
+
+ len = buflen;
+ while (len--) {
+ err = sociic_wait(sc, I2C_F_READ);
+ if (err)
+ goto out;
+
+ /* NACK on last byte. */
+ if (len == 1)
+ sociic_write(sc, I2C_CR,
+ I2C_CR_MEN|I2C_CR_MSTA|I2C_CR_TXAK);
+ /* STOP after last byte. */
+ if (len == 0)
+ sociic_write(sc, I2C_CR,
+ I2C_CR_MEN|I2C_CR_TXAK);
+ *buf++ = sociic_read(sc, I2C_DR);
+ }
+ }
+
+ if (I2C_OP_WRITE_P(op) && cmdlen == 0 && buflen > 0) {
+ /* START if we didn't write a command. */
+ sociic_write(sc, I2C_CR, I2C_CR_MEN|I2C_CR_MSTA|I2C_CR_MTX);
+ sociic_write(sc, I2C_DR, addr << 1);
+ err = sociic_wait(sc, I2C_F_WRITE);
+ if (err)
+ goto out;
+ }
+
+ if (I2C_OP_WRITE_P(op) && buflen > 0) {
+ len = buflen;
+ while (len--) {
+ sociic_write(sc, I2C_DR, *buf++);
+ err = sociic_wait(sc, I2C_F_WRITE);
+ if (err)
+ goto out;
+ }
+ }
+
+out:
+ /* STOP if we're still holding the bus. */
+ sociic_write(sc, I2C_CR, I2C_CR_MEN);
+ return (err);
+}
diff --git a/sys/arch/socppc/dev/socpcic.c b/sys/arch/socppc/dev/socpcic.c
new file mode 100644
index 00000000000..94fef8a70f6
--- /dev/null
+++ b/sys/arch/socppc/dev/socpcic.c
@@ -0,0 +1,266 @@
+/* $OpenBSD: socpcic.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+struct socpcic_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_cfg_ioh;
+ struct ppc_bus_space sc_mem_bus_space;
+ struct ppc_bus_space sc_io_bus_space;
+ struct ppc_pci_chipset sc_pc;
+};
+
+int socpcic_match(struct device *, void *, void *);
+void socpcic_attach(struct device *, struct device *, void *);
+
+struct cfattach socpcic_ca = {
+ sizeof(struct socpcic_softc), socpcic_match, socpcic_attach
+};
+
+struct cfdriver socpcic_cd = {
+ NULL, "socpcic", DV_DULL
+};
+
+void socpcic_attach_hook(struct device *, struct device *,
+ struct pcibus_attach_args *);
+int socpcic_bus_maxdevs(void *, int);
+pcitag_t socpcic_make_tag(void *, int, int, int);
+void socpcic_decompose_tag(void *, pcitag_t, int *, int *, int *);
+pcireg_t socpcic_conf_read(void *, pcitag_t, int);
+void socpcic_conf_write(void *, pcitag_t, int, pcireg_t);
+int socpcic_intr_map(void *, pcitag_t, int, int, pci_intr_handle_t *);
+const char *socpcic_intr_string(void *, pci_intr_handle_t);
+int socpcic_intr_line(void *, pci_intr_handle_t);
+void *socpcic_intr_establish(void *, pci_intr_handle_t, int,
+ int (*)(void *), void *, char *);
+void socpcic_intr_disestablish(void *, void *);
+int socpcic_ether_hw_addr(struct ppc_pci_chipset *, u_int8_t *);
+
+int socpcic_print(void *, const char *);
+
+struct powerpc_bus_dma_tag pci_bus_dma_tag = {
+ NULL,
+ _dmamap_create,
+ _dmamap_destroy,
+ _dmamap_load,
+ _dmamap_load_mbuf,
+ _dmamap_load_uio,
+ _dmamap_load_raw,
+ _dmamap_unload,
+ _dmamap_sync,
+ _dmamem_alloc,
+ _dmamem_free,
+ _dmamem_map,
+ _dmamem_unmap,
+ _dmamem_mmap
+};
+
+int
+socpcic_match(struct device *parent, void *cfdata, void *aux)
+{
+ return (1);
+}
+
+void
+socpcic_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct socpcic_softc *sc = (void *)self;
+ struct obio_attach_args *oa = aux;
+ struct pcibus_attach_args pba;
+
+ sc->sc_iot = oa->oa_iot;
+ if (bus_space_map(sc->sc_iot, oa->oa_offset, 16, 0, &sc->sc_cfg_ioh)) {
+ printf(": can't map configuration registers\n");
+ return;
+ }
+
+ sc->sc_io_bus_space.bus_base = 0xe2000000;
+ sc->sc_io_bus_space.bus_size = 0x01000000;
+
+ sc->sc_pc.pc_conf_v = sc;
+ sc->sc_pc.pc_attach_hook = socpcic_attach_hook;
+ sc->sc_pc.pc_bus_maxdevs = socpcic_bus_maxdevs;
+ sc->sc_pc.pc_make_tag = socpcic_make_tag;
+ sc->sc_pc.pc_decompose_tag = socpcic_decompose_tag;
+ sc->sc_pc.pc_conf_read = socpcic_conf_read;
+ sc->sc_pc.pc_conf_write = socpcic_conf_write;
+
+ sc->sc_pc.pc_intr_v = sc;
+ sc->sc_pc.pc_intr_map = socpcic_intr_map;
+ sc->sc_pc.pc_intr_string = socpcic_intr_string;
+ sc->sc_pc.pc_intr_line = socpcic_intr_line;
+ sc->sc_pc.pc_intr_establish = socpcic_intr_establish;
+ sc->sc_pc.pc_intr_disestablish = socpcic_intr_disestablish;
+ sc->sc_pc.pc_ether_hw_addr = socpcic_ether_hw_addr;
+
+ pba.pba_busname = "pci";
+ pba.pba_iot = &sc->sc_io_bus_space;
+ pba.pba_memt = &sc->sc_mem_bus_space;
+ pba.pba_dmat = &pci_bus_dma_tag;
+ pba.pba_pc = &sc->sc_pc;
+ pba.pba_domain = pci_ndomains++;
+ pba.pba_bus = 0;
+ pba.pba_bridgetag = NULL;
+
+ printf("\n");
+
+ config_found(self, &pba, socpcic_print);
+}
+
+void
+socpcic_attach_hook(struct device *parent, struct device *self,
+ struct pcibus_attach_args *pba)
+{
+}
+
+int
+socpcic_bus_maxdevs(void *cpv, int bus)
+{
+ return (32);
+}
+
+pcitag_t
+socpcic_make_tag(void *cpv, int bus, int dev, int fun)
+{
+ return ((bus << 16) | (dev << 11) | (fun << 8));
+}
+
+void
+socpcic_decompose_tag(void *cpv, pcitag_t tag, int *busp, int *devp, int *funp)
+{
+ if (busp)
+ *busp = (tag >> 16) & 0xff;
+ if (devp)
+ *devp = (tag >> 11) & 0x1f;
+ if (funp)
+ *funp = (tag >> 8) & 0x7;
+}
+
+pcireg_t
+socpcic_conf_read(void *cpv, pcitag_t tag, int offset)
+{
+ struct socpcic_softc *sc = cpv;
+ int bus, dev, fun;
+ pcireg_t addr, data;
+
+ socpcic_decompose_tag(sc, tag, &bus, &dev, &fun);
+ if (bus == 0) {
+ if (dev > 0 && dev < 11)
+ return (0xffffffff);
+ if (dev == 31)
+ tag = (10 << 11) | (fun << 8);
+ }
+
+ addr = 0x80000000 | tag | offset;
+ bus_space_write_4(sc->sc_iot, sc->sc_cfg_ioh, 0, addr);
+ bus_space_read_4(sc->sc_iot, sc->sc_cfg_ioh, 0);
+ data = bus_space_read_4(sc->sc_iot, sc->sc_cfg_ioh, 4);
+ bus_space_write_4(sc->sc_iot, sc->sc_cfg_ioh, 0, 0);
+ bus_space_read_4(sc->sc_iot, sc->sc_cfg_ioh, 0);
+
+ return (data);
+}
+
+void
+socpcic_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data)
+{
+ struct socpcic_softc *sc = cpv;
+ int bus, dev, fun;
+ pcireg_t addr;
+
+ socpcic_decompose_tag(sc, tag, &bus, &dev, &fun);
+ if (bus == 0) {
+ if (dev > 0 && dev < 11)
+ return;
+ if (dev == 31)
+ tag = (10 << 11) | (fun << 8);
+ }
+
+ addr = 0x80000000 | tag | offset;
+ bus_space_write_4(sc->sc_iot, sc->sc_cfg_ioh, 0, addr);
+ bus_space_read_4(sc->sc_iot, sc->sc_cfg_ioh, 0);
+ bus_space_write_4(sc->sc_iot, sc->sc_cfg_ioh, 4, data);
+ bus_space_write_4(sc->sc_iot, sc->sc_cfg_ioh, 0, 0);
+ bus_space_read_4(sc->sc_iot, sc->sc_cfg_ioh, 0);
+}
+
+int
+socpcic_intr_map(void *cpv, pcitag_t tag, int pin, int line,
+ pci_intr_handle_t *ihp)
+{
+ *ihp = 20; /* XXX */
+ return (0);
+}
+
+const char *
+socpcic_intr_string(void *cpv, pci_intr_handle_t ih)
+{
+ static char str[16];
+
+ snprintf(str, sizeof str, "ivec %ld", ih);
+ return (str);
+}
+
+int
+socpcic_intr_line(void *cpv, pci_intr_handle_t ih)
+{
+ return (ih);
+}
+
+void *
+socpcic_intr_establish(void *cpv, pci_intr_handle_t ih, int level,
+ int (*func)(void *), void *arg, char *name)
+{
+ return (intr_establish(ih, IST_LEVEL, level, func, arg, name));
+}
+
+void
+socpcic_intr_disestablish(void *lcv, void *cookie)
+{
+}
+
+int
+socpcic_ether_hw_addr(struct ppc_pci_chipset *lcpc, u_int8_t *oaddr)
+{
+ oaddr[0] = oaddr[1] = oaddr[2] = 0xff;
+ oaddr[3] = oaddr[4] = oaddr[5] = 0xff;
+
+ return (0);
+}
+
+int
+socpcic_print(void *aux, const char *pnp)
+{
+ struct pcibus_attach_args *pba = aux;
+
+ if (pnp)
+ printf("%s at %s", pba->pba_busname, pnp);
+ printf(" bus %d", pba->pba_bus);
+ return (UNCONF);
+}
diff --git a/sys/arch/socppc/include/_types.h b/sys/arch/socppc/include/_types.h
new file mode 100644
index 00000000000..f6f4ea673a5
--- /dev/null
+++ b/sys/arch/socppc/include/_types.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: _types.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/_types.h>
diff --git a/sys/arch/socppc/include/asm.h b/sys/arch/socppc/include/asm.h
new file mode 100644
index 00000000000..35852110f54
--- /dev/null
+++ b/sys/arch/socppc/include/asm.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: asm.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/asm.h>
diff --git a/sys/arch/socppc/include/atomic.h b/sys/arch/socppc/include/atomic.h
new file mode 100644
index 00000000000..1dbd296cee4
--- /dev/null
+++ b/sys/arch/socppc/include/atomic.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: atomic.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/atomic.h>
diff --git a/sys/arch/socppc/include/autoconf.h b/sys/arch/socppc/include/autoconf.h
new file mode 100644
index 00000000000..0f9ba3fc9e7
--- /dev/null
+++ b/sys/arch/socppc/include/autoconf.h
@@ -0,0 +1,45 @@
+/* $OpenBSD: autoconf.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_AUTOCONF_H_
+#define _MACHINE_AUTOCONF_H_
+
+#include <machine/bus.h>
+
+struct mainbus_attach_args {
+ bus_space_tag_t ma_iot;
+ char *ma_name;
+};
+
+struct obio_attach_args {
+ bus_space_tag_t oa_iot;
+ bus_addr_t oa_offset;
+ int oa_ivec;
+ char *oa_name;
+};
+
+#define cf_offset cf_loc[0]
+#define cf_ivec cf_loc[1]
+
+typedef int (time_read_t)(time_t *sec);
+typedef int (time_write_t)(time_t sec);
+
+extern time_read_t *time_read;
+extern time_write_t *time_write;
+
+#endif /* _MACHINE_AUTOCONF_H_ */
diff --git a/sys/arch/socppc/include/bat.h b/sys/arch/socppc/include/bat.h
new file mode 100644
index 00000000000..16a586e725d
--- /dev/null
+++ b/sys/arch/socppc/include/bat.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: bat.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/bat.h>
diff --git a/sys/arch/socppc/include/bus.h b/sys/arch/socppc/include/bus.h
new file mode 100644
index 00000000000..81696e1d3ec
--- /dev/null
+++ b/sys/arch/socppc/include/bus.h
@@ -0,0 +1,609 @@
+/* $OpenBSD: bus.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+/*
+ * Copyright (c) 1997 Per Fogelstrom. All rights reserved.
+ * Copyright (c) 1996 Niklas Hallqvist. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_BUS_H_
+#define _MACHINE_BUS_H_
+
+#include <machine/pio.h>
+
+#ifdef __STDC__
+#define CAT(a,b) a##b
+#define CAT3(a,b,c) a##b##c
+#else
+#define CAT(a,b) a/**/b
+#define CAT3(a,b,c) a/**/b/**/c
+#endif
+
+/*
+ * Bus access types.
+ */
+typedef u_long bus_addr_t;
+typedef u_int32_t bus_size_t;
+typedef u_int32_t bus_space_handle_t;
+typedef struct ppc_bus_space *bus_space_tag_t;
+
+struct ppc_bus_space {
+ u_int32_t bus_base;
+ u_int32_t bus_size;
+ u_int8_t bus_io; /* IO or memory */
+};
+#define POWERPC_BUS_TAG_BASE(x) ((x)->bus_base)
+
+extern struct ppc_bus_space ppc_isa_io, ppc_isa_mem;
+
+/*
+ * Access methods for bus resources
+ */
+int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
+ bus_size_t size, int cacheable, bus_space_handle_t *bshp);
+void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
+ bus_size_t size);
+int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
+ bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);
+int bus_space_alloc(bus_space_tag_t tag, bus_addr_t rstart,
+ bus_addr_t rend, bus_size_t size, bus_size_t alignment,
+ bus_size_t boundary, int cacheable, bus_addr_t *addrp,
+ bus_space_handle_t *handlep);
+void bus_space_free(bus_space_tag_t tag, bus_space_handle_t handle,
+ bus_size_t size);
+
+#define bus_space_read(n,m) \
+static __inline CAT3(u_int,m,_t) \
+CAT(bus_space_read_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \
+ bus_addr_t ba) \
+{ \
+ return CAT3(in,m,rb)((volatile CAT3(u_int,m,_t) *)(bsh + (ba))); \
+}
+
+bus_space_read(1,8)
+bus_space_read(2,16)
+bus_space_read(4,32)
+
+#define bus_space_read_8 !!! bus_space_read_8 unimplemented !!!
+
+#define bus_space_write(n,m) \
+static __inline void \
+CAT(bus_space_write_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \
+ bus_addr_t ba, CAT3(u_int,m,_t) x) \
+{ \
+ CAT3(out,m,rb)((volatile CAT3(u_int,m,_t) *)(bsh + (ba)), x); \
+}
+
+bus_space_write(1,8)
+bus_space_write(2,16)
+bus_space_write(4,32)
+
+#define bus_space_write_8 !!! bus_space_write_8 unimplemented !!!
+
+#define bus_space_read_multi(n, m) \
+static __inline void \
+CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \
+ bus_size_t ba, CAT3(u_int,m,_t) *buf, bus_size_t cnt) \
+{ \
+ while (cnt--) \
+ *buf++ = CAT(bus_space_read_,n)(bst, bsh, ba); \
+}
+
+bus_space_read_multi(1,8)
+bus_space_read_multi(2,16)
+bus_space_read_multi(4,32)
+
+#define bus_space_read_multi_8 !!! bus_space_read_multi_8 not implemented !!!
+
+
+#define bus_space_write_multi_8 !!! bus_space_write_multi_8 not implemented !!!
+
+#define bus_space_write_multi(n, m) \
+static __inline void \
+CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \
+ bus_size_t ba, const CAT3(u_int,m,_t) *buf, bus_size_t cnt) \
+{ \
+ while (cnt--) \
+ CAT(bus_space_write_,n)(bst, bsh, ba, *buf++); \
+}
+
+bus_space_write_multi(1,8)
+bus_space_write_multi(2,16)
+bus_space_write_multi(4,32)
+
+#define bus_space_write_multi_8 !!! bus_space_write_multi_8 not implemented !!!
+
+/*
+ * void bus_space_read_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * u_intN_t *addr, size_t count);
+ *
+ * Read `count' 1, 2, 4, or 8 byte quantities from bus space
+ * described by tag/handle and starting at `offset' and copy into
+ * buffer provided.
+ */
+#define __BA(t, h, o) ((void *)((h) + (o)))
+
+static __inline void
+bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t *addr, size_t count)
+{
+ volatile u_int8_t *s = __BA(tag, bsh, offset);
+
+ while (count--)
+ *addr++ = *s++;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t *addr, size_t count)
+{
+ volatile u_int16_t *s = __BA(tag, bsh, offset);
+
+ while (count--)
+ __asm __volatile("lhbrx %0, 0, %1" :
+ "=r"(*addr++) : "r"(s++));
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int32_t *addr, size_t count)
+{
+ volatile u_int32_t *s = __BA(tag, bsh, offset);
+
+ while (count--)
+ __asm __volatile("lwbrx %0, 0, %1" :
+ "=r"(*addr++) : "r"(s++));
+ __asm __volatile("eieio; sync");
+}
+
+#if 0 /* Cause a link error for bus_space_read_region_8 */
+#define bus_space_read_region_8 !!! unimplemented !!!
+#endif
+
+
+/*
+ * void bus_space_write_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * const u_intN_t *addr, size_t count);
+ *
+ * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
+ * to bus space described by tag/handle starting at `offset'.
+ */
+
+static __inline void
+bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, const u_int8_t *addr, size_t count)
+{
+ volatile u_int8_t *d = __BA(tag, bsh, offset);
+
+ while (count--)
+ *d++ = *addr++;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, const u_int16_t *addr, size_t count)
+{
+ volatile u_int16_t *d = __BA(tag, bsh, offset);
+
+ while (count--)
+ __asm __volatile("sthbrx %0, 0, %1" ::
+ "r"(*addr++), "r"(d++));
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, const u_int32_t *addr, size_t count)
+{
+ volatile u_int32_t *d = __BA(tag, bsh, offset);
+
+ while (count--)
+ __asm __volatile("stwbrx %0, 0, %1" ::
+ "r"(*addr++), "r"(d++));
+ __asm __volatile("eieio; sync");
+}
+
+#if 0
+#define bus_space_write_region_8 !!! bus_space_write_region_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_read_raw_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * u_intN_t *addr, size_t count);
+ *
+ * Read `count' bytes from bus space described by tag/handle and starting
+ * at `offset' and copy into buffer provided w/o bus-host byte swapping.
+ */
+
+static __inline void
+bus_space_read_raw_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t *addr, size_t count)
+{
+ volatile u_int16_t *s = __BA(tag, bsh, offset);
+ u_int16_t *laddr = (void *)addr;
+
+ count = count >> 1;
+
+ while (count--)
+ *laddr++ = *s++;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_read_raw_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t *addr, size_t count)
+{
+ volatile u_int32_t *s = __BA(tag, bsh, offset);
+ u_int32_t *laddr = (void *)addr;
+
+ count = count >> 2;
+
+ while (count--)
+ *laddr++ = *s++;
+ __asm __volatile("eieio; sync");
+}
+
+#if 0 /* Cause a link error for bus_space_read_raw_region_8 */
+#define bus_space_read_raw_region_8 \
+ !!! bus_space_read_raw_region_8 unimplemented !!!
+#endif
+
+
+/*
+ * void bus_space_write_raw_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * const u_intN_t *addr, size_t count);
+ *
+ * Write `count' bytes from the buffer provided to bus space described
+ * by tag/handle starting at `offset' w/o host-bus byte swapping.
+ */
+
+static __inline void
+bus_space_write_raw_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, const u_int8_t *addr, size_t count)
+{
+ volatile u_int16_t *d = __BA(tag, bsh, offset);
+ const u_int16_t *laddr = (void *)addr;
+
+ count = count >> 1;
+
+ while (count--)
+ *d++ = *laddr++;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_write_raw_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, const u_int8_t *addr, size_t count)
+{
+ volatile u_int32_t *d = __BA(tag, bsh, offset);
+ const u_int32_t *laddr = (void *)addr;
+
+ count = count >> 2;
+
+ while (count--)
+ *d++ = *laddr++;
+ __asm __volatile("eieio; sync");
+}
+
+#if 0
+#define bus_space_write_raw_region_8 \
+ !!! bus_space_write_raw_region_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_set_multi_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
+ * size_t count);
+ *
+ * Write the 1, 2, 4, or 8 byte value `val' to bus space described
+ * by tag/handle/offset `count' times.
+ */
+static __inline void bus_space_set_multi_1(bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, u_int8_t, size_t);
+static __inline void bus_space_set_multi_2(bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, u_int16_t, size_t);
+static __inline void bus_space_set_multi_4(bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, u_int32_t, size_t);
+
+static __inline void
+bus_space_set_multi_1(tag, bsh, offset, val, count)
+ bus_space_tag_t tag;
+ bus_space_handle_t bsh;
+ bus_size_t offset;
+ u_int8_t val;
+ size_t count;
+{
+ volatile u_int8_t *d = __BA(tag, bsh, offset);
+
+ while (count--)
+ *d = val;
+ __asm__ volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_set_multi_2(tag, bsh, offset, val, count)
+ bus_space_tag_t tag;
+ bus_space_handle_t bsh;
+ bus_size_t offset;
+ u_int16_t val;
+ size_t count;
+{
+ volatile u_int16_t *d = __BA(tag, bsh, offset);
+
+ while (count--)
+ __asm__ volatile("sthbrx %0, 0, %1" ::
+ "r"(val), "r"(d));
+ __asm__ volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_set_multi_4(tag, bsh, offset, val, count)
+ bus_space_tag_t tag;
+ bus_space_handle_t bsh;
+ bus_size_t offset;
+ u_int32_t val;
+ size_t count;
+{
+ volatile u_int32_t *d = __BA(tag, bsh, offset);
+
+ while (count--)
+ __asm__ volatile("stwbrx %0, 0, %1" ::
+ "r"(val), "r"(d));
+ __asm__ volatile("eieio; sync");
+}
+
+#define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
+
+/* These are OpenBSD extensions to the general NetBSD bus interface. */
+void
+bus_space_read_raw_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_addr_t ba, u_int8_t *dst, bus_size_t size);
+void
+bus_space_read_raw_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_addr_t ba, u_int8_t *dst, bus_size_t size);
+#define bus_space_read_raw_multi_8 \
+ !!! bus_space_read_raw_multi_8 not implemented !!!
+
+void
+bus_space_write_raw_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_addr_t ba, const u_int8_t *src, bus_size_t size);
+void
+bus_space_write_raw_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
+ bus_addr_t ba, const u_int8_t *src, bus_size_t size);
+#define bus_space_write_raw_multi_8 \
+ !!! bus_space_write_raw_multi_8 not implemented !!!
+
+void
+bus_space_set_region_1(bus_space_tag_t bst, bus_space_handle_t h, bus_size_t o,
+ u_int8_t val, bus_size_t c);
+void
+bus_space_set_region_2(bus_space_tag_t bst, bus_space_handle_t h, bus_size_t o,
+ u_int16_t val, bus_size_t c);
+void
+bus_space_set_region_4(bus_space_tag_t bst, bus_space_handle_t h, bus_size_t o,
+ u_int32_t val, bus_size_t c);
+#define bus_space_set_region_8 \
+ !!! bus_space_set_region_8 not implemented !!!
+
+void
+bus_space_copy_1(void *v, bus_space_handle_t h1, bus_space_handle_t h2,
+ bus_size_t o1, bus_size_t o2, bus_size_t c);
+void
+bus_space_copy_2(void *v, bus_space_handle_t h1, bus_space_handle_t h2,
+ bus_size_t o1, bus_size_t o2, bus_size_t c);
+void
+bus_space_copy_4(void *v, bus_space_handle_t h1, bus_space_handle_t h2,
+ bus_size_t o1, bus_size_t o2, bus_size_t c);
+#define bus_space_copy_8 \
+ !!! bus_space_write_raw_multi_8 not implemented !!!
+
+/*
+ * Bus read/write barrier methods.
+ *
+ * void bus_space_barrier(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * bus_size_t len, int flags);
+ *
+ * Note: powerpc does not currently implement barriers, but we must
+ * provide the flags to MI code.
+ * the processor does have eieio which is effectively the barrier
+ * operator, however due to how memory is mapped this should? not
+ * be required.
+ */
+#define bus_space_barrier(t, h, o, l, f) \
+ ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
+#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */
+#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */
+/* Compatibility defines */
+#define BUS_BARRIER_READ BUS_SPACE_BARRIER_READ
+#define BUS_BARRIER_WRITE BUS_SPACE_BARRIER_WRITE
+
+
+#define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */
+#define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */
+#define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */
+#define BUS_DMAMEM_NOSYNC 0x004
+#define BUS_DMA_COHERENT 0x008 /* hint: map memory DMA coherent */
+#define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */
+#define BUS_DMA_BUS2 0x020
+#define BUS_DMA_BUS3 0x040
+#define BUS_DMA_BUS4 0x080
+#define BUS_DMA_READ 0x100 /* mapping is device -> memory only */
+#define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */
+#define BUS_DMA_STREAMING 0x400 /* hint: sequential, unidirectional */
+
+
+/* Forwards needed by prototypes below. */
+struct mbuf;
+struct proc;
+struct uio;
+
+#define BUS_DMASYNC_POSTREAD 0x01
+#define BUS_DMASYNC_POSTWRITE 0x02
+#define BUS_DMASYNC_PREREAD 0x04
+#define BUS_DMASYNC_PREWRITE 0x08
+
+typedef struct powerpc_bus_dma_tag *bus_dma_tag_t;
+typedef struct powerpc_bus_dmamap *bus_dmamap_t;
+
+/*
+ * bus_dma_segment_t
+ *
+ * Describes a single contiguous DMA transaction. Values
+ * are suitable for programming into DMA registers.
+ */
+struct powerpc_bus_dma_segment {
+ bus_addr_t ds_addr; /* DMA address */
+ bus_size_t ds_len; /* length of transfer */
+};
+typedef struct powerpc_bus_dma_segment bus_dma_segment_t;
+
+/*
+ * bus_dma_tag_t
+ *
+ * A machine-dependent opaque type describing the implementation of
+ * DMA for a given bus.
+ */
+
+struct powerpc_bus_dma_tag {
+ void *_cookie; /* cookie used in the guts */
+
+ /*
+ * DMA mapping methods.
+ */
+ int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int,
+ bus_size_t, bus_size_t, int, bus_dmamap_t *);
+ void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t);
+ int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int);
+ int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t,
+ struct mbuf *, int);
+ int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t,
+ struct uio *, int);
+ int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t,
+ bus_dma_segment_t *, int, bus_size_t, int);
+ void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t);
+ void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t,
+ bus_addr_t, bus_size_t, int);
+
+ /*
+ * DMA memory utility functions.
+ */
+ int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
+ bus_size_t, bus_dma_segment_t *, int, int *, int);
+ void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int);
+ int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
+ int, size_t, caddr_t *, int);
+ void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t);
+ paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
+ int, off_t, int, int);
+};
+
+#define bus_dmamap_create(t, s, n, m, b, f, p) \
+ (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
+#define bus_dmamap_destroy(t, p) \
+ (*(t)->_dmamap_destroy)((t), (p))
+#define bus_dmamap_load(t, m, b, s, p, f) \
+ (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
+#define bus_dmamap_load_mbuf(t, m, b, f) \
+ (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
+#define bus_dmamap_load_uio(t, m, u, f) \
+ (*(t)->_dmamap_load_uio)((t), (m), (u), (f))
+#define bus_dmamap_load_raw(t, m, sg, n, s, f) \
+ (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
+#define bus_dmamap_unload(t, p) \
+ (*(t)->_dmamap_unload)((t), (p))
+#define bus_dmamap_sync(t, p, a, l, o) \
+ (void)((t)->_dmamap_sync ? \
+ (*(t)->_dmamap_sync)((t), (p), (a), (l), (o)) : (void)0)
+
+#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \
+ (*(t)->_dmamem_alloc)((t)->_cookie, (s), (a), (b), (sg), (n), (r), (f))
+#define bus_dmamem_free(t, sg, n) \
+ (*(t)->_dmamem_free)((t)->_cookie, (sg), (n))
+#define bus_dmamem_map(t, sg, n, s, k, f) \
+ (*(t)->_dmamem_map)((t)->_cookie, (sg), (n), (s), (k), (f))
+#define bus_dmamem_unmap(t, k, s) \
+ (*(t)->_dmamem_unmap)((t)->_cookie, (k), (s))
+#define bus_dmamem_mmap(t, sg, n, o, p, f) \
+ (*(t)->_dmamem_mmap)((t)->_cookie, (sg), (n), (o), (p), (f))
+
+int _dmamap_create(bus_dma_tag_t, bus_size_t, int,
+ bus_size_t, bus_size_t, int, bus_dmamap_t *);
+void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
+int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int);
+int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int);
+int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int);
+int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
+ bus_dma_segment_t *, int, bus_size_t, int);
+void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
+void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, bus_size_t,
+ int);
+
+int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t,
+ bus_size_t, bus_dma_segment_t *, int, int *, int);
+void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int);
+int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *,
+ int, size_t, caddr_t *, int);
+void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t);
+paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int);
+
+/*
+ * bus_dmamap_t
+ *
+ * Describes a DMA mapping.
+ */
+struct powerpc_bus_dmamap {
+ /*
+ * PRIVATE MEMBERS: not for use by machine-independent code.
+ */
+ bus_size_t _dm_size; /* largest DMA transfer mappable */
+ int _dm_segcnt; /* number of segs this map can map */
+ bus_size_t _dm_maxsegsz; /* largest possible segment */
+ bus_size_t _dm_boundary; /* don't cross this */
+ int _dm_flags; /* misc. flags */
+
+ void *_dm_cookie; /* cookie for bus-specific functions */
+
+ /*
+ * PUBLIC MEMBERS: these are used by machine-independent code.
+ */
+ bus_size_t dm_mapsize; /* size of the mapping */
+ int dm_nsegs; /* # valid segments in mapping */
+ bus_dma_segment_t dm_segs[1]; /* segments; variable length */
+};
+
+#endif /* _MACHINE_BUS_H_ */
diff --git a/sys/arch/socppc/include/cdefs.h b/sys/arch/socppc/include/cdefs.h
new file mode 100644
index 00000000000..8362c75969c
--- /dev/null
+++ b/sys/arch/socppc/include/cdefs.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: cdefs.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/cdefs.h>
diff --git a/sys/arch/socppc/include/conf.h b/sys/arch/socppc/include/conf.h
new file mode 100644
index 00000000000..2797e30ad4c
--- /dev/null
+++ b/sys/arch/socppc/include/conf.h
@@ -0,0 +1,37 @@
+/* $OpenBSD: conf.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */
+
+/*
+ * Copyright (c) 1996 Christos Zoulas. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/conf.h>
+
+#define mmread mmrw
+#define mmwrite mmrw
+cdev_decl(mm);
diff --git a/sys/arch/socppc/include/cpu.h b/sys/arch/socppc/include/cpu.h
new file mode 100644
index 00000000000..9e21d0c6084
--- /dev/null
+++ b/sys/arch/socppc/include/cpu.h
@@ -0,0 +1,53 @@
+/* $OpenBSD: cpu.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+/* $NetBSD: cpu.h,v 1.1 1996/09/30 16:34:21 ws Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_CPU_H_
+#define _MACHINE_CPU_H_
+
+#include <powerpc/cpu.h>
+
+/*
+ * CTL_MACHDEP definitions.
+ */
+#define CPU_ALLOWAPERTURE 1 /* allow mmap of /dev/xf86 */
+#define CPU_ALTIVEC 2 /* altivec is present */
+#define CPU_MAXID 3 /* number of valid machdep ids */
+
+#define CTL_MACHDEP_NAMES { \
+ { 0, 0 }, \
+ { "allowaperture", CTLTYPE_INT }, \
+ { "altivec", CTLTYPE_INT }, \
+}
+
+#endif /* _MACHINE_CPU_H_ */
diff --git a/sys/arch/socppc/include/db_machdep.h b/sys/arch/socppc/include/db_machdep.h
new file mode 100644
index 00000000000..df6783f5cc6
--- /dev/null
+++ b/sys/arch/socppc/include/db_machdep.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: db_machdep.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/db_machdep.h>
diff --git a/sys/arch/socppc/include/disklabel.h b/sys/arch/socppc/include/disklabel.h
new file mode 100644
index 00000000000..1bf6635ae0f
--- /dev/null
+++ b/sys/arch/socppc/include/disklabel.h
@@ -0,0 +1,90 @@
+/* $OpenBSD: disklabel.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+/*
+ * Copyright (c) 1994 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_DISKLABEL_H_
+#define _MACHINE_DISKLABEL_H_
+
+#define LABELSECTOR 1 /* sector containing label */
+#define LABELOFFSET 0 /* offset of label in sector */
+#define MAXPARTITIONS 16 /* number of partitions */
+
+/* HFS/DPME */
+
+/* partition map structure from Inside Macintosh: Devices, SCSI Manager
+ * pp. 13-14. The partition map always begins on physical block 1.
+ *
+ * With the exception of block 0, all blocks on the disk must belong to
+ * exactly one partition. The partition map itself belongs to a partition
+ * of type `APPLE_PARTITION_MAP', and is not limited in size by anything
+ * other than available disk space. The partition map is not necessarily
+ * the first partition listed.
+ */
+struct part_map_entry {
+#define PART_ENTRY_MAGIC 0x504d
+ u_int16_t pmSig; /* partition signature */
+ u_int16_t pmSigPad; /* (reserved) */
+ u_int32_t pmMapBlkCnt; /* number of blocks in partition map */
+ u_int32_t pmPyPartStart; /* first physical block of partition */
+ u_int32_t pmPartBlkCnt; /* number of blocks in partition */
+ char pmPartName[32]; /* partition name */
+ char pmPartType[32]; /* partition type */
+ u_int32_t pmLgDataStart; /* first logical block of data area */
+ u_int32_t pmDataCnt; /* number of blocks in data area */
+ u_int32_t pmPartStatus; /* partition status information */
+ u_int32_t pmLgBootStart; /* first logical block of boot code */
+ u_int32_t pmBootSize; /* size of boot code, in bytes */
+ u_int32_t pmBootLoad; /* boot code load address */
+ u_int32_t pmBootLoad2; /* (reserved) */
+ u_int32_t pmBootEntry; /* boot code entry point */
+ u_int32_t pmBootEntry2; /* (reserved) */
+ u_int32_t pmBootCksum; /* boot code checksum */
+ char pmProcessor[16]; /* processor type (e.g. "68020") */
+ u_int8_t pmBootArgs[128]; /* A/UX boot arguments */
+ /* we do not index the disk image as an array,
+ * leave out the on disk padding
+ */
+#if 0
+ u_int8_t pad[248]; /* pad to end of block */
+#endif
+};
+
+#define PART_TYPE_DRIVER "APPLE_DRIVER"
+#define PART_TYPE_DRIVER43 "APPLE_DRIVER43"
+#define PART_TYPE_DRIVERATA "APPLE_DRIVER_ATA"
+#define PART_TYPE_DRIVERIOKIT "APPLE_DRIVER_IOKIT"
+#define PART_TYPE_FWDRIVER "APPLE_FWDRIVER"
+#define PART_TYPE_FWB_COMPONENT "FWB DRIVER COMPONENTS"
+#define PART_TYPE_FREE "APPLE_FREE"
+#define PART_TYPE_MAC "APPLE_HFS"
+#define PART_TYPE_OPENBSD "OPENBSD"
+
+#endif /* _MACHINE_DISKLABEL_H_ */
diff --git a/sys/arch/socppc/include/endian.h b/sys/arch/socppc/include/endian.h
new file mode 100644
index 00000000000..1a72bba14a8
--- /dev/null
+++ b/sys/arch/socppc/include/endian.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: endian.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/endian.h>
diff --git a/sys/arch/socppc/include/exec.h b/sys/arch/socppc/include/exec.h
new file mode 100644
index 00000000000..01c0c5722a1
--- /dev/null
+++ b/sys/arch/socppc/include/exec.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: exec.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/exec.h>
diff --git a/sys/arch/socppc/include/fpu.h b/sys/arch/socppc/include/fpu.h
new file mode 100644
index 00000000000..83e3b628f83
--- /dev/null
+++ b/sys/arch/socppc/include/fpu.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: fpu.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/fpu.h>
diff --git a/sys/arch/socppc/include/frame.h b/sys/arch/socppc/include/frame.h
new file mode 100644
index 00000000000..ba860b82dd9
--- /dev/null
+++ b/sys/arch/socppc/include/frame.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: frame.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/frame.h>
diff --git a/sys/arch/socppc/include/internal_types.h b/sys/arch/socppc/include/internal_types.h
new file mode 100644
index 00000000000..4eb1ac1cfe1
--- /dev/null
+++ b/sys/arch/socppc/include/internal_types.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: internal_types.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/internal_types.h>
diff --git a/sys/arch/socppc/include/intr.h b/sys/arch/socppc/include/intr.h
new file mode 100644
index 00000000000..f79a4c6d006
--- /dev/null
+++ b/sys/arch/socppc/include/intr.h
@@ -0,0 +1,11 @@
+/* $OpenBSD: intr.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/intr.h>
+
+#ifndef _LOCORE
+
+void softtty(void);
+
+void *intr_establish(int, int, int, int (*)(void *), void *, const char *);
+
+#endif
diff --git a/sys/arch/socppc/include/limits.h b/sys/arch/socppc/include/limits.h
new file mode 100644
index 00000000000..d6468bd2aa1
--- /dev/null
+++ b/sys/arch/socppc/include/limits.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: limits.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/limits.h>
diff --git a/sys/arch/socppc/include/lock.h b/sys/arch/socppc/include/lock.h
new file mode 100644
index 00000000000..0ec5a702b00
--- /dev/null
+++ b/sys/arch/socppc/include/lock.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: lock.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/lock.h>
diff --git a/sys/arch/socppc/include/mutex.h b/sys/arch/socppc/include/mutex.h
new file mode 100644
index 00000000000..6564781e0c5
--- /dev/null
+++ b/sys/arch/socppc/include/mutex.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: mutex.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/mutex.h>
diff --git a/sys/arch/socppc/include/param.h b/sys/arch/socppc/include/param.h
new file mode 100644
index 00000000000..161ce9f6e9c
--- /dev/null
+++ b/sys/arch/socppc/include/param.h
@@ -0,0 +1,51 @@
+/* $OpenBSD: param.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+/* $NetBSD: param.h,v 1.1 1996/09/30 16:34:28 ws Exp $ */
+
+/*-
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef _KERNEL
+#ifndef _LOCORE
+#include <machine/cpu.h>
+#endif /* _LOCORE */
+#endif
+
+#include <powerpc/param.h>
+
+/*
+ * Machine dependent constants for socppc
+ */
+#define MACHINE "socppc"
+#define _MACHINE socppc
+
+#define KERNBASE 0x200000
+
+#define MSGBUFSIZE (NBPG*2)
diff --git a/sys/arch/socppc/include/pcb.h b/sys/arch/socppc/include/pcb.h
new file mode 100644
index 00000000000..0fde40255c1
--- /dev/null
+++ b/sys/arch/socppc/include/pcb.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: pcb.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/pcb.h>
diff --git a/sys/arch/socppc/include/pio.h b/sys/arch/socppc/include/pio.h
new file mode 100644
index 00000000000..6be1eecbd9c
--- /dev/null
+++ b/sys/arch/socppc/include/pio.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: pio.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/pio.h>
diff --git a/sys/arch/socppc/include/pmap.h b/sys/arch/socppc/include/pmap.h
new file mode 100644
index 00000000000..b310d018415
--- /dev/null
+++ b/sys/arch/socppc/include/pmap.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: pmap.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/pmap.h>
diff --git a/sys/arch/socppc/include/powerpc.h b/sys/arch/socppc/include/powerpc.h
new file mode 100644
index 00000000000..378d9259b93
--- /dev/null
+++ b/sys/arch/socppc/include/powerpc.h
@@ -0,0 +1,94 @@
+/* $OpenBSD: powerpc.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+/* $NetBSD: powerpc.h,v 1.1 1996/09/30 16:34:30 ws Exp $ */
+
+/*
+ * Copyright (C) 1996 Wolfgang Solfrank.
+ * Copyright (C) 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_POWERPC_H_
+#define _MACHINE_POWERPC_H_
+
+struct mem_region {
+ vaddr_t start;
+ vsize_t size;
+};
+
+void mem_regions(struct mem_region **, struct mem_region **);
+
+/*
+ * These two functions get used solely in boot() in machdep.c.
+ *
+ * Not sure whether boot itself should be implementation dependent instead. XXX
+ */
+typedef void (exit_f)(void) /*__attribute__((__noreturn__))*/ ;
+typedef void (boot_f)(char *bootspec) /* __attribute__((__noreturn__))*/ ;
+typedef void (vmon_f)(void);
+
+/* firmware interface.
+ * regardless of type of firmware used several items
+ * are need from firmware to boot up.
+ * these include:
+ * memory information
+ * vmsetup for firmware calls.
+ * default character print mechanism ???
+ * firmware exit (return)
+ * firmware boot (reset)
+ * vmon - tell firmware the bsd vm is active.
+ */
+
+typedef void (mem_regions_f)(struct mem_region **memp,
+ struct mem_region **availp);
+
+struct firmware {
+ mem_regions_f *mem_regions;
+ exit_f *exit;
+ boot_f *boot;
+ vmon_f *vmon;
+
+#ifdef FW_HAS_PUTC
+ boot_f *putc;
+#endif
+};
+extern struct firmware *fw;
+int ppc_open_pci_bridge(void);
+void ppc_close_pci_bridge(int);
+void install_extint(void (*handler) (void));
+void ppc_intr_enable(int enable);
+int ppc_intr_disable(void);
+
+struct dumpmem {
+ vaddr_t start;
+ vsize_t end;
+};
+extern struct dumpmem dumpmem[VM_PHYSSEG_MAX];
+extern u_int ndumpmem;
+extern vaddr_t dumpspace;
+
+#endif /* _MACHINE_POWERPC_H_ */
diff --git a/sys/arch/socppc/include/proc.h b/sys/arch/socppc/include/proc.h
new file mode 100644
index 00000000000..1b78bbf4d75
--- /dev/null
+++ b/sys/arch/socppc/include/proc.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: proc.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/proc.h>
diff --git a/sys/arch/socppc/include/psl.h b/sys/arch/socppc/include/psl.h
new file mode 100644
index 00000000000..2efac1c8750
--- /dev/null
+++ b/sys/arch/socppc/include/psl.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: psl.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/psl.h>
diff --git a/sys/arch/socppc/include/pte.h b/sys/arch/socppc/include/pte.h
new file mode 100644
index 00000000000..cca262bf6e7
--- /dev/null
+++ b/sys/arch/socppc/include/pte.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: pte.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/pte.h>
diff --git a/sys/arch/socppc/include/ptrace.h b/sys/arch/socppc/include/ptrace.h
new file mode 100644
index 00000000000..1c82569d472
--- /dev/null
+++ b/sys/arch/socppc/include/ptrace.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: ptrace.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/ptrace.h>
diff --git a/sys/arch/socppc/include/reg.h b/sys/arch/socppc/include/reg.h
new file mode 100644
index 00000000000..26ed5eaa4e2
--- /dev/null
+++ b/sys/arch/socppc/include/reg.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: reg.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/reg.h>
diff --git a/sys/arch/socppc/include/signal.h b/sys/arch/socppc/include/signal.h
new file mode 100644
index 00000000000..7ab86d1b3fe
--- /dev/null
+++ b/sys/arch/socppc/include/signal.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: signal.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/signal.h>
diff --git a/sys/arch/socppc/include/spinlock.h b/sys/arch/socppc/include/spinlock.h
new file mode 100644
index 00000000000..22bbf5008eb
--- /dev/null
+++ b/sys/arch/socppc/include/spinlock.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: spinlock.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/spinlock.h>
diff --git a/sys/arch/socppc/include/trap.h b/sys/arch/socppc/include/trap.h
new file mode 100644
index 00000000000..80a0f96d872
--- /dev/null
+++ b/sys/arch/socppc/include/trap.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: trap.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+#include <powerpc/trap.h>
diff --git a/sys/arch/socppc/include/vmparam.h b/sys/arch/socppc/include/vmparam.h
new file mode 100644
index 00000000000..0cdd4986416
--- /dev/null
+++ b/sys/arch/socppc/include/vmparam.h
@@ -0,0 +1,114 @@
+/* $OpenBSD: vmparam.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+/* $NetBSD: vmparam.h,v 1.1 1996/09/30 16:34:38 ws Exp $ */
+
+/*-
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MACHINE_VMPARAM_H
+#define MACHINE_VMPARAM_H
+
+#define USRTEXT PAGE_SIZE
+#define USRSTACK VM_MAXUSER_ADDRESS
+
+#ifndef MAXTSIZ
+#define MAXTSIZ (64*1024*1024) /* max text size */
+#endif
+
+#ifndef DFLDSIZ
+#define DFLDSIZ (64*1024*1024) /* default data size */
+#endif
+
+#ifndef MAXDSIZ
+#define MAXDSIZ (512*1024*1024) /* max data size */
+#endif
+
+#ifndef DFLSSIZ
+#define DFLSSIZ (1*1024*1024) /* default stack size */
+#endif
+
+#ifndef MAXSSIZ
+#define MAXSSIZ (32*1024*1024) /* max stack size */
+#endif
+
+#define STACKGAP_RANDOM 256*1024
+
+/*
+ * Size of shared memory map
+ */
+#ifndef SHMMAXPGS
+#define SHMMAXPGS 8192 /* 32mb */
+#endif
+
+/*
+ * Size of User Raw I/O map
+ */
+#define USRIOSIZE 1024
+
+/*
+ * Would like to have MAX addresses = 0, but this doesn't (currently) work
+ */
+#define VM_MIN_ADDRESS ((vaddr_t)0)
+#define VM_MAXUSER_ADDRESS ((vaddr_t)0xfffff000)
+#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS
+#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)(PPC_KERNEL_SR << ADDR_SR_SHIFT))
+
+/* ppc_kvm_stolen is so that vm space can be stolen before vm is fully
+ * initialized.
+ */
+extern vaddr_t ppc_kvm_stolen;
+#define VM_KERN_ADDRESS_SIZE (PPC_SEGMENT_LENGTH - (32 * 1024 * 1024))
+#define VM_MAX_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + VM_KERN_ADDRESS_SIZE)
+
+#define VM_PHYS_SIZE (USRIOSIZE * PAGE_SIZE)
+
+#define VM_PHYSSEG_MAX 32 /* actually we could have this many segments */
+#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH
+#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */
+
+#define VM_NFREELIST 1
+#define VM_FREELIST_DEFAULT 0
+
+#ifdef _KERNEL
+
+#define __HAVE_VM_PAGE_MD
+struct pv_entry;
+struct vm_page_md {
+ LIST_HEAD(,pte_desc) pv_list;
+};
+
+#define VM_MDPAGE_INIT(pg) do { \
+ LIST_INIT(&((pg)->mdpage.pv_list)); \
+} while (0)
+
+#endif
+
+
+#endif
diff --git a/sys/arch/socppc/socppc/autoconf.c b/sys/arch/socppc/socppc/autoconf.c
new file mode 100644
index 00000000000..90da6d18b0c
--- /dev/null
+++ b/sys/arch/socppc/socppc/autoconf.c
@@ -0,0 +1,69 @@
+/* $OpenBSD: autoconf.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/powerpc.h>
+
+void dumpconf(void);
+
+int cold = 1;
+
+struct dumpmem dumpmem[VM_PHYSSEG_MAX];
+u_int ndumpmem;
+
+void
+cpu_configure(void)
+{
+ splhigh();
+
+ if (config_rootfound("mainbus", "mainbus") == 0)
+ panic("no mainbus found");
+
+ /* Configuration is finished, turn on interrupts. */
+ spl0();
+ cold = 0;
+}
+
+void
+device_register(struct device *dev, void *aux)
+{
+}
+
+void
+diskconf(void)
+{
+ struct device *dv;
+ dev_t tmpdev;
+
+ dv = parsedisk("wd0a", strlen("wd0a"), 0, &tmpdev);
+ setroot(dv, 0, RB_USERREQ);
+ dumpconf();
+}
+
+struct nam2blk nam2blk[] = {
+ { "wd", 0 },
+ { "sd", 2 },
+ { "rd", 17 },
+ { "raid", 19 },
+ { NULL, -1 }
+};
diff --git a/sys/arch/socppc/socppc/clock.c b/sys/arch/socppc/socppc/clock.c
new file mode 100644
index 00000000000..bb2bcb814a8
--- /dev/null
+++ b/sys/arch/socppc/socppc/clock.c
@@ -0,0 +1,342 @@
+/* $OpenBSD: clock.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+/* $NetBSD: clock.c,v 1.1 1996/09/30 16:34:40 ws Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/timetc.h>
+
+#include <machine/autoconf.h>
+
+#include <dev/clock_subr.h>
+
+void decr_intr(struct clockframe *frame);
+u_int tb_get_timecount(struct timecounter *);
+
+/*
+ * Initially we assume a processor with a bus frequency of 266 MHz.
+ */
+static u_int32_t ticks_per_sec = 66666666;
+static u_int32_t ns_per_tick = 15;
+static int32_t ticks_per_intr;
+
+static struct timecounter tb_timecounter = {
+ tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL
+};
+
+/* Global TOD clock handle. */
+todr_chip_handle_t todr_handle;
+
+/* vars for stats */
+int statint;
+u_int32_t statvar;
+u_int32_t statmin;
+
+static struct evcount clk_count;
+static struct evcount stat_count;
+static int clk_irq = PPC_CLK_IRQ;
+static int stat_irq = PPC_STAT_IRQ;
+
+/*
+ * Set up the system's time, given a `reasonable' time value.
+ */
+void
+inittodr(time_t base)
+{
+ int badbase = 0, waszero = base == 0;
+ char *bad = NULL;
+ struct timeval tv;
+ struct timespec ts;
+
+ if (base < 5 * SECYR) {
+ /*
+ * If base is 0, assume filesystem time is just unknown
+ * instead of preposterous. Don't bark.
+ */
+ if (base != 0)
+ printf("WARNING: preposterous time in file system\n");
+ /* not going to use it anyway, if the chip is readable */
+ base = 21*SECYR + 186*SECDAY + SECDAY/2;
+ badbase = 1;
+ }
+
+ if (todr_handle != NULL && todr_gettime(todr_handle, &tv) != 0)
+ tv.tv_sec = tv.tv_usec = 0;
+
+ if (tv.tv_sec == 0) {
+ /*
+ * Believe the time in the file system for lack of
+ * anything better, resetting the clock.
+ */
+ bad = "WARNING: unable to get date/time";
+ tv.tv_sec = base;
+ tv.tv_usec = 0;
+ if (!badbase)
+ resettodr();
+ } else {
+ int deltat;
+
+ tv.tv_sec += tz.tz_minuteswest * 60;
+ if (tz.tz_dsttime)
+ tv.tv_sec -= 3600;
+
+ deltat = tv.tv_sec - base;
+
+ if (deltat < 0)
+ deltat = -deltat;
+ if (!(waszero || deltat < 2 * SECDAY)) {
+ printf("WARNING: clock %s %d days",
+ tv.tv_sec < base ? "lost" : "gained", deltat / SECDAY);
+ bad = "";
+
+ if (tv.tv_sec < base && deltat > 1000 * SECDAY) {
+ printf(", using FS time");
+ tv.tv_sec = base;
+ }
+ }
+ }
+
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+ tc_setclock(&ts);
+
+ if (bad) {
+ printf("%s", bad);
+ printf(" -- CHECK AND RESET THE DATE!\n");
+ }
+}
+
+/*
+ * Similar to the above
+ */
+void
+resettodr(void)
+{
+ struct timeval tv;
+
+ if (time_second == 0)
+ return;
+
+ microtime(&tv);
+
+ if (todr_handle == NULL || todr_settime(todr_handle, &tv) != 0)
+ printf("Cannot set time in time-of-day clock\n");
+}
+
+void
+decr_intr(struct clockframe *frame)
+{
+ u_int64_t tb;
+ u_int64_t nextevent;
+ struct cpu_info *ci = curcpu();
+ int nstats;
+ int s;
+
+ /*
+ * Check whether we are initialized.
+ */
+ if (!ticks_per_intr)
+ return;
+
+ /*
+ * Based on the actual time delay since the last decrementer reload,
+ * we arrange for earlier interrupt next time.
+ */
+
+ tb = ppc_mftb();
+ while (ci->ci_nexttimerevent <= tb)
+ ci->ci_nexttimerevent += ticks_per_intr;
+
+ ci->ci_prevtb = ci->ci_nexttimerevent - ticks_per_intr;
+
+ for (nstats = 0; ci->ci_nextstatevent <= tb; nstats++) {
+ int r;
+ do {
+ r = random() & (statvar -1);
+ } while (r == 0); /* random == 0 not allowed */
+ ci->ci_nextstatevent += statmin + r;
+ }
+
+ /* only count timer ticks for CLK_IRQ */
+ stat_count.ec_count += nstats;
+
+ if (ci->ci_nexttimerevent < ci->ci_nextstatevent)
+ nextevent = ci->ci_nexttimerevent;
+ else
+ nextevent = ci->ci_nextstatevent;
+
+ /*
+ * Need to work about the near constant skew this introduces???
+ * reloading tb here could cause a missed tick.
+ */
+ ppc_mtdec(nextevent - tb);
+
+ if (curcpu()->ci_cpl & SPL_CLOCK) {
+ ci->ci_statspending += nstats;
+ } else {
+ KERNEL_LOCK();
+
+ nstats += ci->ci_statspending;
+ ci->ci_statspending = 0;
+
+ s = splclock();
+
+ /*
+ * Reenable interrupts
+ */
+ ppc_intr_enable(1);
+
+ /*
+ * Do standard timer interrupt stuff.
+ */
+ while (ci->ci_lasttb < ci->ci_prevtb) {
+ /* sync lasttb with hardclock */
+ ci->ci_lasttb += ticks_per_intr;
+ clk_count.ec_count++;
+ hardclock(frame);
+ }
+
+ while (nstats-- > 0)
+ statclock(frame);
+
+ splx(s);
+ (void) ppc_intr_disable();
+
+ /* if a tick has occurred while dealing with these,
+ * dont service it now, delay until the next tick.
+ */
+ KERNEL_UNLOCK();
+ }
+}
+
+void cpu_startclock(void);
+
+void
+cpu_initclocks(void)
+{
+ int intrstate;
+ int minint;
+
+ intrstate = ppc_intr_disable();
+
+ stathz = 100;
+ profhz = 1000; /* must be a multiple of stathz */
+
+ /* init secondary clock to stathz */
+ statint = ticks_per_sec / stathz;
+ statvar = 0x40000000; /* really big power of two */
+ /* find largest 2^n which is nearly smaller than statint/2 */
+ minint = statint / 2 + 100;
+ while (statvar > minint)
+ statvar >>= 1;
+ statmin = statint - (statvar >> 1);
+
+ evcount_attach(&clk_count, "clock", (void *)&clk_irq, &evcount_intr);
+ evcount_attach(&stat_count, "stat", (void *)&stat_irq, &evcount_intr);
+
+ ticks_per_intr = ticks_per_sec / hz;
+ cpu_startclock();
+
+ tb_timecounter.tc_frequency = ticks_per_sec;
+ tc_init(&tb_timecounter);
+ ppc_intr_enable(intrstate);
+}
+
+void
+cpu_startclock()
+{
+ struct cpu_info *ci = curcpu();
+ u_int64_t nextevent;
+
+ ci->ci_lasttb = ppc_mftb();
+
+ /*
+ * no point in having random on the first tick,
+ * it just complicates the code.
+ */
+ ci->ci_nexttimerevent = ci->ci_lasttb + ticks_per_intr;
+ nextevent = ci->ci_nextstatevent = ci->ci_nexttimerevent;
+
+ ci->ci_statspending = 0;
+
+ ppc_mtdec(nextevent - ci->ci_lasttb);
+}
+
+void
+delay(unsigned n)
+{
+ u_int64_t tb;
+ u_int32_t tbh, tbl, scratch;
+
+ tb = ppc_mftb();
+ tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick;
+ tbh = tb >> 32;
+ tbl = (u_int32_t)tb;
+ asm ("1: mftbu %0; cmplw %0,%1; blt 1b; bgt 2f;"
+ " mftb %0; cmplw %0,%2; blt 1b; 2:"
+ :: "r"(scratch), "r"(tbh), "r"(tbl));
+}
+
+/*
+ * Nothing to do.
+ */
+void
+setstatclockrate(int newhz)
+{
+ int minint;
+ int intrstate;
+
+ intrstate = ppc_intr_disable();
+
+ statint = ticks_per_sec / newhz;
+ statvar = 0x40000000; /* really big power of two */
+ /* find largest 2^n which is nearly smaller than statint/2 */
+ minint = statint / 2 + 100;
+ while (statvar > minint)
+ statvar >>= 1;
+
+ statmin = statint - (statvar >> 1);
+ ppc_intr_enable(intrstate);
+
+ /*
+ * XXX this allows the next stat timer to occur then it switches
+ * to the new frequency. Rather than switching instantly.
+ */
+}
+
+u_int
+tb_get_timecount(struct timecounter *tc)
+{
+ return ppc_mftbl();
+}
diff --git a/sys/arch/socppc/socppc/conf.c b/sys/arch/socppc/socppc/conf.c
new file mode 100644
index 00000000000..db8ce25396c
--- /dev/null
+++ b/sys/arch/socppc/socppc/conf.c
@@ -0,0 +1,287 @@
+/* $OpenBSD: conf.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+/*
+ * Copyright (c) 1997 Per Fogelstrom
+ * Copyright (c) 1997 RTMX Inc, North Carolina
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed under OpenBSD for RTMX Inc,
+ * North Carolina, USA, by Per Fogelstrom, Opsycon AB, Sweden.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/tty.h>
+
+#include <machine/conf.h>
+
+#include "sd.h"
+#include "cd.h"
+#include "rd.h"
+#include "wd.h"
+bdev_decl(wd);
+cdev_decl(wd);
+
+#include "vnd.h"
+
+struct bdevsw bdevsw[] = {
+ bdev_disk_init(NWD,wd), /* 0: ST506/ESDI/IDE disk */
+ bdev_swap_init(1,sw), /* 1 swap pseudo device */
+ bdev_disk_init(NSD,sd), /* 2 SCSI Disk */
+ bdev_disk_init(NCD,cd), /* 3 SCSI CD-ROM */
+ bdev_notdef(), /* 4 unknown*/
+ bdev_notdef(), /* 5 unknown*/
+ bdev_notdef(), /* 6 unknown*/
+ bdev_notdef(), /* 7 unknown*/
+ bdev_lkm_dummy(), /* 8 */
+ bdev_lkm_dummy(), /* 9 */
+ bdev_lkm_dummy(), /* 10 */
+ bdev_lkm_dummy(), /* 11 */
+ bdev_lkm_dummy(), /* 12 */
+ bdev_lkm_dummy(), /* 13 */
+ bdev_disk_init(NVND,vnd), /* 14 vnode disk driver*/
+ bdev_notdef(), /* 15 unknown*/
+ bdev_notdef(), /* 16 unknown*/
+ bdev_disk_init(NRD,rd), /* 17 ram disk driver*/
+};
+int nblkdev = sizeof bdevsw / sizeof bdevsw[0];
+
+#include "pty.h"
+
+#include "com.h"
+cdev_decl(com);
+
+#include "bpfilter.h"
+
+#include "tun.h"
+
+#ifdef USER_PCICONF
+#include "pci.h"
+cdev_decl(pci);
+#endif
+
+#include "pf.h"
+
+#include "systrace.h"
+
+#ifdef LKM
+#define NLKM 1
+#else
+#define NLKM 0
+#endif
+
+#include "ksyms.h"
+#include "usb.h"
+
+struct cdevsw cdevsw[] = {
+ cdev_cn_init(1,cn), /* 0: virtual console */
+ cdev_ctty_init(1,ctty), /* 1: controlling terminal */
+ cdev_mm_init(1,mm), /* 2: /dev/{null,mem,kmem,...} */
+ cdev_swap_init(1,sw), /* 3: /dev/drum (swap pseudo-device) */
+ cdev_tty_init(NPTY,pts), /* 4: pseudo-tty slave */
+ cdev_ptc_init(NPTY,ptc), /* 5: pseudo-tty master */
+ cdev_log_init(1,log), /* 6: /dev/klog */
+ cdev_notdef(), /* 7 */
+ cdev_disk_init(NSD,sd), /* 8: SCSI disk */
+ cdev_disk_init(NCD,cd), /* 9: SCSI CD-ROM */
+ cdev_notdef(), /* 10 */
+ cdev_disk_init(NWD,wd), /* 11: ST506/ESDI/IDE disk */
+ cdev_notdef(), /* 12 */
+ cdev_notdef(), /* 13 */
+ cdev_notdef(), /* 14 */
+ cdev_notdef(), /* 15 */
+ cdev_notdef(), /* 16 */
+ cdev_disk_init(NRD,rd), /* 17 ram disk driver*/
+ cdev_notdef(), /* 18 */
+ cdev_disk_init(NVND,vnd), /* 19: vnode disk */
+ cdev_notdef(), /* 20 */
+ cdev_fd_init(1,filedesc), /* 21: file descriptor pseudo-dev */
+ cdev_bpf_init(NBPFILTER,bpf), /* 22: berkeley packet filter */
+ cdev_tun_init(NTUN,tun), /* 23: network tunnel */
+ cdev_lkm_init(NLKM,lkm), /* 24: loadable module driver */
+ cdev_notdef(), /* 25 */
+ cdev_tty_init(NCOM,com), /* 26: serial port */
+ cdev_notdef(), /* 27 */
+ cdev_notdef(), /* 28 */
+ cdev_notdef(), /* 29 */
+ cdev_notdef(), /* 30 */
+ cdev_notdef(), /* 31 */
+ cdev_notdef(), /* 32 */
+ cdev_lkm_dummy(), /* 33 */
+ cdev_lkm_dummy(), /* 34 */
+ cdev_lkm_dummy(), /* 35 */
+ cdev_lkm_dummy(), /* 36 */
+ cdev_lkm_dummy(), /* 37 */
+ cdev_lkm_dummy(), /* 38 */
+ cdev_pf_init(NPF,pf), /* 39: packet filter */
+ cdev_random_init(1,random), /* 40: random data source */
+ cdev_notdef(), /* 41 */
+ cdev_notdef(), /* 42 */
+ cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */
+ cdev_notdef(), /* 44 */
+ cdev_notdef(), /* 45 */
+ cdev_notdef(), /* 46 */
+ cdev_notdef(), /* 47 */
+ cdev_notdef(), /* 48 */
+ cdev_notdef(), /* 49 */
+ cdev_systrace_init(NSYSTRACE,systrace), /* 50 system call tracing */
+ cdev_notdef(), /* 51 */
+ cdev_notdef(), /* 52 */
+ cdev_notdef(), /* 53 */
+ cdev_notdef(), /* 54 */
+ cdev_notdef(), /* 55 */
+ cdev_notdef(), /* 56 */
+ cdev_notdef(), /* 57 */
+ cdev_notdef(), /* 58 */
+ cdev_notdef(), /* 59 */
+ cdev_notdef(), /* 60 */
+ cdev_usb_init(NUSB,usb), /* 61: USB controller */
+ cdev_notdef(), /* 62 */
+ cdev_notdef(), /* 63 */
+ cdev_notdef(), /* 64 */
+ cdev_notdef(), /* 65 */
+ cdev_notdef(), /* 66 */
+ cdev_notdef(), /* 67 */
+ cdev_notdef(), /* 68 */
+ cdev_notdef(), /* 69 */
+ cdev_notdef(), /* 70 */
+#ifdef USER_PCICONF
+ cdev_pci_init(NPCI,pci), /* 71: PCI user */
+#else
+ cdev_notdef(),
+#endif
+ cdev_notdef(), /* 72 */
+ cdev_notdef(), /* 73 */
+ cdev_notdef(), /* 74 */
+ cdev_notdef(), /* 75 */
+ cdev_notdef(), /* 76 */
+ cdev_ptm_init(NPTY,ptm), /* 77: pseudo-tty ptm device */
+};
+int nchrdev = sizeof cdevsw / sizeof cdevsw[0];
+
+int mem_no = 2; /* major number of /dev/mem */
+
+/*
+ * Swapdev is a fake device implemented in sw.c.
+ * It is used only internally to get to swstrategy.
+ */
+dev_t swapdev = makedev(1, 0);
+
+/*
+ * Check whether dev is /dev/mem or /dev/kmem.
+ */
+int
+iskmemdev(dev_t dev)
+{
+ return major(dev) == mem_no && minor(dev) < 2;
+}
+
+/*
+ * Check whether dev is /dev/zero.
+ */
+int
+iszerodev(dev_t dev)
+{
+ return major(dev) == mem_no && minor(dev) == 12;
+}
+
+dev_t
+getnulldev()
+{
+ return makedev(mem_no, 2);
+}
+
+int chrtoblktbl[] = {
+ /*VCHR*/ /*VBLK*/
+ /* 0 */ NODEV,
+ /* 1 */ NODEV,
+ /* 2 */ NODEV,
+ /* 3 */ NODEV,
+ /* 4 */ NODEV,
+ /* 5 */ NODEV,
+ /* 6 */ NODEV,
+ /* 7 */ NODEV,
+ /* 8 */ 2,
+ /* 9 */ NODEV,
+ /* 10 */ NODEV,
+ /* 11 */ 0,
+ /* 12 */ NODEV,
+ /* 13 */ 4,
+ /* 14 */ NODEV,
+ /* 15 */ NODEV,
+ /* 16 */ NODEV,
+ /* 17 */ 17,
+ /* 18 */ NODEV,
+ /* 19 */ NODEV,
+ /* 20 */ NODEV,
+ /* 21 */ NODEV,
+ /* 22 */ NODEV,
+ /* 23 */ NODEV,
+ /* 24 */ NODEV,
+ /* 25 */ NODEV,
+ /* 26 */ NODEV,
+ /* 27 */ NODEV,
+ /* 28 */ NODEV,
+ /* 29 */ NODEV,
+ /* 30 */ NODEV,
+ /* 31 */ NODEV,
+ /* 32 */ NODEV,
+ /* 33 */ NODEV,
+ /* 34 */ NODEV,
+ /* 35 */ NODEV,
+ /* 36 */ NODEV,
+ /* 37 */ NODEV,
+ /* 38 */ NODEV,
+ /* 39 */ NODEV,
+ /* 40 */ NODEV,
+ /* 41 */ NODEV,
+ /* 42 */ NODEV,
+ /* 43 */ NODEV,
+ /* 44 */ NODEV,
+ /* 45 */ NODEV,
+ /* 46 */ NODEV,
+ /* 47 */ NODEV,
+ /* 48 */ NODEV,
+ /* 49 */ NODEV,
+ /* 50 */ NODEV,
+ /* 51 */ NODEV,
+ /* 52 */ NODEV,
+ /* 53 */ NODEV,
+ /* 54 */ 19,
+};
+int nchrtoblktbl = sizeof(chrtoblktbl) / sizeof(chrtoblktbl[0]);
+
+#include <dev/cons.h>
+
+cons_decl(com);
+
+struct consdev constab[] = {
+#if NCOM > 0
+ cons_init(com),
+#endif
+ { 0 },
+};
diff --git a/sys/arch/socppc/socppc/cpu.c b/sys/arch/socppc/socppc/cpu.c
new file mode 100644
index 00000000000..72c4c59ee73
--- /dev/null
+++ b/sys/arch/socppc/socppc/cpu.c
@@ -0,0 +1,115 @@
+/* $OpenBSD: cpu.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#define HID0_DOZE (1 << (31-8))
+#define HID0_NAP (1 << (31-9))
+#define HID0_SLEEP (1 << (31-10))
+#define HID0_DPM (1 << (31-11))
+#define HID0_ICE (1 << (31-16))
+#define HID0_DCE (1 << (31-17))
+#define HID0_ICFI (1 << (31-20))
+#define HID0_DCFI (1 << (31-21))
+
+extern u_int32_t hid0_idle;
+
+
+struct cpu_info cpu_info[PPC_MAXPROCS] = { { NULL } }; /* XXX */
+
+char *cpu_model = "8347";
+char machine[] = MACHINE; /* cpu architecture */
+
+int cpu_match(struct device *, void *, void *);
+void cpu_attach(struct device *, struct device *, void *);
+
+struct cfattach cpu_ca = {
+ sizeof(struct device), cpu_match, cpu_attach
+};
+
+struct cfdriver cpu_cd = {
+ NULL, "cpu", DV_DULL
+};
+
+int
+cpu_match(struct device *parent, void *cfdata, void *aux)
+{
+ return (1);
+}
+
+void
+cpu_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct cpu_info *ci;
+ u_int32_t hid0;
+
+ ci = &cpu_info[0];
+ ci->ci_cpuid = 0;
+ ci->ci_intrdepth = -1;
+ ci->ci_randseed = 1;
+ ci->ci_dev = self;
+
+ printf(": %s\n", cpu_model);
+
+ /* Enable data cache. */
+ hid0 = ppc_mfhid0();
+ if ((hid0 & HID0_DCE) == 0) {
+ __asm __volatile (
+ "sync; mtspr 1008,%0; mtspr 1008,%1"
+ :: "r" (hid0 | HID0_DCFI), "r" (hid0 | HID0_DCE));
+ }
+
+ /* Enable instruction cache. */
+ hid0 = ppc_mfhid0();
+ if ((hid0 & HID0_ICE) == 0) {
+ __asm __volatile (
+ "isync; mtspr 1008,%0; mtspr 1008,%1"
+ :: "r" (hid0 | HID0_ICFI), "r" (hid0 | HID0_ICE));
+ }
+
+ /* Select DOZE mode. */
+ hid0 = ppc_mfhid0();
+ hid0 &= ~(HID0_NAP | HID0_DOZE | HID0_SLEEP);
+ hid0_idle = HID0_DOZE;
+ hid0 |= HID0_DPM;
+ ppc_mthid0(hid0);
+}
+
+int ppc_proc_is_64b;
+extern u_int32_t nop_inst;
+struct patch {
+ u_int32_t *s;
+ u_int32_t *e;
+};
+extern struct patch nop32_start;
+
+void
+ppc_check_procid()
+{
+ u_int32_t *inst;
+ struct patch *p;
+
+ ppc_proc_is_64b = 0;
+ for (p = &nop32_start; p->s; p++) {
+ for (inst = p->s; inst < p->e; inst++)
+ *inst = nop_inst;
+ syncicache(p->s, (p->e - p->s) * sizeof(p->e));
+ }
+}
diff --git a/sys/arch/socppc/socppc/db_interface.c b/sys/arch/socppc/socppc/db_interface.c
new file mode 100644
index 00000000000..02a44a53a76
--- /dev/null
+++ b/sys/arch/socppc/socppc/db_interface.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: db_interface.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+/* $NetBSD: db_interface.c,v 1.12 2001/07/22 11:29:46 wiz Exp $ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+
+#include <dev/cons.h>
+
+#include <machine/db_machdep.h>
+#include <ddb/db_extern.h>
+
+int ddb_trap_glue(struct trapframe *frame); /* called from locore */
+
+void
+Debugger()
+{
+ ddb_trap();
+}
+
+int
+ddb_trap_glue(struct trapframe *frame)
+{
+ if (!(frame->srr1 & PSL_PR)
+ && (frame->exc == EXC_TRC
+ || (frame->exc == EXC_PGM && (frame->srr1 & 0x20000))
+ || frame->exc == EXC_BPT)) {
+
+ bcopy(frame->fixreg, DDB_REGS->tf.fixreg,
+ 32 * sizeof(u_int32_t));
+ DDB_REGS->tf.srr0 = frame->srr0;
+ DDB_REGS->tf.srr1 = frame->srr1;
+
+ cnpollc(TRUE);
+ db_trap(T_BREAKPOINT, 0);
+ cnpollc(FALSE);
+
+ bcopy(DDB_REGS->tf.fixreg, frame->fixreg,
+ 32 * sizeof(u_int32_t));
+
+ return 1;
+ }
+ return 0;
+}
diff --git a/sys/arch/socppc/socppc/disksubr.c b/sys/arch/socppc/socppc/disksubr.c
new file mode 100644
index 00000000000..f41bd161701
--- /dev/null
+++ b/sys/arch/socppc/socppc/disksubr.c
@@ -0,0 +1,214 @@
+/* $OpenBSD: disksubr.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+/* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */
+
+/*
+ * Copyright (c) 1996 Theo de Raadt
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/disklabel.h>
+#include <sys/disk.h>
+
+char *readdpmelabel(struct buf *, void (*)(struct buf *),
+ struct disklabel *, int *, int);
+
+/*
+ * Attempt to read a disk label from a device
+ * using the indicated strategy routine.
+ * The label must be partly set up before this:
+ * secpercyl, secsize and anything required for a block i/o read
+ * operation in the driver's strategy/start routines
+ * must be filled in before calling us.
+ *
+ * If dos partition table requested, attempt to load it and
+ * find disklabel inside a DOS partition. Return buffer
+ * for use in signalling errors if requested.
+ *
+ * We would like to check if each MBR has a valid DOSMBR_SIGNATURE, but
+ * we cannot because it doesn't always exist. So.. we assume the
+ * MBR is valid.
+ *
+ * Returns null on success and an error string on failure.
+ */
+char *
+readdisklabel(dev_t dev, void (*strat)(struct buf *),
+ struct disklabel *lp, int spoofonly)
+{
+ struct buf *bp = NULL;
+ char *msg;
+
+ if ((msg = initdisklabel(lp)))
+ goto done;
+
+ /* get a buffer and initialize it */
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ msg = readdpmelabel(bp, strat, lp, NULL, spoofonly);
+ if (msg == NULL)
+ goto done;
+
+ msg = readdoslabel(bp, strat, lp, NULL, spoofonly);
+ if (msg == NULL)
+ goto done;
+
+#if defined(CD9660)
+ if (iso_disklabelspoof(dev, strat, lp) == 0) {
+ msg = NULL;
+ goto done;
+ }
+#endif
+#if defined(UDF)
+ if (udf_disklabelspoof(dev, strat, lp) == 0) {
+ msg = NULL;
+ goto done;
+ }
+#endif
+
+done:
+ if (bp) {
+ bp->b_flags |= B_INVAL;
+ brelse(bp);
+ }
+ return (msg);
+}
+
+char *
+readdpmelabel(struct buf *bp, void (*strat)(struct buf *),
+ struct disklabel *lp, int *partoffp, int spoofonly)
+{
+ int i, part_cnt, n, hfspartoff = -1;
+ struct part_map_entry *part;
+
+ /* First check for a DPME (HFS) disklabel */
+ bp->b_blkno = 1;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+ if (biowait(bp))
+ return ("DPME partition I/O error");
+
+ /* if successful, wander through DPME partition table */
+ part = (struct part_map_entry *)bp->b_data;
+ /* if first partition is not valid, assume not HFS/DPME partitioned */
+ if (part->pmSig != PART_ENTRY_MAGIC)
+ return ("not a DPMI partition");
+ part_cnt = part->pmMapBlkCnt;
+ n = 0;
+ for (i = 0; i < part_cnt; i++) {
+ struct partition *pp = &lp->d_partitions[8+n];
+ char *s;
+
+ bp->b_blkno = 1+i;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+ if (biowait(bp))
+ return ("DPME partition I/O error");
+
+ part = (struct part_map_entry *)bp->b_data;
+ /* toupper the string, in case caps are different... */
+ for (s = part->pmPartType; *s; s++)
+ if ((*s >= 'a') && (*s <= 'z'))
+ *s = (*s - 'a' + 'A');
+
+ if (strcmp(part->pmPartType, PART_TYPE_OPENBSD) == 0)
+ hfspartoff = part->pmPyPartStart - LABELSECTOR;
+
+ /* currently we ignore all but HFS partitions */
+ if (strcmp(part->pmPartType, PART_TYPE_MAC) == 0) {
+ DL_SETPOFFSET(pp, part->pmPyPartStart);
+ DL_SETPSIZE(pp, part->pmPartBlkCnt);
+ pp->p_fstype = FS_HFS;
+ n++;
+ }
+ }
+ lp->d_npartitions = MAXPARTITIONS;
+
+ if (hfspartoff == -1)
+ return ("no OpenBSD parition inside DPME label");
+
+ if (partoffp)
+ *partoffp = hfspartoff;
+
+ if (spoofonly)
+ return (NULL);
+
+ /* next, dig out disk label */
+ bp->b_blkno = hfspartoff + LABELSECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+ if (biowait(bp))
+ return("disk label I/O error");
+
+ return checkdisklabel(bp->b_data + LABELOFFSET, lp);
+}
+
+/*
+ * Write disk label back to device after modification.
+ */
+int
+writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
+{
+ int error = EIO, partoff = -1;
+ struct disklabel *dlp;
+ struct buf *bp = NULL;
+
+ /* get a buffer and initialize it */
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ if (readdpmelabel(bp, strat, lp, &partoff, 1) != NULL &&
+ readdoslabel(bp, strat, lp, &partoff, 1) != NULL)
+ goto done;
+
+ /* Read it in, slap the new label in, and write it back out */
+ bp->b_blkno = partoff + LABELSECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+ if ((error = biowait(bp)) != 0)
+ goto done;
+
+ dlp = (struct disklabel *)(bp->b_data + LABELOFFSET);
+ *dlp = *lp;
+ bp->b_flags = B_BUSY | B_WRITE;
+ (*strat)(bp);
+ error = biowait(bp);
+
+done:
+ if (bp) {
+ bp->b_flags |= B_INVAL;
+ brelse(bp);
+ }
+ return (error);
+}
diff --git a/sys/arch/socppc/socppc/dma.c b/sys/arch/socppc/socppc/dma.c
new file mode 100644
index 00000000000..49f2d951595
--- /dev/null
+++ b/sys/arch/socppc/socppc/dma.c
@@ -0,0 +1,608 @@
+/* $OpenBSD: dma.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/extent.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/mount.h>
+
+#include <uvm/uvm.h>
+#include <uvm/uvm_page.h>
+
+#include <machine/bus.h>
+int _dmamem_alloc_range( bus_dma_tag_t t, bus_size_t size,
+ bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs,
+ int nsegs, int *rsegs, int flags, vaddr_t low, vaddr_t high);
+int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
+ struct proc *, int, bus_addr_t *, int *, int);
+/*
+ * Common function for DMA map creation. May be called by bus-specific
+ * DMA map creation functions.
+ */
+int
+_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments,
+ bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp)
+{
+ struct powerpc_bus_dmamap *map;
+ void *mapstore;
+ size_t mapsize;
+
+ /*
+ * Allocate and initialize the DMA map. The end of the map
+ * is a variable-sized array of segments, so we allocate enough
+ * room for them in one shot.
+ *
+ * Note we don't preserve the WAITOK or NOWAIT flags. Preservation
+ * of ALLOCNOW notifies others that we've reserved these resources,
+ * and they are not to be freed.
+ *
+ * The bus_dmamap_t includes one bus_dma_segment_t, hence
+ * the (nsegments - 1).
+ */
+ mapsize = sizeof(struct powerpc_bus_dmamap) +
+ (sizeof(bus_dma_segment_t) * (nsegments - 1));
+ if ((mapstore = malloc(mapsize, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ?
+ (M_NOWAIT | M_ZERO) : (M_WAITOK | M_ZERO))) == NULL)
+ return (ENOMEM);
+
+ map = (struct powerpc_bus_dmamap *)mapstore;
+ map->_dm_size = size;
+ map->_dm_segcnt = nsegments;
+ map->_dm_maxsegsz = maxsegsz;
+ map->_dm_boundary = boundary;
+ map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
+ map->dm_nsegs = 0; /* no valid mappings */
+ map->dm_mapsize = 0;
+
+ *dmamp = map;
+ return (0);
+}
+
+/*
+ * Common function for DMA map destruction. May be called by bus-specific
+ * DMA map destruction functions.
+ */
+void
+_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map)
+{
+
+ free(map, M_DEVBUF);
+}
+
+
+int
+_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
+ bus_size_t buflen, struct proc *p, int flags, bus_addr_t *lastaddrp,
+ int *segp, int first)
+{
+ bus_size_t sgsize;
+ bus_addr_t curaddr, lastaddr, baddr, bmask;
+ vaddr_t vaddr = (vaddr_t)buf;
+ pmap_t pmap;
+ int seg;
+
+ lastaddr = *lastaddrp;
+ bmask = ~(map->_dm_boundary - 1);
+
+ if (p != NULL)
+ pmap = p->p_vmspace->vm_map.pmap;
+ else
+ pmap = pmap_kernel();
+
+ for (seg = *segp; buflen > 0; ) {
+ /*
+ * Get the physical address for this segment.
+ */
+ if (pmap_extract(pmap, vaddr, (paddr_t *)&curaddr) != TRUE) {
+ panic("dmamap_load_buffer pmap %p vaddr %lx "
+ "pmap_extract failed", pmap, vaddr);
+ }
+
+ /*
+ * Compute the segment size, and adjust counts.
+ */
+ sgsize = PAGE_SIZE - ((u_long)vaddr & PGOFSET);
+ if (buflen < sgsize)
+ sgsize = buflen;
+
+ /*
+ * Make sure we don't cross any boundaries.
+ */
+ if (map->_dm_boundary > 0) {
+ baddr = (curaddr + map->_dm_boundary) & bmask;
+ if (sgsize > (baddr - curaddr))
+ sgsize = (baddr - curaddr);
+ }
+
+ /*
+ * Insert chunk into a segment, coalescing with the
+ * previous segment if possible.
+ */
+ if (first) {
+ map->dm_segs[seg].ds_addr = curaddr;
+ map->dm_segs[seg].ds_len = sgsize;
+ first = 0;
+ } else {
+ if (curaddr == lastaddr &&
+ (map->dm_segs[seg].ds_len + sgsize) <=
+ map->_dm_maxsegsz &&
+ (map->_dm_boundary == 0 ||
+ (map->dm_segs[seg].ds_addr & bmask) ==
+ (curaddr & bmask)))
+ map->dm_segs[seg].ds_len += sgsize;
+ else {
+ if (++seg >= map->_dm_segcnt)
+ break;
+ map->dm_segs[seg].ds_addr = curaddr;
+ map->dm_segs[seg].ds_len = sgsize;
+ }
+ }
+
+ lastaddr = curaddr + sgsize;
+ vaddr += sgsize;
+ buflen -= sgsize;
+ }
+
+ *segp = seg;
+ *lastaddrp = lastaddr;
+
+ /*
+ * Did we fit?
+ */
+ if (buflen != 0)
+ return (EFBIG); /* XX better return value here? */
+
+ return (0);
+}
+
+/*
+ * Common function for loading a DMA map with a linear buffer. May
+ * be called by bus-specific DMA map load functions.
+ */
+int
+_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf, bus_size_t buflen,
+ struct proc *p, int flags)
+{
+ bus_addr_t lastaddr;
+ int seg, error;
+
+ /*
+ * Make sure that on error condition we return "no valid mappings".
+ */
+ map->dm_mapsize = 0;
+ map->dm_nsegs = 0;
+
+ if (buflen > map->_dm_size)
+ return (EINVAL);
+
+ seg = 0;
+ error = _dmamap_load_buffer(t, map, buf, buflen, p, flags,
+ &lastaddr, &seg, 1);
+ if (error == 0) {
+ map->dm_mapsize = buflen;
+ map->dm_nsegs = seg + 1;
+ }
+ return (error);
+}
+
+/*
+ * Like _bus_dmamap_load(), but for mbufs.
+ */
+int
+_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m0,
+ int flags)
+{
+ bus_addr_t lastaddr;
+ int seg, error, first;
+ struct mbuf *m;
+
+ /*
+ * Make sure that on error condition we return "no valid mappings".
+ */
+ map->dm_mapsize = 0;
+ map->dm_nsegs = 0;
+
+#ifdef DIAGNOSTIC
+ if ((m0->m_flags & M_PKTHDR) == 0)
+ panic("_bus_dmamap_load_mbuf: no packet header");
+#endif
+
+ if (m0->m_pkthdr.len > map->_dm_size)
+ return (EINVAL);
+
+ first = 1;
+ seg = 0;
+ error = 0;
+ for (m = m0; m != NULL && error == 0; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ error = _dmamap_load_buffer(t, map, m->m_data, m->m_len,
+ NULL, flags, &lastaddr, &seg, first);
+ first = 0;
+ }
+ if (error == 0) {
+ map->dm_mapsize = m0->m_pkthdr.len;
+ map->dm_nsegs = seg + 1;
+ }
+ return (error);
+}
+
+/*
+ * Like _bus_dmamap_load(), but for uios.
+ */
+int
+_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio, int flags)
+{
+ bus_addr_t lastaddr;
+ int seg, i, error, first;
+ bus_size_t minlen, resid;
+ struct proc *p = NULL;
+ struct iovec *iov;
+ caddr_t addr;
+
+ /*
+ * Make sure that on error condition we return "no valid mappings".
+ */
+ map->dm_mapsize = 0;
+ map->dm_nsegs = 0;
+
+ resid = uio->uio_resid;
+ iov = uio->uio_iov;
+
+ if (resid > map->_dm_size)
+ return (EINVAL);
+
+ if (uio->uio_segflg == UIO_USERSPACE) {
+ p = uio->uio_procp;
+#ifdef DIAGNOSTIC
+ if (p == NULL)
+ panic("_bus_dmamap_load_uio: USERSPACE but no proc");
+#endif
+ }
+
+ first = 1;
+ seg = 0;
+ error = 0;
+ for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
+ /*
+ * Now at the first iovec to load. Load each iovec
+ * until we have exhausted the residual count.
+ */
+ minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
+ addr = (caddr_t)iov[i].iov_base;
+
+ error = _dmamap_load_buffer(t, map, addr, minlen,
+ p, flags, &lastaddr, &seg, first);
+ first = 0;
+
+ resid -= minlen;
+ }
+ if (error == 0) {
+ map->dm_mapsize = uio->uio_resid;
+ map->dm_nsegs = seg + 1;
+ }
+ return (error);
+}
+
+/*
+ * Like _bus_dmamap_load(), but for raw memory allocated with
+ * bus_dmamem_alloc().
+ */
+int
+_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map, bus_dma_segment_t *segs,
+ int nsegs, bus_size_t size, int flags)
+{
+ if (nsegs > map->_dm_segcnt || size > map->_dm_size)
+ return (EINVAL);
+
+ /*
+ * Make sure we don't cross any boundaries.
+ */
+ if (map->_dm_boundary) {
+ bus_addr_t bmask = ~(map->_dm_boundary - 1);
+ int i;
+
+ for (i = 0; i < nsegs; i++) {
+ if (segs[i].ds_len > map->_dm_maxsegsz)
+ return (EINVAL);
+ if ((segs[i].ds_addr & bmask) !=
+ ((segs[i].ds_addr + segs[i].ds_len - 1) & bmask))
+ return (EINVAL);
+ }
+ }
+
+ bcopy(segs, map->dm_segs, nsegs * sizeof(*segs));
+ map->dm_nsegs = nsegs;
+ map->dm_mapsize = size;
+ return (0);
+}
+
+/*
+ * Common function for unloading a DMA map. May be called by
+ * bus-specific DMA map unload functions.
+ */
+void
+_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map)
+{
+
+ /*
+ * No resources to free; just mark the mappings as
+ * invalid.
+ */
+ map->dm_nsegs = 0;
+ map->dm_mapsize = 0;
+}
+
+/*
+ * Common function for DMA map synchronization. May be called
+ * by bus-specific DMA map synchronization functions.
+ */
+void
+_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
+bus_size_t len, int op)
+{
+ int i;
+ bus_size_t minlen, wlen;
+ bus_addr_t pa, addr;
+ struct vm_page *pg;
+
+ for (i = 0; i < map->dm_nsegs && len != 0; i++) {
+ /* Find the beginning segment. */
+ if (offset >= map->dm_segs[i].ds_len) {
+ offset -= map->dm_segs[i].ds_len;
+ continue;
+ }
+
+ minlen = len < map->dm_segs[i].ds_len - offset ?
+ len : map->dm_segs[i].ds_len - offset;
+
+ addr = map->dm_segs[i].ds_addr + offset;
+
+ switch (op) {
+ case BUS_DMASYNC_POSTWRITE:
+ for (pa = trunc_page(addr), wlen = 0;
+ pa < round_page(addr + minlen);
+ pa += PAGE_SIZE) {
+ pg = PHYS_TO_VM_PAGE(pa);
+ if (pg != NULL)
+ atomic_clearbits_int(&pg->pg_flags,
+ PG_PMAP_EXE);
+ }
+ }
+
+ }
+}
+
+/*
+ * Common function for DMA-safe memory allocation. May be called
+ * by bus-specific DMA memory allocation functions.
+ */
+int
+_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment,
+ bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
+ int flags)
+{
+ return (_dmamem_alloc_range(t, size, alignment, boundary,
+ segs, nsegs, rsegs, flags, 0, 0xf0000000));
+}
+
+/*
+ * Common function for freeing DMA-safe memory. May be called by
+ * bus-specific DMA memory free functions.
+ */
+void
+_dmamem_free(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs)
+{
+ struct vm_page *m;
+ bus_addr_t addr;
+ struct pglist mlist;
+ int curseg;
+
+ /*
+ * Build a list of pages to free back to the VM system.
+ */
+ TAILQ_INIT(&mlist);
+ for (curseg = 0; curseg < nsegs; curseg++) {
+ for (addr = segs[curseg].ds_addr;
+ addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
+ addr += PAGE_SIZE) {
+ m = PHYS_TO_VM_PAGE(addr);
+ TAILQ_INSERT_TAIL(&mlist, m, pageq);
+ }
+ }
+
+ uvm_pglistfree(&mlist);
+}
+
+/*
+ * Common function for mapping DMA-safe memory. May be called by
+ * bus-specific DMA memory map functions.
+ */
+int
+_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size,
+ caddr_t *kvap, int flags)
+{
+ vaddr_t va;
+ bus_addr_t addr;
+ int curseg;
+
+ size = round_page(size);
+ va = uvm_km_valloc(kernel_map, size);
+ if (va == 0)
+ return (ENOMEM);
+
+ *kvap = (caddr_t)va;
+
+ for (curseg = 0; curseg < nsegs; curseg++) {
+ for (addr = segs[curseg].ds_addr;
+ addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
+ addr += PAGE_SIZE, va += PAGE_SIZE, size -= PAGE_SIZE) {
+ if (size == 0)
+ panic("_bus_dmamem_map: size botch");
+ pmap_enter(pmap_kernel(), va, addr,
+ VM_PROT_READ | VM_PROT_WRITE,
+ VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED);
+ }
+ }
+ pmap_update(pmap_kernel());
+
+ return (0);
+}
+
+/*
+ * Common function for unmapping DMA-safe memory. May be called by
+ * bus-specific DMA memory unmapping functions.
+ */
+void
+_dmamem_unmap(bus_dma_tag_t t, caddr_t kva, size_t size)
+{
+
+#ifdef DIAGNOSTIC
+ if ((u_long)kva & PGOFSET)
+ panic("_bus_dmamem_unmap");
+#endif
+
+ size = round_page(size);
+ uvm_km_free(kernel_map, (vaddr_t)kva, size);
+}
+
+/*
+ * Common function for mmap(2)'ing DMA-safe memory. May be called by
+ * bus-specific DMA mmap(2)'ing functions.
+ */
+paddr_t
+_dmamem_mmap(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, off_t off,
+ int prot, int flags)
+{
+ int i;
+
+ for (i = 0; i < nsegs; i++) {
+#ifdef DIAGNOSTIC
+ if (off & PGOFSET)
+ panic("_bus_dmamem_mmap: offset unaligned");
+ if (segs[i].ds_addr & PGOFSET)
+ panic("_bus_dmamem_mmap: segment unaligned");
+ if (segs[i].ds_len & PGOFSET)
+ panic("_bus_dmamem_mmap: segment size not multiple"
+ " of page size");
+#endif
+ if (off >= segs[i].ds_len) {
+ off -= segs[i].ds_len;
+ continue;
+ }
+
+ return (atop(segs[i].ds_addr + off));
+ }
+
+ /* Page not found. */
+ return (-1);
+}
+
+/**********************************************************************
+ * DMA utility functions
+ **********************************************************************/
+
+/*
+ * Allocate physical memory from the given physical address range.
+ * Called by DMA-safe memory allocation methods.
+ */
+int
+_dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment,
+ bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
+ int flags, vaddr_t low, vaddr_t high)
+{
+ vaddr_t curaddr, lastaddr;
+ struct vm_page *m;
+ struct pglist mlist;
+ int curseg, error;
+
+ /* Always round the size. */
+ size = round_page(size);
+
+ /*
+ * Allocate pages from the VM system.
+ */
+ TAILQ_INIT(&mlist);
+ error = uvm_pglistalloc(size, low, high,
+ alignment, boundary, &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
+ if (error)
+ return (error);
+
+ /*
+ * Compute the location, size, and number of segments actually
+ * returned by the VM code.
+ */
+ m = TAILQ_FIRST(&mlist);
+ curseg = 0;
+ lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m);
+ segs[curseg].ds_len = PAGE_SIZE;
+ m = TAILQ_NEXT(m, pageq);
+
+ for (; m != NULL; m = TAILQ_NEXT(m, pageq)) {
+ curaddr = VM_PAGE_TO_PHYS(m);
+#ifdef DIAGNOSTIC
+ if (curaddr < low || curaddr >= high) {
+ printf("vm_page_alloc_memory returned non-sensical"
+ " address 0x%lx\n", curaddr);
+ panic("dmamem_alloc_range");
+ }
+#endif
+ if (curaddr == (lastaddr + PAGE_SIZE))
+ segs[curseg].ds_len += PAGE_SIZE;
+ else {
+ curseg++;
+ segs[curseg].ds_addr = curaddr;
+ segs[curseg].ds_len = PAGE_SIZE;
+ }
+ lastaddr = curaddr;
+ }
+
+ *rsegs = curseg + 1;
+
+ return (0);
+}
diff --git a/sys/arch/socppc/socppc/machdep.c b/sys/arch/socppc/socppc/machdep.c
new file mode 100644
index 00000000000..d95c625e504
--- /dev/null
+++ b/sys/arch/socppc/socppc/machdep.c
@@ -0,0 +1,1147 @@
+/* $OpenBSD: machdep.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+/* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#include <sys/exec.h>
+#include <sys/extent.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#ifdef SYSVMSG
+#include <sys/msg.h>
+#endif
+#include <sys/msgbuf.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/signalvar.h>
+#include <sys/syscallargs.h>
+#include <sys/sysctl.h>
+#include <sys/tty.h>
+#include <sys/user.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/bat.h>
+#include <machine/bus.h>
+#include <machine/pio.h>
+#include <machine/powerpc.h>
+#include <machine/trap.h>
+
+#include <net/netisr.h>
+
+#include <dev/cons.h>
+
+#include <dev/ic/comvar.h>
+
+/*
+ * Global variables used here and there
+ */
+extern struct user *proc0paddr;
+
+/*
+ * Declare these as initialized data so we can patch them.
+ */
+#ifndef BUFCACHEPERCENT
+#define BUFCACHEPERCENT 5
+#endif
+
+#ifdef BUFPAGES
+int bufpages = BUFPAGES;
+#else
+int bufpages = 0;
+#endif
+int bufcachepercent = BUFCACHEPERCENT;
+
+struct bat battable[16];
+
+struct vm_map *exec_map = NULL;
+struct vm_map *phys_map = NULL;
+
+int ppc_malloc_ok = 0;
+
+void uboot_mem_regions(struct mem_region **, struct mem_region **);
+void uboot_vmon(void);
+
+struct firmware uboot_firmware = {
+ uboot_mem_regions,
+ NULL,
+ NULL,
+ uboot_vmon
+};
+
+struct firmware *fw = &uboot_firmware;
+
+#ifdef APERTURE
+#ifdef INSECURE
+int allowaperture = 1;
+#else
+int allowaperture = 0;
+#endif
+#endif
+
+caddr_t allocsys(caddr_t);
+void dumpsys(void);
+int lcsplx(int ipl);
+int bus_mem_add_mapping(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
+bus_addr_t bus_space_unmap_p(bus_space_tag_t, bus_space_handle_t, bus_size_t);
+void bus_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t);
+
+/*
+ * Extent maps to manage I/O. Allocate storage for 8 regions in each,
+ * initially. Later devio_malloc_safe will indicate that it's safe to
+ * use malloc() to dynamically allocate region descriptors.
+ */
+static long devio_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof (long)];
+struct extent *devio_ex;
+static int devio_malloc_safe = 0;
+
+void initppc(u_int, u_int, char *);
+
+void prom_printf(const char *, ...);
+
+extern struct ppc_bus_space mainbus_bus_space;
+
+void
+initppc(u_int startkernel, u_int endkernel, char *args)
+{
+ extern void *trapcode; extern int trapsize;
+ extern void *extint; extern int extsize;
+ extern void *dsitrap; extern int dsisize;
+ extern void *isitrap; extern int isisize;
+ extern void *alitrap; extern int alisize;
+ extern void *decrint; extern int decrsize;
+ extern void *tlbimiss; extern int tlbimsize;
+ extern void *tlbdlmiss; extern int tlbdlmsize;
+ extern void *tlbdsmiss; extern int tlbdsmsize;
+#ifdef DDB
+ extern void *ddblow; extern int ddbsize;
+#endif
+ extern void *msgbuf_addr;
+ int exc, scratch;
+
+ extern char __bss_start[], __end[];
+ bzero(__bss_start, __end - __bss_start);
+
+ proc0.p_cpu = &cpu_info[0];
+ proc0.p_addr = proc0paddr;
+ bzero(proc0.p_addr, sizeof *proc0.p_addr);
+
+ curpcb = &proc0paddr->u_pcb;
+
+ curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel();
+
+ ppc_check_procid();
+
+#if 0
+ {
+ prom_printf("AER: 0x%08x\n", *(uint32_t *)0xe000080c);
+ prom_printf("AIDR: 0x%08x\n", *(uint32_t *)0xe0000810);
+ prom_printf("AEATR: 0x%08x\n", *(uint32_t *)0xe0000818);
+ prom_printf("AEADR: 0x%08x\n", *(uint32_t *)0xe000081c);
+ *(uint32_t *)0xe0000810 = 0x00000001;
+ *(uint32_t *)0xe0000814 = 0x00000001;
+ *(uint32_t *)0xe0000818 = 0x00000000;
+ *(uint32_t *)0xe000081c = 0x00000000;
+ }
+#endif
+
+ /*
+ * Initialize BAT registers to unmapped to not generate
+ * overlapping mappings below.
+ */
+ ppc_mtibat0u(0);
+ ppc_mtibat1u(0);
+ ppc_mtibat2u(0);
+ ppc_mtibat3u(0);
+ ppc_mtdbat0u(0);
+ ppc_mtdbat1u(0);
+ ppc_mtdbat2u(0);
+ ppc_mtdbat3u(0);
+
+ /*
+ * Set up initial BAT table to only map the lowest 256 MB area
+ */
+ battable[0].batl = BATL(0x00000000, BAT_M);
+#if 0
+ battable[0].batu = BATU(0x00000000);
+#else
+ battable[0].batu = 0x0ffe; /* XXX only map 128MB for now */
+#endif
+
+ /*
+ * Now setup fixed bat registers
+ *
+ * Note that we still run in real mode, and the BAT
+ * registers were cleared above.
+ */
+ /* IBAT0 used for initial 256 MB segment */
+ ppc_mtibat0l(battable[0].batl);
+ ppc_mtibat0u(battable[0].batu);
+
+ /* DBAT0 used similar */
+ ppc_mtdbat0l(battable[0].batl);
+ ppc_mtdbat0u(battable[0].batu);
+
+ /*
+ * Set up trap vectors
+ */
+ for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) {
+ switch (exc) {
+ default:
+ bcopy(&trapcode, (void *)exc, (size_t)&trapsize);
+ break;
+ case EXC_EXI:
+ bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize);
+ break;
+ case EXC_DSI:
+ bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
+ break;
+ case EXC_ISI:
+ bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize);
+ break;
+ case EXC_ALI:
+ bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize);
+ break;
+ case EXC_DECR:
+ bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize);
+ break;
+ case EXC_IMISS:
+ bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize);
+ break;
+ case EXC_DLMISS:
+ bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize);
+ break;
+ case EXC_DSMISS:
+ bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize);
+ break;
+ case EXC_PGM:
+ case EXC_TRC:
+ case EXC_BPT:
+#if defined(DDB)
+ bcopy(&ddblow, (void *)exc, (size_t)&ddbsize);
+#endif
+ break;
+ }
+ }
+
+ syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
+
+
+ uvmexp.pagesize = 4096;
+ uvm_setpagesize();
+
+ /*
+ * Initialize pmap module.
+ */
+ pmap_bootstrap(startkernel, endkernel);
+
+ /* now that we know physmem size, map physical memory with BATs */
+ if (physmem > atop(0x10000000)) {
+ battable[0x1].batl = BATL(0x10000000, BAT_M);
+ battable[0x1].batu = BATU(0x10000000);
+ }
+ if (physmem > atop(0x20000000)) {
+ battable[0x2].batl = BATL(0x20000000, BAT_M);
+ battable[0x2].batu = BATU(0x20000000);
+ }
+ if (physmem > atop(0x30000000)) {
+ battable[0x3].batl = BATL(0x30000000, BAT_M);
+ battable[0x3].batu = BATU(0x30000000);
+ }
+ if (physmem > atop(0x40000000)) {
+ battable[0x4].batl = BATL(0x40000000, BAT_M);
+ battable[0x4].batu = BATU(0x40000000);
+ }
+ if (physmem > atop(0x50000000)) {
+ battable[0x5].batl = BATL(0x50000000, BAT_M);
+ battable[0x5].batu = BATU(0x50000000);
+ }
+ if (physmem > atop(0x60000000)) {
+ battable[0x6].batl = BATL(0x60000000, BAT_M);
+ battable[0x6].batu = BATU(0x60000000);
+ }
+ if (physmem > atop(0x70000000)) {
+ battable[0x7].batl = BATL(0x70000000, BAT_M);
+ battable[0x7].batu = BATU(0x70000000);
+ }
+
+ /*
+ * Now enable translation (and machine checks/recoverable interrupts).
+ */
+ (fw->vmon)();
+
+#if 0
+ ppc_mtdbat1l(BATL(0xe0000000, BAT_M | BAT_I | BAT_G));
+ ppc_mtdbat1u(0xe000000e);
+#endif
+
+ __asm__ volatile ("eieio; mfmsr %0; ori %0,%0,%1; mtmsr %0; sync;isync"
+ : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI));
+
+ /*
+ * use the memory provided by pmap_bootstrap for message buffer
+ */
+ initmsgbuf(msgbuf_addr, MSGBUFSIZE);
+
+ /*
+ * Look at arguments passed to us and compute boothowto.
+ */
+ boothowto = RB_AUTOBOOT;
+
+ devio_ex = extent_create("devio", 0x80000000, 0xffffffff, M_DEVBUF,
+ (caddr_t)devio_ex_storage, sizeof(devio_ex_storage),
+ EX_NOCOALESCE|EX_NOWAIT);
+
+ /*
+ * Replace with real console.
+ */
+ extern int comconsrate;
+ comconsfreq = 266666666;
+ comconsrate = 115200;
+ comconsaddr = 0x00004500;
+ comconsiot = &mainbus_bus_space;
+ consinit();
+}
+
+void
+dumpsys(void)
+{
+}
+
+int imask[IPL_NUM];
+
+int netisr;
+
+/*
+ * Soft networking interrupts.
+ */
+void
+softnet(int isr)
+{
+#define DONETISR(flag, func) \
+ if (isr & (1 << flag))\
+ func();
+
+#include <net/netisr_dispatch.h>
+}
+
+int
+lcsplx(int ipl)
+{
+ return spllower(ipl);
+}
+
+/* BUS functions */
+int
+bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
+ int cacheable, bus_space_handle_t *bshp)
+{
+ int error;
+
+ if (POWERPC_BUS_TAG_BASE(t) == 0) {
+ /* if bus has base of 0 fail. */
+ return 1;
+ }
+ bpa |= POWERPC_BUS_TAG_BASE(t);
+ if ((error = extent_alloc_region(devio_ex, bpa, size, EX_NOWAIT |
+ (ppc_malloc_ok ? EX_MALLOCOK : 0))))
+ return error;
+
+ if ((error = bus_mem_add_mapping(bpa, size, cacheable, bshp))) {
+ if (extent_free(devio_ex, bpa, size, EX_NOWAIT |
+ (ppc_malloc_ok ? EX_MALLOCOK : 0)))
+ {
+ printf("bus_space_map: pa 0x%lx, size 0x%x\n",
+ bpa, size);
+ printf("bus_space_map: can't free region\n");
+ }
+ }
+ return 0;
+}
+
+bus_addr_t
+bus_space_unmap_p(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
+{
+ bus_addr_t paddr;
+
+ pmap_extract(pmap_kernel(), bsh, &paddr);
+ bus_space_unmap((t), (bsh), (size));
+ return paddr ;
+}
+
+void
+bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
+{
+ bus_addr_t sva;
+ bus_size_t off, len;
+ bus_addr_t bpa;
+
+ /* should this verify that the proper size is freed? */
+ sva = trunc_page(bsh);
+ off = bsh - sva;
+ len = size+off;
+
+ if (pmap_extract(pmap_kernel(), sva, &bpa) == TRUE) {
+ if (extent_free(devio_ex, bpa | (bsh & PAGE_MASK), size, EX_NOWAIT |
+ (ppc_malloc_ok ? EX_MALLOCOK : 0)))
+ {
+ printf("bus_space_map: pa 0x%lx, size 0x%x\n",
+ bpa, size);
+ printf("bus_space_map: can't free region\n");
+ }
+ }
+ /* do not free memory which was stolen from the vm system */
+ if (ppc_malloc_ok &&
+ ((sva >= VM_MIN_KERNEL_ADDRESS) && (sva < VM_MAX_KERNEL_ADDRESS)))
+ uvm_km_free(phys_map, sva, len);
+ else {
+ pmap_remove(pmap_kernel(), sva, sva+len);
+ pmap_update(pmap_kernel());
+ }
+}
+
+vaddr_t ppc_kvm_stolen = VM_KERN_ADDRESS_SIZE;
+
+int
+bus_mem_add_mapping(bus_addr_t bpa, bus_size_t size, int cacheable,
+ bus_space_handle_t *bshp)
+{
+ bus_addr_t vaddr;
+ bus_addr_t spa, epa;
+ bus_size_t off;
+ int len;
+
+ spa = trunc_page(bpa);
+ epa = bpa + size;
+ off = bpa - spa;
+ len = size+off;
+
+#if 0
+ if (epa <= spa) {
+ panic("bus_mem_add_mapping: overflow");
+ }
+#endif
+ if (ppc_malloc_ok == 0) {
+ bus_size_t alloc_size;
+
+ /* need to steal vm space before kernel vm is initialized */
+ alloc_size = round_page(len);
+
+ vaddr = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen;
+ ppc_kvm_stolen += alloc_size;
+ if (ppc_kvm_stolen > PPC_SEGMENT_LENGTH) {
+ panic("ppc_kvm_stolen, out of space");
+ }
+ } else {
+ vaddr = uvm_km_kmemalloc(phys_map, NULL, len,
+ UVM_KMF_NOWAIT|UVM_KMF_VALLOC);
+ if (vaddr == 0)
+ panic("bus_mem_add_mapping: kvm alloc of 0x%x failed",
+ len);
+ }
+ *bshp = vaddr + off;
+#ifdef DEBUG_BUS_MEM_ADD_MAPPING
+ printf("mapping %x size %x to %x vbase %x\n",
+ bpa, size, *bshp, spa);
+#endif
+ for (; len > 0; len -= PAGE_SIZE) {
+ pmap_kenter_cache(vaddr, spa,
+ VM_PROT_READ | VM_PROT_WRITE,
+ cacheable ? PMAP_CACHE_WT : PMAP_CACHE_CI);
+ spa += PAGE_SIZE;
+ vaddr += PAGE_SIZE;
+ }
+ return 0;
+}
+
+int
+bus_space_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend,
+ bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable,
+ bus_addr_t *addrp, bus_space_handle_t *handlep)
+{
+
+ panic("bus_space_alloc: unimplemented");
+}
+
+void
+bus_space_free(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size)
+{
+
+ panic("bus_space_free: unimplemented");
+}
+
+void *
+mapiodev(paddr_t pa, psize_t len)
+{
+ paddr_t spa;
+ vaddr_t vaddr, va;
+ int off;
+ int size;
+
+ spa = trunc_page(pa);
+ off = pa - spa;
+ size = round_page(off+len);
+ if (ppc_malloc_ok == 0) {
+ /* need to steal vm space before kernel vm is initialized */
+ va = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen;
+ ppc_kvm_stolen += size;
+ if (ppc_kvm_stolen > PPC_SEGMENT_LENGTH) {
+ panic("ppc_kvm_stolen, out of space");
+ }
+ } else {
+ va = uvm_km_kmemalloc(phys_map, NULL, size,
+ UVM_KMF_NOWAIT|UVM_KMF_VALLOC);
+ }
+
+ if (va == 0)
+ return NULL;
+
+ for (vaddr = va; size > 0; size -= PAGE_SIZE) {
+ pmap_kenter_cache(vaddr, spa,
+ VM_PROT_READ | VM_PROT_WRITE, PMAP_CACHE_DEFAULT);
+ spa += PAGE_SIZE;
+ vaddr += PAGE_SIZE;
+ }
+ return (void *) (va+off);
+}
+
+void
+unmapiodev(void *kva, psize_t p_size)
+{
+ vaddr_t vaddr;
+ int size;
+
+ size = p_size;
+
+ vaddr = trunc_page((vaddr_t)kva);
+
+ uvm_km_free_wakeup(phys_map, vaddr, size);
+
+ for (; size > 0; size -= PAGE_SIZE) {
+ pmap_remove(pmap_kernel(), vaddr, vaddr+PAGE_SIZE-1);
+ vaddr += PAGE_SIZE;
+ }
+ pmap_update(pmap_kernel());
+}
+
+
+/*
+ * probably should be ppc_space_copy
+ */
+
+#define _CONCAT(A,B) A ## B
+#define __C(A,B) _CONCAT(A,B)
+
+#define BUS_SPACE_COPY_N(BYTES,TYPE) \
+void \
+__C(bus_space_copy_,BYTES)(void *v, bus_space_handle_t h1, \
+ bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, \
+ bus_size_t c) \
+{ \
+ TYPE *src, *dst; \
+ int i; \
+ \
+ src = (TYPE *) (h1+o1); \
+ dst = (TYPE *) (h2+o2); \
+ \
+ if (h1 == h2 && o2 > o1) \
+ for (i = c-1; i >= 0; i--) \
+ dst[i] = src[i]; \
+ else \
+ for (i = 0; i < c; i++) \
+ dst[i] = src[i]; \
+}
+BUS_SPACE_COPY_N(1,u_int8_t)
+BUS_SPACE_COPY_N(2,u_int16_t)
+BUS_SPACE_COPY_N(4,u_int32_t)
+
+void
+bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int8_t val, bus_size_t c)
+{
+ u_int8_t *dst;
+ int i;
+
+ dst = (u_int8_t *) (h+o);
+
+ for (i = 0; i < c; i++)
+ dst[i] = val;
+}
+
+void
+bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int16_t val, bus_size_t c)
+{
+ u_int16_t *dst;
+ int i;
+
+ dst = (u_int16_t *) (h+o);
+ val = swap16(val);
+
+ for (i = 0; i < c; i++)
+ dst[i] = val;
+}
+void
+bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int32_t val, bus_size_t c)
+{
+ u_int32_t *dst;
+ int i;
+
+ dst = (u_int32_t *) (h+o);
+ val = swap32(val);
+
+ for (i = 0; i < c; i++)
+ dst[i] = val;
+}
+
+#define BUS_SPACE_READ_RAW_MULTI_N(BYTES,SHIFT,TYPE) \
+void \
+__C(bus_space_read_raw_multi_,BYTES)(bus_space_tag_t bst, \
+ bus_space_handle_t h, bus_addr_t o, u_int8_t *dst, bus_size_t size) \
+{ \
+ TYPE *src; \
+ TYPE *rdst = (TYPE *)dst; \
+ int i; \
+ int count = size >> SHIFT; \
+ \
+ src = (TYPE *)(h+o); \
+ for (i = 0; i < count; i++) { \
+ rdst[i] = *src; \
+ __asm__("eieio"); \
+ } \
+}
+BUS_SPACE_READ_RAW_MULTI_N(2,1,u_int16_t)
+BUS_SPACE_READ_RAW_MULTI_N(4,2,u_int32_t)
+
+#define BUS_SPACE_WRITE_RAW_MULTI_N(BYTES,SHIFT,TYPE) \
+void \
+__C(bus_space_write_raw_multi_,BYTES)( bus_space_tag_t bst, \
+ bus_space_handle_t h, bus_addr_t o, const u_int8_t *src, \
+ bus_size_t size) \
+{ \
+ int i; \
+ TYPE *dst; \
+ TYPE *rsrc = (TYPE *)src; \
+ int count = size >> SHIFT; \
+ \
+ dst = (TYPE *)(h+o); \
+ for (i = 0; i < count; i++) { \
+ *dst = rsrc[i]; \
+ __asm__("eieio"); \
+ } \
+}
+
+BUS_SPACE_WRITE_RAW_MULTI_N(2,1,u_int16_t)
+BUS_SPACE_WRITE_RAW_MULTI_N(4,2,u_int32_t)
+
+int
+bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
+ bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
+{
+ *nbshp = bsh + offset;
+ return (0);
+}
+
+/*
+ * Machine dependent startup code.
+ */
+void
+cpu_startup()
+{
+ int sz;
+ caddr_t v;
+ vaddr_t minaddr, maxaddr;
+
+ v = (caddr_t)proc0paddr + USPACE;
+ proc0.p_addr = proc0paddr;
+
+ printf("%s", version);
+
+ printf("real mem = %u (%uMB)\n", ptoa(physmem),
+ ptoa(physmem)/1024/1024);
+
+ /*
+ * Find out how much space we need, allocate it,
+ * and then give everything true virtual addresses.
+ */
+ sz = (int)allocsys((caddr_t)0);
+ if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
+ panic("startup: no room for tables");
+ if (allocsys(v) - v != sz)
+ panic("startup: table size inconsistency");
+
+ /*
+ * Determine how many buffers to allocate.
+ * We allocate bufcachepercent% of memory for buffer space.
+ */
+ if (bufpages == 0)
+ bufpages = physmem * bufcachepercent / 100;
+
+ /* Restrict to at most 25% filled kvm */
+ if (bufpages >
+ (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
+ bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
+ PAGE_SIZE / 4;
+
+ /*
+ * Allocate a submap for exec arguments. This map effectively
+ * limits the number of processes exec'ing at any time.
+ */
+ minaddr = vm_map_min(kernel_map);
+ exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16 * NCARGS,
+ VM_MAP_PAGEABLE, FALSE, NULL);
+
+ /*
+ * Allocate a submap for physio
+ */
+ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
+ VM_PHYS_SIZE, 0, FALSE, NULL);
+ ppc_malloc_ok = 1;
+
+ printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
+ ptoa(uvmexp.free) / 1024 / 1024);
+
+ /*
+ * Set up the buffers.
+ */
+ bufinit();
+
+ devio_malloc_safe = 1;
+}
+
+/*
+ * Allocate space for system data structures.
+ */
+caddr_t
+allocsys(caddr_t v)
+{
+#define valloc(name, type, num) \
+ v = (caddr_t)(((name) = (type *)v) + (num))
+
+#ifdef SYSVMSG
+ valloc(msgpool, char, msginfo.msgmax);
+ valloc(msgmaps, struct msgmap, msginfo.msgseg);
+ valloc(msghdrs, struct msg, msginfo.msgtql);
+ valloc(msqids, struct msqid_ds, msginfo.msgmni);
+#endif
+
+ return v;
+}
+
+/*
+ * consinit
+ * Initialize system console.
+ */
+void
+consinit()
+{
+ static int cons_initted = 0;
+
+ if (cons_initted)
+ return;
+ cninit();
+ cons_initted = 1;
+}
+
+/*
+ * Clear registers on exec
+ */
+void
+setregs(struct proc *p, struct exec_package *pack, u_long stack,
+ register_t *retval)
+{
+ u_int32_t newstack;
+ u_int32_t pargs;
+ u_int32_t args[4];
+
+ struct trapframe *tf = trapframe(p);
+ pargs = -roundup(-stack + 8, 16);
+ newstack = (u_int32_t)(pargs - 32);
+
+ copyin ((void *)(VM_MAX_ADDRESS-0x10), &args, 0x10);
+
+ bzero(tf, sizeof *tf);
+ tf->fixreg[1] = newstack;
+ tf->fixreg[3] = retval[0] = args[1]; /* XXX */
+ tf->fixreg[4] = retval[1] = args[0]; /* XXX */
+ tf->fixreg[5] = args[2]; /* XXX */
+ tf->fixreg[6] = args[3]; /* XXX */
+ tf->srr0 = pack->ep_entry;
+ tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
+ p->p_addr->u_pcb.pcb_flags = 0;
+}
+
+/*
+ * Send a signal to process.
+ */
+void
+sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
+ union sigval val)
+{
+ struct proc *p = curproc;
+ struct trapframe *tf;
+ struct sigframe *fp, frame;
+ struct sigacts *psp = p->p_sigacts;
+ int oldonstack;
+
+ frame.sf_signum = sig;
+
+ tf = trapframe(p);
+ oldonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
+
+ /*
+ * Allocate stack space for signal handler.
+ */
+ if ((psp->ps_flags & SAS_ALTSTACK)
+ && !oldonstack
+ && (psp->ps_sigonstack & sigmask(sig))) {
+ fp = (struct sigframe *)(psp->ps_sigstk.ss_sp
+ + psp->ps_sigstk.ss_size);
+ psp->ps_sigstk.ss_flags |= SS_ONSTACK;
+ } else
+ fp = (struct sigframe *)tf->fixreg[1];
+
+ fp = (struct sigframe *)((int)(fp - 1) & ~0xf);
+
+ /*
+ * Generate signal context for SYS_sigreturn.
+ */
+ frame.sf_sc.sc_onstack = oldonstack;
+ frame.sf_sc.sc_mask = mask;
+ frame.sf_sip = NULL;
+ bcopy(tf, &frame.sf_sc.sc_frame, sizeof *tf);
+ if (psp->ps_siginfo & sigmask(sig)) {
+ frame.sf_sip = &fp->sf_si;
+ initsiginfo(&frame.sf_si, sig, code, type, val);
+ }
+ if (copyout(&frame, fp, sizeof frame) != 0)
+ sigexit(p, SIGILL);
+
+
+ tf->fixreg[1] = (int)fp;
+ tf->lr = (int)catcher;
+ tf->fixreg[3] = (int)sig;
+ tf->fixreg[4] = (psp->ps_siginfo & sigmask(sig)) ? (int)&fp->sf_si : 0;
+ tf->fixreg[5] = (int)&fp->sf_sc;
+ tf->srr0 = p->p_sigcode;
+
+#if WHEN_WE_ONLY_FLUSH_DATA_WHEN_DOING_PMAP_ENTER
+ pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map),tf->srr0, &pa);
+ syncicache(pa, (p->p_emul->e_esigcode - p->p_emul->e_sigcode));
+#endif
+}
+
+/*
+ * System call to cleanup state after a signal handler returns.
+ */
+int
+sys_sigreturn(struct proc *p, void *v, register_t *retval)
+{
+ struct sys_sigreturn_args /* {
+ syscallarg(struct sigcontext *) sigcntxp;
+ } */ *uap = v;
+ struct sigcontext sc;
+ struct trapframe *tf;
+ int error;
+
+ if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc)))
+ return error;
+ tf = trapframe(p);
+ if ((sc.sc_frame.srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC))
+ return EINVAL;
+ bcopy(&sc.sc_frame, tf, sizeof *tf);
+ if (sc.sc_onstack & 1)
+ p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
+ p->p_sigmask = sc.sc_mask & ~sigcantmask;
+ return EJUSTRETURN;
+}
+
+/*
+ * Machine dependent system variables.
+ * None for now.
+ */
+int
+cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
+ size_t newlen, struct proc *p)
+{
+ /* all sysctl names at this level are terminal */
+ if (namelen != 1)
+ return ENOTDIR;
+ switch (name[0]) {
+ case CPU_ALLOWAPERTURE:
+#ifdef APERTURE
+ if (securelevel > 0)
+ return (sysctl_int_lower(oldp, oldlenp, newp, newlen,
+ &allowaperture));
+ else
+ return (sysctl_int(oldp, oldlenp, newp, newlen,
+ &allowaperture));
+#else
+ return (sysctl_rdint(oldp, oldlenp, newp, 0));
+#endif
+ case CPU_ALTIVEC:
+ return (sysctl_rdint(oldp, oldlenp, newp, 0));
+ default:
+ return EOPNOTSUPP;
+ }
+}
+
+u_long dumpmag = 0x04959fca; /* magic number */
+int dumpsize = 0; /* size of dump in pages */
+long dumplo = -1; /* blocks */
+
+/*
+ * This is called by configure to set dumplo and dumpsize.
+ * Dumps always skip the first CLBYTES of disk space
+ * in case there might be a disk label stored there.
+ * If there is extra space, put dump at the end to
+ * reduce the chance that swapping trashes it.
+ */
+void dumpconf(void);
+
+void
+dumpconf(void)
+{
+ int nblks; /* size of dump area */
+ int i;
+
+ if (dumpdev == NODEV ||
+ (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
+ return;
+ if (nblks <= ctod(1))
+ return;
+
+ /* Always skip the first block, in case there is a label there. */
+ if (dumplo < ctod(1))
+ dumplo = ctod(1);
+
+ for (i = 0; i < ndumpmem; i++)
+ dumpsize = max(dumpsize, dumpmem[i].end);
+
+ /* Put dump at end of partition, and make it fit. */
+ if (dumpsize > dtoc(nblks - dumplo - 1))
+ dumpsize = dtoc(nblks - dumplo - 1);
+ if (dumplo < nblks - ctod(dumpsize) - 1)
+ dumplo = nblks - ctod(dumpsize) - 1;
+
+}
+
+#define BYTES_PER_DUMP (PAGE_SIZE) /* must be a multiple of pagesize */
+vaddr_t dumpspace;
+
+int
+reserve_dumppages(caddr_t p)
+{
+ dumpspace = (vaddr_t)p;
+ return BYTES_PER_DUMP;
+}
+
+/*
+ * Halt or reboot the machine after syncing/dumping according to howto.
+ */
+void
+boot(int howto)
+{
+ static int syncing;
+
+ boothowto = howto;
+ if (!cold && !(howto & RB_NOSYNC) && !syncing) {
+ syncing = 1;
+ vfs_shutdown(); /* sync */
+
+ /*
+ * If we've been adjusting the clock, the todr
+ * will be out of synch; adjust it now unless
+ * the system was sitting in ddb.
+ */
+ if ((howto & RB_TIMEBAD) == 0) {
+ resettodr();
+ } else {
+ printf("WARNING: not updating battery clock\n");
+ }
+ }
+
+ uvm_shutdown();
+ splhigh();
+ if (howto & RB_HALT) {
+ doshutdownhooks();
+ if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
+ ;
+ }
+
+ printf("halted\n\n");
+ (fw->exit)();
+ }
+ if (!cold && (howto & RB_DUMP))
+ dumpsys();
+ doshutdownhooks();
+ printf("rebooting\n\n");
+
+ {
+ volatile int32_t *reset;
+ int32_t v;
+
+ reset = mapiodev(0xe0000900, 0x100);
+ reset[6] = 0x52535445;
+ v = reset[6];
+ reset[7] = 0x00000002;
+ }
+
+ printf("boot failed, spinning\n");
+ while(1) /* forever */;
+}
+
+extern void ipic_do_pending_int(void);
+
+void
+do_pending_int(void)
+{
+ struct cpu_info *ci = curcpu();
+ int pcpl, s;
+
+ if (ci->ci_iactive)
+ return;
+
+ ci->ci_iactive = 1;
+ s = ppc_intr_disable();
+ pcpl = ci->ci_cpl;
+
+ ipic_do_pending_int();
+
+ do {
+ if((ci->ci_ipending & SINT_CLOCK) & ~pcpl) {
+ ci->ci_ipending &= ~SINT_CLOCK;
+ ci->ci_cpl = SINT_CLOCK|SINT_NET|SINT_TTY;
+ ppc_intr_enable(1);
+ KERNEL_LOCK();
+ softclock();
+ KERNEL_UNLOCK();
+ ppc_intr_disable();
+ continue;
+ }
+ if((ci->ci_ipending & SINT_NET) & ~pcpl) {
+ extern int netisr;
+ int pisr;
+
+ ci->ci_ipending &= ~SINT_NET;
+ ci->ci_cpl = SINT_NET|SINT_TTY;
+ while ((pisr = netisr) != 0) {
+ atomic_clearbits_int(&netisr, pisr);
+ ppc_intr_enable(1);
+ KERNEL_LOCK();
+ softnet(pisr);
+ KERNEL_UNLOCK();
+ ppc_intr_disable();
+ }
+ continue;
+ }
+#if 0
+ if((ci->ci_ipending & SINT_TTY) & ~pcpl) {
+ ci->ci_ipending &= ~SINT_TTY;
+ ci->ci_cpl = SINT_TTY;
+ ppc_intr_enable(1);
+ KERNEL_LOCK();
+ softtty();
+ KERNEL_UNLOCK();
+ ppc_intr_disable();
+ continue;
+ }
+#endif
+ } while ((ci->ci_ipending & SINT_MASK) & ~pcpl);
+ ci->ci_cpl = pcpl; /* Don't use splx... we are here already! */
+
+ ci->ci_iactive = 0;
+ ppc_intr_enable(s);
+}
+
+/*
+ * Notify the current process (p) that it has a signal pending,
+ * process as soon as possible.
+ */
+void
+signotify(struct proc *p)
+{
+ aston(p);
+}
+
+/* bcopy(), error on fault */
+int
+kcopy(const void *from, void *to, size_t size)
+{
+ faultbuf env;
+ void *oldh = curproc->p_addr->u_pcb.pcb_onfault;
+
+ if (setfault(&env)) {
+ curproc->p_addr->u_pcb.pcb_onfault = oldh;
+ return EFAULT;
+ }
+ bcopy(from, to, size);
+ curproc->p_addr->u_pcb.pcb_onfault = oldh;
+
+ return 0;
+}
+
+struct mem_region uboot_mem[2] = {
+ { 0x00000000, 0x04000000 },
+ { 0, 0 }
+};
+
+struct mem_region uboot_avail[2] = {
+ { 0x00800000, 0x04000000 },
+ { 0, 0 }
+};
+
+void
+uboot_mem_regions(struct mem_region **memp, struct mem_region **availp)
+{
+ *memp = uboot_mem;
+ *availp = uboot_avail;
+}
+
+void
+uboot_vmon(void)
+{
+}
+
+/* prototype for locore function */
+void cpu_switchto_asm(struct proc *oldproc, struct proc *newproc);
+
+void cpu_switchto(struct proc *oldproc, struct proc *newproc)
+{
+ cpu_switchto_asm(oldproc, newproc);
+}
diff --git a/sys/arch/socppc/socppc/mainbus.c b/sys/arch/socppc/socppc/mainbus.c
new file mode 100644
index 00000000000..ecd92ab7389
--- /dev/null
+++ b/sys/arch/socppc/socppc/mainbus.c
@@ -0,0 +1,77 @@
+/* $OpenBSD: mainbus.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+
+int mainbus_match(struct device *, void *, void *);
+void mainbus_attach(struct device *, struct device *, void *);
+
+struct cfattach mainbus_ca = {
+ sizeof(struct device), mainbus_match, mainbus_attach
+};
+
+struct cfdriver mainbus_cd = {
+ NULL, "mainbus", DV_DULL
+};
+
+int mainbus_search(struct device *, void *, void *);
+int mainbus_print(void *, const char *);
+
+int
+mainbus_match(struct device *parent, void *cfdata, void *aux)
+{
+ return (1);
+}
+
+void
+mainbus_attach(struct device *parent, struct device *self, void *aux)
+{
+ printf("\n");
+
+ config_search(mainbus_search, self, self);
+}
+
+struct ppc_bus_space mainbus_bus_space = { 0xe0000000, 0x1000000, 1 };
+
+int
+mainbus_search(struct device *parent, void *cfdata, void *aux)
+{
+ struct mainbus_attach_args ma;
+ struct cfdata *cf = cfdata;
+
+ ma.ma_iot = &mainbus_bus_space;
+ ma.ma_name = cf->cf_driver->cd_name;
+ config_found(parent, &ma, mainbus_print);
+
+ return (1);
+}
+
+int
+mainbus_print(void *aux, const char *name)
+{
+ struct mainbus_attach_args *ma = aux;
+
+ if (name)
+ printf("%s at %s", ma->ma_name, name);
+
+ return (UNCONF);
+}
diff --git a/sys/arch/socppc/socppc/mem.c b/sys/arch/socppc/socppc/mem.c
new file mode 100644
index 00000000000..add5fc64368
--- /dev/null
+++ b/sys/arch/socppc/socppc/mem.c
@@ -0,0 +1,179 @@
+/* $OpenBSD: mem.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */
+/* $NetBSD: mem.c,v 1.1 1996/09/30 16:34:50 ws Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)mem.c 8.3 (Berkeley) 1/12/94
+ */
+
+/*
+ * Memory special file
+ */
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/systm.h>
+#include <sys/ioccom.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/types.h>
+
+#include <machine/cpu.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/conf.h>
+
+/*ARGSUSED*/
+int
+mmopen(dev_t dev, int flag, int mode, struct proc *p)
+{
+
+ switch (minor(dev)) {
+ case 0:
+ case 1:
+ case 2:
+ case 12:
+ break;
+#ifdef xAPERTURE
+ case 4:
+ if (suser(p, 0) != 0 || !allowaperture)
+ return (EPERM);
+
+ /* authorize only one simultaneous open() */
+ if (ap_open_count > 0)
+ return(EPERM);
+ ap_open_count++;
+ break;
+#endif
+ default:
+ return (ENXIO);
+ }
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmclose(dev_t dev, int flag, int mode, struct proc *p)
+{
+#ifdef xAPERTURE
+ if (minor(dev) == 4)
+ ap_open_count--;
+#endif
+ return 0;
+}
+
+/*ARGSUSED*/
+int
+mmrw(dev_t dev, struct uio *uio, int flags)
+{
+ vaddr_t v;
+ vsize_t c;
+ struct iovec *iov;
+ int error = 0;
+ static caddr_t zeropage;
+
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("mmrw");
+ continue;
+ }
+ switch (minor(dev)) {
+
+ /* minor device 0 is physical memory */
+ case 0:
+ v = uio->uio_offset;
+ c = uio->uio_resid;
+ /* This doesn't allow device mapping! XXX */
+ pmap_real_memory(&v, &c);
+ error = uiomove((caddr_t)v, c, uio);
+ continue;
+
+ /* minor device 1 is kernel memory */
+ case 1:
+ v = uio->uio_offset;
+ c = min(iov->iov_len, MAXPHYS);
+ error = uiomove((caddr_t)v, c, uio);
+ continue;
+
+ /* minor device 2 is EOF/RATHOLE */
+ case 2:
+ if (uio->uio_rw == UIO_WRITE)
+ uio->uio_resid = 0;
+ return 0;
+
+ /* minor device 12 (/dev/zero) is source of nulls on read,
+ * rathole on write
+ */
+ case 12:
+ if (uio->uio_rw == UIO_WRITE) {
+ c = iov->iov_len;
+ break;
+ }
+ if (zeropage == NULL)
+ zeropage = malloc(PAGE_SIZE, M_TEMP,
+ M_WAITOK | M_ZERO);
+ c = min(iov->iov_len, PAGE_SIZE);
+ error = uiomove(zeropage, c, uio);
+ continue;
+
+ default:
+ return ENXIO;
+ }
+ if (error)
+ break;
+ iov->iov_base += c;
+ iov->iov_len -= c;
+ uio->uio_offset += c;
+ uio->uio_resid -= c;
+ }
+ return error;
+}
+
+paddr_t
+mmmmap(dev_t dev, off_t off, int prot)
+{
+ return (-1);
+}
+
+/*ARGSUSED*/
+int
+mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
+{
+ return (EOPNOTSUPP);
+}