[Midnightbsd-cvs] src [9916] trunk/sys/powerpc: sync with freebsd

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Fri May 25 08:54:09 EDT 2018


Revision: 9916
          http://svnweb.midnightbsd.org/src/?rev=9916
Author:   laffer1
Date:     2018-05-25 08:54:08 -0400 (Fri, 25 May 2018)
Log Message:
-----------
sync with freebsd

Added Paths:
-----------
    trunk/sys/powerpc/
    trunk/sys/powerpc/aim/
    trunk/sys/powerpc/aim/interrupt.c
    trunk/sys/powerpc/aim/locore.S
    trunk/sys/powerpc/aim/locore32.S
    trunk/sys/powerpc/aim/locore64.S
    trunk/sys/powerpc/aim/machdep.c
    trunk/sys/powerpc/aim/mmu_oea.c
    trunk/sys/powerpc/aim/mmu_oea64.c
    trunk/sys/powerpc/aim/mmu_oea64.h
    trunk/sys/powerpc/aim/moea64_if.m
    trunk/sys/powerpc/aim/moea64_native.c
    trunk/sys/powerpc/aim/mp_cpudep.c
    trunk/sys/powerpc/aim/slb.c
    trunk/sys/powerpc/aim/trap.c
    trunk/sys/powerpc/aim/trap_subr32.S
    trunk/sys/powerpc/aim/trap_subr64.S
    trunk/sys/powerpc/aim/uma_machdep.c
    trunk/sys/powerpc/booke/
    trunk/sys/powerpc/booke/interrupt.c
    trunk/sys/powerpc/booke/locore.S
    trunk/sys/powerpc/booke/machdep.c
    trunk/sys/powerpc/booke/machdep_e500.c
    trunk/sys/powerpc/booke/machdep_ppc4xx.c
    trunk/sys/powerpc/booke/mp_cpudep.c
    trunk/sys/powerpc/booke/platform_bare.c
    trunk/sys/powerpc/booke/pmap.c
    trunk/sys/powerpc/booke/trap.c
    trunk/sys/powerpc/booke/trap_subr.S
    trunk/sys/powerpc/compile/
    trunk/sys/powerpc/conf/
    trunk/sys/powerpc/conf/DEFAULTS
    trunk/sys/powerpc/conf/GENERIC
    trunk/sys/powerpc/conf/GENERIC.hints
    trunk/sys/powerpc/conf/GENERIC64
    trunk/sys/powerpc/conf/MPC85XX
    trunk/sys/powerpc/conf/Makefile
    trunk/sys/powerpc/conf/NOTES
    trunk/sys/powerpc/conf/WII
    trunk/sys/powerpc/cpufreq/
    trunk/sys/powerpc/cpufreq/dfs.c
    trunk/sys/powerpc/cpufreq/pcr.c
    trunk/sys/powerpc/cpufreq/pmufreq.c
    trunk/sys/powerpc/fpu/
    trunk/sys/powerpc/fpu/fpu_add.c
    trunk/sys/powerpc/fpu/fpu_arith.h
    trunk/sys/powerpc/fpu/fpu_compare.c
    trunk/sys/powerpc/fpu/fpu_div.c
    trunk/sys/powerpc/fpu/fpu_emu.c
    trunk/sys/powerpc/fpu/fpu_emu.h
    trunk/sys/powerpc/fpu/fpu_explode.c
    trunk/sys/powerpc/fpu/fpu_extern.h
    trunk/sys/powerpc/fpu/fpu_implode.c
    trunk/sys/powerpc/fpu/fpu_instr.h
    trunk/sys/powerpc/fpu/fpu_mul.c
    trunk/sys/powerpc/fpu/fpu_sqrt.c
    trunk/sys/powerpc/fpu/fpu_subr.c
    trunk/sys/powerpc/include/
    trunk/sys/powerpc/include/_align.h
    trunk/sys/powerpc/include/_bus.h
    trunk/sys/powerpc/include/_inttypes.h
    trunk/sys/powerpc/include/_limits.h
    trunk/sys/powerpc/include/_stdint.h
    trunk/sys/powerpc/include/_types.h
    trunk/sys/powerpc/include/altivec.h
    trunk/sys/powerpc/include/asm.h
    trunk/sys/powerpc/include/atomic.h
    trunk/sys/powerpc/include/bat.h
    trunk/sys/powerpc/include/bus.h
    trunk/sys/powerpc/include/bus_dma.h
    trunk/sys/powerpc/include/clock.h
    trunk/sys/powerpc/include/counter.h
    trunk/sys/powerpc/include/cpu.h
    trunk/sys/powerpc/include/cpufunc.h
    trunk/sys/powerpc/include/db_machdep.h
    trunk/sys/powerpc/include/dbdma.h
    trunk/sys/powerpc/include/elf.h
    trunk/sys/powerpc/include/endian.h
    trunk/sys/powerpc/include/exec.h
    trunk/sys/powerpc/include/float.h
    trunk/sys/powerpc/include/floatingpoint.h
    trunk/sys/powerpc/include/fpu.h
    trunk/sys/powerpc/include/frame.h
    trunk/sys/powerpc/include/gdb_machdep.h
    trunk/sys/powerpc/include/hid.h
    trunk/sys/powerpc/include/ieee.h
    trunk/sys/powerpc/include/ieeefp.h
    trunk/sys/powerpc/include/in_cksum.h
    trunk/sys/powerpc/include/intr_machdep.h
    trunk/sys/powerpc/include/kdb.h
    trunk/sys/powerpc/include/limits.h
    trunk/sys/powerpc/include/machdep.h
    trunk/sys/powerpc/include/md_var.h
    trunk/sys/powerpc/include/memdev.h
    trunk/sys/powerpc/include/metadata.h
    trunk/sys/powerpc/include/mmuvar.h
    trunk/sys/powerpc/include/ofw_machdep.h
    trunk/sys/powerpc/include/openpicreg.h
    trunk/sys/powerpc/include/openpicvar.h
    trunk/sys/powerpc/include/param.h
    trunk/sys/powerpc/include/pcb.h
    trunk/sys/powerpc/include/pcpu.h
    trunk/sys/powerpc/include/pio.h
    trunk/sys/powerpc/include/platform.h
    trunk/sys/powerpc/include/platformvar.h
    trunk/sys/powerpc/include/pmap.h
    trunk/sys/powerpc/include/pmc_mdep.h
    trunk/sys/powerpc/include/proc.h
    trunk/sys/powerpc/include/profile.h
    trunk/sys/powerpc/include/psl.h
    trunk/sys/powerpc/include/pte.h
    trunk/sys/powerpc/include/ptrace.h
    trunk/sys/powerpc/include/reg.h
    trunk/sys/powerpc/include/reloc.h
    trunk/sys/powerpc/include/resource.h
    trunk/sys/powerpc/include/rtas.h
    trunk/sys/powerpc/include/runq.h
    trunk/sys/powerpc/include/sc_machdep.h
    trunk/sys/powerpc/include/setjmp.h
    trunk/sys/powerpc/include/sf_buf.h
    trunk/sys/powerpc/include/sigframe.h
    trunk/sys/powerpc/include/signal.h
    trunk/sys/powerpc/include/slb.h
    trunk/sys/powerpc/include/smp.h
    trunk/sys/powerpc/include/spr.h
    trunk/sys/powerpc/include/sr.h
    trunk/sys/powerpc/include/stack.h
    trunk/sys/powerpc/include/stdarg.h
    trunk/sys/powerpc/include/sysarch.h
    trunk/sys/powerpc/include/tlb.h
    trunk/sys/powerpc/include/trap.h
    trunk/sys/powerpc/include/ucontext.h
    trunk/sys/powerpc/include/varargs.h
    trunk/sys/powerpc/include/vdso.h
    trunk/sys/powerpc/include/vm.h
    trunk/sys/powerpc/include/vmparam.h
    trunk/sys/powerpc/mambo/
    trunk/sys/powerpc/mambo/mambo.c
    trunk/sys/powerpc/mambo/mambo_console.c
    trunk/sys/powerpc/mambo/mambo_disk.c
    trunk/sys/powerpc/mambo/mambocall.S
    trunk/sys/powerpc/mambo/mambocall.h
    trunk/sys/powerpc/mpc85xx/
    trunk/sys/powerpc/mpc85xx/atpic.c
    trunk/sys/powerpc/mpc85xx/ds1553_bus_fdt.c
    trunk/sys/powerpc/mpc85xx/ds1553_core.c
    trunk/sys/powerpc/mpc85xx/ds1553_reg.h
    trunk/sys/powerpc/mpc85xx/fsl_sdhc.c
    trunk/sys/powerpc/mpc85xx/fsl_sdhc.h
    trunk/sys/powerpc/mpc85xx/i2c.c
    trunk/sys/powerpc/mpc85xx/isa.c
    trunk/sys/powerpc/mpc85xx/lbc.c
    trunk/sys/powerpc/mpc85xx/lbc.h
    trunk/sys/powerpc/mpc85xx/mpc85xx.c
    trunk/sys/powerpc/mpc85xx/mpc85xx.h
    trunk/sys/powerpc/mpc85xx/pci_mpc85xx.c
    trunk/sys/powerpc/mpc85xx/platform_mpc85xx.c
    trunk/sys/powerpc/ofw/
    trunk/sys/powerpc/ofw/ofw_machdep.c
    trunk/sys/powerpc/ofw/ofw_pci.c
    trunk/sys/powerpc/ofw/ofw_pci.h
    trunk/sys/powerpc/ofw/ofw_pcib_pci.c
    trunk/sys/powerpc/ofw/ofw_pcibus.c
    trunk/sys/powerpc/ofw/ofw_pcibus.h
    trunk/sys/powerpc/ofw/ofw_real.c
    trunk/sys/powerpc/ofw/ofw_syscons.c
    trunk/sys/powerpc/ofw/ofw_syscons.h
    trunk/sys/powerpc/ofw/ofwcall32.S
    trunk/sys/powerpc/ofw/ofwcall64.S
    trunk/sys/powerpc/ofw/ofwmagic.S
    trunk/sys/powerpc/ofw/openpic_ofw.c
    trunk/sys/powerpc/ofw/rtas.c
    trunk/sys/powerpc/powermac/
    trunk/sys/powerpc/powermac/ata_dbdma.c
    trunk/sys/powerpc/powermac/ata_dbdma.h
    trunk/sys/powerpc/powermac/ata_kauai.c
    trunk/sys/powerpc/powermac/ata_macio.c
    trunk/sys/powerpc/powermac/atibl.c
    trunk/sys/powerpc/powermac/cpcht.c
    trunk/sys/powerpc/powermac/cuda.c
    trunk/sys/powerpc/powermac/cudavar.h
    trunk/sys/powerpc/powermac/dbdma.c
    trunk/sys/powerpc/powermac/dbdmavar.h
    trunk/sys/powerpc/powermac/fcu.c
    trunk/sys/powerpc/powermac/grackle.c
    trunk/sys/powerpc/powermac/gracklevar.h
    trunk/sys/powerpc/powermac/hrowpic.c
    trunk/sys/powerpc/powermac/hrowpicvar.h
    trunk/sys/powerpc/powermac/kiic.c
    trunk/sys/powerpc/powermac/macgpio.c
    trunk/sys/powerpc/powermac/macgpiovar.h
    trunk/sys/powerpc/powermac/macio.c
    trunk/sys/powerpc/powermac/maciovar.h
    trunk/sys/powerpc/powermac/nvbl.c
    trunk/sys/powerpc/powermac/platform_powermac.c
    trunk/sys/powerpc/powermac/pmu.c
    trunk/sys/powerpc/powermac/pmuvar.h
    trunk/sys/powerpc/powermac/powermac_thermal.c
    trunk/sys/powerpc/powermac/powermac_thermal.h
    trunk/sys/powerpc/powermac/pswitch.c
    trunk/sys/powerpc/powermac/smu.c
    trunk/sys/powerpc/powermac/smusat.c
    trunk/sys/powerpc/powermac/uninorth.c
    trunk/sys/powerpc/powermac/uninorthpci.c
    trunk/sys/powerpc/powermac/uninorthvar.h
    trunk/sys/powerpc/powermac/vcoregpio.c
    trunk/sys/powerpc/powermac/viareg.h
    trunk/sys/powerpc/powermac/windtunnel.c
    trunk/sys/powerpc/powerpc/
    trunk/sys/powerpc/powerpc/altivec.c
    trunk/sys/powerpc/powerpc/autoconf.c
    trunk/sys/powerpc/powerpc/bcopy.c
    trunk/sys/powerpc/powerpc/bus_machdep.c
    trunk/sys/powerpc/powerpc/busdma_machdep.c
    trunk/sys/powerpc/powerpc/clock.c
    trunk/sys/powerpc/powerpc/copyinout.c
    trunk/sys/powerpc/powerpc/copystr.c
    trunk/sys/powerpc/powerpc/cpu.c
    trunk/sys/powerpc/powerpc/db_disasm.c
    trunk/sys/powerpc/powerpc/db_hwwatch.c
    trunk/sys/powerpc/powerpc/db_interface.c
    trunk/sys/powerpc/powerpc/db_trace.c
    trunk/sys/powerpc/powerpc/dump_machdep.c
    trunk/sys/powerpc/powerpc/elf32_machdep.c
    trunk/sys/powerpc/powerpc/elf64_machdep.c
    trunk/sys/powerpc/powerpc/exec_machdep.c
    trunk/sys/powerpc/powerpc/fpu.c
    trunk/sys/powerpc/powerpc/fuswintr.c
    trunk/sys/powerpc/powerpc/gdb_machdep.c
    trunk/sys/powerpc/powerpc/genassym.c
    trunk/sys/powerpc/powerpc/in_cksum.c
    trunk/sys/powerpc/powerpc/intr_machdep.c
    trunk/sys/powerpc/powerpc/iommu_if.m
    trunk/sys/powerpc/powerpc/mem.c
    trunk/sys/powerpc/powerpc/mmu_if.m
    trunk/sys/powerpc/powerpc/mp_machdep.c
    trunk/sys/powerpc/powerpc/nexus.c
    trunk/sys/powerpc/powerpc/openpic.c
    trunk/sys/powerpc/powerpc/pic_if.m
    trunk/sys/powerpc/powerpc/platform.c
    trunk/sys/powerpc/powerpc/platform_if.m
    trunk/sys/powerpc/powerpc/pmap_dispatch.c
    trunk/sys/powerpc/powerpc/sc_machdep.c
    trunk/sys/powerpc/powerpc/setjmp.S
    trunk/sys/powerpc/powerpc/sigcode32.S
    trunk/sys/powerpc/powerpc/sigcode64.S
    trunk/sys/powerpc/powerpc/stack_machdep.c
    trunk/sys/powerpc/powerpc/suswintr.c
    trunk/sys/powerpc/powerpc/swtch32.S
    trunk/sys/powerpc/powerpc/swtch64.S
    trunk/sys/powerpc/powerpc/syncicache.c
    trunk/sys/powerpc/powerpc/sys_machdep.c
    trunk/sys/powerpc/powerpc/uio_machdep.c
    trunk/sys/powerpc/powerpc/vm_machdep.c
    trunk/sys/powerpc/ps3/
    trunk/sys/powerpc/ps3/ehci_ps3.c
    trunk/sys/powerpc/ps3/if_glc.c
    trunk/sys/powerpc/ps3/if_glcreg.h
    trunk/sys/powerpc/ps3/mmu_ps3.c
    trunk/sys/powerpc/ps3/ohci_ps3.c
    trunk/sys/powerpc/ps3/platform_ps3.c
    trunk/sys/powerpc/ps3/ps3-hv-asm.awk
    trunk/sys/powerpc/ps3/ps3-hv-header.awk
    trunk/sys/powerpc/ps3/ps3-hvcall.S
    trunk/sys/powerpc/ps3/ps3-hvcall.h
    trunk/sys/powerpc/ps3/ps3-hvcall.master
    trunk/sys/powerpc/ps3/ps3_syscons.c
    trunk/sys/powerpc/ps3/ps3bus.c
    trunk/sys/powerpc/ps3/ps3bus.h
    trunk/sys/powerpc/ps3/ps3cdrom.c
    trunk/sys/powerpc/ps3/ps3disk.c
    trunk/sys/powerpc/ps3/ps3pic.c
    trunk/sys/powerpc/pseries/
    trunk/sys/powerpc/pseries/mmu_phyp.c
    trunk/sys/powerpc/pseries/phyp-hvcall.S
    trunk/sys/powerpc/pseries/phyp-hvcall.h
    trunk/sys/powerpc/pseries/phyp_console.c
    trunk/sys/powerpc/pseries/phyp_llan.c
    trunk/sys/powerpc/pseries/phyp_vscsi.c
    trunk/sys/powerpc/pseries/platform_chrp.c
    trunk/sys/powerpc/pseries/plpar_iommu.c
    trunk/sys/powerpc/pseries/plpar_iommu.h
    trunk/sys/powerpc/pseries/plpar_pcibus.c
    trunk/sys/powerpc/pseries/rtas_dev.c
    trunk/sys/powerpc/pseries/rtas_pci.c
    trunk/sys/powerpc/pseries/vdevice.c
    trunk/sys/powerpc/pseries/xics.c
    trunk/sys/powerpc/psim/
    trunk/sys/powerpc/psim/ata_iobus.c
    trunk/sys/powerpc/psim/iobus.c
    trunk/sys/powerpc/psim/iobusvar.h
    trunk/sys/powerpc/psim/openpic_iobus.c
    trunk/sys/powerpc/psim/psim-tree
    trunk/sys/powerpc/psim/uart_iobus.c
    trunk/sys/powerpc/wii/
    trunk/sys/powerpc/wii/locore.S
    trunk/sys/powerpc/wii/platform_wii.c
    trunk/sys/powerpc/wii/wii_bus.c
    trunk/sys/powerpc/wii/wii_exireg.h
    trunk/sys/powerpc/wii/wii_fb.c
    trunk/sys/powerpc/wii/wii_fbreg.h
    trunk/sys/powerpc/wii/wii_fbvar.h
    trunk/sys/powerpc/wii/wii_gpio.c
    trunk/sys/powerpc/wii/wii_gpioreg.h
    trunk/sys/powerpc/wii/wii_ipc.c
    trunk/sys/powerpc/wii/wii_ipcreg.h
    trunk/sys/powerpc/wii/wii_pic.c
    trunk/sys/powerpc/wii/wii_picreg.h

Added: trunk/sys/powerpc/aim/interrupt.c
===================================================================
--- trunk/sys/powerpc/aim/interrupt.c	                        (rev 0)
+++ trunk/sys/powerpc/aim/interrupt.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,123 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2002 by Peter Grehan. 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/aim/interrupt.c 260667 2014-01-15 04:16:45Z jhibbits $
+ */
+
+/*
+ * Interrupts are dispatched to here from locore asm
+ */
+
+#include "opt_hwpmc_hooks.h"
+
+#include <sys/cdefs.h>                  /* RCS ID & Copyright macro defns */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#ifdef HWPMC_HOOKS
+#include <sys/pmckern.h>
+#endif
+#include <sys/proc.h>
+#include <sys/smp.h>
+#include <sys/unistd.h>
+#include <sys/vmmeter.h>
+
+#include <machine/cpu.h>
+#include <machine/clock.h>
+#include <machine/db_machdep.h>
+#include <machine/fpu.h>
+#include <machine/frame.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+#include <machine/psl.h>
+#include <machine/trap.h>
+#include <machine/spr.h>
+#include <machine/sr.h>
+
+#include "pic_if.h"
+
+/*
+ * A very short dispatch, to try and maximise assembler code use
+ * between all exception types. Maybe 'true' interrupts should go
+ * here, and the trap code can come in separately
+ */
+void
+powerpc_interrupt(struct trapframe *framep)
+{
+	struct thread *td;
+	struct trapframe *oldframe;
+	register_t ee;
+
+	td = curthread;
+
+	CTR2(KTR_INTR, "%s: EXC=%x", __func__, framep->exc);
+
+	switch (framep->exc) {
+	case EXC_EXI:
+		critical_enter();
+		PIC_DISPATCH(root_pic, framep);
+		critical_exit();
+		break;
+
+	case EXC_DECR:
+		critical_enter();
+		atomic_add_int(&td->td_intr_nesting_level, 1);
+		oldframe = td->td_intr_frame;
+		td->td_intr_frame = framep;
+		decr_intr(framep);
+		td->td_intr_frame = oldframe;
+		atomic_subtract_int(&td->td_intr_nesting_level, 1);
+		critical_exit();
+		break;
+#ifdef HWPMC_HOOKS
+	case EXC_PERF:
+		critical_enter();
+		KASSERT(pmc_intr != NULL, ("Performance exception, but no handler!"));
+		(*pmc_intr)(PCPU_GET(cpuid), framep);
+		if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
+			pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, framep);
+		critical_exit();
+		break;
+#endif
+
+	default:
+		/* Re-enable interrupts if applicable. */
+		ee = framep->srr1 & PSL_EE;
+		if (ee != 0)
+			mtmsr(mfmsr() | ee);
+		trap(framep);
+	}	        
+}


Property changes on: trunk/sys/powerpc/aim/interrupt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/locore.S
===================================================================
--- trunk/sys/powerpc/aim/locore.S	                        (rev 0)
+++ trunk/sys/powerpc/aim/locore.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,9 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/aim/locore.S 209975 2010-07-13 05:32:19Z nwhitehorn $ */
+
+#ifdef __powerpc64__
+#include <powerpc/aim/locore64.S>
+#else
+#include <powerpc/aim/locore32.S>
+#endif
+


Property changes on: trunk/sys/powerpc/aim/locore.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/locore32.S
===================================================================
--- trunk/sys/powerpc/aim/locore32.S	                        (rev 0)
+++ trunk/sys/powerpc/aim/locore32.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,214 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/aim/locore32.S 243370 2012-11-21 08:04:21Z adrian $ */
+/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */
+
+/*-
+ * Copyright (C) 2001 Benno Rice
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ */
+/*-
+ * 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 "assym.s"
+
+#include <sys/syscall.h>
+
+#include <machine/trap.h>
+#include <machine/param.h>
+#include <machine/spr.h>
+#include <machine/asm.h>
+#include "opt_platform.h"
+
+#include "opt_kdtrace.h"
+
+/* Locate the per-CPU data structure */
+#define GET_CPUINFO(r)  \
+        mfsprg0  r
+
+/*
+ * Compiled KERNBASE location and the kernel load address
+ */
+        .globl  kernbase
+        .set    kernbase, KERNBASE
+
+#define	TMPSTKSZ	8192		/* 8K temporary stack */
+
+/*
+ * Globals
+ */
+	.data
+	.align	4
+GLOBAL(tmpstk)
+	.space	TMPSTKSZ
+GLOBAL(esym)
+	.long	0			/* end of symbol table */
+
+#define	INTRCNT_COUNT	256		/* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
+GLOBAL(intrnames)
+	.space	INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+GLOBAL(sintrnames)
+	.long	INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+
+	.align 4
+GLOBAL(intrcnt)
+	.space	INTRCNT_COUNT * 4 * 2
+GLOBAL(sintrcnt)
+	.long	INTRCNT_COUNT * 4 * 2
+
+	.text
+	.globl	btext
+btext:
+
+/*
+ * This symbol is here for the benefit of kvm_mkdb, and is supposed to
+ * mark the start of kernel text.
+ */
+	.globl	kernel_text
+kernel_text:
+
+/*
+ * Startup entry.  Note, this must be the first thing in the text
+ * segment!
+ */
+	.text
+	.globl	__start
+__start:
+	li	8,0
+	li	9,0x100
+	mtctr	9
+1:
+	dcbf	0,8
+	icbi	0,8
+	addi	8,8,0x20
+	bdnz	1b
+	sync
+	isync
+#ifdef WII
+#include <powerpc/wii/locore.S>
+#endif
+	/* Zero bss, in case we were started by something unhelpful */
+	li	0,0
+	lis	8,_edata at ha
+	addi	8,8,_edata at l
+	lis	9,_end at ha
+	addi	9,9,_end at l
+2:	stw     0,0(8)
+	addi	8,8,4
+	cmplw	8,9
+	blt	2b
+	
+	/* Save the argument pointer and length */
+	mr	20,6
+	mr	21,7
+
+	lis	8,openfirmware_entry at ha
+	stw	5,openfirmware_entry at l(8) /* save client interface handler */
+
+	lis	1,(tmpstk+TMPSTKSZ-16)@ha
+	addi	1,1,(tmpstk+TMPSTKSZ-16)@l
+
+	mfmsr	0
+	lis	9,ofmsr at ha
+	stwu	0,ofmsr at l(9)
+
+	mfsprg0	0			/* save SPRG0-3 */
+	stw	0,4(9)			/* ofmsr[1] = sprg0 */
+	mfsprg1 0
+	stw	0,8(9)			/* ofmsr[2] = sprg1 */
+	mfsprg2 0
+	stw	0,12(9)			/* ofmsr[3] = sprg2 */
+	mfsprg3 0
+	stw	0,16(9)			/* ofmsr[4] = sprg3 */
+	
+	bl	OF_initial_setup
+
+	lis	3,kernel_text at ha
+	addi	3,3,kernel_text at l
+
+	lis	4,end at ha
+	addi	4,4,end at l
+	add	4,4,3
+	mr	5,4
+
+	/* Restore the argument pointer and length */
+	mr	6,20
+	mr	7,21
+
+	bl	powerpc_init
+	mr	%r1, %r3
+	li	%r3, 0
+	stw	%r3, 0(%r1)
+	bl	mi_startup
+	b	OF_exit
+
+/*
+ * int setfault()
+ *
+ * Similar to setjmp to setup for handling faults on accesses to user memory.
+ * Any routine using this may only call bcopy, either the form below,
+ * or the (currently used) C code optimized, so it doesn't use any non-volatile
+ * registers.
+ */
+	.globl	setfault
+setfault:
+	mflr	0
+	mfcr	12
+	mfsprg	4,0
+	lwz	4,TD_PCB(2)	/* curthread = r2 */
+	stw	3,PCB_ONFAULT(4)
+	stw	0,0(3)
+	stw	1,4(3)
+	stw	2,8(3)
+	stmw	12,12(3)
+	xor	3,3,3
+	blr
+
+#include <powerpc/aim/trap_subr32.S>


Property changes on: trunk/sys/powerpc/aim/locore32.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/locore64.S
===================================================================
--- trunk/sys/powerpc/aim/locore64.S	                        (rev 0)
+++ trunk/sys/powerpc/aim/locore64.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,243 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/aim/locore64.S 242723 2012-11-07 23:45:09Z jhibbits $ */
+/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */
+
+/*-
+ * Copyright (C) 2001 Benno Rice
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ */
+/*-
+ * 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 "assym.s"
+
+#include <sys/syscall.h>
+
+#include <machine/trap.h>
+#include <machine/param.h>
+#include <machine/spr.h>
+#include <machine/asm.h>
+
+#include "opt_kdtrace.h"
+
+/* Locate the per-CPU data structure */
+#define GET_CPUINFO(r)  \
+        mfsprg0  r
+
+/*
+ * Compiled KERNBASE location and the kernel load address
+ */
+        .globl  kernbase
+        .set    kernbase, KERNBASE
+
+#define	TMPSTKSZ	16384		/* 16K temporary stack */
+
+/*
+ * Globals
+ */
+	.data
+	.align	4
+GLOBAL(tmpstk)
+	.space	TMPSTKSZ
+GLOBAL(esym)
+	.llong	0			/* end of symbol table */
+
+#define	INTRCNT_COUNT	256		/* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
+GLOBAL(intrnames)
+	.space	INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+GLOBAL(sintrnames)
+	.quad	INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+
+	.align 4
+GLOBAL(intrcnt)
+	.space	INTRCNT_COUNT * 4 * 2
+GLOBAL(sintrcnt)
+	.quad	INTRCNT_COUNT * 4 * 2
+
+	.text
+	.globl	btext
+btext:
+
+/*
+ * This symbol is here for the benefit of kvm_mkdb, and is supposed to
+ * mark the start of kernel text.
+ */
+	.globl	kernel_text
+kernel_text:
+
+/*
+ * Startup entry.  Note, this must be the first thing in the text
+ * segment!
+ */
+	.text
+ASENTRY_NOPROF(__start)
+	li	8,0
+	li	9,0x100
+	mtctr	9
+1:
+	dcbf	0,8
+	icbi	0,8
+	addi	8,8,0x20
+	bdnz	1b
+	sync
+	isync
+
+	/* Save the argument pointer and length */
+	mr	20,6
+	mr	21,7
+
+	lis	8,openfirmware_entry at ha
+	std	5,openfirmware_entry at l(8) /* save client interface handler */
+
+	/* Set up the stack pointer */
+	lis	1,(tmpstk+TMPSTKSZ-48)@ha
+	addi	1,1,(tmpstk+TMPSTKSZ-48)@l
+
+	/* Set up the TOC pointer */
+	lis	2,tocbase at ha
+	ld	2,tocbase at l(2)
+
+	mfmsr	0
+	lis	9,ofmsr at ha
+	stdu	0,ofmsr at l(9)
+
+	mfsprg0	0			/* save SPRG0-3 */
+	std	0,8(9)			/* ofmsr[1] = sprg0 */
+	mfsprg1 0
+	std	0,16(9)			/* ofmsr[2] = sprg1 */
+	mfsprg2 0
+	std	0,24(9)			/* ofmsr[3] = sprg2 */
+	mfsprg3 0
+	std	0,32(9)			/* ofmsr[4] = sprg3 */
+
+	/* Switch to 64-bit mode */
+	mfmsr	9
+	li	8,1
+	insrdi	9,8,1,0
+	mtmsrd	9
+	
+	bl	OF_initial_setup
+	nop
+
+	lis	3,kernbase at ha
+	addi	3,3,kernbase at l
+
+	lis	4,end at ha
+	addi	4,4,end at l
+	add	4,4,3
+	mr	5,4
+
+	/* Restore the argument pointer and length */
+	mr	6,20
+	mr	7,21
+
+	bl	powerpc_init
+	nop
+	mr	%r1, %r3
+	li	%r3, 0
+	std	%r3, 0(%r1)
+	bl	mi_startup
+	nop
+	b	OF_exit
+	nop
+
+/*
+ * PPC64 ABI TOC base
+ */
+
+        .align  3
+	.globl	tocbase
+tocbase:
+        .llong  .TOC. at tocbase
+
+/*
+ * int setfault()
+ *
+ * Similar to setjmp to setup for handling faults on accesses to user memory.
+ * Any routine using this may only call bcopy, either the form below,
+ * or the (currently used) C code optimized, so it doesn't use any non-volatile
+ * registers.
+ */
+ASENTRY_NOPROF(setfault)
+	mflr	0
+	mfcr	12
+	mfsprg	4,0
+	ld	4,TD_PCB(13)	/* curthread = r13 */
+	std	3,PCB_ONFAULT(4)
+	std	0,0(3)
+	std	1,8(3)
+	std	2,16(3)
+
+	std	%r12,24(%r3)	/* Save the non-volatile GP regs. */
+	std	%r13,24+1*8(%r3)	
+	std	%r14,24+2*8(%r3)	
+	std	%r15,24+3*8(%r3)	
+	std	%r16,24+4*8(%r3)	
+	std	%r17,24+5*8(%r3)	
+	std	%r18,24+6*8(%r3)	
+	std	%r19,24+7*8(%r3)	
+	std	%r20,24+8*8(%r3)	
+	std	%r21,24+9*8(%r3)	
+	std	%r22,24+10*8(%r3)	
+	std	%r23,24+11*8(%r3)	
+	std	%r24,24+12*8(%r3)	
+	std	%r25,24+13*8(%r3)	
+	std	%r26,24+14*8(%r3)	
+	std	%r27,24+15*8(%r3)	
+	std	%r28,24+16*8(%r3)
+	std	%r29,24+17*8(%r3)	
+	std	%r30,24+18*8(%r3)	
+	std	%r31,24+19*8(%r3)	
+
+	xor	3,3,3
+	blr
+
+#include <powerpc/aim/trap_subr64.S>


Property changes on: trunk/sys/powerpc/aim/locore64.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/machdep.c
===================================================================
--- trunk/sys/powerpc/aim/machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/aim/machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,953 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ */
+/*-
+ * Copyright (C) 2001 Benno Rice
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ *	$NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/aim/machdep.c 266019 2014-05-14 14:08:45Z ian $");
+
+#include "opt_compat.h"
+#include "opt_ddb.h"
+#include "opt_kstack_pages.h"
+#include "opt_platform.h"
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <sys/cpu.h>
+#include <sys/eventhandler.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/msgbuf.h>
+#include <sys/mutex.h>
+#include <sys/ptrace.h>
+#include <sys/reboot.h>
+#include <sys/rwlock.h>
+#include <sys/signalvar.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/ucontext.h>
+#include <sys/uio.h>
+#include <sys/vmmeter.h>
+#include <sys/vnode.h>
+
+#include <net/netisr.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_pager.h>
+
+#include <machine/altivec.h>
+#ifndef __powerpc64__
+#include <machine/bat.h>
+#endif
+#include <machine/cpu.h>
+#include <machine/elf.h>
+#include <machine/fpu.h>
+#include <machine/hid.h>
+#include <machine/kdb.h>
+#include <machine/md_var.h>
+#include <machine/metadata.h>
+#include <machine/mmuvar.h>
+#include <machine/pcb.h>
+#include <machine/reg.h>
+#include <machine/sigframe.h>
+#include <machine/spr.h>
+#include <machine/trap.h>
+#include <machine/vmparam.h>
+#include <machine/ofw_machdep.h>
+
+#include <ddb/ddb.h>
+
+#include <dev/ofw/openfirm.h>
+
+#ifdef DDB
+extern vm_offset_t ksym_start, ksym_end;
+#endif
+
+int cold = 1;
+#ifdef __powerpc64__
+extern int n_slbs;
+int cacheline_size = 128;
+#else
+int cacheline_size = 32;
+#endif
+int hw_direct_map = 1;
+
+extern void *ap_pcpu;
+
+struct pcpu __pcpu[MAXCPU];
+
+static struct trapframe frame0;
+
+char		machine[] = "powerpc";
+SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
+
+static void	cpu_startup(void *);
+SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
+
+SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
+	   CTLFLAG_RD, &cacheline_size, 0, "");
+
+uintptr_t	powerpc_init(vm_offset_t, vm_offset_t, vm_offset_t, void *);
+
+long		Maxmem = 0;
+long		realmem = 0;
+
+#ifndef __powerpc64__
+struct bat	battable[16];
+#endif
+
+struct kva_md_info kmi;
+
+static void
+cpu_startup(void *dummy)
+{
+
+	/*
+	 * Initialise the decrementer-based clock.
+	 */
+	decr_init();
+
+	/*
+	 * Good {morning,afternoon,evening,night}.
+	 */
+	cpu_setup(PCPU_GET(cpuid));
+
+#ifdef PERFMON
+	perfmon_init();
+#endif
+	printf("real memory  = %ld (%ld MB)\n", ptoa(physmem),
+	    ptoa(physmem) / 1048576);
+	realmem = physmem;
+
+	if (bootverbose)
+		printf("available KVA = %zd (%zd MB)\n",
+		    virtual_end - virtual_avail,
+		    (virtual_end - virtual_avail) / 1048576);
+
+	/*
+	 * Display any holes after the first chunk of extended memory.
+	 */
+	if (bootverbose) {
+		int indx;
+
+		printf("Physical memory chunk(s):\n");
+		for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
+			vm_offset_t size1 =
+			    phys_avail[indx + 1] - phys_avail[indx];
+
+			#ifdef __powerpc64__
+			printf("0x%016lx - 0x%016lx, %ld bytes (%ld pages)\n",
+			#else
+			printf("0x%08x - 0x%08x, %d bytes (%ld pages)\n",
+			#endif
+			    phys_avail[indx], phys_avail[indx + 1] - 1, size1,
+			    size1 / PAGE_SIZE);
+		}
+	}
+
+	vm_ksubmap_init(&kmi);
+
+	printf("avail memory = %ld (%ld MB)\n", ptoa(cnt.v_free_count),
+	    ptoa(cnt.v_free_count) / 1048576);
+
+	/*
+	 * Set up buffers, so they can be used to read disk labels.
+	 */
+	bufinit();
+	vm_pager_bufferinit();
+}
+
+extern char	kernel_text[], _end[];
+
+#ifndef __powerpc64__
+/* Bits for running on 64-bit systems in 32-bit mode. */
+extern void	*testppc64, *testppc64size;
+extern void	*restorebridge, *restorebridgesize;
+extern void	*rfid_patch, *rfi_patch1, *rfi_patch2;
+extern void	*trapcode64;
+#endif
+
+extern void	*rstcode, *rstsize;
+extern void	*trapcode, *trapsize;
+extern void	*slbtrap, *slbtrapsize;
+extern void	*alitrap, *alisize;
+extern void	*dsitrap, *dsisize;
+extern void	*decrint, *decrsize;
+extern void     *extint, *extsize;
+extern void	*dblow, *dbsize;
+extern void	*imisstrap, *imisssize;
+extern void	*dlmisstrap, *dlmisssize;
+extern void	*dsmisstrap, *dsmisssize;
+char 		save_trap_init[0x2f00];		/* EXC_LAST */
+
+uintptr_t
+powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
+    vm_offset_t basekernel, void *mdp)
+{
+	struct		pcpu *pc;
+	void		*generictrap;
+	size_t		trap_offset;
+	void		*kmdp;
+        char		*env;
+	register_t	msr, scratch;
+#ifdef WII
+	register_t 	vers;
+#endif
+	uint8_t		*cache_check;
+	int		cacheline_warn;
+	#ifndef __powerpc64__
+	int		ppc64;
+	#endif
+
+	kmdp = NULL;
+	trap_offset = 0;
+	cacheline_warn = 0;
+
+	/* Save trap vectors. */
+	ofw_save_trap_vec(save_trap_init);
+
+#ifdef WII
+	/*
+	 * The Wii loader doesn't pass us any environment so, mdp
+	 * points to garbage at this point. The Wii CPU is a 750CL.
+	 */
+	vers = mfpvr();
+	if ((vers & 0xfffff0e0) == (MPC750 << 16 | MPC750CL)) 
+		mdp = NULL;
+#endif
+
+	/*
+	 * Parse metadata if present and fetch parameters.  Must be done
+	 * before console is inited so cninit gets the right value of
+	 * boothowto.
+	 */
+	if (mdp != NULL) {
+		preload_metadata = mdp;
+		kmdp = preload_search_by_type("elf kernel");
+		if (kmdp != NULL) {
+			boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
+			kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
+			endkernel = ulmax(endkernel, MD_FETCH(kmdp,
+			    MODINFOMD_KERNEND, vm_offset_t));
+#ifdef DDB
+			ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
+			ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
+#endif
+		}
+	}
+
+	/*
+	 * Init params/tunables that can be overridden by the loader
+	 */
+	init_param1();
+
+	/*
+	 * Start initializing proc0 and thread0.
+	 */
+	proc_linkup0(&proc0, &thread0);
+	thread0.td_frame = &frame0;
+
+	/*
+	 * Set up per-cpu data.
+	 */
+	pc = __pcpu;
+	pcpu_init(pc, 0, sizeof(struct pcpu));
+	pc->pc_curthread = &thread0;
+#ifdef __powerpc64__
+	__asm __volatile("mr 13,%0" :: "r"(pc->pc_curthread));
+#else
+	__asm __volatile("mr 2,%0" :: "r"(pc->pc_curthread));
+#endif
+	pc->pc_cpuid = 0;
+
+	__asm __volatile("mtsprg 0, %0" :: "r"(pc));
+
+	/*
+	 * Init mutexes, which we use heavily in PMAP
+	 */
+
+	mutex_init();
+
+	/*
+	 * Install the OF client interface
+	 */
+
+	OF_bootstrap();
+
+	/*
+	 * Initialize the console before printing anything.
+	 */
+	cninit();
+
+	/*
+	 * Complain if there is no metadata.
+	 */
+	if (mdp == NULL || kmdp == NULL) {
+		printf("powerpc_init: no loader metadata.\n");
+	}
+
+	/*
+	 * Init KDB
+	 */
+
+	kdb_init();
+
+	/* Various very early CPU fix ups */
+	switch (mfpvr() >> 16) {
+		/*
+		 * PowerPC 970 CPUs have a misfeature requested by Apple that
+		 * makes them pretend they have a 32-byte cacheline. Turn this
+		 * off before we measure the cacheline size.
+		 */
+		case IBM970:
+		case IBM970FX:
+		case IBM970MP:
+		case IBM970GX:
+			scratch = mfspr(SPR_HID5);
+			scratch &= ~HID5_970_DCBZ_SIZE_HI;
+			mtspr(SPR_HID5, scratch);
+			break;
+	#ifdef __powerpc64__
+		case IBMPOWER7:
+			/* XXX: get from ibm,slb-size in device tree */
+			n_slbs = 32;
+			break;
+	#endif
+	}
+
+	/*
+	 * Initialize the interrupt tables and figure out our cache line
+	 * size and whether or not we need the 64-bit bridge code.
+	 */
+
+	/*
+	 * Disable translation in case the vector area hasn't been
+	 * mapped (G5). Note that no OFW calls can be made until
+	 * translation is re-enabled.
+	 */
+
+	msr = mfmsr();
+	mtmsr((msr & ~(PSL_IR | PSL_DR)) | PSL_RI);
+
+	/*
+	 * Measure the cacheline size using dcbz
+	 *
+	 * Use EXC_PGM as a playground. We are about to overwrite it
+	 * anyway, we know it exists, and we know it is cache-aligned.
+	 */
+
+	cache_check = (void *)EXC_PGM;
+
+	for (cacheline_size = 0; cacheline_size < 0x100; cacheline_size++)
+		cache_check[cacheline_size] = 0xff;
+
+	__asm __volatile("dcbz 0,%0":: "r" (cache_check) : "memory");
+
+	/* Find the first byte dcbz did not zero to get the cache line size */
+	for (cacheline_size = 0; cacheline_size < 0x100 &&
+	    cache_check[cacheline_size] == 0; cacheline_size++);
+
+	/* Work around psim bug */
+	if (cacheline_size == 0) {
+		cacheline_warn = 1;
+		cacheline_size = 32;
+	}
+
+	/* Make sure the kernel icache is valid before we go too much further */
+	__syncicache((caddr_t)startkernel, endkernel - startkernel);
+
+	#ifndef __powerpc64__
+	/*
+	 * Figure out whether we need to use the 64 bit PMAP. This works by
+	 * executing an instruction that is only legal on 64-bit PPC (mtmsrd),
+	 * and setting ppc64 = 0 if that causes a trap.
+	 */
+
+	ppc64 = 1;
+
+	bcopy(&testppc64, (void *)EXC_PGM,  (size_t)&testppc64size);
+	__syncicache((void *)EXC_PGM, (size_t)&testppc64size);
+
+	__asm __volatile("\
+		mfmsr %0;	\
+		mtsprg2 %1;	\
+				\
+		mtmsrd %0;	\
+		mfsprg2 %1;"
+	    : "=r"(scratch), "=r"(ppc64));
+
+	if (ppc64)
+		cpu_features |= PPC_FEATURE_64;
+
+	/*
+	 * Now copy restorebridge into all the handlers, if necessary,
+	 * and set up the trap tables.
+	 */
+
+	if (cpu_features & PPC_FEATURE_64) {
+		/* Patch the two instances of rfi -> rfid */
+		bcopy(&rfid_patch,&rfi_patch1,4);
+	#ifdef KDB
+		/* rfi_patch2 is at the end of dbleave */
+		bcopy(&rfid_patch,&rfi_patch2,4);
+	#endif
+
+		/*
+		 * Copy a code snippet to restore 32-bit bridge mode
+		 * to the top of every non-generic trap handler
+		 */
+
+		trap_offset += (size_t)&restorebridgesize;
+		bcopy(&restorebridge, (void *)EXC_RST, trap_offset); 
+		bcopy(&restorebridge, (void *)EXC_DSI, trap_offset); 
+		bcopy(&restorebridge, (void *)EXC_ALI, trap_offset); 
+		bcopy(&restorebridge, (void *)EXC_PGM, trap_offset); 
+		bcopy(&restorebridge, (void *)EXC_MCHK, trap_offset); 
+		bcopy(&restorebridge, (void *)EXC_TRC, trap_offset); 
+		bcopy(&restorebridge, (void *)EXC_BPT, trap_offset); 
+
+		/*
+		 * Set the common trap entry point to the one that
+		 * knows to restore 32-bit operation on execution.
+		 */
+
+		generictrap = &trapcode64;
+	} else {
+		generictrap = &trapcode;
+	}
+
+	#else /* powerpc64 */
+	cpu_features |= PPC_FEATURE_64;
+	generictrap = &trapcode;
+	#endif
+
+	bcopy(&rstcode, (void *)(EXC_RST + trap_offset),  (size_t)&rstsize);
+
+#ifdef KDB
+	bcopy(&dblow,	(void *)(EXC_MCHK + trap_offset), (size_t)&dbsize);
+	bcopy(&dblow,   (void *)(EXC_PGM + trap_offset),  (size_t)&dbsize);
+	bcopy(&dblow,   (void *)(EXC_TRC + trap_offset),  (size_t)&dbsize);
+	bcopy(&dblow,   (void *)(EXC_BPT + trap_offset),  (size_t)&dbsize);
+#else
+	bcopy(generictrap, (void *)EXC_MCHK, (size_t)&trapsize);
+	bcopy(generictrap, (void *)EXC_PGM,  (size_t)&trapsize);
+	bcopy(generictrap, (void *)EXC_TRC,  (size_t)&trapsize);
+	bcopy(generictrap, (void *)EXC_BPT,  (size_t)&trapsize);
+#endif
+	bcopy(&alitrap,  (void *)(EXC_ALI + trap_offset),  (size_t)&alisize);
+	bcopy(&dsitrap,  (void *)(EXC_DSI + trap_offset),  (size_t)&dsisize);
+	bcopy(generictrap, (void *)EXC_ISI,  (size_t)&trapsize);
+	#ifdef __powerpc64__
+	bcopy(&slbtrap, (void *)EXC_DSE,  (size_t)&slbtrapsize);
+	bcopy(&slbtrap, (void *)EXC_ISE,  (size_t)&slbtrapsize);
+	#endif
+	bcopy(generictrap, (void *)EXC_EXI,  (size_t)&trapsize);
+	bcopy(generictrap, (void *)EXC_FPU,  (size_t)&trapsize);
+	bcopy(generictrap, (void *)EXC_DECR, (size_t)&trapsize);
+	bcopy(generictrap, (void *)EXC_SC,   (size_t)&trapsize);
+	bcopy(generictrap, (void *)EXC_FPA,  (size_t)&trapsize);
+	bcopy(generictrap, (void *)EXC_VEC,  (size_t)&trapsize);
+	bcopy(generictrap, (void *)EXC_PERF,  (size_t)&trapsize);
+	bcopy(generictrap, (void *)EXC_VECAST_G4, (size_t)&trapsize);
+	bcopy(generictrap, (void *)EXC_VECAST_G5, (size_t)&trapsize);
+	#ifndef __powerpc64__
+	/* G2-specific TLB miss helper handlers */
+	bcopy(&imisstrap, (void *)EXC_IMISS,  (size_t)&imisssize);
+	bcopy(&dlmisstrap, (void *)EXC_DLMISS,  (size_t)&dlmisssize);
+	bcopy(&dsmisstrap, (void *)EXC_DSMISS,  (size_t)&dsmisssize);
+	#endif
+	__syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
+
+	/*
+	 * Restore MSR
+	 */
+	mtmsr(msr);
+	
+	/* Warn if cachline size was not determined */
+	if (cacheline_warn == 1) {
+		printf("WARNING: cacheline size undetermined, setting to 32\n");
+	}
+
+	/*
+	 * Choose a platform module so we can get the physical memory map.
+	 */
+	
+	platform_probe_and_attach();
+
+	/*
+	 * Initialise virtual memory. Use BUS_PROBE_GENERIC priority
+	 * in case the platform module had a better idea of what we
+	 * should do.
+	 */
+	if (cpu_features & PPC_FEATURE_64)
+		pmap_mmu_install(MMU_TYPE_G5, BUS_PROBE_GENERIC);
+	else
+		pmap_mmu_install(MMU_TYPE_OEA, BUS_PROBE_GENERIC);
+
+	pmap_bootstrap(startkernel, endkernel);
+	mtmsr(PSL_KERNSET & ~PSL_EE);
+
+	/*
+	 * Initialize params/tunables that are derived from memsize
+	 */
+	init_param2(physmem);
+
+	/*
+	 * Grab booted kernel's name
+	 */
+        env = getenv("kernelname");
+        if (env != NULL) {
+		strlcpy(kernelname, env, sizeof(kernelname));
+		freeenv(env);
+	}
+
+	/*
+	 * Finish setting up thread0.
+	 */
+	thread0.td_pcb = (struct pcb *)
+	    ((thread0.td_kstack + thread0.td_kstack_pages * PAGE_SIZE -
+	    sizeof(struct pcb)) & ~15UL);
+	bzero((void *)thread0.td_pcb, sizeof(struct pcb));
+	pc->pc_curpcb = thread0.td_pcb;
+
+	/* Initialise the message buffer. */
+	msgbufinit(msgbufp, msgbufsize);
+
+#ifdef KDB
+	if (boothowto & RB_KDB)
+		kdb_enter(KDB_WHY_BOOTFLAGS,
+		    "Boot flags requested debugger");
+#endif
+
+	return (((uintptr_t)thread0.td_pcb -
+	    (sizeof(struct callframe) - 3*sizeof(register_t))) & ~15UL);
+}
+
+void
+bzero(void *buf, size_t len)
+{
+	caddr_t	p;
+
+	p = buf;
+
+	while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
+		*p++ = 0;
+		len--;
+	}
+
+	while (len >= sizeof(u_long) * 8) {
+		*(u_long*) p = 0;
+		*((u_long*) p + 1) = 0;
+		*((u_long*) p + 2) = 0;
+		*((u_long*) p + 3) = 0;
+		len -= sizeof(u_long) * 8;
+		*((u_long*) p + 4) = 0;
+		*((u_long*) p + 5) = 0;
+		*((u_long*) p + 6) = 0;
+		*((u_long*) p + 7) = 0;
+		p += sizeof(u_long) * 8;
+	}
+
+	while (len >= sizeof(u_long)) {
+		*(u_long*) p = 0;
+		len -= sizeof(u_long);
+		p += sizeof(u_long);
+	}
+
+	while (len) {
+		*p++ = 0;
+		len--;
+	}
+}
+
+void
+cpu_boot(int howto)
+{
+}
+
+/*
+ * Flush the D-cache for non-DMA I/O so that the I-cache can
+ * be made coherent later.
+ */
+void
+cpu_flush_dcache(void *ptr, size_t len)
+{
+	/* TBD */
+}
+
+/*
+ * Shutdown the CPU as much as possible.
+ */
+void
+cpu_halt(void)
+{
+
+	OF_exit();
+}
+
+int
+ptrace_set_pc(struct thread *td, unsigned long addr)
+{
+	struct trapframe *tf;
+
+	tf = td->td_frame;
+	tf->srr0 = (register_t)addr;
+
+	return (0);
+}
+
+int
+ptrace_single_step(struct thread *td)
+{
+	struct trapframe *tf;
+	
+	tf = td->td_frame;
+	tf->srr1 |= PSL_SE;
+
+	return (0);
+}
+
+int
+ptrace_clear_single_step(struct thread *td)
+{
+	struct trapframe *tf;
+
+	tf = td->td_frame;
+	tf->srr1 &= ~PSL_SE;
+
+	return (0);
+}
+
+void
+kdb_cpu_clear_singlestep(void)
+{
+
+	kdb_frame->srr1 &= ~PSL_SE;
+}
+
+void
+kdb_cpu_set_singlestep(void)
+{
+
+	kdb_frame->srr1 |= PSL_SE;
+}
+
+/*
+ * Initialise a struct pcpu.
+ */
+void
+cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
+{
+#ifdef __powerpc64__
+/* Copy the SLB contents from the current CPU */
+memcpy(pcpu->pc_slb, PCPU_GET(slb), sizeof(pcpu->pc_slb));
+#endif
+}
+
+void
+spinlock_enter(void)
+{
+	struct thread *td;
+	register_t msr;
+
+	td = curthread;
+	if (td->td_md.md_spinlock_count == 0) {
+		msr = intr_disable();
+		td->td_md.md_spinlock_count = 1;
+		td->td_md.md_saved_msr = msr;
+	} else
+		td->td_md.md_spinlock_count++;
+	critical_enter();
+}
+
+void
+spinlock_exit(void)
+{
+	struct thread *td;
+	register_t msr;
+
+	td = curthread;
+	critical_exit();
+	msr = td->td_md.md_saved_msr;
+	td->td_md.md_spinlock_count--;
+	if (td->td_md.md_spinlock_count == 0)
+		intr_restore(msr);
+}
+
+int db_trap_glue(struct trapframe *);		/* Called from trap_subr.S */
+
+int
+db_trap_glue(struct trapframe *frame)
+{
+	if (!(frame->srr1 & PSL_PR)
+	    && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC
+		|| (frame->exc == EXC_PGM
+		    && (frame->srr1 & 0x20000))
+		|| frame->exc == EXC_BPT
+		|| frame->exc == EXC_DSI)) {
+		int type = frame->exc;
+		if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
+			type = T_BREAKPOINT;
+		}
+		return (kdb_trap(type, 0, frame));
+	}
+
+	return (0);
+}
+
+#ifndef __powerpc64__
+
+uint64_t
+va_to_vsid(pmap_t pm, vm_offset_t va)
+{
+	return ((pm->pm_sr[(uintptr_t)va >> ADDR_SR_SHFT]) & SR_VSID_MASK);
+}
+
+#endif
+
+vm_offset_t
+pmap_early_io_map(vm_paddr_t pa, vm_size_t size)
+{
+
+	return (pa);
+}
+
+/* From p3-53 of the MPC7450 RISC Microprocessor Family Reference Manual */
+void
+flush_disable_caches(void)
+{
+	register_t msr;
+	register_t msscr0;
+	register_t cache_reg;
+	volatile uint32_t *memp;
+	uint32_t temp;
+	int i;
+	int x;
+
+	msr = mfmsr();
+	powerpc_sync();
+	mtmsr(msr & ~(PSL_EE | PSL_DR));
+	msscr0 = mfspr(SPR_MSSCR0);
+	msscr0 &= ~MSSCR0_L2PFE;
+	mtspr(SPR_MSSCR0, msscr0);
+	powerpc_sync();
+	isync();
+	__asm__ __volatile__("dssall; sync");
+	powerpc_sync();
+	isync();
+	__asm__ __volatile__("dcbf 0,%0" :: "r"(0));
+	__asm__ __volatile__("dcbf 0,%0" :: "r"(0));
+	__asm__ __volatile__("dcbf 0,%0" :: "r"(0));
+
+	/* Lock the L1 Data cache. */
+	mtspr(SPR_LDSTCR, mfspr(SPR_LDSTCR) | 0xFF);
+	powerpc_sync();
+	isync();
+
+	mtspr(SPR_LDSTCR, 0);
+
+	/*
+	 * Perform this in two stages: Flush the cache starting in RAM, then do it
+	 * from ROM.
+	 */
+	memp = (volatile uint32_t *)0x00000000;
+	for (i = 0; i < 128 * 1024; i++) {
+		temp = *memp;
+		__asm__ __volatile__("dcbf 0,%0" :: "r"(memp));
+		memp += 32/sizeof(*memp);
+	}
+
+	memp = (volatile uint32_t *)0xfff00000;
+	x = 0xfe;
+
+	for (; x != 0xff;) {
+		mtspr(SPR_LDSTCR, x);
+		for (i = 0; i < 128; i++) {
+			temp = *memp;
+			__asm__ __volatile__("dcbf 0,%0" :: "r"(memp));
+			memp += 32/sizeof(*memp);
+		}
+		x = ((x << 1) | 1) & 0xff;
+	}
+	mtspr(SPR_LDSTCR, 0);
+
+	cache_reg = mfspr(SPR_L2CR);
+	if (cache_reg & L2CR_L2E) {
+		cache_reg &= ~(L2CR_L2IO_7450 | L2CR_L2DO_7450);
+		mtspr(SPR_L2CR, cache_reg);
+		powerpc_sync();
+		mtspr(SPR_L2CR, cache_reg | L2CR_L2HWF);
+		while (mfspr(SPR_L2CR) & L2CR_L2HWF)
+			; /* Busy wait for cache to flush */
+		powerpc_sync();
+		cache_reg &= ~L2CR_L2E;
+		mtspr(SPR_L2CR, cache_reg);
+		powerpc_sync();
+		mtspr(SPR_L2CR, cache_reg | L2CR_L2I);
+		powerpc_sync();
+		while (mfspr(SPR_L2CR) & L2CR_L2I)
+			; /* Busy wait for L2 cache invalidate */
+		powerpc_sync();
+	}
+
+	cache_reg = mfspr(SPR_L3CR);
+	if (cache_reg & L3CR_L3E) {
+		cache_reg &= ~(L3CR_L3IO | L3CR_L3DO);
+		mtspr(SPR_L3CR, cache_reg);
+		powerpc_sync();
+		mtspr(SPR_L3CR, cache_reg | L3CR_L3HWF);
+		while (mfspr(SPR_L3CR) & L3CR_L3HWF)
+			; /* Busy wait for cache to flush */
+		powerpc_sync();
+		cache_reg &= ~L3CR_L3E;
+		mtspr(SPR_L3CR, cache_reg);
+		powerpc_sync();
+		mtspr(SPR_L3CR, cache_reg | L3CR_L3I);
+		powerpc_sync();
+		while (mfspr(SPR_L3CR) & L3CR_L3I)
+			; /* Busy wait for L3 cache invalidate */
+		powerpc_sync();
+	}
+
+	mtspr(SPR_HID0, mfspr(SPR_HID0) & ~HID0_DCE);
+	powerpc_sync();
+	isync();
+
+	mtmsr(msr);
+}
+
+void
+cpu_sleep()
+{
+	static u_quad_t timebase = 0;
+	static register_t sprgs[4];
+	static register_t srrs[2];
+
+	jmp_buf resetjb;
+	struct thread *fputd;
+	struct thread *vectd;
+	register_t hid0;
+	register_t msr;
+	register_t saved_msr;
+
+	ap_pcpu = pcpup;
+
+	PCPU_SET(restore, &resetjb);
+
+	saved_msr = mfmsr();
+	fputd = PCPU_GET(fputhread);
+	vectd = PCPU_GET(vecthread);
+	if (fputd != NULL)
+		save_fpu(fputd);
+	if (vectd != NULL)
+		save_vec(vectd);
+	if (setjmp(resetjb) == 0) {
+		sprgs[0] = mfspr(SPR_SPRG0);
+		sprgs[1] = mfspr(SPR_SPRG1);
+		sprgs[2] = mfspr(SPR_SPRG2);
+		sprgs[3] = mfspr(SPR_SPRG3);
+		srrs[0] = mfspr(SPR_SRR0);
+		srrs[1] = mfspr(SPR_SRR1);
+		timebase = mftb();
+		powerpc_sync();
+		flush_disable_caches();
+		hid0 = mfspr(SPR_HID0);
+		hid0 = (hid0 & ~(HID0_DOZE | HID0_NAP)) | HID0_SLEEP;
+		powerpc_sync();
+		isync();
+		msr = mfmsr() | PSL_POW;
+		mtspr(SPR_HID0, hid0);
+		powerpc_sync();
+
+		while (1)
+			mtmsr(msr);
+	}
+	mttb(timebase);
+	PCPU_SET(curthread, curthread);
+	PCPU_SET(curpcb, curthread->td_pcb);
+	pmap_activate(curthread);
+	powerpc_sync();
+	mtspr(SPR_SPRG0, sprgs[0]);
+	mtspr(SPR_SPRG1, sprgs[1]);
+	mtspr(SPR_SPRG2, sprgs[2]);
+	mtspr(SPR_SPRG3, sprgs[3]);
+	mtspr(SPR_SRR0, srrs[0]);
+	mtspr(SPR_SRR1, srrs[1]);
+	mtmsr(saved_msr);
+	if (fputd == curthread)
+		enable_fpu(curthread);
+	if (vectd == curthread)
+		enable_vec(curthread);
+	powerpc_sync();
+}
\ No newline at end of file


Property changes on: trunk/sys/powerpc/aim/machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/mmu_oea.c
===================================================================
--- trunk/sys/powerpc/aim/mmu_oea.c	                        (rev 0)
+++ trunk/sys/powerpc/aim/mmu_oea.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,2737 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt at 3am-software.com> of Allegro Networks, Inc.
+ *
+ * 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.
+ *
+ * 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.
+ */
+/*-
+ * 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.
+ *
+ * $NetBSD: pmap.c,v 1.28 2000/03/26 20:42:36 kleink Exp $
+ */
+/*-
+ * Copyright (C) 2001 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/aim/mmu_oea.c 270920 2014-09-01 07:58:15Z kib $");
+
+/*
+ * Manages physical address maps.
+ *
+ * Since the information managed by this module is also stored by the
+ * logical address mapping module, this module may throw away valid virtual
+ * to physical mappings at almost any time.  However, invalidations of
+ * mappings must be done as requested.
+ *
+ * In order to cope with hardware architectures which make virtual to
+ * physical map invalidates expensive, this module may delay invalidate
+ * reduced protection operations until such time as they are actually
+ * necessary.  This module is given full information as to which processors
+ * are currently using which maps, and to when physical maps must be made
+ * correct.
+ */
+
+#include "opt_kstack_pages.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/cpuset.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/msgbuf.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/rwlock.h>
+#include <sys/sched.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/vmmeter.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_pageout.h>
+#include <vm/uma.h>
+
+#include <machine/cpu.h>
+#include <machine/platform.h>
+#include <machine/bat.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/psl.h>
+#include <machine/pte.h>
+#include <machine/smp.h>
+#include <machine/sr.h>
+#include <machine/mmuvar.h>
+#include <machine/trap.h>
+
+#include "mmu_if.h"
+
+#define	MOEA_DEBUG
+
+#define TODO	panic("%s: not implemented", __func__);
+
+#define	VSID_MAKE(sr, hash)	((sr) | (((hash) & 0xfffff) << 4))
+#define	VSID_TO_SR(vsid)	((vsid) & 0xf)
+#define	VSID_TO_HASH(vsid)	(((vsid) >> 4) & 0xfffff)
+
+struct ofw_map {
+	vm_offset_t	om_va;
+	vm_size_t	om_len;
+	vm_offset_t	om_pa;
+	u_int		om_mode;
+};
+
+extern unsigned char _etext[];
+extern unsigned char _end[];
+
+extern int dumpsys_minidump;
+
+/*
+ * Map of physical memory regions.
+ */
+static struct	mem_region *regions;
+static struct	mem_region *pregions;
+static u_int    phys_avail_count;
+static int	regions_sz, pregions_sz;
+static struct	ofw_map *translations;
+
+/*
+ * Lock for the pteg and pvo tables.
+ */
+struct mtx	moea_table_mutex;
+struct mtx	moea_vsid_mutex;
+
+/* tlbie instruction synchronization */
+static struct mtx tlbie_mtx;
+
+/*
+ * PTEG data.
+ */
+static struct	pteg *moea_pteg_table;
+u_int		moea_pteg_count;
+u_int		moea_pteg_mask;
+
+/*
+ * PVO data.
+ */
+struct	pvo_head *moea_pvo_table;		/* pvo entries by pteg index */
+struct	pvo_head moea_pvo_kunmanaged =
+    LIST_HEAD_INITIALIZER(moea_pvo_kunmanaged);	/* list of unmanaged pages */
+
+static struct rwlock_padalign pvh_global_lock;
+
+uma_zone_t	moea_upvo_zone;	/* zone for pvo entries for unmanaged pages */
+uma_zone_t	moea_mpvo_zone;	/* zone for pvo entries for managed pages */
+
+#define	BPVO_POOL_SIZE	32768
+static struct	pvo_entry *moea_bpvo_pool;
+static int	moea_bpvo_pool_index = 0;
+
+#define	VSID_NBPW	(sizeof(u_int32_t) * 8)
+static u_int	moea_vsid_bitmap[NPMAPS / VSID_NBPW];
+
+static boolean_t moea_initialized = FALSE;
+
+/*
+ * Statistics.
+ */
+u_int	moea_pte_valid = 0;
+u_int	moea_pte_overflow = 0;
+u_int	moea_pte_replacements = 0;
+u_int	moea_pvo_entries = 0;
+u_int	moea_pvo_enter_calls = 0;
+u_int	moea_pvo_remove_calls = 0;
+u_int	moea_pte_spills = 0;
+SYSCTL_INT(_machdep, OID_AUTO, moea_pte_valid, CTLFLAG_RD, &moea_pte_valid,
+    0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea_pte_overflow, CTLFLAG_RD,
+    &moea_pte_overflow, 0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea_pte_replacements, CTLFLAG_RD,
+    &moea_pte_replacements, 0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea_pvo_entries, CTLFLAG_RD, &moea_pvo_entries,
+    0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea_pvo_enter_calls, CTLFLAG_RD,
+    &moea_pvo_enter_calls, 0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea_pvo_remove_calls, CTLFLAG_RD,
+    &moea_pvo_remove_calls, 0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea_pte_spills, CTLFLAG_RD,
+    &moea_pte_spills, 0, "");
+
+/*
+ * Allocate physical memory for use in moea_bootstrap.
+ */
+static vm_offset_t	moea_bootstrap_alloc(vm_size_t, u_int);
+
+/*
+ * PTE calls.
+ */
+static int		moea_pte_insert(u_int, struct pte *);
+
+/*
+ * PVO calls.
+ */
+static int	moea_pvo_enter(pmap_t, uma_zone_t, struct pvo_head *,
+		    vm_offset_t, vm_offset_t, u_int, int);
+static void	moea_pvo_remove(struct pvo_entry *, int);
+static struct	pvo_entry *moea_pvo_find_va(pmap_t, vm_offset_t, int *);
+static struct	pte *moea_pvo_to_pte(const struct pvo_entry *, int);
+
+/*
+ * Utility routines.
+ */
+static int		moea_enter_locked(pmap_t, vm_offset_t, vm_page_t,
+			    vm_prot_t, u_int, int8_t);
+static void		moea_syncicache(vm_offset_t, vm_size_t);
+static boolean_t	moea_query_bit(vm_page_t, int);
+static u_int		moea_clear_bit(vm_page_t, int);
+static void		moea_kremove(mmu_t, vm_offset_t);
+int		moea_pte_spill(vm_offset_t);
+
+/*
+ * Kernel MMU interface
+ */
+void moea_clear_modify(mmu_t, vm_page_t);
+void moea_copy_page(mmu_t, vm_page_t, vm_page_t);
+void moea_copy_pages(mmu_t mmu, vm_page_t *ma, vm_offset_t a_offset,
+    vm_page_t *mb, vm_offset_t b_offset, int xfersize);
+int moea_enter(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t, u_int,
+    int8_t);
+void moea_enter_object(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_page_t,
+    vm_prot_t);
+void moea_enter_quick(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t);
+vm_paddr_t moea_extract(mmu_t, pmap_t, vm_offset_t);
+vm_page_t moea_extract_and_hold(mmu_t, pmap_t, vm_offset_t, vm_prot_t);
+void moea_init(mmu_t);
+boolean_t moea_is_modified(mmu_t, vm_page_t);
+boolean_t moea_is_prefaultable(mmu_t, pmap_t, vm_offset_t);
+boolean_t moea_is_referenced(mmu_t, vm_page_t);
+int moea_ts_referenced(mmu_t, vm_page_t);
+vm_offset_t moea_map(mmu_t, vm_offset_t *, vm_paddr_t, vm_paddr_t, int);
+boolean_t moea_page_exists_quick(mmu_t, pmap_t, vm_page_t);
+int moea_page_wired_mappings(mmu_t, vm_page_t);
+void moea_pinit(mmu_t, pmap_t);
+void moea_pinit0(mmu_t, pmap_t);
+void moea_protect(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_prot_t);
+void moea_qenter(mmu_t, vm_offset_t, vm_page_t *, int);
+void moea_qremove(mmu_t, vm_offset_t, int);
+void moea_release(mmu_t, pmap_t);
+void moea_remove(mmu_t, pmap_t, vm_offset_t, vm_offset_t);
+void moea_remove_all(mmu_t, vm_page_t);
+void moea_remove_write(mmu_t, vm_page_t);
+void moea_unwire(mmu_t, pmap_t, vm_offset_t, vm_offset_t);
+void moea_zero_page(mmu_t, vm_page_t);
+void moea_zero_page_area(mmu_t, vm_page_t, int, int);
+void moea_zero_page_idle(mmu_t, vm_page_t);
+void moea_activate(mmu_t, struct thread *);
+void moea_deactivate(mmu_t, struct thread *);
+void moea_cpu_bootstrap(mmu_t, int);
+void moea_bootstrap(mmu_t, vm_offset_t, vm_offset_t);
+void *moea_mapdev(mmu_t, vm_paddr_t, vm_size_t);
+void *moea_mapdev_attr(mmu_t, vm_offset_t, vm_size_t, vm_memattr_t);
+void moea_unmapdev(mmu_t, vm_offset_t, vm_size_t);
+vm_paddr_t moea_kextract(mmu_t, vm_offset_t);
+void moea_kenter_attr(mmu_t, vm_offset_t, vm_offset_t, vm_memattr_t);
+void moea_kenter(mmu_t, vm_offset_t, vm_paddr_t);
+void moea_page_set_memattr(mmu_t mmu, vm_page_t m, vm_memattr_t ma);
+boolean_t moea_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
+static void moea_sync_icache(mmu_t, pmap_t, vm_offset_t, vm_size_t);
+vm_offset_t moea_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
+    vm_size_t *sz);
+struct pmap_md * moea_scan_md(mmu_t mmu, struct pmap_md *prev);
+
+static mmu_method_t moea_methods[] = {
+	MMUMETHOD(mmu_clear_modify,	moea_clear_modify),
+	MMUMETHOD(mmu_copy_page,	moea_copy_page),
+	MMUMETHOD(mmu_copy_pages,	moea_copy_pages),
+	MMUMETHOD(mmu_enter,		moea_enter),
+	MMUMETHOD(mmu_enter_object,	moea_enter_object),
+	MMUMETHOD(mmu_enter_quick,	moea_enter_quick),
+	MMUMETHOD(mmu_extract,		moea_extract),
+	MMUMETHOD(mmu_extract_and_hold,	moea_extract_and_hold),
+	MMUMETHOD(mmu_init,		moea_init),
+	MMUMETHOD(mmu_is_modified,	moea_is_modified),
+	MMUMETHOD(mmu_is_prefaultable,	moea_is_prefaultable),
+	MMUMETHOD(mmu_is_referenced,	moea_is_referenced),
+	MMUMETHOD(mmu_ts_referenced,	moea_ts_referenced),
+	MMUMETHOD(mmu_map,     		moea_map),
+	MMUMETHOD(mmu_page_exists_quick,moea_page_exists_quick),
+	MMUMETHOD(mmu_page_wired_mappings,moea_page_wired_mappings),
+	MMUMETHOD(mmu_pinit,		moea_pinit),
+	MMUMETHOD(mmu_pinit0,		moea_pinit0),
+	MMUMETHOD(mmu_protect,		moea_protect),
+	MMUMETHOD(mmu_qenter,		moea_qenter),
+	MMUMETHOD(mmu_qremove,		moea_qremove),
+	MMUMETHOD(mmu_release,		moea_release),
+	MMUMETHOD(mmu_remove,		moea_remove),
+	MMUMETHOD(mmu_remove_all,      	moea_remove_all),
+	MMUMETHOD(mmu_remove_write,	moea_remove_write),
+	MMUMETHOD(mmu_sync_icache,	moea_sync_icache),
+	MMUMETHOD(mmu_unwire,		moea_unwire),
+	MMUMETHOD(mmu_zero_page,       	moea_zero_page),
+	MMUMETHOD(mmu_zero_page_area,	moea_zero_page_area),
+	MMUMETHOD(mmu_zero_page_idle,	moea_zero_page_idle),
+	MMUMETHOD(mmu_activate,		moea_activate),
+	MMUMETHOD(mmu_deactivate,      	moea_deactivate),
+	MMUMETHOD(mmu_page_set_memattr,	moea_page_set_memattr),
+
+	/* Internal interfaces */
+	MMUMETHOD(mmu_bootstrap,       	moea_bootstrap),
+	MMUMETHOD(mmu_cpu_bootstrap,   	moea_cpu_bootstrap),
+	MMUMETHOD(mmu_mapdev_attr,	moea_mapdev_attr),
+	MMUMETHOD(mmu_mapdev,		moea_mapdev),
+	MMUMETHOD(mmu_unmapdev,		moea_unmapdev),
+	MMUMETHOD(mmu_kextract,		moea_kextract),
+	MMUMETHOD(mmu_kenter,		moea_kenter),
+	MMUMETHOD(mmu_kenter_attr,	moea_kenter_attr),
+	MMUMETHOD(mmu_dev_direct_mapped,moea_dev_direct_mapped),
+	MMUMETHOD(mmu_scan_md,		moea_scan_md),
+	MMUMETHOD(mmu_dumpsys_map,	moea_dumpsys_map),
+
+	{ 0, 0 }
+};
+
+MMU_DEF(oea_mmu, MMU_TYPE_OEA, moea_methods, 0);
+
+static __inline uint32_t
+moea_calc_wimg(vm_offset_t pa, vm_memattr_t ma)
+{
+	uint32_t pte_lo;
+	int i;
+
+	if (ma != VM_MEMATTR_DEFAULT) {
+		switch (ma) {
+		case VM_MEMATTR_UNCACHEABLE:
+			return (PTE_I | PTE_G);
+		case VM_MEMATTR_WRITE_COMBINING:
+		case VM_MEMATTR_WRITE_BACK:
+		case VM_MEMATTR_PREFETCHABLE:
+			return (PTE_I);
+		case VM_MEMATTR_WRITE_THROUGH:
+			return (PTE_W | PTE_M);
+		}
+	}
+
+	/*
+	 * Assume the page is cache inhibited and access is guarded unless
+	 * it's in our available memory array.
+	 */
+	pte_lo = PTE_I | PTE_G;
+	for (i = 0; i < pregions_sz; i++) {
+		if ((pa >= pregions[i].mr_start) &&
+		    (pa < (pregions[i].mr_start + pregions[i].mr_size))) {
+			pte_lo = PTE_M;
+			break;
+		}
+	}
+
+	return pte_lo;
+}
+
+static void
+tlbie(vm_offset_t va)
+{
+
+	mtx_lock_spin(&tlbie_mtx);
+	__asm __volatile("ptesync");
+	__asm __volatile("tlbie %0" :: "r"(va));
+	__asm __volatile("eieio; tlbsync; ptesync");
+	mtx_unlock_spin(&tlbie_mtx);
+}
+
+static void
+tlbia(void)
+{
+	vm_offset_t va;
+ 
+	for (va = 0; va < 0x00040000; va += 0x00001000) {
+		__asm __volatile("tlbie %0" :: "r"(va));
+		powerpc_sync();
+	}
+	__asm __volatile("tlbsync");
+	powerpc_sync();
+}
+
+static __inline int
+va_to_sr(u_int *sr, vm_offset_t va)
+{
+	return (sr[(uintptr_t)va >> ADDR_SR_SHFT]);
+}
+
+static __inline u_int
+va_to_pteg(u_int sr, vm_offset_t addr)
+{
+	u_int hash;
+
+	hash = (sr & SR_VSID_MASK) ^ (((u_int)addr & ADDR_PIDX) >>
+	    ADDR_PIDX_SHFT);
+	return (hash & moea_pteg_mask);
+}
+
+static __inline struct pvo_head *
+vm_page_to_pvoh(vm_page_t m)
+{
+
+	return (&m->md.mdpg_pvoh);
+}
+
+static __inline void
+moea_attr_clear(vm_page_t m, int ptebit)
+{
+
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
+	m->md.mdpg_attrs &= ~ptebit;
+}
+
+static __inline int
+moea_attr_fetch(vm_page_t m)
+{
+
+	return (m->md.mdpg_attrs);
+}
+
+static __inline void
+moea_attr_save(vm_page_t m, int ptebit)
+{
+
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
+	m->md.mdpg_attrs |= ptebit;
+}
+
+static __inline int
+moea_pte_compare(const struct pte *pt, const struct pte *pvo_pt)
+{
+	if (pt->pte_hi == pvo_pt->pte_hi)
+		return (1);
+
+	return (0);
+}
+
+static __inline int
+moea_pte_match(struct pte *pt, u_int sr, vm_offset_t va, int which)
+{
+	return (pt->pte_hi & ~PTE_VALID) ==
+	    (((sr & SR_VSID_MASK) << PTE_VSID_SHFT) |
+	    ((va >> ADDR_API_SHFT) & PTE_API) | which);
+}
+
+static __inline void
+moea_pte_create(struct pte *pt, u_int sr, vm_offset_t va, u_int pte_lo)
+{
+
+	mtx_assert(&moea_table_mutex, MA_OWNED);
+
+	/*
+	 * Construct a PTE.  Default to IMB initially.  Valid bit only gets
+	 * set when the real pte is set in memory.
+	 *
+	 * Note: Don't set the valid bit for correct operation of tlb update.
+	 */
+	pt->pte_hi = ((sr & SR_VSID_MASK) << PTE_VSID_SHFT) |
+	    (((va & ADDR_PIDX) >> ADDR_API_SHFT) & PTE_API);
+	pt->pte_lo = pte_lo;
+}
+
+static __inline void
+moea_pte_synch(struct pte *pt, struct pte *pvo_pt)
+{
+
+	mtx_assert(&moea_table_mutex, MA_OWNED);
+	pvo_pt->pte_lo |= pt->pte_lo & (PTE_REF | PTE_CHG);
+}
+
+static __inline void
+moea_pte_clear(struct pte *pt, vm_offset_t va, int ptebit)
+{
+
+	mtx_assert(&moea_table_mutex, MA_OWNED);
+
+	/*
+	 * As shown in Section 7.6.3.2.3
+	 */
+	pt->pte_lo &= ~ptebit;
+	tlbie(va);
+}
+
+static __inline void
+moea_pte_set(struct pte *pt, struct pte *pvo_pt)
+{
+
+	mtx_assert(&moea_table_mutex, MA_OWNED);
+	pvo_pt->pte_hi |= PTE_VALID;
+
+	/*
+	 * Update the PTE as defined in section 7.6.3.1.
+	 * Note that the REF/CHG bits are from pvo_pt and thus should have
+	 * been saved so this routine can restore them (if desired).
+	 */
+	pt->pte_lo = pvo_pt->pte_lo;
+	powerpc_sync();
+	pt->pte_hi = pvo_pt->pte_hi;
+	powerpc_sync();
+	moea_pte_valid++;
+}
+
+static __inline void
+moea_pte_unset(struct pte *pt, struct pte *pvo_pt, vm_offset_t va)
+{
+
+	mtx_assert(&moea_table_mutex, MA_OWNED);
+	pvo_pt->pte_hi &= ~PTE_VALID;
+
+	/*
+	 * Force the reg & chg bits back into the PTEs.
+	 */
+	powerpc_sync();
+
+	/*
+	 * Invalidate the pte.
+	 */
+	pt->pte_hi &= ~PTE_VALID;
+
+	tlbie(va);
+
+	/*
+	 * Save the reg & chg bits.
+	 */
+	moea_pte_synch(pt, pvo_pt);
+	moea_pte_valid--;
+}
+
+static __inline void
+moea_pte_change(struct pte *pt, struct pte *pvo_pt, vm_offset_t va)
+{
+
+	/*
+	 * Invalidate the PTE
+	 */
+	moea_pte_unset(pt, pvo_pt, va);
+	moea_pte_set(pt, pvo_pt);
+}
+
+/*
+ * Quick sort callout for comparing memory regions.
+ */
+static int	om_cmp(const void *a, const void *b);
+
+static int
+om_cmp(const void *a, const void *b)
+{
+	const struct	ofw_map *mapa;
+	const struct	ofw_map *mapb;
+
+	mapa = a;
+	mapb = b;
+	if (mapa->om_pa < mapb->om_pa)
+		return (-1);
+	else if (mapa->om_pa > mapb->om_pa)
+		return (1);
+	else
+		return (0);
+}
+
+void
+moea_cpu_bootstrap(mmu_t mmup, int ap)
+{
+	u_int sdr;
+	int i;
+
+	if (ap) {
+		powerpc_sync();
+		__asm __volatile("mtdbatu 0,%0" :: "r"(battable[0].batu));
+		__asm __volatile("mtdbatl 0,%0" :: "r"(battable[0].batl));
+		isync();
+		__asm __volatile("mtibatu 0,%0" :: "r"(battable[0].batu));
+		__asm __volatile("mtibatl 0,%0" :: "r"(battable[0].batl));
+		isync();
+	}
+
+#ifdef WII
+	/*
+	 * Special case for the Wii: don't install the PCI BAT.
+	 */
+	if (strcmp(installed_platform(), "wii") != 0) {
+#endif
+		__asm __volatile("mtdbatu 1,%0" :: "r"(battable[8].batu));
+		__asm __volatile("mtdbatl 1,%0" :: "r"(battable[8].batl));
+#ifdef WII
+	}
+#endif
+	isync();
+
+	__asm __volatile("mtibatu 1,%0" :: "r"(0));
+	__asm __volatile("mtdbatu 2,%0" :: "r"(0));
+	__asm __volatile("mtibatu 2,%0" :: "r"(0));
+	__asm __volatile("mtdbatu 3,%0" :: "r"(0));
+	__asm __volatile("mtibatu 3,%0" :: "r"(0));
+	isync();
+
+	for (i = 0; i < 16; i++)
+		mtsrin(i << ADDR_SR_SHFT, kernel_pmap->pm_sr[i]);
+	powerpc_sync();
+
+	sdr = (u_int)moea_pteg_table | (moea_pteg_mask >> 10);
+	__asm __volatile("mtsdr1 %0" :: "r"(sdr));
+	isync();
+
+	tlbia();
+}
+
+void
+moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
+{
+	ihandle_t	mmui;
+	phandle_t	chosen, mmu;
+	int		sz;
+	int		i, j;
+	vm_size_t	size, physsz, hwphyssz;
+	vm_offset_t	pa, va, off;
+	void		*dpcpu;
+	register_t	msr;
+
+        /*
+         * Set up BAT0 to map the lowest 256 MB area
+         */
+        battable[0x0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW);
+        battable[0x0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs);
+
+	/*
+	 * Map PCI memory space.
+	 */
+	battable[0x8].batl = BATL(0x80000000, BAT_I|BAT_G, BAT_PP_RW);
+	battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs);
+
+	battable[0x9].batl = BATL(0x90000000, BAT_I|BAT_G, BAT_PP_RW);
+	battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs);
+
+	battable[0xa].batl = BATL(0xa0000000, BAT_I|BAT_G, BAT_PP_RW);
+	battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs);
+
+	battable[0xb].batl = BATL(0xb0000000, BAT_I|BAT_G, BAT_PP_RW);
+	battable[0xb].batu = BATU(0xb0000000, BAT_BL_256M, BAT_Vs);
+
+	/*
+	 * Map obio devices.
+	 */
+	battable[0xf].batl = BATL(0xf0000000, BAT_I|BAT_G, BAT_PP_RW);
+	battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs);
+
+	/*
+	 * Use an IBAT and a DBAT to map the bottom segment of memory
+	 * where we are. Turn off instruction relocation temporarily
+	 * to prevent faults while reprogramming the IBAT.
+	 */
+	msr = mfmsr();
+	mtmsr(msr & ~PSL_IR);
+	__asm (".balign 32; \n"
+	       "mtibatu 0,%0; mtibatl 0,%1; isync; \n"
+	       "mtdbatu 0,%0; mtdbatl 0,%1; isync"
+	    :: "r"(battable[0].batu), "r"(battable[0].batl));
+	mtmsr(msr);
+
+#ifdef WII
+        if (strcmp(installed_platform(), "wii") != 0) {
+#endif
+		/* map pci space */
+		__asm __volatile("mtdbatu 1,%0" :: "r"(battable[8].batu));
+		__asm __volatile("mtdbatl 1,%0" :: "r"(battable[8].batl));
+#ifdef WII
+	}
+#endif
+	isync();
+
+	/* set global direct map flag */
+	hw_direct_map = 1;
+
+	mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
+	CTR0(KTR_PMAP, "moea_bootstrap: physical memory");
+
+	for (i = 0; i < pregions_sz; i++) {
+		vm_offset_t pa;
+		vm_offset_t end;
+
+		CTR3(KTR_PMAP, "physregion: %#x - %#x (%#x)",
+			pregions[i].mr_start,
+			pregions[i].mr_start + pregions[i].mr_size,
+			pregions[i].mr_size);
+		/*
+		 * Install entries into the BAT table to allow all
+		 * of physmem to be convered by on-demand BAT entries.
+		 * The loop will sometimes set the same battable element
+		 * twice, but that's fine since they won't be used for
+		 * a while yet.
+		 */
+		pa = pregions[i].mr_start & 0xf0000000;
+		end = pregions[i].mr_start + pregions[i].mr_size;
+		do {
+                        u_int n = pa >> ADDR_SR_SHFT;
+
+			battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW);
+			battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs);
+			pa += SEGMENT_LENGTH;
+		} while (pa < end);
+	}
+
+	if (sizeof(phys_avail)/sizeof(phys_avail[0]) < regions_sz)
+		panic("moea_bootstrap: phys_avail too small");
+
+	phys_avail_count = 0;
+	physsz = 0;
+	hwphyssz = 0;
+	TUNABLE_ULONG_FETCH("hw.physmem", (u_long *) &hwphyssz);
+	for (i = 0, j = 0; i < regions_sz; i++, j += 2) {
+		CTR3(KTR_PMAP, "region: %#x - %#x (%#x)", regions[i].mr_start,
+		    regions[i].mr_start + regions[i].mr_size,
+		    regions[i].mr_size);
+		if (hwphyssz != 0 &&
+		    (physsz + regions[i].mr_size) >= hwphyssz) {
+			if (physsz < hwphyssz) {
+				phys_avail[j] = regions[i].mr_start;
+				phys_avail[j + 1] = regions[i].mr_start +
+				    hwphyssz - physsz;
+				physsz = hwphyssz;
+				phys_avail_count++;
+			}
+			break;
+		}
+		phys_avail[j] = regions[i].mr_start;
+		phys_avail[j + 1] = regions[i].mr_start + regions[i].mr_size;
+		phys_avail_count++;
+		physsz += regions[i].mr_size;
+	}
+
+	/* Check for overlap with the kernel and exception vectors */
+	for (j = 0; j < 2*phys_avail_count; j+=2) {
+		if (phys_avail[j] < EXC_LAST)
+			phys_avail[j] += EXC_LAST;
+
+		if (kernelstart >= phys_avail[j] &&
+		    kernelstart < phys_avail[j+1]) {
+			if (kernelend < phys_avail[j+1]) {
+				phys_avail[2*phys_avail_count] =
+				    (kernelend & ~PAGE_MASK) + PAGE_SIZE;
+				phys_avail[2*phys_avail_count + 1] =
+				    phys_avail[j+1];
+				phys_avail_count++;
+			}
+
+			phys_avail[j+1] = kernelstart & ~PAGE_MASK;
+		}
+
+		if (kernelend >= phys_avail[j] &&
+		    kernelend < phys_avail[j+1]) {
+			if (kernelstart > phys_avail[j]) {
+				phys_avail[2*phys_avail_count] = phys_avail[j];
+				phys_avail[2*phys_avail_count + 1] =
+				    kernelstart & ~PAGE_MASK;
+				phys_avail_count++;
+			}
+
+			phys_avail[j] = (kernelend & ~PAGE_MASK) + PAGE_SIZE;
+		}
+	}
+
+	physmem = btoc(physsz);
+
+	/*
+	 * Allocate PTEG table.
+	 */
+#ifdef PTEGCOUNT
+	moea_pteg_count = PTEGCOUNT;
+#else
+	moea_pteg_count = 0x1000;
+
+	while (moea_pteg_count < physmem)
+		moea_pteg_count <<= 1;
+
+	moea_pteg_count >>= 1;
+#endif /* PTEGCOUNT */
+
+	size = moea_pteg_count * sizeof(struct pteg);
+	CTR2(KTR_PMAP, "moea_bootstrap: %d PTEGs, %d bytes", moea_pteg_count,
+	    size);
+	moea_pteg_table = (struct pteg *)moea_bootstrap_alloc(size, size);
+	CTR1(KTR_PMAP, "moea_bootstrap: PTEG table at %p", moea_pteg_table);
+	bzero((void *)moea_pteg_table, moea_pteg_count * sizeof(struct pteg));
+	moea_pteg_mask = moea_pteg_count - 1;
+
+	/*
+	 * Allocate pv/overflow lists.
+	 */
+	size = sizeof(struct pvo_head) * moea_pteg_count;
+	moea_pvo_table = (struct pvo_head *)moea_bootstrap_alloc(size,
+	    PAGE_SIZE);
+	CTR1(KTR_PMAP, "moea_bootstrap: PVO table at %p", moea_pvo_table);
+	for (i = 0; i < moea_pteg_count; i++)
+		LIST_INIT(&moea_pvo_table[i]);
+
+	/*
+	 * Initialize the lock that synchronizes access to the pteg and pvo
+	 * tables.
+	 */
+	mtx_init(&moea_table_mutex, "pmap table", NULL, MTX_DEF |
+	    MTX_RECURSE);
+	mtx_init(&moea_vsid_mutex, "VSID table", NULL, MTX_DEF);
+
+	mtx_init(&tlbie_mtx, "tlbie", NULL, MTX_SPIN);
+
+	/*
+	 * Initialise the unmanaged pvo pool.
+	 */
+	moea_bpvo_pool = (struct pvo_entry *)moea_bootstrap_alloc(
+		BPVO_POOL_SIZE*sizeof(struct pvo_entry), 0);
+	moea_bpvo_pool_index = 0;
+
+	/*
+	 * Make sure kernel vsid is allocated as well as VSID 0.
+	 */
+	moea_vsid_bitmap[(KERNEL_VSIDBITS & (NPMAPS - 1)) / VSID_NBPW]
+		|= 1 << (KERNEL_VSIDBITS % VSID_NBPW);
+	moea_vsid_bitmap[0] |= 1;
+
+	/*
+	 * Initialize the kernel pmap (which is statically allocated).
+	 */
+	PMAP_LOCK_INIT(kernel_pmap);
+	for (i = 0; i < 16; i++)
+		kernel_pmap->pm_sr[i] = EMPTY_SEGMENT + i;
+	CPU_FILL(&kernel_pmap->pm_active);
+	RB_INIT(&kernel_pmap->pmap_pvo);
+
+ 	/*
+	 * Initialize the global pv list lock.
+	 */
+	rw_init(&pvh_global_lock, "pmap pv global");
+
+	/*
+	 * Set up the Open Firmware mappings
+	 */
+	chosen = OF_finddevice("/chosen");
+	if (chosen != -1 && OF_getprop(chosen, "mmu", &mmui, 4) != -1 &&
+	    (mmu = OF_instance_to_package(mmui)) != -1 && 
+	    (sz = OF_getproplen(mmu, "translations")) != -1) {
+		translations = NULL;
+		for (i = 0; phys_avail[i] != 0; i += 2) {
+			if (phys_avail[i + 1] >= sz) {
+				translations = (struct ofw_map *)phys_avail[i];
+				break;
+			}
+		}
+		if (translations == NULL)
+			panic("moea_bootstrap: no space to copy translations");
+		bzero(translations, sz);
+		if (OF_getprop(mmu, "translations", translations, sz) == -1)
+			panic("moea_bootstrap: can't get ofw translations");
+		CTR0(KTR_PMAP, "moea_bootstrap: translations");
+		sz /= sizeof(*translations);
+		qsort(translations, sz, sizeof (*translations), om_cmp);
+		for (i = 0; i < sz; i++) {
+			CTR3(KTR_PMAP, "translation: pa=%#x va=%#x len=%#x",
+			    translations[i].om_pa, translations[i].om_va,
+			    translations[i].om_len);
+
+			/*
+			 * If the mapping is 1:1, let the RAM and device
+			 * on-demand BAT tables take care of the translation.
+			 */
+			if (translations[i].om_va == translations[i].om_pa)
+				continue;
+
+			/* Enter the pages */
+			for (off = 0; off < translations[i].om_len;
+			    off += PAGE_SIZE)
+				moea_kenter(mmup, translations[i].om_va + off, 
+					    translations[i].om_pa + off);
+		}
+	}
+
+	/*
+	 * Calculate the last available physical address.
+	 */
+	for (i = 0; phys_avail[i + 2] != 0; i += 2)
+		;
+	Maxmem = powerpc_btop(phys_avail[i + 1]);
+
+	moea_cpu_bootstrap(mmup,0);
+
+	pmap_bootstrapped++;
+
+	/*
+	 * Set the start and end of kva.
+	 */
+	virtual_avail = VM_MIN_KERNEL_ADDRESS;
+	virtual_end = VM_MAX_SAFE_KERNEL_ADDRESS;
+
+	/*
+	 * Allocate a kernel stack with a guard page for thread0 and map it
+	 * into the kernel page map.
+	 */
+	pa = moea_bootstrap_alloc(KSTACK_PAGES * PAGE_SIZE, PAGE_SIZE);
+	va = virtual_avail + KSTACK_GUARD_PAGES * PAGE_SIZE;
+	virtual_avail = va + KSTACK_PAGES * PAGE_SIZE;
+	CTR2(KTR_PMAP, "moea_bootstrap: kstack0 at %#x (%#x)", pa, va);
+	thread0.td_kstack = va;
+	thread0.td_kstack_pages = KSTACK_PAGES;
+	for (i = 0; i < KSTACK_PAGES; i++) {
+		moea_kenter(mmup, va, pa);
+		pa += PAGE_SIZE;
+		va += PAGE_SIZE;
+	}
+
+	/*
+	 * Allocate virtual address space for the message buffer.
+	 */
+	pa = msgbuf_phys = moea_bootstrap_alloc(msgbufsize, PAGE_SIZE);
+	msgbufp = (struct msgbuf *)virtual_avail;
+	va = virtual_avail;
+	virtual_avail += round_page(msgbufsize);
+	while (va < virtual_avail) {
+		moea_kenter(mmup, va, pa);
+		pa += PAGE_SIZE;
+		va += PAGE_SIZE;
+	}
+
+	/*
+	 * Allocate virtual address space for the dynamic percpu area.
+	 */
+	pa = moea_bootstrap_alloc(DPCPU_SIZE, PAGE_SIZE);
+	dpcpu = (void *)virtual_avail;
+	va = virtual_avail;
+	virtual_avail += DPCPU_SIZE;
+	while (va < virtual_avail) {
+		moea_kenter(mmup, va, pa);
+		pa += PAGE_SIZE;
+		va += PAGE_SIZE;
+	}
+	dpcpu_init(dpcpu, 0);
+}
+
+/*
+ * Activate a user pmap.  The pmap must be activated before it's address
+ * space can be accessed in any way.
+ */
+void
+moea_activate(mmu_t mmu, struct thread *td)
+{
+	pmap_t	pm, pmr;
+
+	/*
+	 * Load all the data we need up front to encourage the compiler to
+	 * not issue any loads while we have interrupts disabled below.
+	 */
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+	pmr = pm->pmap_phys;
+
+	CPU_SET(PCPU_GET(cpuid), &pm->pm_active);
+	PCPU_SET(curpmap, pmr);
+}
+
+void
+moea_deactivate(mmu_t mmu, struct thread *td)
+{
+	pmap_t	pm;
+
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+	CPU_CLR(PCPU_GET(cpuid), &pm->pm_active);
+	PCPU_SET(curpmap, NULL);
+}
+
+void
+moea_unwire(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva)
+{
+	struct	pvo_entry key, *pvo;
+
+	PMAP_LOCK(pm);
+	key.pvo_vaddr = sva;
+	for (pvo = RB_NFIND(pvo_tree, &pm->pmap_pvo, &key);
+	    pvo != NULL && PVO_VADDR(pvo) < eva;
+	    pvo = RB_NEXT(pvo_tree, &pm->pmap_pvo, pvo)) {
+		if ((pvo->pvo_vaddr & PVO_WIRED) == 0)
+			panic("moea_unwire: pvo %p is missing PVO_WIRED", pvo);
+		pvo->pvo_vaddr &= ~PVO_WIRED;
+		pm->pm_stats.wired_count--;
+	}
+	PMAP_UNLOCK(pm);
+}
+
+void
+moea_copy_page(mmu_t mmu, vm_page_t msrc, vm_page_t mdst)
+{
+	vm_offset_t	dst;
+	vm_offset_t	src;
+
+	dst = VM_PAGE_TO_PHYS(mdst);
+	src = VM_PAGE_TO_PHYS(msrc);
+
+	bcopy((void *)src, (void *)dst, PAGE_SIZE);
+}
+
+void
+moea_copy_pages(mmu_t mmu, vm_page_t *ma, vm_offset_t a_offset,
+    vm_page_t *mb, vm_offset_t b_offset, int xfersize)
+{
+	void *a_cp, *b_cp;
+	vm_offset_t a_pg_offset, b_pg_offset;
+	int cnt;
+
+	while (xfersize > 0) {
+		a_pg_offset = a_offset & PAGE_MASK;
+		cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
+		a_cp = (char *)VM_PAGE_TO_PHYS(ma[a_offset >> PAGE_SHIFT]) +
+		    a_pg_offset;
+		b_pg_offset = b_offset & PAGE_MASK;
+		cnt = min(cnt, PAGE_SIZE - b_pg_offset);
+		b_cp = (char *)VM_PAGE_TO_PHYS(mb[b_offset >> PAGE_SHIFT]) +
+		    b_pg_offset;
+		bcopy(a_cp, b_cp, cnt);
+		a_offset += cnt;
+		b_offset += cnt;
+		xfersize -= cnt;
+	}
+}
+
+/*
+ * Zero a page of physical memory by temporarily mapping it into the tlb.
+ */
+void
+moea_zero_page(mmu_t mmu, vm_page_t m)
+{
+	vm_offset_t off, pa = VM_PAGE_TO_PHYS(m);
+
+	for (off = 0; off < PAGE_SIZE; off += cacheline_size)
+		__asm __volatile("dcbz 0,%0" :: "r"(pa + off));
+}
+
+void
+moea_zero_page_area(mmu_t mmu, vm_page_t m, int off, int size)
+{
+	vm_offset_t pa = VM_PAGE_TO_PHYS(m);
+	void *va = (void *)(pa + off);
+
+	bzero(va, size);
+}
+
+void
+moea_zero_page_idle(mmu_t mmu, vm_page_t m)
+{
+
+	moea_zero_page(mmu, m);
+}
+
+/*
+ * Map the given physical page at the specified virtual address in the
+ * target pmap with the protection requested.  If specified the page
+ * will be wired down.
+ */
+int
+moea_enter(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
+    u_int flags, int8_t psind)
+{
+	int error;
+
+	for (;;) {
+		rw_wlock(&pvh_global_lock);
+		PMAP_LOCK(pmap);
+		error = moea_enter_locked(pmap, va, m, prot, flags, psind);
+		rw_wunlock(&pvh_global_lock);
+		PMAP_UNLOCK(pmap);
+		if (error != ENOMEM)
+			return (KERN_SUCCESS);
+		if ((flags & PMAP_ENTER_NOSLEEP) != 0)
+			return (KERN_RESOURCE_SHORTAGE);
+		VM_OBJECT_ASSERT_UNLOCKED(m->object);
+		VM_WAIT;
+	}
+}
+
+/*
+ * Map the given physical page at the specified virtual address in the
+ * target pmap with the protection requested.  If specified the page
+ * will be wired down.
+ *
+ * The page queues and pmap must be locked.
+ */
+static int
+moea_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
+    u_int flags, int8_t psind __unused)
+{
+	struct		pvo_head *pvo_head;
+	uma_zone_t	zone;
+	vm_page_t	pg;
+	u_int		pte_lo, pvo_flags;
+	int		error;
+
+	if (!moea_initialized) {
+		pvo_head = &moea_pvo_kunmanaged;
+		zone = moea_upvo_zone;
+		pvo_flags = 0;
+		pg = NULL;
+	} else {
+		pvo_head = vm_page_to_pvoh(m);
+		pg = m;
+		zone = moea_mpvo_zone;
+		pvo_flags = PVO_MANAGED;
+	}
+	if (pmap_bootstrapped)
+		rw_assert(&pvh_global_lock, RA_WLOCKED);
+	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+	if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
+		VM_OBJECT_ASSERT_LOCKED(m->object);
+
+	/* XXX change the pvo head for fake pages */
+	if ((m->oflags & VPO_UNMANAGED) != 0) {
+		pvo_flags &= ~PVO_MANAGED;
+		pvo_head = &moea_pvo_kunmanaged;
+		zone = moea_upvo_zone;
+	}
+
+	pte_lo = moea_calc_wimg(VM_PAGE_TO_PHYS(m), pmap_page_get_memattr(m));
+
+	if (prot & VM_PROT_WRITE) {
+		pte_lo |= PTE_BW;
+		if (pmap_bootstrapped &&
+		    (m->oflags & VPO_UNMANAGED) == 0)
+			vm_page_aflag_set(m, PGA_WRITEABLE);
+	} else
+		pte_lo |= PTE_BR;
+
+	if ((flags & PMAP_ENTER_WIRED) != 0)
+		pvo_flags |= PVO_WIRED;
+
+	error = moea_pvo_enter(pmap, zone, pvo_head, va, VM_PAGE_TO_PHYS(m),
+	    pte_lo, pvo_flags);
+
+	/*
+	 * Flush the real page from the instruction cache. This has be done
+	 * for all user mappings to prevent information leakage via the
+	 * instruction cache. moea_pvo_enter() returns ENOENT for the first
+	 * mapping for a page.
+	 */
+	if (pmap != kernel_pmap && error == ENOENT &&
+	    (pte_lo & (PTE_I | PTE_G)) == 0)
+		moea_syncicache(VM_PAGE_TO_PHYS(m), PAGE_SIZE);
+
+	return (error);
+}
+
+/*
+ * Maps a sequence of resident pages belonging to the same object.
+ * The sequence begins with the given page m_start.  This page is
+ * mapped at the given virtual address start.  Each subsequent page is
+ * mapped at a virtual address that is offset from start by the same
+ * amount as the page is offset from m_start within the object.  The
+ * last page in the sequence is the page with the largest offset from
+ * m_start that can be mapped at a virtual address less than the given
+ * virtual address end.  Not every virtual page between start and end
+ * is mapped; only those for which a resident page exists with the
+ * corresponding offset from m_start are mapped.
+ */
+void
+moea_enter_object(mmu_t mmu, pmap_t pm, vm_offset_t start, vm_offset_t end,
+    vm_page_t m_start, vm_prot_t prot)
+{
+	vm_page_t m;
+	vm_pindex_t diff, psize;
+
+	VM_OBJECT_ASSERT_LOCKED(m_start->object);
+
+	psize = atop(end - start);
+	m = m_start;
+	rw_wlock(&pvh_global_lock);
+	PMAP_LOCK(pm);
+	while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
+		moea_enter_locked(pm, start + ptoa(diff), m, prot &
+		    (VM_PROT_READ | VM_PROT_EXECUTE), 0, 0);
+		m = TAILQ_NEXT(m, listq);
+	}
+	rw_wunlock(&pvh_global_lock);
+	PMAP_UNLOCK(pm);
+}
+
+void
+moea_enter_quick(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_page_t m,
+    vm_prot_t prot)
+{
+
+	rw_wlock(&pvh_global_lock);
+	PMAP_LOCK(pm);
+	moea_enter_locked(pm, va, m, prot & (VM_PROT_READ | VM_PROT_EXECUTE),
+	    0, 0);
+	rw_wunlock(&pvh_global_lock);
+	PMAP_UNLOCK(pm);
+}
+
+vm_paddr_t
+moea_extract(mmu_t mmu, pmap_t pm, vm_offset_t va)
+{
+	struct	pvo_entry *pvo;
+	vm_paddr_t pa;
+
+	PMAP_LOCK(pm);
+	pvo = moea_pvo_find_va(pm, va & ~ADDR_POFF, NULL);
+	if (pvo == NULL)
+		pa = 0;
+	else
+		pa = (pvo->pvo_pte.pte.pte_lo & PTE_RPGN) | (va & ADDR_POFF);
+	PMAP_UNLOCK(pm);
+	return (pa);
+}
+
+/*
+ * Atomically extract and hold the physical page with the given
+ * pmap and virtual address pair if that mapping permits the given
+ * protection.
+ */
+vm_page_t
+moea_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot)
+{
+	struct	pvo_entry *pvo;
+	vm_page_t m;
+        vm_paddr_t pa;
+
+	m = NULL;
+	pa = 0;
+	PMAP_LOCK(pmap);
+retry:
+	pvo = moea_pvo_find_va(pmap, va & ~ADDR_POFF, NULL);
+	if (pvo != NULL && (pvo->pvo_pte.pte.pte_hi & PTE_VALID) &&
+	    ((pvo->pvo_pte.pte.pte_lo & PTE_PP) == PTE_RW ||
+	     (prot & VM_PROT_WRITE) == 0)) {
+		if (vm_page_pa_tryrelock(pmap, pvo->pvo_pte.pte.pte_lo & PTE_RPGN, &pa))
+			goto retry;
+		m = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte.pte_lo & PTE_RPGN);
+		vm_page_hold(m);
+	}
+	PA_UNLOCK_COND(pa);
+	PMAP_UNLOCK(pmap);
+	return (m);
+}
+
+void
+moea_init(mmu_t mmu)
+{
+
+	moea_upvo_zone = uma_zcreate("UPVO entry", sizeof (struct pvo_entry),
+	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,
+	    UMA_ZONE_VM | UMA_ZONE_NOFREE);
+	moea_mpvo_zone = uma_zcreate("MPVO entry", sizeof(struct pvo_entry),
+	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,
+	    UMA_ZONE_VM | UMA_ZONE_NOFREE);
+	moea_initialized = TRUE;
+}
+
+boolean_t
+moea_is_referenced(mmu_t mmu, vm_page_t m)
+{
+	boolean_t rv;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("moea_is_referenced: page %p is not managed", m));
+	rw_wlock(&pvh_global_lock);
+	rv = moea_query_bit(m, PTE_REF);
+	rw_wunlock(&pvh_global_lock);
+	return (rv);
+}
+
+boolean_t
+moea_is_modified(mmu_t mmu, vm_page_t m)
+{
+	boolean_t rv;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("moea_is_modified: page %p is not managed", m));
+
+	/*
+	 * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
+	 * concurrently set while the object is locked.  Thus, if PGA_WRITEABLE
+	 * is clear, no PTEs can have PTE_CHG set.
+	 */
+	VM_OBJECT_ASSERT_WLOCKED(m->object);
+	if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
+		return (FALSE);
+	rw_wlock(&pvh_global_lock);
+	rv = moea_query_bit(m, PTE_CHG);
+	rw_wunlock(&pvh_global_lock);
+	return (rv);
+}
+
+boolean_t
+moea_is_prefaultable(mmu_t mmu, pmap_t pmap, vm_offset_t va)
+{
+	struct pvo_entry *pvo;
+	boolean_t rv;
+
+	PMAP_LOCK(pmap);
+	pvo = moea_pvo_find_va(pmap, va & ~ADDR_POFF, NULL);
+	rv = pvo == NULL || (pvo->pvo_pte.pte.pte_hi & PTE_VALID) == 0;
+	PMAP_UNLOCK(pmap);
+	return (rv);
+}
+
+void
+moea_clear_modify(mmu_t mmu, vm_page_t m)
+{
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("moea_clear_modify: page %p is not managed", m));
+	VM_OBJECT_ASSERT_WLOCKED(m->object);
+	KASSERT(!vm_page_xbusied(m),
+	    ("moea_clear_modify: page %p is exclusive busy", m));
+
+	/*
+	 * If the page is not PGA_WRITEABLE, then no PTEs can have PTE_CHG
+	 * set.  If the object containing the page is locked and the page is
+	 * not exclusive busied, then PGA_WRITEABLE cannot be concurrently set.
+	 */
+	if ((m->aflags & PGA_WRITEABLE) == 0)
+		return;
+	rw_wlock(&pvh_global_lock);
+	moea_clear_bit(m, PTE_CHG);
+	rw_wunlock(&pvh_global_lock);
+}
+
+/*
+ * Clear the write and modified bits in each of the given page's mappings.
+ */
+void
+moea_remove_write(mmu_t mmu, vm_page_t m)
+{
+	struct	pvo_entry *pvo;
+	struct	pte *pt;
+	pmap_t	pmap;
+	u_int	lo;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("moea_remove_write: page %p is not managed", m));
+
+	/*
+	 * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
+	 * set by another thread while the object is locked.  Thus,
+	 * if PGA_WRITEABLE is clear, no page table entries need updating.
+	 */
+	VM_OBJECT_ASSERT_WLOCKED(m->object);
+	if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
+		return;
+	rw_wlock(&pvh_global_lock);
+	lo = moea_attr_fetch(m);
+	powerpc_sync();
+	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+		pmap = pvo->pvo_pmap;
+		PMAP_LOCK(pmap);
+		if ((pvo->pvo_pte.pte.pte_lo & PTE_PP) != PTE_BR) {
+			pt = moea_pvo_to_pte(pvo, -1);
+			pvo->pvo_pte.pte.pte_lo &= ~PTE_PP;
+			pvo->pvo_pte.pte.pte_lo |= PTE_BR;
+			if (pt != NULL) {
+				moea_pte_synch(pt, &pvo->pvo_pte.pte);
+				lo |= pvo->pvo_pte.pte.pte_lo;
+				pvo->pvo_pte.pte.pte_lo &= ~PTE_CHG;
+				moea_pte_change(pt, &pvo->pvo_pte.pte,
+				    pvo->pvo_vaddr);
+				mtx_unlock(&moea_table_mutex);
+			}
+		}
+		PMAP_UNLOCK(pmap);
+	}
+	if ((lo & PTE_CHG) != 0) {
+		moea_attr_clear(m, PTE_CHG);
+		vm_page_dirty(m);
+	}
+	vm_page_aflag_clear(m, PGA_WRITEABLE);
+	rw_wunlock(&pvh_global_lock);
+}
+
+/*
+ *	moea_ts_referenced:
+ *
+ *	Return a count of reference bits for a page, clearing those bits.
+ *	It is not necessary for every reference bit to be cleared, but it
+ *	is necessary that 0 only be returned when there are truly no
+ *	reference bits set.
+ *
+ *	XXX: The exact number of bits to check and clear is a matter that
+ *	should be tested and standardized at some point in the future for
+ *	optimal aging of shared pages.
+ */
+int
+moea_ts_referenced(mmu_t mmu, vm_page_t m)
+{
+	int count;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("moea_ts_referenced: page %p is not managed", m));
+	rw_wlock(&pvh_global_lock);
+	count = moea_clear_bit(m, PTE_REF);
+	rw_wunlock(&pvh_global_lock);
+	return (count);
+}
+
+/*
+ * Modify the WIMG settings of all mappings for a page.
+ */
+void
+moea_page_set_memattr(mmu_t mmu, vm_page_t m, vm_memattr_t ma)
+{
+	struct	pvo_entry *pvo;
+	struct	pvo_head *pvo_head;
+	struct	pte *pt;
+	pmap_t	pmap;
+	u_int	lo;
+
+	if ((m->oflags & VPO_UNMANAGED) != 0) {
+		m->md.mdpg_cache_attrs = ma;
+		return;
+	}
+
+	rw_wlock(&pvh_global_lock);
+	pvo_head = vm_page_to_pvoh(m);
+	lo = moea_calc_wimg(VM_PAGE_TO_PHYS(m), ma);
+
+	LIST_FOREACH(pvo, pvo_head, pvo_vlink) {
+		pmap = pvo->pvo_pmap;
+		PMAP_LOCK(pmap);
+		pt = moea_pvo_to_pte(pvo, -1);
+		pvo->pvo_pte.pte.pte_lo &= ~PTE_WIMG;
+		pvo->pvo_pte.pte.pte_lo |= lo;
+		if (pt != NULL) {
+			moea_pte_change(pt, &pvo->pvo_pte.pte,
+			    pvo->pvo_vaddr);
+			if (pvo->pvo_pmap == kernel_pmap)
+				isync();
+		}
+		mtx_unlock(&moea_table_mutex);
+		PMAP_UNLOCK(pmap);
+	}
+	m->md.mdpg_cache_attrs = ma;
+	rw_wunlock(&pvh_global_lock);
+}
+
+/*
+ * Map a wired page into kernel virtual address space.
+ */
+void
+moea_kenter(mmu_t mmu, vm_offset_t va, vm_paddr_t pa)
+{
+
+	moea_kenter_attr(mmu, va, pa, VM_MEMATTR_DEFAULT);
+}
+
+void
+moea_kenter_attr(mmu_t mmu, vm_offset_t va, vm_offset_t pa, vm_memattr_t ma)
+{
+	u_int		pte_lo;
+	int		error;	
+
+#if 0
+	if (va < VM_MIN_KERNEL_ADDRESS)
+		panic("moea_kenter: attempt to enter non-kernel address %#x",
+		    va);
+#endif
+
+	pte_lo = moea_calc_wimg(pa, ma);
+
+	PMAP_LOCK(kernel_pmap);
+	error = moea_pvo_enter(kernel_pmap, moea_upvo_zone,
+	    &moea_pvo_kunmanaged, va, pa, pte_lo, PVO_WIRED);
+
+	if (error != 0 && error != ENOENT)
+		panic("moea_kenter: failed to enter va %#x pa %#x: %d", va,
+		    pa, error);
+
+	PMAP_UNLOCK(kernel_pmap);
+}
+
+/*
+ * Extract the physical page address associated with the given kernel virtual
+ * address.
+ */
+vm_paddr_t
+moea_kextract(mmu_t mmu, vm_offset_t va)
+{
+	struct		pvo_entry *pvo;
+	vm_paddr_t pa;
+
+	/*
+	 * Allow direct mappings on 32-bit OEA
+	 */
+	if (va < VM_MIN_KERNEL_ADDRESS) {
+		return (va);
+	}
+
+	PMAP_LOCK(kernel_pmap);
+	pvo = moea_pvo_find_va(kernel_pmap, va & ~ADDR_POFF, NULL);
+	KASSERT(pvo != NULL, ("moea_kextract: no addr found"));
+	pa = (pvo->pvo_pte.pte.pte_lo & PTE_RPGN) | (va & ADDR_POFF);
+	PMAP_UNLOCK(kernel_pmap);
+	return (pa);
+}
+
+/*
+ * Remove a wired page from kernel virtual address space.
+ */
+void
+moea_kremove(mmu_t mmu, vm_offset_t va)
+{
+
+	moea_remove(mmu, kernel_pmap, va, va + PAGE_SIZE);
+}
+
+/*
+ * Map a range of physical addresses into kernel virtual address space.
+ *
+ * The value passed in *virt is a suggested virtual address for the mapping.
+ * Architectures which can support a direct-mapped physical to virtual region
+ * can return the appropriate address within that region, leaving '*virt'
+ * unchanged.  We cannot and therefore do not; *virt is updated with the
+ * first usable address after the mapped region.
+ */
+vm_offset_t
+moea_map(mmu_t mmu, vm_offset_t *virt, vm_paddr_t pa_start,
+    vm_paddr_t pa_end, int prot)
+{
+	vm_offset_t	sva, va;
+
+	sva = *virt;
+	va = sva;
+	for (; pa_start < pa_end; pa_start += PAGE_SIZE, va += PAGE_SIZE)
+		moea_kenter(mmu, va, pa_start);
+	*virt = va;
+	return (sva);
+}
+
+/*
+ * Returns true if the pmap's pv is one of the first
+ * 16 pvs linked to from this page.  This count may
+ * be changed upwards or downwards in the future; it
+ * is only necessary that true be returned for a small
+ * subset of pmaps for proper page aging.
+ */
+boolean_t
+moea_page_exists_quick(mmu_t mmu, pmap_t pmap, vm_page_t m)
+{
+        int loops;
+	struct pvo_entry *pvo;
+	boolean_t rv;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("moea_page_exists_quick: page %p is not managed", m));
+	loops = 0;
+	rv = FALSE;
+	rw_wlock(&pvh_global_lock);
+	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+		if (pvo->pvo_pmap == pmap) {
+			rv = TRUE;
+			break;
+		}
+		if (++loops >= 16)
+			break;
+	}
+	rw_wunlock(&pvh_global_lock);
+	return (rv);
+}
+
+/*
+ * Return the number of managed mappings to the given physical page
+ * that are wired.
+ */
+int
+moea_page_wired_mappings(mmu_t mmu, vm_page_t m)
+{
+	struct pvo_entry *pvo;
+	int count;
+
+	count = 0;
+	if ((m->oflags & VPO_UNMANAGED) != 0)
+		return (count);
+	rw_wlock(&pvh_global_lock);
+	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink)
+		if ((pvo->pvo_vaddr & PVO_WIRED) != 0)
+			count++;
+	rw_wunlock(&pvh_global_lock);
+	return (count);
+}
+
+static u_int	moea_vsidcontext;
+
+void
+moea_pinit(mmu_t mmu, pmap_t pmap)
+{
+	int	i, mask;
+	u_int	entropy;
+
+	KASSERT((int)pmap < VM_MIN_KERNEL_ADDRESS, ("moea_pinit: virt pmap"));
+	RB_INIT(&pmap->pmap_pvo);
+
+	entropy = 0;
+	__asm __volatile("mftb %0" : "=r"(entropy));
+
+	if ((pmap->pmap_phys = (pmap_t)moea_kextract(mmu, (vm_offset_t)pmap))
+	    == NULL) {
+		pmap->pmap_phys = pmap;
+	}
+	
+
+	mtx_lock(&moea_vsid_mutex);
+	/*
+	 * Allocate some segment registers for this pmap.
+	 */
+	for (i = 0; i < NPMAPS; i += VSID_NBPW) {
+		u_int	hash, n;
+
+		/*
+		 * Create a new value by mutiplying by a prime and adding in
+		 * entropy from the timebase register.  This is to make the
+		 * VSID more random so that the PT hash function collides
+		 * less often.  (Note that the prime casues gcc to do shifts
+		 * instead of a multiply.)
+		 */
+		moea_vsidcontext = (moea_vsidcontext * 0x1105) + entropy;
+		hash = moea_vsidcontext & (NPMAPS - 1);
+		if (hash == 0)		/* 0 is special, avoid it */
+			continue;
+		n = hash >> 5;
+		mask = 1 << (hash & (VSID_NBPW - 1));
+		hash = (moea_vsidcontext & 0xfffff);
+		if (moea_vsid_bitmap[n] & mask) {	/* collision? */
+			/* anything free in this bucket? */
+			if (moea_vsid_bitmap[n] == 0xffffffff) {
+				entropy = (moea_vsidcontext >> 20);
+				continue;
+			}
+			i = ffs(~moea_vsid_bitmap[n]) - 1;
+			mask = 1 << i;
+			hash &= 0xfffff & ~(VSID_NBPW - 1);
+			hash |= i;
+		}
+		KASSERT(!(moea_vsid_bitmap[n] & mask),
+		    ("Allocating in-use VSID group %#x\n", hash));
+		moea_vsid_bitmap[n] |= mask;
+		for (i = 0; i < 16; i++)
+			pmap->pm_sr[i] = VSID_MAKE(i, hash);
+		mtx_unlock(&moea_vsid_mutex);
+		return;
+	}
+
+	mtx_unlock(&moea_vsid_mutex);
+	panic("moea_pinit: out of segments");
+}
+
+/*
+ * Initialize the pmap associated with process 0.
+ */
+void
+moea_pinit0(mmu_t mmu, pmap_t pm)
+{
+
+	PMAP_LOCK_INIT(pm);
+	moea_pinit(mmu, pm);
+	bzero(&pm->pm_stats, sizeof(pm->pm_stats));
+}
+
+/*
+ * Set the physical protection on the specified range of this map as requested.
+ */
+void
+moea_protect(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva,
+    vm_prot_t prot)
+{
+	struct	pvo_entry *pvo, *tpvo, key;
+	struct	pte *pt;
+
+	KASSERT(pm == &curproc->p_vmspace->vm_pmap || pm == kernel_pmap,
+	    ("moea_protect: non current pmap"));
+
+	if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+		moea_remove(mmu, pm, sva, eva);
+		return;
+	}
+
+	rw_wlock(&pvh_global_lock);
+	PMAP_LOCK(pm);
+	key.pvo_vaddr = sva;
+	for (pvo = RB_NFIND(pvo_tree, &pm->pmap_pvo, &key);
+	    pvo != NULL && PVO_VADDR(pvo) < eva; pvo = tpvo) {
+		tpvo = RB_NEXT(pvo_tree, &pm->pmap_pvo, pvo);
+
+		/*
+		 * Grab the PTE pointer before we diddle with the cached PTE
+		 * copy.
+		 */
+		pt = moea_pvo_to_pte(pvo, -1);
+		/*
+		 * Change the protection of the page.
+		 */
+		pvo->pvo_pte.pte.pte_lo &= ~PTE_PP;
+		pvo->pvo_pte.pte.pte_lo |= PTE_BR;
+
+		/*
+		 * If the PVO is in the page table, update that pte as well.
+		 */
+		if (pt != NULL) {
+			moea_pte_change(pt, &pvo->pvo_pte.pte, pvo->pvo_vaddr);
+			mtx_unlock(&moea_table_mutex);
+		}
+	}
+	rw_wunlock(&pvh_global_lock);
+	PMAP_UNLOCK(pm);
+}
+
+/*
+ * Map a list of wired pages into kernel virtual address space.  This is
+ * intended for temporary mappings which do not need page modification or
+ * references recorded.  Existing mappings in the region are overwritten.
+ */
+void
+moea_qenter(mmu_t mmu, vm_offset_t sva, vm_page_t *m, int count)
+{
+	vm_offset_t va;
+
+	va = sva;
+	while (count-- > 0) {
+		moea_kenter(mmu, va, VM_PAGE_TO_PHYS(*m));
+		va += PAGE_SIZE;
+		m++;
+	}
+}
+
+/*
+ * Remove page mappings from kernel virtual address space.  Intended for
+ * temporary mappings entered by moea_qenter.
+ */
+void
+moea_qremove(mmu_t mmu, vm_offset_t sva, int count)
+{
+	vm_offset_t va;
+
+	va = sva;
+	while (count-- > 0) {
+		moea_kremove(mmu, va);
+		va += PAGE_SIZE;
+	}
+}
+
+void
+moea_release(mmu_t mmu, pmap_t pmap)
+{
+        int idx, mask;
+        
+	/*
+	 * Free segment register's VSID
+	 */
+        if (pmap->pm_sr[0] == 0)
+                panic("moea_release");
+
+	mtx_lock(&moea_vsid_mutex);
+        idx = VSID_TO_HASH(pmap->pm_sr[0]) & (NPMAPS-1);
+        mask = 1 << (idx % VSID_NBPW);
+        idx /= VSID_NBPW;
+        moea_vsid_bitmap[idx] &= ~mask;
+	mtx_unlock(&moea_vsid_mutex);
+}
+
+/*
+ * Remove the given range of addresses from the specified map.
+ */
+void
+moea_remove(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva)
+{
+	struct	pvo_entry *pvo, *tpvo, key;
+
+	rw_wlock(&pvh_global_lock);
+	PMAP_LOCK(pm);
+	key.pvo_vaddr = sva;
+	for (pvo = RB_NFIND(pvo_tree, &pm->pmap_pvo, &key);
+	    pvo != NULL && PVO_VADDR(pvo) < eva; pvo = tpvo) {
+		tpvo = RB_NEXT(pvo_tree, &pm->pmap_pvo, pvo);
+		moea_pvo_remove(pvo, -1);
+	}
+	PMAP_UNLOCK(pm);
+	rw_wunlock(&pvh_global_lock);
+}
+
+/*
+ * Remove physical page from all pmaps in which it resides. moea_pvo_remove()
+ * will reflect changes in pte's back to the vm_page.
+ */
+void
+moea_remove_all(mmu_t mmu, vm_page_t m)
+{
+	struct  pvo_head *pvo_head;
+	struct	pvo_entry *pvo, *next_pvo;
+	pmap_t	pmap;
+
+	rw_wlock(&pvh_global_lock);
+	pvo_head = vm_page_to_pvoh(m);
+	for (pvo = LIST_FIRST(pvo_head); pvo != NULL; pvo = next_pvo) {
+		next_pvo = LIST_NEXT(pvo, pvo_vlink);
+
+		pmap = pvo->pvo_pmap;
+		PMAP_LOCK(pmap);
+		moea_pvo_remove(pvo, -1);
+		PMAP_UNLOCK(pmap);
+	}
+	if ((m->aflags & PGA_WRITEABLE) && moea_query_bit(m, PTE_CHG)) {
+		moea_attr_clear(m, PTE_CHG);
+		vm_page_dirty(m);
+	}
+	vm_page_aflag_clear(m, PGA_WRITEABLE);
+	rw_wunlock(&pvh_global_lock);
+}
+
+/*
+ * Allocate a physical page of memory directly from the phys_avail map.
+ * Can only be called from moea_bootstrap before avail start and end are
+ * calculated.
+ */
+static vm_offset_t
+moea_bootstrap_alloc(vm_size_t size, u_int align)
+{
+	vm_offset_t	s, e;
+	int		i, j;
+
+	size = round_page(size);
+	for (i = 0; phys_avail[i + 1] != 0; i += 2) {
+		if (align != 0)
+			s = (phys_avail[i] + align - 1) & ~(align - 1);
+		else
+			s = phys_avail[i];
+		e = s + size;
+
+		if (s < phys_avail[i] || e > phys_avail[i + 1])
+			continue;
+
+		if (s == phys_avail[i]) {
+			phys_avail[i] += size;
+		} else if (e == phys_avail[i + 1]) {
+			phys_avail[i + 1] -= size;
+		} else {
+			for (j = phys_avail_count * 2; j > i; j -= 2) {
+				phys_avail[j] = phys_avail[j - 2];
+				phys_avail[j + 1] = phys_avail[j - 1];
+			}
+
+			phys_avail[i + 3] = phys_avail[i + 1];
+			phys_avail[i + 1] = s;
+			phys_avail[i + 2] = e;
+			phys_avail_count++;
+		}
+
+		return (s);
+	}
+	panic("moea_bootstrap_alloc: could not allocate memory");
+}
+
+static void
+moea_syncicache(vm_offset_t pa, vm_size_t len)
+{
+	__syncicache((void *)pa, len);
+}
+
+static int
+moea_pvo_enter(pmap_t pm, uma_zone_t zone, struct pvo_head *pvo_head,
+    vm_offset_t va, vm_offset_t pa, u_int pte_lo, int flags)
+{
+	struct	pvo_entry *pvo;
+	u_int	sr;
+	int	first;
+	u_int	ptegidx;
+	int	i;
+	int     bootstrap;
+
+	moea_pvo_enter_calls++;
+	first = 0;
+	bootstrap = 0;
+
+	/*
+	 * Compute the PTE Group index.
+	 */
+	va &= ~ADDR_POFF;
+	sr = va_to_sr(pm->pm_sr, va);
+	ptegidx = va_to_pteg(sr, va);
+
+	/*
+	 * Remove any existing mapping for this page.  Reuse the pvo entry if
+	 * there is a mapping.
+	 */
+	mtx_lock(&moea_table_mutex);
+	LIST_FOREACH(pvo, &moea_pvo_table[ptegidx], pvo_olink) {
+		if (pvo->pvo_pmap == pm && PVO_VADDR(pvo) == va) {
+			if ((pvo->pvo_pte.pte.pte_lo & PTE_RPGN) == pa &&
+			    (pvo->pvo_pte.pte.pte_lo & PTE_PP) ==
+			    (pte_lo & PTE_PP)) {
+				/*
+				 * The PTE is not changing.  Instead, this may
+				 * be a request to change the mapping's wired
+				 * attribute.
+				 */
+				mtx_unlock(&moea_table_mutex);
+				if ((flags & PVO_WIRED) != 0 &&
+				    (pvo->pvo_vaddr & PVO_WIRED) == 0) {
+					pvo->pvo_vaddr |= PVO_WIRED;
+					pm->pm_stats.wired_count++;
+				} else if ((flags & PVO_WIRED) == 0 &&
+				    (pvo->pvo_vaddr & PVO_WIRED) != 0) {
+					pvo->pvo_vaddr &= ~PVO_WIRED;
+					pm->pm_stats.wired_count--;
+				}
+				return (0);
+			}
+			moea_pvo_remove(pvo, -1);
+			break;
+		}
+	}
+
+	/*
+	 * If we aren't overwriting a mapping, try to allocate.
+	 */
+	if (moea_initialized) {
+		pvo = uma_zalloc(zone, M_NOWAIT);
+	} else {
+		if (moea_bpvo_pool_index >= BPVO_POOL_SIZE) {
+			panic("moea_enter: bpvo pool exhausted, %d, %d, %d",
+			      moea_bpvo_pool_index, BPVO_POOL_SIZE, 
+			      BPVO_POOL_SIZE * sizeof(struct pvo_entry));
+		}
+		pvo = &moea_bpvo_pool[moea_bpvo_pool_index];
+		moea_bpvo_pool_index++;
+		bootstrap = 1;
+	}
+
+	if (pvo == NULL) {
+		mtx_unlock(&moea_table_mutex);
+		return (ENOMEM);
+	}
+
+	moea_pvo_entries++;
+	pvo->pvo_vaddr = va;
+	pvo->pvo_pmap = pm;
+	LIST_INSERT_HEAD(&moea_pvo_table[ptegidx], pvo, pvo_olink);
+	pvo->pvo_vaddr &= ~ADDR_POFF;
+	if (flags & PVO_WIRED)
+		pvo->pvo_vaddr |= PVO_WIRED;
+	if (pvo_head != &moea_pvo_kunmanaged)
+		pvo->pvo_vaddr |= PVO_MANAGED;
+	if (bootstrap)
+		pvo->pvo_vaddr |= PVO_BOOTSTRAP;
+
+	moea_pte_create(&pvo->pvo_pte.pte, sr, va, pa | pte_lo);
+
+	/*
+	 * Add to pmap list
+	 */
+	RB_INSERT(pvo_tree, &pm->pmap_pvo, pvo);
+
+	/*
+	 * Remember if the list was empty and therefore will be the first
+	 * item.
+	 */
+	if (LIST_FIRST(pvo_head) == NULL)
+		first = 1;
+	LIST_INSERT_HEAD(pvo_head, pvo, pvo_vlink);
+
+	if (pvo->pvo_pte.pte.pte_lo & PVO_WIRED)
+		pm->pm_stats.wired_count++;
+	pm->pm_stats.resident_count++;
+
+	i = moea_pte_insert(ptegidx, &pvo->pvo_pte.pte);
+	KASSERT(i < 8, ("Invalid PTE index"));
+	if (i >= 0) {
+		PVO_PTEGIDX_SET(pvo, i);
+	} else {
+		panic("moea_pvo_enter: overflow");
+		moea_pte_overflow++;
+	}
+	mtx_unlock(&moea_table_mutex);
+
+	return (first ? ENOENT : 0);
+}
+
+static void
+moea_pvo_remove(struct pvo_entry *pvo, int pteidx)
+{
+	struct	pte *pt;
+
+	/*
+	 * If there is an active pte entry, we need to deactivate it (and
+	 * save the ref & cfg bits).
+	 */
+	pt = moea_pvo_to_pte(pvo, pteidx);
+	if (pt != NULL) {
+		moea_pte_unset(pt, &pvo->pvo_pte.pte, pvo->pvo_vaddr);
+		mtx_unlock(&moea_table_mutex);
+		PVO_PTEGIDX_CLR(pvo);
+	} else {
+		moea_pte_overflow--;
+	}
+
+	/*
+	 * Update our statistics.
+	 */
+	pvo->pvo_pmap->pm_stats.resident_count--;
+	if (pvo->pvo_pte.pte.pte_lo & PVO_WIRED)
+		pvo->pvo_pmap->pm_stats.wired_count--;
+
+	/*
+	 * Save the REF/CHG bits into their cache if the page is managed.
+	 */
+	if ((pvo->pvo_vaddr & PVO_MANAGED) == PVO_MANAGED) {
+		struct	vm_page *pg;
+
+		pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte.pte_lo & PTE_RPGN);
+		if (pg != NULL) {
+			moea_attr_save(pg, pvo->pvo_pte.pte.pte_lo &
+			    (PTE_REF | PTE_CHG));
+		}
+	}
+
+	/*
+	 * Remove this PVO from the PV and pmap lists.
+	 */
+	LIST_REMOVE(pvo, pvo_vlink);
+	RB_REMOVE(pvo_tree, &pvo->pvo_pmap->pmap_pvo, pvo);
+
+	/*
+	 * Remove this from the overflow list and return it to the pool
+	 * if we aren't going to reuse it.
+	 */
+	LIST_REMOVE(pvo, pvo_olink);
+	if (!(pvo->pvo_vaddr & PVO_BOOTSTRAP))
+		uma_zfree(pvo->pvo_vaddr & PVO_MANAGED ? moea_mpvo_zone :
+		    moea_upvo_zone, pvo);
+	moea_pvo_entries--;
+	moea_pvo_remove_calls++;
+}
+
+static __inline int
+moea_pvo_pte_index(const struct pvo_entry *pvo, int ptegidx)
+{
+	int	pteidx;
+
+	/*
+	 * We can find the actual pte entry without searching by grabbing
+	 * the PTEG index from 3 unused bits in pte_lo[11:9] and by
+	 * noticing the HID bit.
+	 */
+	pteidx = ptegidx * 8 + PVO_PTEGIDX_GET(pvo);
+	if (pvo->pvo_pte.pte.pte_hi & PTE_HID)
+		pteidx ^= moea_pteg_mask * 8;
+
+	return (pteidx);
+}
+
+static struct pvo_entry *
+moea_pvo_find_va(pmap_t pm, vm_offset_t va, int *pteidx_p)
+{
+	struct	pvo_entry *pvo;
+	int	ptegidx;
+	u_int	sr;
+
+	va &= ~ADDR_POFF;
+	sr = va_to_sr(pm->pm_sr, va);
+	ptegidx = va_to_pteg(sr, va);
+
+	mtx_lock(&moea_table_mutex);
+	LIST_FOREACH(pvo, &moea_pvo_table[ptegidx], pvo_olink) {
+		if (pvo->pvo_pmap == pm && PVO_VADDR(pvo) == va) {
+			if (pteidx_p)
+				*pteidx_p = moea_pvo_pte_index(pvo, ptegidx);
+			break;
+		}
+	}
+	mtx_unlock(&moea_table_mutex);
+
+	return (pvo);
+}
+
+static struct pte *
+moea_pvo_to_pte(const struct pvo_entry *pvo, int pteidx)
+{
+	struct	pte *pt;
+
+	/*
+	 * If we haven't been supplied the ptegidx, calculate it.
+	 */
+	if (pteidx == -1) {
+		int	ptegidx;
+		u_int	sr;
+
+		sr = va_to_sr(pvo->pvo_pmap->pm_sr, pvo->pvo_vaddr);
+		ptegidx = va_to_pteg(sr, pvo->pvo_vaddr);
+		pteidx = moea_pvo_pte_index(pvo, ptegidx);
+	}
+
+	pt = &moea_pteg_table[pteidx >> 3].pt[pteidx & 7];
+	mtx_lock(&moea_table_mutex);
+
+	if ((pvo->pvo_pte.pte.pte_hi & PTE_VALID) && !PVO_PTEGIDX_ISSET(pvo)) {
+		panic("moea_pvo_to_pte: pvo %p has valid pte in pvo but no "
+		    "valid pte index", pvo);
+	}
+
+	if ((pvo->pvo_pte.pte.pte_hi & PTE_VALID) == 0 && PVO_PTEGIDX_ISSET(pvo)) {
+		panic("moea_pvo_to_pte: pvo %p has valid pte index in pvo "
+		    "pvo but no valid pte", pvo);
+	}
+
+	if ((pt->pte_hi ^ (pvo->pvo_pte.pte.pte_hi & ~PTE_VALID)) == PTE_VALID) {
+		if ((pvo->pvo_pte.pte.pte_hi & PTE_VALID) == 0) {
+			panic("moea_pvo_to_pte: pvo %p has valid pte in "
+			    "moea_pteg_table %p but invalid in pvo", pvo, pt);
+		}
+
+		if (((pt->pte_lo ^ pvo->pvo_pte.pte.pte_lo) & ~(PTE_CHG|PTE_REF))
+		    != 0) {
+			panic("moea_pvo_to_pte: pvo %p pte does not match "
+			    "pte %p in moea_pteg_table", pvo, pt);
+		}
+
+		mtx_assert(&moea_table_mutex, MA_OWNED);
+		return (pt);
+	}
+
+	if (pvo->pvo_pte.pte.pte_hi & PTE_VALID) {
+		panic("moea_pvo_to_pte: pvo %p has invalid pte %p in "
+		    "moea_pteg_table but valid in pvo: %8x, %8x", pvo, pt, pvo->pvo_pte.pte.pte_hi, pt->pte_hi);
+	}
+
+	mtx_unlock(&moea_table_mutex);
+	return (NULL);
+}
+
+/*
+ * XXX: THIS STUFF SHOULD BE IN pte.c?
+ */
+int
+moea_pte_spill(vm_offset_t addr)
+{
+	struct	pvo_entry *source_pvo, *victim_pvo;
+	struct	pvo_entry *pvo;
+	int	ptegidx, i, j;
+	u_int	sr;
+	struct	pteg *pteg;
+	struct	pte *pt;
+
+	moea_pte_spills++;
+
+	sr = mfsrin(addr);
+	ptegidx = va_to_pteg(sr, addr);
+
+	/*
+	 * Have to substitute some entry.  Use the primary hash for this.
+	 * Use low bits of timebase as random generator.
+	 */
+	pteg = &moea_pteg_table[ptegidx];
+	mtx_lock(&moea_table_mutex);
+	__asm __volatile("mftb %0" : "=r"(i));
+	i &= 7;
+	pt = &pteg->pt[i];
+
+	source_pvo = NULL;
+	victim_pvo = NULL;
+	LIST_FOREACH(pvo, &moea_pvo_table[ptegidx], pvo_olink) {
+		/*
+		 * We need to find a pvo entry for this address.
+		 */
+		if (source_pvo == NULL &&
+		    moea_pte_match(&pvo->pvo_pte.pte, sr, addr,
+		    pvo->pvo_pte.pte.pte_hi & PTE_HID)) {
+			/*
+			 * Now found an entry to be spilled into the pteg.
+			 * The PTE is now valid, so we know it's active.
+			 */
+			j = moea_pte_insert(ptegidx, &pvo->pvo_pte.pte);
+
+			if (j >= 0) {
+				PVO_PTEGIDX_SET(pvo, j);
+				moea_pte_overflow--;
+				mtx_unlock(&moea_table_mutex);
+				return (1);
+			}
+
+			source_pvo = pvo;
+
+			if (victim_pvo != NULL)
+				break;
+		}
+
+		/*
+		 * We also need the pvo entry of the victim we are replacing
+		 * so save the R & C bits of the PTE.
+		 */
+		if ((pt->pte_hi & PTE_HID) == 0 && victim_pvo == NULL &&
+		    moea_pte_compare(pt, &pvo->pvo_pte.pte)) {
+			victim_pvo = pvo;
+			if (source_pvo != NULL)
+				break;
+		}
+	}
+
+	if (source_pvo == NULL) {
+		mtx_unlock(&moea_table_mutex);
+		return (0);
+	}
+
+	if (victim_pvo == NULL) {
+		if ((pt->pte_hi & PTE_HID) == 0)
+			panic("moea_pte_spill: victim p-pte (%p) has no pvo"
+			    "entry", pt);
+
+		/*
+		 * If this is a secondary PTE, we need to search it's primary
+		 * pvo bucket for the matching PVO.
+		 */
+		LIST_FOREACH(pvo, &moea_pvo_table[ptegidx ^ moea_pteg_mask],
+		    pvo_olink) {
+			/*
+			 * We also need the pvo entry of the victim we are
+			 * replacing so save the R & C bits of the PTE.
+			 */
+			if (moea_pte_compare(pt, &pvo->pvo_pte.pte)) {
+				victim_pvo = pvo;
+				break;
+			}
+		}
+
+		if (victim_pvo == NULL)
+			panic("moea_pte_spill: victim s-pte (%p) has no pvo"
+			    "entry", pt);
+	}
+
+	/*
+	 * We are invalidating the TLB entry for the EA we are replacing even
+	 * though it's valid.  If we don't, we lose any ref/chg bit changes
+	 * contained in the TLB entry.
+	 */
+	source_pvo->pvo_pte.pte.pte_hi &= ~PTE_HID;
+
+	moea_pte_unset(pt, &victim_pvo->pvo_pte.pte, victim_pvo->pvo_vaddr);
+	moea_pte_set(pt, &source_pvo->pvo_pte.pte);
+
+	PVO_PTEGIDX_CLR(victim_pvo);
+	PVO_PTEGIDX_SET(source_pvo, i);
+	moea_pte_replacements++;
+
+	mtx_unlock(&moea_table_mutex);
+	return (1);
+}
+
+static __inline struct pvo_entry *
+moea_pte_spillable_ident(u_int ptegidx)
+{
+	struct	pte *pt;
+	struct	pvo_entry *pvo_walk, *pvo = NULL;
+
+	LIST_FOREACH(pvo_walk, &moea_pvo_table[ptegidx], pvo_olink) {
+		if (pvo_walk->pvo_vaddr & PVO_WIRED)
+			continue;
+
+		if (!(pvo_walk->pvo_pte.pte.pte_hi & PTE_VALID))
+			continue;
+
+		pt = moea_pvo_to_pte(pvo_walk, -1);
+
+		if (pt == NULL)
+			continue;
+
+		pvo = pvo_walk;
+
+		mtx_unlock(&moea_table_mutex);
+		if (!(pt->pte_lo & PTE_REF))
+			return (pvo_walk);
+	}
+	
+	return (pvo);
+}
+
+static int
+moea_pte_insert(u_int ptegidx, struct pte *pvo_pt)
+{
+	struct	pte *pt;
+	struct	pvo_entry *victim_pvo;
+	int	i;
+	int	victim_idx;
+	u_int	pteg_bkpidx = ptegidx;
+
+	mtx_assert(&moea_table_mutex, MA_OWNED);
+
+	/*
+	 * First try primary hash.
+	 */
+	for (pt = moea_pteg_table[ptegidx].pt, i = 0; i < 8; i++, pt++) {
+		if ((pt->pte_hi & PTE_VALID) == 0) {
+			pvo_pt->pte_hi &= ~PTE_HID;
+			moea_pte_set(pt, pvo_pt);
+			return (i);
+		}
+	}
+
+	/*
+	 * Now try secondary hash.
+	 */
+	ptegidx ^= moea_pteg_mask;
+
+	for (pt = moea_pteg_table[ptegidx].pt, i = 0; i < 8; i++, pt++) {
+		if ((pt->pte_hi & PTE_VALID) == 0) {
+			pvo_pt->pte_hi |= PTE_HID;
+			moea_pte_set(pt, pvo_pt);
+			return (i);
+		}
+	}
+
+	/* Try again, but this time try to force a PTE out. */
+	ptegidx = pteg_bkpidx;
+
+	victim_pvo = moea_pte_spillable_ident(ptegidx);
+	if (victim_pvo == NULL) {
+		ptegidx ^= moea_pteg_mask;
+		victim_pvo = moea_pte_spillable_ident(ptegidx);
+	}
+
+	if (victim_pvo == NULL) {
+		panic("moea_pte_insert: overflow");
+		return (-1);
+	}
+
+	victim_idx = moea_pvo_pte_index(victim_pvo, ptegidx);
+
+	if (pteg_bkpidx == ptegidx)
+		pvo_pt->pte_hi &= ~PTE_HID;
+	else
+		pvo_pt->pte_hi |= PTE_HID;
+
+	/*
+	 * Synchronize the sacrifice PTE with its PVO, then mark both
+	 * invalid. The PVO will be reused when/if the VM system comes
+	 * here after a fault.
+	 */
+	pt = &moea_pteg_table[victim_idx >> 3].pt[victim_idx & 7];
+
+	if (pt->pte_hi != victim_pvo->pvo_pte.pte.pte_hi)
+	    panic("Victim PVO doesn't match PTE! PVO: %8x, PTE: %8x", victim_pvo->pvo_pte.pte.pte_hi, pt->pte_hi);
+
+	/*
+	 * Set the new PTE.
+	 */
+	moea_pte_unset(pt, &victim_pvo->pvo_pte.pte, victim_pvo->pvo_vaddr);
+	PVO_PTEGIDX_CLR(victim_pvo);
+	moea_pte_overflow++;
+	moea_pte_set(pt, pvo_pt);
+
+	return (victim_idx & 7);
+}
+
+static boolean_t
+moea_query_bit(vm_page_t m, int ptebit)
+{
+	struct	pvo_entry *pvo;
+	struct	pte *pt;
+
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
+	if (moea_attr_fetch(m) & ptebit)
+		return (TRUE);
+
+	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+
+		/*
+		 * See if we saved the bit off.  If so, cache it and return
+		 * success.
+		 */
+		if (pvo->pvo_pte.pte.pte_lo & ptebit) {
+			moea_attr_save(m, ptebit);
+			return (TRUE);
+		}
+	}
+
+	/*
+	 * No luck, now go through the hard part of looking at the PTEs
+	 * themselves.  Sync so that any pending REF/CHG bits are flushed to
+	 * the PTEs.
+	 */
+	powerpc_sync();
+	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+
+		/*
+		 * See if this pvo has a valid PTE.  if so, fetch the
+		 * REF/CHG bits from the valid PTE.  If the appropriate
+		 * ptebit is set, cache it and return success.
+		 */
+		pt = moea_pvo_to_pte(pvo, -1);
+		if (pt != NULL) {
+			moea_pte_synch(pt, &pvo->pvo_pte.pte);
+			mtx_unlock(&moea_table_mutex);
+			if (pvo->pvo_pte.pte.pte_lo & ptebit) {
+				moea_attr_save(m, ptebit);
+				return (TRUE);
+			}
+		}
+	}
+
+	return (FALSE);
+}
+
+static u_int
+moea_clear_bit(vm_page_t m, int ptebit)
+{
+	u_int	count;
+	struct	pvo_entry *pvo;
+	struct	pte *pt;
+
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
+
+	/*
+	 * Clear the cached value.
+	 */
+	moea_attr_clear(m, ptebit);
+
+	/*
+	 * Sync so that any pending REF/CHG bits are flushed to the PTEs (so
+	 * we can reset the right ones).  note that since the pvo entries and
+	 * list heads are accessed via BAT0 and are never placed in the page
+	 * table, we don't have to worry about further accesses setting the
+	 * REF/CHG bits.
+	 */
+	powerpc_sync();
+
+	/*
+	 * For each pvo entry, clear the pvo's ptebit.  If this pvo has a
+	 * valid pte clear the ptebit from the valid pte.
+	 */
+	count = 0;
+	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+		pt = moea_pvo_to_pte(pvo, -1);
+		if (pt != NULL) {
+			moea_pte_synch(pt, &pvo->pvo_pte.pte);
+			if (pvo->pvo_pte.pte.pte_lo & ptebit) {
+				count++;
+				moea_pte_clear(pt, PVO_VADDR(pvo), ptebit);
+			}
+			mtx_unlock(&moea_table_mutex);
+		}
+		pvo->pvo_pte.pte.pte_lo &= ~ptebit;
+	}
+
+	return (count);
+}
+
+/*
+ * Return true if the physical range is encompassed by the battable[idx]
+ */
+static int
+moea_bat_mapped(int idx, vm_offset_t pa, vm_size_t size)
+{
+	u_int prot;
+	u_int32_t start;
+	u_int32_t end;
+	u_int32_t bat_ble;
+
+	/*
+	 * Return immediately if not a valid mapping
+	 */
+	if (!(battable[idx].batu & BAT_Vs))
+		return (EINVAL);
+
+	/*
+	 * The BAT entry must be cache-inhibited, guarded, and r/w
+	 * so it can function as an i/o page
+	 */
+	prot = battable[idx].batl & (BAT_I|BAT_G|BAT_PP_RW);
+	if (prot != (BAT_I|BAT_G|BAT_PP_RW))
+		return (EPERM);	
+
+	/*
+	 * The address should be within the BAT range. Assume that the
+	 * start address in the BAT has the correct alignment (thus
+	 * not requiring masking)
+	 */
+	start = battable[idx].batl & BAT_PBS;
+	bat_ble = (battable[idx].batu & ~(BAT_EBS)) | 0x03;
+	end = start | (bat_ble << 15) | 0x7fff;
+
+	if ((pa < start) || ((pa + size) > end))
+		return (ERANGE);
+
+	return (0);
+}
+
+boolean_t
+moea_dev_direct_mapped(mmu_t mmu, vm_paddr_t pa, vm_size_t size)
+{
+	int i;
+
+	/*
+	 * This currently does not work for entries that 
+	 * overlap 256M BAT segments.
+	 */
+
+	for(i = 0; i < 16; i++)
+		if (moea_bat_mapped(i, pa, size) == 0)
+			return (0);
+
+	return (EFAULT);
+}
+
+/*
+ * Map a set of physical memory pages into the kernel virtual
+ * address space. Return a pointer to where it is mapped. This
+ * routine is intended to be used for mapping device memory,
+ * NOT real memory.
+ */
+void *
+moea_mapdev(mmu_t mmu, vm_paddr_t pa, vm_size_t size)
+{
+
+	return (moea_mapdev_attr(mmu, pa, size, VM_MEMATTR_DEFAULT));
+}
+
+void *
+moea_mapdev_attr(mmu_t mmu, vm_offset_t pa, vm_size_t size, vm_memattr_t ma)
+{
+	vm_offset_t va, tmpva, ppa, offset;
+	int i;
+
+	ppa = trunc_page(pa);
+	offset = pa & PAGE_MASK;
+	size = roundup(offset + size, PAGE_SIZE);
+	
+	/*
+	 * If the physical address lies within a valid BAT table entry,
+	 * return the 1:1 mapping. This currently doesn't work
+	 * for regions that overlap 256M BAT segments.
+	 */
+	for (i = 0; i < 16; i++) {
+		if (moea_bat_mapped(i, pa, size) == 0)
+			return ((void *) pa);
+	}
+
+	va = kva_alloc(size);
+	if (!va)
+		panic("moea_mapdev: Couldn't alloc kernel virtual memory");
+
+	for (tmpva = va; size > 0;) {
+		moea_kenter_attr(mmu, tmpva, ppa, ma);
+		tlbie(tmpva);
+		size -= PAGE_SIZE;
+		tmpva += PAGE_SIZE;
+		ppa += PAGE_SIZE;
+	}
+
+	return ((void *)(va + offset));
+}
+
+void
+moea_unmapdev(mmu_t mmu, vm_offset_t va, vm_size_t size)
+{
+	vm_offset_t base, offset;
+
+	/*
+	 * If this is outside kernel virtual space, then it's a
+	 * battable entry and doesn't require unmapping
+	 */
+	if ((va >= VM_MIN_KERNEL_ADDRESS) && (va <= virtual_end)) {
+		base = trunc_page(va);
+		offset = va & PAGE_MASK;
+		size = roundup(offset + size, PAGE_SIZE);
+		kva_free(base, size);
+	}
+}
+
+static void
+moea_sync_icache(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_size_t sz)
+{
+	struct pvo_entry *pvo;
+	vm_offset_t lim;
+	vm_paddr_t pa;
+	vm_size_t len;
+
+	PMAP_LOCK(pm);
+	while (sz > 0) {
+		lim = round_page(va);
+		len = MIN(lim - va, sz);
+		pvo = moea_pvo_find_va(pm, va & ~ADDR_POFF, NULL);
+		if (pvo != NULL) {
+			pa = (pvo->pvo_pte.pte.pte_lo & PTE_RPGN) |
+			    (va & ADDR_POFF);
+			moea_syncicache(pa, len);
+		}
+		va += len;
+		sz -= len;
+	}
+	PMAP_UNLOCK(pm);
+}
+
+vm_offset_t
+moea_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
+    vm_size_t *sz)
+{
+	if (md->md_vaddr == ~0UL)
+	    return (md->md_paddr + ofs);
+	else
+	    return (md->md_vaddr + ofs);
+}
+
+struct pmap_md *
+moea_scan_md(mmu_t mmu, struct pmap_md *prev)
+{
+	static struct pmap_md md;
+	struct pvo_entry *pvo;
+	vm_offset_t va;
+ 
+	if (dumpsys_minidump) {
+		md.md_paddr = ~0UL;	/* Minidumps use virtual addresses. */
+		if (prev == NULL) {
+			/* 1st: kernel .data and .bss. */
+			md.md_index = 1;
+			md.md_vaddr = trunc_page((uintptr_t)_etext);
+			md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
+			return (&md);
+		}
+		switch (prev->md_index) {
+		case 1:
+			/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
+			md.md_index = 2;
+			md.md_vaddr = (vm_offset_t)msgbufp->msg_ptr;
+			md.md_size = round_page(msgbufp->msg_size);
+			break;
+		case 2:
+			/* 3rd: kernel VM. */
+			va = prev->md_vaddr + prev->md_size;
+			/* Find start of next chunk (from va). */
+			while (va < virtual_end) {
+				/* Don't dump the buffer cache. */
+				if (va >= kmi.buffer_sva &&
+				    va < kmi.buffer_eva) {
+					va = kmi.buffer_eva;
+					continue;
+				}
+				pvo = moea_pvo_find_va(kernel_pmap,
+				    va & ~ADDR_POFF, NULL);
+				if (pvo != NULL &&
+				    (pvo->pvo_pte.pte.pte_hi & PTE_VALID))
+					break;
+				va += PAGE_SIZE;
+			}
+			if (va < virtual_end) {
+				md.md_vaddr = va;
+				va += PAGE_SIZE;
+				/* Find last page in chunk. */
+				while (va < virtual_end) {
+					/* Don't run into the buffer cache. */
+					if (va == kmi.buffer_sva)
+						break;
+					pvo = moea_pvo_find_va(kernel_pmap,
+					    va & ~ADDR_POFF, NULL);
+					if (pvo == NULL ||
+					    !(pvo->pvo_pte.pte.pte_hi & PTE_VALID))
+						break;
+					va += PAGE_SIZE;
+				}
+				md.md_size = va - md.md_vaddr;
+				break;
+			}
+			md.md_index = 3;
+			/* FALLTHROUGH */
+		default:
+			return (NULL);
+		}
+	} else { /* minidumps */
+		mem_regions(&pregions, &pregions_sz,
+		    &regions, &regions_sz);
+
+		if (prev == NULL) {
+			/* first physical chunk. */
+			md.md_paddr = pregions[0].mr_start;
+			md.md_size = pregions[0].mr_size;
+			md.md_vaddr = ~0UL;
+			md.md_index = 1;
+		} else if (md.md_index < pregions_sz) {
+			md.md_paddr = pregions[md.md_index].mr_start;
+			md.md_size = pregions[md.md_index].mr_size;
+			md.md_vaddr = ~0UL;
+			md.md_index++;
+		} else {
+			/* There's no next physical chunk. */
+			return (NULL);
+		}
+	}
+
+	return (&md);
+}


Property changes on: trunk/sys/powerpc/aim/mmu_oea.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/mmu_oea64.c
===================================================================
--- trunk/sys/powerpc/aim/mmu_oea64.c	                        (rev 0)
+++ trunk/sys/powerpc/aim/mmu_oea64.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,2720 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt at 3am-software.com> of Allegro Networks, Inc.
+ *
+ * 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.
+ *
+ * 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.
+ */
+/*-
+ * 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.
+ *
+ * $NetBSD: pmap.c,v 1.28 2000/03/26 20:42:36 kleink Exp $
+ */
+/*-
+ * Copyright (C) 2001 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/aim/mmu_oea64.c 287945 2015-09-17 23:31:44Z rstone $");
+
+/*
+ * Manages physical address maps.
+ *
+ * Since the information managed by this module is also stored by the
+ * logical address mapping module, this module may throw away valid virtual
+ * to physical mappings at almost any time.  However, invalidations of
+ * mappings must be done as requested.
+ *
+ * In order to cope with hardware architectures which make virtual to
+ * physical map invalidates expensive, this module may delay invalidate
+ * reduced protection operations until such time as they are actually
+ * necessary.  This module is given full information as to which processors
+ * are currently using which maps, and to when physical maps must be made
+ * correct.
+ */
+
+#include "opt_compat.h"
+#include "opt_kstack_pages.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/cpuset.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/msgbuf.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/rwlock.h>
+#include <sys/sched.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/vmmeter.h>
+
+#include <sys/kdb.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_pageout.h>
+#include <vm/uma.h>
+
+#include <machine/_inttypes.h>
+#include <machine/cpu.h>
+#include <machine/platform.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/psl.h>
+#include <machine/bat.h>
+#include <machine/hid.h>
+#include <machine/pte.h>
+#include <machine/sr.h>
+#include <machine/trap.h>
+#include <machine/mmuvar.h>
+
+#include "mmu_oea64.h"
+#include "mmu_if.h"
+#include "moea64_if.h"
+
+void moea64_release_vsid(uint64_t vsid);
+uintptr_t moea64_get_unique_vsid(void); 
+
+#define DISABLE_TRANS(msr)	msr = mfmsr(); mtmsr(msr & ~PSL_DR)
+#define ENABLE_TRANS(msr)	mtmsr(msr)
+
+#define	VSID_MAKE(sr, hash)	((sr) | (((hash) & 0xfffff) << 4))
+#define	VSID_TO_HASH(vsid)	(((vsid) >> 4) & 0xfffff)
+#define	VSID_HASH_MASK		0x0000007fffffffffULL
+
+/*
+ * Locking semantics:
+ * -- Read lock: if no modifications are being made to either the PVO lists
+ *    or page table or if any modifications being made result in internal
+ *    changes (e.g. wiring, protection) such that the existence of the PVOs
+ *    is unchanged and they remain associated with the same pmap (in which
+ *    case the changes should be protected by the pmap lock)
+ * -- Write lock: required if PTEs/PVOs are being inserted or removed.
+ */
+
+#define LOCK_TABLE_RD() rw_rlock(&moea64_table_lock)
+#define UNLOCK_TABLE_RD() rw_runlock(&moea64_table_lock)
+#define LOCK_TABLE_WR() rw_wlock(&moea64_table_lock)
+#define UNLOCK_TABLE_WR() rw_wunlock(&moea64_table_lock)
+
+struct ofw_map {
+	cell_t	om_va;
+	cell_t	om_len;
+	uint64_t om_pa;
+	cell_t	om_mode;
+};
+
+extern unsigned char _etext[];
+extern unsigned char _end[];
+
+extern int dumpsys_minidump;
+
+/*
+ * Map of physical memory regions.
+ */
+static struct	mem_region *regions;
+static struct	mem_region *pregions;
+static u_int	phys_avail_count;
+static int	regions_sz, pregions_sz;
+
+extern void bs_remap_earlyboot(void);
+
+/*
+ * Lock for the pteg and pvo tables.
+ */
+struct rwlock	moea64_table_lock;
+struct mtx	moea64_slb_mutex;
+
+/*
+ * PTEG data.
+ */
+u_int		moea64_pteg_count;
+u_int		moea64_pteg_mask;
+
+/*
+ * PVO data.
+ */
+struct	pvo_head *moea64_pvo_table;		/* pvo entries by pteg index */
+
+uma_zone_t	moea64_upvo_zone; /* zone for pvo entries for unmanaged pages */
+uma_zone_t	moea64_mpvo_zone; /* zone for pvo entries for managed pages */
+
+#define	BPVO_POOL_SIZE	327680
+static struct	pvo_entry *moea64_bpvo_pool;
+static int	moea64_bpvo_pool_index = 0;
+
+#define	VSID_NBPW	(sizeof(u_int32_t) * 8)
+#ifdef __powerpc64__
+#define	NVSIDS		(NPMAPS * 16)
+#define VSID_HASHMASK	0xffffffffUL
+#else
+#define NVSIDS		NPMAPS
+#define VSID_HASHMASK	0xfffffUL
+#endif
+static u_int	moea64_vsid_bitmap[NVSIDS / VSID_NBPW];
+
+static boolean_t moea64_initialized = FALSE;
+
+/*
+ * Statistics.
+ */
+u_int	moea64_pte_valid = 0;
+u_int	moea64_pte_overflow = 0;
+u_int	moea64_pvo_entries = 0;
+u_int	moea64_pvo_enter_calls = 0;
+u_int	moea64_pvo_remove_calls = 0;
+SYSCTL_INT(_machdep, OID_AUTO, moea64_pte_valid, CTLFLAG_RD, 
+    &moea64_pte_valid, 0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea64_pte_overflow, CTLFLAG_RD,
+    &moea64_pte_overflow, 0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea64_pvo_entries, CTLFLAG_RD, 
+    &moea64_pvo_entries, 0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea64_pvo_enter_calls, CTLFLAG_RD,
+    &moea64_pvo_enter_calls, 0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea64_pvo_remove_calls, CTLFLAG_RD,
+    &moea64_pvo_remove_calls, 0, "");
+
+vm_offset_t	moea64_scratchpage_va[2];
+struct pvo_entry *moea64_scratchpage_pvo[2];
+uintptr_t	moea64_scratchpage_pte[2];
+struct	mtx	moea64_scratchpage_mtx;
+
+uint64_t 	moea64_large_page_mask = 0;
+uint64_t	moea64_large_page_size = 0;
+int		moea64_large_page_shift = 0;
+
+/*
+ * PVO calls.
+ */
+static int	moea64_pvo_enter(mmu_t, pmap_t, uma_zone_t, struct pvo_head *,
+		    vm_offset_t, vm_offset_t, uint64_t, int, int8_t);
+static void	moea64_pvo_remove(mmu_t, struct pvo_entry *);
+static struct	pvo_entry *moea64_pvo_find_va(pmap_t, vm_offset_t);
+
+/*
+ * Utility routines.
+ */
+static boolean_t	moea64_query_bit(mmu_t, vm_page_t, u_int64_t);
+static u_int		moea64_clear_bit(mmu_t, vm_page_t, u_int64_t);
+static void		moea64_kremove(mmu_t, vm_offset_t);
+static void		moea64_syncicache(mmu_t, pmap_t pmap, vm_offset_t va, 
+			    vm_offset_t pa, vm_size_t sz);
+
+/*
+ * Kernel MMU interface
+ */
+void moea64_clear_modify(mmu_t, vm_page_t);
+void moea64_copy_page(mmu_t, vm_page_t, vm_page_t);
+void moea64_copy_pages(mmu_t mmu, vm_page_t *ma, vm_offset_t a_offset,
+    vm_page_t *mb, vm_offset_t b_offset, int xfersize);
+int moea64_enter(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t,
+    u_int flags, int8_t psind);
+void moea64_enter_object(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_page_t,
+    vm_prot_t);
+void moea64_enter_quick(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t);
+vm_paddr_t moea64_extract(mmu_t, pmap_t, vm_offset_t);
+vm_page_t moea64_extract_and_hold(mmu_t, pmap_t, vm_offset_t, vm_prot_t);
+void moea64_init(mmu_t);
+boolean_t moea64_is_modified(mmu_t, vm_page_t);
+boolean_t moea64_is_prefaultable(mmu_t, pmap_t, vm_offset_t);
+boolean_t moea64_is_referenced(mmu_t, vm_page_t);
+int moea64_ts_referenced(mmu_t, vm_page_t);
+vm_offset_t moea64_map(mmu_t, vm_offset_t *, vm_paddr_t, vm_paddr_t, int);
+boolean_t moea64_page_exists_quick(mmu_t, pmap_t, vm_page_t);
+int moea64_page_wired_mappings(mmu_t, vm_page_t);
+void moea64_pinit(mmu_t, pmap_t);
+void moea64_pinit0(mmu_t, pmap_t);
+void moea64_protect(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_prot_t);
+void moea64_qenter(mmu_t, vm_offset_t, vm_page_t *, int);
+void moea64_qremove(mmu_t, vm_offset_t, int);
+void moea64_release(mmu_t, pmap_t);
+void moea64_remove(mmu_t, pmap_t, vm_offset_t, vm_offset_t);
+void moea64_remove_pages(mmu_t, pmap_t);
+void moea64_remove_all(mmu_t, vm_page_t);
+void moea64_remove_write(mmu_t, vm_page_t);
+void moea64_unwire(mmu_t, pmap_t, vm_offset_t, vm_offset_t);
+void moea64_zero_page(mmu_t, vm_page_t);
+void moea64_zero_page_area(mmu_t, vm_page_t, int, int);
+void moea64_zero_page_idle(mmu_t, vm_page_t);
+void moea64_activate(mmu_t, struct thread *);
+void moea64_deactivate(mmu_t, struct thread *);
+void *moea64_mapdev(mmu_t, vm_paddr_t, vm_size_t);
+void *moea64_mapdev_attr(mmu_t, vm_offset_t, vm_size_t, vm_memattr_t);
+void moea64_unmapdev(mmu_t, vm_offset_t, vm_size_t);
+vm_paddr_t moea64_kextract(mmu_t, vm_offset_t);
+void moea64_page_set_memattr(mmu_t, vm_page_t m, vm_memattr_t ma);
+void moea64_kenter_attr(mmu_t, vm_offset_t, vm_offset_t, vm_memattr_t ma);
+void moea64_kenter(mmu_t, vm_offset_t, vm_paddr_t);
+boolean_t moea64_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
+static void moea64_sync_icache(mmu_t, pmap_t, vm_offset_t, vm_size_t);
+vm_offset_t moea64_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
+    vm_size_t *sz);
+struct pmap_md * moea64_scan_md(mmu_t mmu, struct pmap_md *prev);
+
+static mmu_method_t moea64_methods[] = {
+	MMUMETHOD(mmu_clear_modify,	moea64_clear_modify),
+	MMUMETHOD(mmu_copy_page,	moea64_copy_page),
+	MMUMETHOD(mmu_copy_pages,	moea64_copy_pages),
+	MMUMETHOD(mmu_enter,		moea64_enter),
+	MMUMETHOD(mmu_enter_object,	moea64_enter_object),
+	MMUMETHOD(mmu_enter_quick,	moea64_enter_quick),
+	MMUMETHOD(mmu_extract,		moea64_extract),
+	MMUMETHOD(mmu_extract_and_hold,	moea64_extract_and_hold),
+	MMUMETHOD(mmu_init,		moea64_init),
+	MMUMETHOD(mmu_is_modified,	moea64_is_modified),
+	MMUMETHOD(mmu_is_prefaultable,	moea64_is_prefaultable),
+	MMUMETHOD(mmu_is_referenced,	moea64_is_referenced),
+	MMUMETHOD(mmu_ts_referenced,	moea64_ts_referenced),
+	MMUMETHOD(mmu_map,     		moea64_map),
+	MMUMETHOD(mmu_page_exists_quick,moea64_page_exists_quick),
+	MMUMETHOD(mmu_page_wired_mappings,moea64_page_wired_mappings),
+	MMUMETHOD(mmu_pinit,		moea64_pinit),
+	MMUMETHOD(mmu_pinit0,		moea64_pinit0),
+	MMUMETHOD(mmu_protect,		moea64_protect),
+	MMUMETHOD(mmu_qenter,		moea64_qenter),
+	MMUMETHOD(mmu_qremove,		moea64_qremove),
+	MMUMETHOD(mmu_release,		moea64_release),
+	MMUMETHOD(mmu_remove,		moea64_remove),
+	MMUMETHOD(mmu_remove_pages,	moea64_remove_pages),
+	MMUMETHOD(mmu_remove_all,      	moea64_remove_all),
+	MMUMETHOD(mmu_remove_write,	moea64_remove_write),
+	MMUMETHOD(mmu_sync_icache,	moea64_sync_icache),
+	MMUMETHOD(mmu_unwire,		moea64_unwire),
+	MMUMETHOD(mmu_zero_page,       	moea64_zero_page),
+	MMUMETHOD(mmu_zero_page_area,	moea64_zero_page_area),
+	MMUMETHOD(mmu_zero_page_idle,	moea64_zero_page_idle),
+	MMUMETHOD(mmu_activate,		moea64_activate),
+	MMUMETHOD(mmu_deactivate,      	moea64_deactivate),
+	MMUMETHOD(mmu_page_set_memattr,	moea64_page_set_memattr),
+
+	/* Internal interfaces */
+	MMUMETHOD(mmu_mapdev,		moea64_mapdev),
+	MMUMETHOD(mmu_mapdev_attr,	moea64_mapdev_attr),
+	MMUMETHOD(mmu_unmapdev,		moea64_unmapdev),
+	MMUMETHOD(mmu_kextract,		moea64_kextract),
+	MMUMETHOD(mmu_kenter,		moea64_kenter),
+	MMUMETHOD(mmu_kenter_attr,	moea64_kenter_attr),
+	MMUMETHOD(mmu_dev_direct_mapped,moea64_dev_direct_mapped),
+	MMUMETHOD(mmu_scan_md,		moea64_scan_md),
+	MMUMETHOD(mmu_dumpsys_map,	moea64_dumpsys_map),
+
+	{ 0, 0 }
+};
+
+MMU_DEF(oea64_mmu, "mmu_oea64_base", moea64_methods, 0);
+
+static __inline u_int
+va_to_pteg(uint64_t vsid, vm_offset_t addr, int large)
+{
+	uint64_t hash;
+	int shift;
+
+	shift = large ? moea64_large_page_shift : ADDR_PIDX_SHFT;
+	hash = (vsid & VSID_HASH_MASK) ^ (((uint64_t)addr & ADDR_PIDX) >>
+	    shift);
+	return (hash & moea64_pteg_mask);
+}
+
+static __inline struct pvo_head *
+vm_page_to_pvoh(vm_page_t m)
+{
+
+	return (&m->md.mdpg_pvoh);
+}
+
+static __inline void
+moea64_pte_create(struct lpte *pt, uint64_t vsid, vm_offset_t va, 
+    uint64_t pte_lo, int flags)
+{
+
+	/*
+	 * Construct a PTE.  Default to IMB initially.  Valid bit only gets
+	 * set when the real pte is set in memory.
+	 *
+	 * Note: Don't set the valid bit for correct operation of tlb update.
+	 */
+	pt->pte_hi = (vsid << LPTE_VSID_SHIFT) |
+	    (((uint64_t)(va & ADDR_PIDX) >> ADDR_API_SHFT64) & LPTE_API);
+
+	if (flags & PVO_LARGE)
+		pt->pte_hi |= LPTE_BIG;
+
+	pt->pte_lo = pte_lo;
+}
+
+static __inline uint64_t
+moea64_calc_wimg(vm_offset_t pa, vm_memattr_t ma)
+{
+	uint64_t pte_lo;
+	int i;
+
+	if (ma != VM_MEMATTR_DEFAULT) {
+		switch (ma) {
+		case VM_MEMATTR_UNCACHEABLE:
+			return (LPTE_I | LPTE_G);
+		case VM_MEMATTR_WRITE_COMBINING:
+		case VM_MEMATTR_WRITE_BACK:
+		case VM_MEMATTR_PREFETCHABLE:
+			return (LPTE_I);
+		case VM_MEMATTR_WRITE_THROUGH:
+			return (LPTE_W | LPTE_M);
+		}
+	}
+
+	/*
+	 * Assume the page is cache inhibited and access is guarded unless
+	 * it's in our available memory array.
+	 */
+	pte_lo = LPTE_I | LPTE_G;
+	for (i = 0; i < pregions_sz; i++) {
+		if ((pa >= pregions[i].mr_start) &&
+		    (pa < (pregions[i].mr_start + pregions[i].mr_size))) {
+			pte_lo &= ~(LPTE_I | LPTE_G);
+			pte_lo |= LPTE_M;
+			break;
+		}
+	}
+
+	return pte_lo;
+}
+
+/*
+ * Quick sort callout for comparing memory regions.
+ */
+static int	om_cmp(const void *a, const void *b);
+
+static int
+om_cmp(const void *a, const void *b)
+{
+	const struct	ofw_map *mapa;
+	const struct	ofw_map *mapb;
+
+	mapa = a;
+	mapb = b;
+	if (mapa->om_pa < mapb->om_pa)
+		return (-1);
+	else if (mapa->om_pa > mapb->om_pa)
+		return (1);
+	else
+		return (0);
+}
+
+static void
+moea64_add_ofw_mappings(mmu_t mmup, phandle_t mmu, size_t sz)
+{
+	struct ofw_map	translations[sz/(4*sizeof(cell_t))]; /*>= 4 cells per */
+	pcell_t		acells, trans_cells[sz/sizeof(cell_t)];
+	register_t	msr;
+	vm_offset_t	off;
+	vm_paddr_t	pa_base;
+	int		i, j;
+
+	bzero(translations, sz);
+	OF_getprop(OF_finddevice("/"), "#address-cells", &acells,
+	    sizeof(acells));
+	if (OF_getprop(mmu, "translations", trans_cells, sz) == -1)
+		panic("moea64_bootstrap: can't get ofw translations");
+
+	CTR0(KTR_PMAP, "moea64_add_ofw_mappings: translations");
+	sz /= sizeof(cell_t);
+	for (i = 0, j = 0; i < sz; j++) {
+		translations[j].om_va = trans_cells[i++];
+		translations[j].om_len = trans_cells[i++];
+		translations[j].om_pa = trans_cells[i++];
+		if (acells == 2) {
+			translations[j].om_pa <<= 32;
+			translations[j].om_pa |= trans_cells[i++];
+		}
+		translations[j].om_mode = trans_cells[i++];
+	}
+	KASSERT(i == sz, ("Translations map has incorrect cell count (%d/%zd)",
+	    i, sz));
+
+	sz = j;
+	qsort(translations, sz, sizeof (*translations), om_cmp);
+
+	for (i = 0; i < sz; i++) {
+		pa_base = translations[i].om_pa;
+	      #ifndef __powerpc64__
+		if ((translations[i].om_pa >> 32) != 0)
+			panic("OFW translations above 32-bit boundary!");
+	      #endif
+
+		if (pa_base % PAGE_SIZE)
+			panic("OFW translation not page-aligned (phys)!");
+		if (translations[i].om_va % PAGE_SIZE)
+			panic("OFW translation not page-aligned (virt)!");
+
+		CTR3(KTR_PMAP, "translation: pa=%#zx va=%#x len=%#x",
+		    pa_base, translations[i].om_va, translations[i].om_len);
+
+		/* Now enter the pages for this mapping */
+
+		DISABLE_TRANS(msr);
+		for (off = 0; off < translations[i].om_len; off += PAGE_SIZE) {
+			if (moea64_pvo_find_va(kernel_pmap,
+			    translations[i].om_va + off) != NULL)
+				continue;
+
+			moea64_kenter(mmup, translations[i].om_va + off,
+			    pa_base + off);
+		}
+		ENABLE_TRANS(msr);
+	}
+}
+
+#ifdef __powerpc64__
+static void
+moea64_probe_large_page(void)
+{
+	uint16_t pvr = mfpvr() >> 16;
+
+	switch (pvr) {
+	case IBM970:
+	case IBM970FX:
+	case IBM970MP:
+		powerpc_sync(); isync();
+		mtspr(SPR_HID4, mfspr(SPR_HID4) & ~HID4_970_DISABLE_LG_PG);
+		powerpc_sync(); isync();
+		
+		/* FALLTHROUGH */
+	default:
+		moea64_large_page_size = 0x1000000; /* 16 MB */
+		moea64_large_page_shift = 24;
+	}
+
+	moea64_large_page_mask = moea64_large_page_size - 1;
+}
+
+static void
+moea64_bootstrap_slb_prefault(vm_offset_t va, int large)
+{
+	struct slb *cache;
+	struct slb entry;
+	uint64_t esid, slbe;
+	uint64_t i;
+
+	cache = PCPU_GET(slb);
+	esid = va >> ADDR_SR_SHFT;
+	slbe = (esid << SLBE_ESID_SHIFT) | SLBE_VALID;
+
+	for (i = 0; i < 64; i++) {
+		if (cache[i].slbe == (slbe | i))
+			return;
+	}
+
+	entry.slbe = slbe;
+	entry.slbv = KERNEL_VSID(esid) << SLBV_VSID_SHIFT;
+	if (large)
+		entry.slbv |= SLBV_L;
+
+	slb_insert_kernel(entry.slbe, entry.slbv);
+}
+#endif
+
+static void
+moea64_setup_direct_map(mmu_t mmup, vm_offset_t kernelstart,
+    vm_offset_t kernelend)
+{
+	register_t msr;
+	vm_paddr_t pa;
+	vm_offset_t size, off;
+	uint64_t pte_lo;
+	int i;
+
+	if (moea64_large_page_size == 0) 
+		hw_direct_map = 0;
+
+	DISABLE_TRANS(msr);
+	if (hw_direct_map) {
+		LOCK_TABLE_WR();
+		PMAP_LOCK(kernel_pmap);
+		for (i = 0; i < pregions_sz; i++) {
+		  for (pa = pregions[i].mr_start; pa < pregions[i].mr_start +
+		     pregions[i].mr_size; pa += moea64_large_page_size) {
+			pte_lo = LPTE_M;
+
+			/*
+			 * Set memory access as guarded if prefetch within
+			 * the page could exit the available physmem area.
+			 */
+			if (pa & moea64_large_page_mask) {
+				pa &= moea64_large_page_mask;
+				pte_lo |= LPTE_G;
+			}
+			if (pa + moea64_large_page_size >
+			    pregions[i].mr_start + pregions[i].mr_size)
+				pte_lo |= LPTE_G;
+
+			moea64_pvo_enter(mmup, kernel_pmap, moea64_upvo_zone,
+				    NULL, pa, pa, pte_lo,
+				    PVO_WIRED | PVO_LARGE, 0);
+		  }
+		}
+		PMAP_UNLOCK(kernel_pmap);
+		UNLOCK_TABLE_WR();
+	} else {
+		size = sizeof(struct pvo_head) * moea64_pteg_count;
+		off = (vm_offset_t)(moea64_pvo_table);
+		for (pa = off; pa < off + size; pa += PAGE_SIZE) 
+			moea64_kenter(mmup, pa, pa);
+		size = BPVO_POOL_SIZE*sizeof(struct pvo_entry);
+		off = (vm_offset_t)(moea64_bpvo_pool);
+		for (pa = off; pa < off + size; pa += PAGE_SIZE) 
+		moea64_kenter(mmup, pa, pa);
+
+		/*
+		 * Map certain important things, like ourselves.
+		 *
+		 * NOTE: We do not map the exception vector space. That code is
+		 * used only in real mode, and leaving it unmapped allows us to
+		 * catch NULL pointer deferences, instead of making NULL a valid
+		 * address.
+		 */
+
+		for (pa = kernelstart & ~PAGE_MASK; pa < kernelend;
+		    pa += PAGE_SIZE) 
+			moea64_kenter(mmup, pa, pa);
+	}
+	ENABLE_TRANS(msr);
+
+	/*
+	 * Allow user to override unmapped_buf_allowed for testing.
+	 * XXXKIB Only direct map implementation was tested.
+	 */
+	if (!TUNABLE_INT_FETCH("vfs.unmapped_buf_allowed",
+	    &unmapped_buf_allowed))
+		unmapped_buf_allowed = hw_direct_map;
+}
+
+void
+moea64_early_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
+{
+	int		i, j;
+	vm_size_t	physsz, hwphyssz;
+
+#ifndef __powerpc64__
+	/* We don't have a direct map since there is no BAT */
+	hw_direct_map = 0;
+
+	/* Make sure battable is zero, since we have no BAT */
+	for (i = 0; i < 16; i++) {
+		battable[i].batu = 0;
+		battable[i].batl = 0;
+	}
+#else
+	moea64_probe_large_page();
+
+	/* Use a direct map if we have large page support */
+	if (moea64_large_page_size > 0)
+		hw_direct_map = 1;
+	else
+		hw_direct_map = 0;
+#endif
+
+	/* Get physical memory regions from firmware */
+	mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
+	CTR0(KTR_PMAP, "moea64_bootstrap: physical memory");
+
+	if (sizeof(phys_avail)/sizeof(phys_avail[0]) < regions_sz)
+		panic("moea64_bootstrap: phys_avail too small");
+
+	phys_avail_count = 0;
+	physsz = 0;
+	hwphyssz = 0;
+	TUNABLE_ULONG_FETCH("hw.physmem", (u_long *) &hwphyssz);
+	for (i = 0, j = 0; i < regions_sz; i++, j += 2) {
+		CTR3(KTR_PMAP, "region: %#zx - %#zx (%#zx)",
+		    regions[i].mr_start, regions[i].mr_start +
+		    regions[i].mr_size, regions[i].mr_size);
+		if (hwphyssz != 0 &&
+		    (physsz + regions[i].mr_size) >= hwphyssz) {
+			if (physsz < hwphyssz) {
+				phys_avail[j] = regions[i].mr_start;
+				phys_avail[j + 1] = regions[i].mr_start +
+				    hwphyssz - physsz;
+				physsz = hwphyssz;
+				phys_avail_count++;
+			}
+			break;
+		}
+		phys_avail[j] = regions[i].mr_start;
+		phys_avail[j + 1] = regions[i].mr_start + regions[i].mr_size;
+		phys_avail_count++;
+		physsz += regions[i].mr_size;
+	}
+
+	/* Check for overlap with the kernel and exception vectors */
+	for (j = 0; j < 2*phys_avail_count; j+=2) {
+		if (phys_avail[j] < EXC_LAST)
+			phys_avail[j] += EXC_LAST;
+
+		if (kernelstart >= phys_avail[j] &&
+		    kernelstart < phys_avail[j+1]) {
+			if (kernelend < phys_avail[j+1]) {
+				phys_avail[2*phys_avail_count] =
+				    (kernelend & ~PAGE_MASK) + PAGE_SIZE;
+				phys_avail[2*phys_avail_count + 1] =
+				    phys_avail[j+1];
+				phys_avail_count++;
+			}
+
+			phys_avail[j+1] = kernelstart & ~PAGE_MASK;
+		}
+
+		if (kernelend >= phys_avail[j] &&
+		    kernelend < phys_avail[j+1]) {
+			if (kernelstart > phys_avail[j]) {
+				phys_avail[2*phys_avail_count] = phys_avail[j];
+				phys_avail[2*phys_avail_count + 1] =
+				    kernelstart & ~PAGE_MASK;
+				phys_avail_count++;
+			}
+
+			phys_avail[j] = (kernelend & ~PAGE_MASK) + PAGE_SIZE;
+		}
+	}
+
+	physmem = btoc(physsz);
+
+#ifdef PTEGCOUNT
+	moea64_pteg_count = PTEGCOUNT;
+#else
+	moea64_pteg_count = 0x1000;
+
+	while (moea64_pteg_count < physmem)
+		moea64_pteg_count <<= 1;
+
+	moea64_pteg_count >>= 1;
+#endif /* PTEGCOUNT */
+}
+
+void
+moea64_mid_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
+{
+	vm_size_t	size;
+	register_t	msr;
+	int		i;
+
+	/*
+	 * Set PTEG mask
+	 */
+	moea64_pteg_mask = moea64_pteg_count - 1;
+
+	/*
+	 * Allocate pv/overflow lists.
+	 */
+	size = sizeof(struct pvo_head) * moea64_pteg_count;
+
+	moea64_pvo_table = (struct pvo_head *)moea64_bootstrap_alloc(size,
+	    PAGE_SIZE);
+	CTR1(KTR_PMAP, "moea64_bootstrap: PVO table at %p", moea64_pvo_table);
+
+	DISABLE_TRANS(msr);
+	for (i = 0; i < moea64_pteg_count; i++)
+		LIST_INIT(&moea64_pvo_table[i]);
+	ENABLE_TRANS(msr);
+
+	/*
+	 * Initialize the lock that synchronizes access to the pteg and pvo
+	 * tables.
+	 */
+	rw_init_flags(&moea64_table_lock, "pmap tables", RW_RECURSE);
+	mtx_init(&moea64_slb_mutex, "SLB table", NULL, MTX_DEF);
+
+	/*
+	 * Initialise the unmanaged pvo pool.
+	 */
+	moea64_bpvo_pool = (struct pvo_entry *)moea64_bootstrap_alloc(
+		BPVO_POOL_SIZE*sizeof(struct pvo_entry), 0);
+	moea64_bpvo_pool_index = 0;
+
+	/*
+	 * Make sure kernel vsid is allocated as well as VSID 0.
+	 */
+	#ifndef __powerpc64__
+	moea64_vsid_bitmap[(KERNEL_VSIDBITS & (NVSIDS - 1)) / VSID_NBPW]
+		|= 1 << (KERNEL_VSIDBITS % VSID_NBPW);
+	moea64_vsid_bitmap[0] |= 1;
+	#endif
+
+	/*
+	 * Initialize the kernel pmap (which is statically allocated).
+	 */
+	#ifdef __powerpc64__
+	for (i = 0; i < 64; i++) {
+		pcpup->pc_slb[i].slbv = 0;
+		pcpup->pc_slb[i].slbe = 0;
+	}
+	#else
+	for (i = 0; i < 16; i++) 
+		kernel_pmap->pm_sr[i] = EMPTY_SEGMENT + i;
+	#endif
+
+	kernel_pmap->pmap_phys = kernel_pmap;
+	CPU_FILL(&kernel_pmap->pm_active);
+	RB_INIT(&kernel_pmap->pmap_pvo);
+
+	PMAP_LOCK_INIT(kernel_pmap);
+
+	/*
+	 * Now map in all the other buffers we allocated earlier
+	 */
+
+	moea64_setup_direct_map(mmup, kernelstart, kernelend);
+}
+
+void
+moea64_late_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
+{
+	ihandle_t	mmui;
+	phandle_t	chosen;
+	phandle_t	mmu;
+	size_t		sz;
+	int		i;
+	vm_offset_t	pa, va;
+	void		*dpcpu;
+
+	/*
+	 * Set up the Open Firmware pmap and add its mappings if not in real
+	 * mode.
+	 */
+
+	chosen = OF_finddevice("/chosen");
+	if (chosen != -1 && OF_getprop(chosen, "mmu", &mmui, 4) != -1) {
+	    mmu = OF_instance_to_package(mmui);
+	    if (mmu == -1 || (sz = OF_getproplen(mmu, "translations")) == -1)
+		sz = 0;
+	    if (sz > 6144 /* tmpstksz - 2 KB headroom */)
+		panic("moea64_bootstrap: too many ofw translations");
+
+	    if (sz > 0)
+		moea64_add_ofw_mappings(mmup, mmu, sz);
+	}
+
+	/*
+	 * Calculate the last available physical address.
+	 */
+	for (i = 0; phys_avail[i + 2] != 0; i += 2)
+		;
+	Maxmem = powerpc_btop(phys_avail[i + 1]);
+
+	/*
+	 * Initialize MMU and remap early physical mappings
+	 */
+	MMU_CPU_BOOTSTRAP(mmup,0);
+	mtmsr(mfmsr() | PSL_DR | PSL_IR);
+	pmap_bootstrapped++;
+	bs_remap_earlyboot();
+
+	/*
+	 * Set the start and end of kva.
+	 */
+	virtual_avail = VM_MIN_KERNEL_ADDRESS;
+	virtual_end = VM_MAX_SAFE_KERNEL_ADDRESS; 
+
+	/*
+	 * Map the entire KVA range into the SLB. We must not fault there.
+	 */
+	#ifdef __powerpc64__
+	for (va = virtual_avail; va < virtual_end; va += SEGMENT_LENGTH)
+		moea64_bootstrap_slb_prefault(va, 0);
+	#endif
+
+	/*
+	 * Figure out how far we can extend virtual_end into segment 16
+	 * without running into existing mappings. Segment 16 is guaranteed
+	 * to contain neither RAM nor devices (at least on Apple hardware),
+	 * but will generally contain some OFW mappings we should not
+	 * step on.
+	 */
+
+	#ifndef __powerpc64__	/* KVA is in high memory on PPC64 */
+	PMAP_LOCK(kernel_pmap);
+	while (virtual_end < VM_MAX_KERNEL_ADDRESS &&
+	    moea64_pvo_find_va(kernel_pmap, virtual_end+1) == NULL)
+		virtual_end += PAGE_SIZE;
+	PMAP_UNLOCK(kernel_pmap);
+	#endif
+
+	/*
+	 * Allocate a kernel stack with a guard page for thread0 and map it
+	 * into the kernel page map.
+	 */
+	pa = moea64_bootstrap_alloc(KSTACK_PAGES * PAGE_SIZE, PAGE_SIZE);
+	va = virtual_avail + KSTACK_GUARD_PAGES * PAGE_SIZE;
+	virtual_avail = va + KSTACK_PAGES * PAGE_SIZE;
+	CTR2(KTR_PMAP, "moea64_bootstrap: kstack0 at %#x (%#x)", pa, va);
+	thread0.td_kstack = va;
+	thread0.td_kstack_pages = KSTACK_PAGES;
+	for (i = 0; i < KSTACK_PAGES; i++) {
+		moea64_kenter(mmup, va, pa);
+		pa += PAGE_SIZE;
+		va += PAGE_SIZE;
+	}
+
+	/*
+	 * Allocate virtual address space for the message buffer.
+	 */
+	pa = msgbuf_phys = moea64_bootstrap_alloc(msgbufsize, PAGE_SIZE);
+	msgbufp = (struct msgbuf *)virtual_avail;
+	va = virtual_avail;
+	virtual_avail += round_page(msgbufsize);
+	while (va < virtual_avail) {
+		moea64_kenter(mmup, va, pa);
+		pa += PAGE_SIZE;
+		va += PAGE_SIZE;
+	}
+
+	/*
+	 * Allocate virtual address space for the dynamic percpu area.
+	 */
+	pa = moea64_bootstrap_alloc(DPCPU_SIZE, PAGE_SIZE);
+	dpcpu = (void *)virtual_avail;
+	va = virtual_avail;
+	virtual_avail += DPCPU_SIZE;
+	while (va < virtual_avail) {
+		moea64_kenter(mmup, va, pa);
+		pa += PAGE_SIZE;
+		va += PAGE_SIZE;
+	}
+	dpcpu_init(dpcpu, 0);
+
+	/*
+	 * Allocate some things for page zeroing. We put this directly
+	 * in the page table, marked with LPTE_LOCKED, to avoid any
+	 * of the PVO book-keeping or other parts of the VM system
+	 * from even knowing that this hack exists.
+	 */
+
+	if (!hw_direct_map) {
+		mtx_init(&moea64_scratchpage_mtx, "pvo zero page", NULL,
+		    MTX_DEF);
+		for (i = 0; i < 2; i++) {
+			moea64_scratchpage_va[i] = (virtual_end+1) - PAGE_SIZE;
+			virtual_end -= PAGE_SIZE;
+
+			moea64_kenter(mmup, moea64_scratchpage_va[i], 0);
+
+			moea64_scratchpage_pvo[i] = moea64_pvo_find_va(
+			    kernel_pmap, (vm_offset_t)moea64_scratchpage_va[i]);
+			LOCK_TABLE_RD();
+			moea64_scratchpage_pte[i] = MOEA64_PVO_TO_PTE(
+			    mmup, moea64_scratchpage_pvo[i]);
+			moea64_scratchpage_pvo[i]->pvo_pte.lpte.pte_hi
+			    |= LPTE_LOCKED;
+			MOEA64_PTE_CHANGE(mmup, moea64_scratchpage_pte[i],
+			    &moea64_scratchpage_pvo[i]->pvo_pte.lpte,
+			    moea64_scratchpage_pvo[i]->pvo_vpn);
+			UNLOCK_TABLE_RD();
+		}
+	}
+}
+
+/*
+ * Activate a user pmap.  The pmap must be activated before its address
+ * space can be accessed in any way.
+ */
+void
+moea64_activate(mmu_t mmu, struct thread *td)
+{
+	pmap_t	pm;
+
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+	CPU_SET(PCPU_GET(cpuid), &pm->pm_active);
+
+	#ifdef __powerpc64__
+	PCPU_SET(userslb, pm->pm_slb);
+	#else
+	PCPU_SET(curpmap, pm->pmap_phys);
+	#endif
+}
+
+void
+moea64_deactivate(mmu_t mmu, struct thread *td)
+{
+	pmap_t	pm;
+
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+	CPU_CLR(PCPU_GET(cpuid), &pm->pm_active);
+	#ifdef __powerpc64__
+	PCPU_SET(userslb, NULL);
+	#else
+	PCPU_SET(curpmap, NULL);
+	#endif
+}
+
+void
+moea64_unwire(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva)
+{
+	struct	pvo_entry key, *pvo;
+	uintptr_t pt;
+
+	LOCK_TABLE_RD();
+	PMAP_LOCK(pm);
+	key.pvo_vaddr = sva;
+	for (pvo = RB_NFIND(pvo_tree, &pm->pmap_pvo, &key);
+	    pvo != NULL && PVO_VADDR(pvo) < eva;
+	    pvo = RB_NEXT(pvo_tree, &pm->pmap_pvo, pvo)) {
+		pt = MOEA64_PVO_TO_PTE(mmu, pvo);
+		if ((pvo->pvo_vaddr & PVO_WIRED) == 0)
+			panic("moea64_unwire: pvo %p is missing PVO_WIRED",
+			    pvo);
+		pvo->pvo_vaddr &= ~PVO_WIRED;
+		if ((pvo->pvo_pte.lpte.pte_hi & LPTE_WIRED) == 0)
+			panic("moea64_unwire: pte %p is missing LPTE_WIRED",
+			    &pvo->pvo_pte.lpte);
+		pvo->pvo_pte.lpte.pte_hi &= ~LPTE_WIRED;
+		if (pt != -1) {
+			/*
+			 * The PTE's wired attribute is not a hardware
+			 * feature, so there is no need to invalidate any TLB
+			 * entries.
+			 */
+			MOEA64_PTE_CHANGE(mmu, pt, &pvo->pvo_pte.lpte,
+			    pvo->pvo_vpn);
+		}
+		pm->pm_stats.wired_count--;
+	}
+	UNLOCK_TABLE_RD();
+	PMAP_UNLOCK(pm);
+}
+
+/*
+ * This goes through and sets the physical address of our
+ * special scratch PTE to the PA we want to zero or copy. Because
+ * of locking issues (this can get called in pvo_enter() by
+ * the UMA allocator), we can't use most other utility functions here
+ */
+
+static __inline
+void moea64_set_scratchpage_pa(mmu_t mmup, int which, vm_offset_t pa) {
+
+	KASSERT(!hw_direct_map, ("Using OEA64 scratchpage with a direct map!"));
+	mtx_assert(&moea64_scratchpage_mtx, MA_OWNED);
+
+	moea64_scratchpage_pvo[which]->pvo_pte.lpte.pte_lo &=
+	    ~(LPTE_WIMG | LPTE_RPGN);
+	moea64_scratchpage_pvo[which]->pvo_pte.lpte.pte_lo |=
+	    moea64_calc_wimg(pa, VM_MEMATTR_DEFAULT) | (uint64_t)pa;
+	MOEA64_PTE_CHANGE(mmup, moea64_scratchpage_pte[which],
+	    &moea64_scratchpage_pvo[which]->pvo_pte.lpte,
+	    moea64_scratchpage_pvo[which]->pvo_vpn);
+	isync();
+}
+
+void
+moea64_copy_page(mmu_t mmu, vm_page_t msrc, vm_page_t mdst)
+{
+	vm_offset_t	dst;
+	vm_offset_t	src;
+
+	dst = VM_PAGE_TO_PHYS(mdst);
+	src = VM_PAGE_TO_PHYS(msrc);
+
+	if (hw_direct_map) {
+		bcopy((void *)src, (void *)dst, PAGE_SIZE);
+	} else {
+		mtx_lock(&moea64_scratchpage_mtx);
+
+		moea64_set_scratchpage_pa(mmu, 0, src);
+		moea64_set_scratchpage_pa(mmu, 1, dst);
+
+		bcopy((void *)moea64_scratchpage_va[0], 
+		    (void *)moea64_scratchpage_va[1], PAGE_SIZE);
+
+		mtx_unlock(&moea64_scratchpage_mtx);
+	}
+}
+
+static inline void
+moea64_copy_pages_dmap(mmu_t mmu, vm_page_t *ma, vm_offset_t a_offset,
+    vm_page_t *mb, vm_offset_t b_offset, int xfersize)
+{
+	void *a_cp, *b_cp;
+	vm_offset_t a_pg_offset, b_pg_offset;
+	int cnt;
+
+	while (xfersize > 0) {
+		a_pg_offset = a_offset & PAGE_MASK;
+		cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
+		a_cp = (char *)VM_PAGE_TO_PHYS(ma[a_offset >> PAGE_SHIFT]) +
+		    a_pg_offset;
+		b_pg_offset = b_offset & PAGE_MASK;
+		cnt = min(cnt, PAGE_SIZE - b_pg_offset);
+		b_cp = (char *)VM_PAGE_TO_PHYS(mb[b_offset >> PAGE_SHIFT]) +
+		    b_pg_offset;
+		bcopy(a_cp, b_cp, cnt);
+		a_offset += cnt;
+		b_offset += cnt;
+		xfersize -= cnt;
+	}
+}
+
+static inline void
+moea64_copy_pages_nodmap(mmu_t mmu, vm_page_t *ma, vm_offset_t a_offset,
+    vm_page_t *mb, vm_offset_t b_offset, int xfersize)
+{
+	void *a_cp, *b_cp;
+	vm_offset_t a_pg_offset, b_pg_offset;
+	int cnt;
+
+	mtx_lock(&moea64_scratchpage_mtx);
+	while (xfersize > 0) {
+		a_pg_offset = a_offset & PAGE_MASK;
+		cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
+		moea64_set_scratchpage_pa(mmu, 0,
+		    VM_PAGE_TO_PHYS(ma[a_offset >> PAGE_SHIFT]));
+		a_cp = (char *)moea64_scratchpage_va[0] + a_pg_offset;
+		b_pg_offset = b_offset & PAGE_MASK;
+		cnt = min(cnt, PAGE_SIZE - b_pg_offset);
+		moea64_set_scratchpage_pa(mmu, 1,
+		    VM_PAGE_TO_PHYS(mb[b_offset >> PAGE_SHIFT]));
+		b_cp = (char *)moea64_scratchpage_va[1] + b_pg_offset;
+		bcopy(a_cp, b_cp, cnt);
+		a_offset += cnt;
+		b_offset += cnt;
+		xfersize -= cnt;
+	}
+	mtx_unlock(&moea64_scratchpage_mtx);
+}
+
+void
+moea64_copy_pages(mmu_t mmu, vm_page_t *ma, vm_offset_t a_offset,
+    vm_page_t *mb, vm_offset_t b_offset, int xfersize)
+{
+
+	if (hw_direct_map) {
+		moea64_copy_pages_dmap(mmu, ma, a_offset, mb, b_offset,
+		    xfersize);
+	} else {
+		moea64_copy_pages_nodmap(mmu, ma, a_offset, mb, b_offset,
+		    xfersize);
+	}
+}
+
+void
+moea64_zero_page_area(mmu_t mmu, vm_page_t m, int off, int size)
+{
+	vm_offset_t pa = VM_PAGE_TO_PHYS(m);
+
+	if (size + off > PAGE_SIZE)
+		panic("moea64_zero_page: size + off > PAGE_SIZE");
+
+	if (hw_direct_map) {
+		bzero((caddr_t)pa + off, size);
+	} else {
+		mtx_lock(&moea64_scratchpage_mtx);
+		moea64_set_scratchpage_pa(mmu, 0, pa);
+		bzero((caddr_t)moea64_scratchpage_va[0] + off, size);
+		mtx_unlock(&moea64_scratchpage_mtx);
+	}
+}
+
+/*
+ * Zero a page of physical memory by temporarily mapping it
+ */
+void
+moea64_zero_page(mmu_t mmu, vm_page_t m)
+{
+	vm_offset_t pa = VM_PAGE_TO_PHYS(m);
+	vm_offset_t va, off;
+
+	if (!hw_direct_map) {
+		mtx_lock(&moea64_scratchpage_mtx);
+
+		moea64_set_scratchpage_pa(mmu, 0, pa);
+		va = moea64_scratchpage_va[0];
+	} else {
+		va = pa;
+	}
+
+	for (off = 0; off < PAGE_SIZE; off += cacheline_size)
+		__asm __volatile("dcbz 0,%0" :: "r"(va + off));
+
+	if (!hw_direct_map)
+		mtx_unlock(&moea64_scratchpage_mtx);
+}
+
+void
+moea64_zero_page_idle(mmu_t mmu, vm_page_t m)
+{
+
+	moea64_zero_page(mmu, m);
+}
+
+/*
+ * Map the given physical page at the specified virtual address in the
+ * target pmap with the protection requested.  If specified the page
+ * will be wired down.
+ */
+
+int
+moea64_enter(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m, 
+    vm_prot_t prot, u_int flags, int8_t psind)
+{
+	struct		pvo_head *pvo_head;
+	uma_zone_t	zone;
+	vm_page_t	pg;
+	uint64_t	pte_lo;
+	u_int		pvo_flags;
+	int		error;
+
+	if (!moea64_initialized) {
+		pvo_head = NULL;
+		pg = NULL;
+		zone = moea64_upvo_zone;
+		pvo_flags = 0;
+	} else {
+		pvo_head = vm_page_to_pvoh(m);
+		pg = m;
+		zone = moea64_mpvo_zone;
+		pvo_flags = PVO_MANAGED;
+	}
+
+	if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
+		VM_OBJECT_ASSERT_LOCKED(m->object);
+
+	/* XXX change the pvo head for fake pages */
+	if ((m->oflags & VPO_UNMANAGED) != 0) {
+		pvo_flags &= ~PVO_MANAGED;
+		pvo_head = NULL;
+		zone = moea64_upvo_zone;
+	}
+
+	pte_lo = moea64_calc_wimg(VM_PAGE_TO_PHYS(m), pmap_page_get_memattr(m));
+
+	if (prot & VM_PROT_WRITE) {
+		pte_lo |= LPTE_BW;
+		if (pmap_bootstrapped &&
+		    (m->oflags & VPO_UNMANAGED) == 0)
+			vm_page_aflag_set(m, PGA_WRITEABLE);
+	} else
+		pte_lo |= LPTE_BR;
+
+	if ((prot & VM_PROT_EXECUTE) == 0)
+		pte_lo |= LPTE_NOEXEC;
+
+	if ((flags & PMAP_ENTER_WIRED) != 0)
+		pvo_flags |= PVO_WIRED;
+
+	for (;;) {
+		LOCK_TABLE_WR();
+		PMAP_LOCK(pmap);
+		error = moea64_pvo_enter(mmu, pmap, zone, pvo_head, va,
+		    VM_PAGE_TO_PHYS(m), pte_lo, pvo_flags, psind);
+		PMAP_UNLOCK(pmap);
+		UNLOCK_TABLE_WR();
+		if (error != ENOMEM)
+			break;
+		if ((flags & PMAP_ENTER_NOSLEEP) != 0)
+			return (KERN_RESOURCE_SHORTAGE);
+		VM_OBJECT_ASSERT_UNLOCKED(m->object);
+		VM_WAIT;
+	}
+
+	/*
+	 * Flush the page from the instruction cache if this page is
+	 * mapped executable and cacheable.
+	 */
+	if (pmap != kernel_pmap && !(m->aflags & PGA_EXECUTABLE) &&
+	    (pte_lo & (LPTE_I | LPTE_G | LPTE_NOEXEC)) == 0) {
+		vm_page_aflag_set(m, PGA_EXECUTABLE);
+		moea64_syncicache(mmu, pmap, va, VM_PAGE_TO_PHYS(m), PAGE_SIZE);
+	}
+	return (KERN_SUCCESS);
+}
+
+static void
+moea64_syncicache(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_offset_t pa,
+    vm_size_t sz)
+{
+
+	/*
+	 * This is much trickier than on older systems because
+	 * we can't sync the icache on physical addresses directly
+	 * without a direct map. Instead we check a couple of cases
+	 * where the memory is already mapped in and, failing that,
+	 * use the same trick we use for page zeroing to create
+	 * a temporary mapping for this physical address.
+	 */
+
+	if (!pmap_bootstrapped) {
+		/*
+		 * If PMAP is not bootstrapped, we are likely to be
+		 * in real mode.
+		 */
+		__syncicache((void *)pa, sz);
+	} else if (pmap == kernel_pmap) {
+		__syncicache((void *)va, sz);
+	} else if (hw_direct_map) {
+		__syncicache((void *)pa, sz);
+	} else {
+		/* Use the scratch page to set up a temp mapping */
+
+		mtx_lock(&moea64_scratchpage_mtx);
+
+		moea64_set_scratchpage_pa(mmu, 1, pa & ~ADDR_POFF);
+		__syncicache((void *)(moea64_scratchpage_va[1] + 
+		    (va & ADDR_POFF)), sz);
+
+		mtx_unlock(&moea64_scratchpage_mtx);
+	}
+}
+
+/*
+ * Maps a sequence of resident pages belonging to the same object.
+ * The sequence begins with the given page m_start.  This page is
+ * mapped at the given virtual address start.  Each subsequent page is
+ * mapped at a virtual address that is offset from start by the same
+ * amount as the page is offset from m_start within the object.  The
+ * last page in the sequence is the page with the largest offset from
+ * m_start that can be mapped at a virtual address less than the given
+ * virtual address end.  Not every virtual page between start and end
+ * is mapped; only those for which a resident page exists with the
+ * corresponding offset from m_start are mapped.
+ */
+void
+moea64_enter_object(mmu_t mmu, pmap_t pm, vm_offset_t start, vm_offset_t end,
+    vm_page_t m_start, vm_prot_t prot)
+{
+	vm_page_t m;
+	vm_pindex_t diff, psize;
+
+	VM_OBJECT_ASSERT_LOCKED(m_start->object);
+
+	psize = atop(end - start);
+	m = m_start;
+	while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
+		moea64_enter(mmu, pm, start + ptoa(diff), m, prot &
+		    (VM_PROT_READ | VM_PROT_EXECUTE), PMAP_ENTER_NOSLEEP, 0);
+		m = TAILQ_NEXT(m, listq);
+	}
+}
+
+void
+moea64_enter_quick(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_page_t m,
+    vm_prot_t prot)
+{
+
+	moea64_enter(mmu, pm, va, m, prot & (VM_PROT_READ | VM_PROT_EXECUTE),
+	    PMAP_ENTER_NOSLEEP, 0);
+}
+
+vm_paddr_t
+moea64_extract(mmu_t mmu, pmap_t pm, vm_offset_t va)
+{
+	struct	pvo_entry *pvo;
+	vm_paddr_t pa;
+
+	PMAP_LOCK(pm);
+	pvo = moea64_pvo_find_va(pm, va);
+	if (pvo == NULL)
+		pa = 0;
+	else
+		pa = (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) |
+		    (va - PVO_VADDR(pvo));
+	PMAP_UNLOCK(pm);
+	return (pa);
+}
+
+/*
+ * Atomically extract and hold the physical page with the given
+ * pmap and virtual address pair if that mapping permits the given
+ * protection.
+ */
+vm_page_t
+moea64_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot)
+{
+	struct	pvo_entry *pvo;
+	vm_page_t m;
+        vm_paddr_t pa;
+        
+	m = NULL;
+	pa = 0;
+	PMAP_LOCK(pmap);
+retry:
+	pvo = moea64_pvo_find_va(pmap, va & ~ADDR_POFF);
+	if (pvo != NULL && (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) &&
+	    ((pvo->pvo_pte.lpte.pte_lo & LPTE_PP) == LPTE_RW ||
+	     (prot & VM_PROT_WRITE) == 0)) {
+		if (vm_page_pa_tryrelock(pmap,
+			pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN, &pa))
+			goto retry;
+		m = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);
+		vm_page_hold(m);
+	}
+	PA_UNLOCK_COND(pa);
+	PMAP_UNLOCK(pmap);
+	return (m);
+}
+
+static mmu_t installed_mmu;
+
+static void *
+moea64_uma_page_alloc(uma_zone_t zone, vm_size_t bytes, uint8_t *flags,
+    int wait)
+{
+	/*
+	 * This entire routine is a horrible hack to avoid bothering kmem
+	 * for new KVA addresses. Because this can get called from inside
+	 * kmem allocation routines, calling kmem for a new address here
+	 * can lead to multiply locking non-recursive mutexes.
+	 */
+        vm_offset_t va;
+
+        vm_page_t m;
+        int pflags, needed_lock;
+
+	*flags = UMA_SLAB_PRIV;
+	needed_lock = !PMAP_LOCKED(kernel_pmap);
+	pflags = malloc2vm_flags(wait) | VM_ALLOC_WIRED;
+
+        for (;;) {
+                m = vm_page_alloc(NULL, 0, pflags | VM_ALLOC_NOOBJ);
+                if (m == NULL) {
+                        if (wait & M_NOWAIT)
+                                return (NULL);
+                        VM_WAIT;
+                } else
+                        break;
+        }
+
+	va = VM_PAGE_TO_PHYS(m);
+
+	LOCK_TABLE_WR();
+	if (needed_lock)
+		PMAP_LOCK(kernel_pmap);
+
+	moea64_pvo_enter(installed_mmu, kernel_pmap, moea64_upvo_zone,
+	    NULL, va, VM_PAGE_TO_PHYS(m), LPTE_M, PVO_WIRED | PVO_BOOTSTRAP,
+	    0);
+
+	if (needed_lock)
+		PMAP_UNLOCK(kernel_pmap);
+	UNLOCK_TABLE_WR();
+	
+	if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0)
+                bzero((void *)va, PAGE_SIZE);
+
+	return (void *)va;
+}
+
+extern int elf32_nxstack;
+
+void
+moea64_init(mmu_t mmu)
+{
+
+	CTR0(KTR_PMAP, "moea64_init");
+
+	moea64_upvo_zone = uma_zcreate("UPVO entry", sizeof (struct pvo_entry),
+	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,
+	    UMA_ZONE_VM | UMA_ZONE_NOFREE);
+	moea64_mpvo_zone = uma_zcreate("MPVO entry", sizeof(struct pvo_entry),
+	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,
+	    UMA_ZONE_VM | UMA_ZONE_NOFREE);
+
+	if (!hw_direct_map) {
+		installed_mmu = mmu;
+		uma_zone_set_allocf(moea64_upvo_zone,moea64_uma_page_alloc);
+		uma_zone_set_allocf(moea64_mpvo_zone,moea64_uma_page_alloc);
+	}
+
+#ifdef COMPAT_FREEBSD32
+	elf32_nxstack = 1;
+#endif
+
+	moea64_initialized = TRUE;
+}
+
+boolean_t
+moea64_is_referenced(mmu_t mmu, vm_page_t m)
+{
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("moea64_is_referenced: page %p is not managed", m));
+	return (moea64_query_bit(mmu, m, PTE_REF));
+}
+
+boolean_t
+moea64_is_modified(mmu_t mmu, vm_page_t m)
+{
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("moea64_is_modified: page %p is not managed", m));
+
+	/*
+	 * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
+	 * concurrently set while the object is locked.  Thus, if PGA_WRITEABLE
+	 * is clear, no PTEs can have LPTE_CHG set.
+	 */
+	VM_OBJECT_ASSERT_LOCKED(m->object);
+	if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
+		return (FALSE);
+	return (moea64_query_bit(mmu, m, LPTE_CHG));
+}
+
+boolean_t
+moea64_is_prefaultable(mmu_t mmu, pmap_t pmap, vm_offset_t va)
+{
+	struct pvo_entry *pvo;
+	boolean_t rv;
+
+	PMAP_LOCK(pmap);
+	pvo = moea64_pvo_find_va(pmap, va & ~ADDR_POFF);
+	rv = pvo == NULL || (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) == 0;
+	PMAP_UNLOCK(pmap);
+	return (rv);
+}
+
+void
+moea64_clear_modify(mmu_t mmu, vm_page_t m)
+{
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("moea64_clear_modify: page %p is not managed", m));
+	VM_OBJECT_ASSERT_WLOCKED(m->object);
+	KASSERT(!vm_page_xbusied(m),
+	    ("moea64_clear_modify: page %p is exclusive busied", m));
+
+	/*
+	 * If the page is not PGA_WRITEABLE, then no PTEs can have LPTE_CHG
+	 * set.  If the object containing the page is locked and the page is
+	 * not exclusive busied, then PGA_WRITEABLE cannot be concurrently set.
+	 */
+	if ((m->aflags & PGA_WRITEABLE) == 0)
+		return;
+	moea64_clear_bit(mmu, m, LPTE_CHG);
+}
+
+/*
+ * Clear the write and modified bits in each of the given page's mappings.
+ */
+void
+moea64_remove_write(mmu_t mmu, vm_page_t m)
+{
+	struct	pvo_entry *pvo;
+	uintptr_t pt;
+	pmap_t	pmap;
+	uint64_t lo = 0;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("moea64_remove_write: page %p is not managed", m));
+
+	/*
+	 * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
+	 * set by another thread while the object is locked.  Thus,
+	 * if PGA_WRITEABLE is clear, no page table entries need updating.
+	 */
+	VM_OBJECT_ASSERT_WLOCKED(m->object);
+	if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
+		return;
+	powerpc_sync();
+	LOCK_TABLE_RD();
+	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+		pmap = pvo->pvo_pmap;
+		PMAP_LOCK(pmap);
+		if ((pvo->pvo_pte.lpte.pte_lo & LPTE_PP) != LPTE_BR) {
+			pt = MOEA64_PVO_TO_PTE(mmu, pvo);
+			pvo->pvo_pte.lpte.pte_lo &= ~LPTE_PP;
+			pvo->pvo_pte.lpte.pte_lo |= LPTE_BR;
+			if (pt != -1) {
+				MOEA64_PTE_SYNCH(mmu, pt, &pvo->pvo_pte.lpte);
+				lo |= pvo->pvo_pte.lpte.pte_lo;
+				pvo->pvo_pte.lpte.pte_lo &= ~LPTE_CHG;
+				MOEA64_PTE_CHANGE(mmu, pt,
+				    &pvo->pvo_pte.lpte, pvo->pvo_vpn);
+				if (pvo->pvo_pmap == kernel_pmap)
+					isync();
+			}
+		}
+		if ((lo & LPTE_CHG) != 0) 
+			vm_page_dirty(m);
+		PMAP_UNLOCK(pmap);
+	}
+	UNLOCK_TABLE_RD();
+	vm_page_aflag_clear(m, PGA_WRITEABLE);
+}
+
+/*
+ *	moea64_ts_referenced:
+ *
+ *	Return a count of reference bits for a page, clearing those bits.
+ *	It is not necessary for every reference bit to be cleared, but it
+ *	is necessary that 0 only be returned when there are truly no
+ *	reference bits set.
+ *
+ *	XXX: The exact number of bits to check and clear is a matter that
+ *	should be tested and standardized at some point in the future for
+ *	optimal aging of shared pages.
+ */
+int
+moea64_ts_referenced(mmu_t mmu, vm_page_t m)
+{
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("moea64_ts_referenced: page %p is not managed", m));
+	return (moea64_clear_bit(mmu, m, LPTE_REF));
+}
+
+/*
+ * Modify the WIMG settings of all mappings for a page.
+ */
+void
+moea64_page_set_memattr(mmu_t mmu, vm_page_t m, vm_memattr_t ma)
+{
+	struct	pvo_entry *pvo;
+	struct  pvo_head *pvo_head;
+	uintptr_t pt;
+	pmap_t	pmap;
+	uint64_t lo;
+
+	if ((m->oflags & VPO_UNMANAGED) != 0) {
+		m->md.mdpg_cache_attrs = ma;
+		return;
+	}
+
+	pvo_head = vm_page_to_pvoh(m);
+	lo = moea64_calc_wimg(VM_PAGE_TO_PHYS(m), ma);
+	LOCK_TABLE_RD();
+	LIST_FOREACH(pvo, pvo_head, pvo_vlink) {
+		pmap = pvo->pvo_pmap;
+		PMAP_LOCK(pmap);
+		pt = MOEA64_PVO_TO_PTE(mmu, pvo);
+		pvo->pvo_pte.lpte.pte_lo &= ~LPTE_WIMG;
+		pvo->pvo_pte.lpte.pte_lo |= lo;
+		if (pt != -1) {
+			MOEA64_PTE_CHANGE(mmu, pt, &pvo->pvo_pte.lpte,
+			    pvo->pvo_vpn);
+			if (pvo->pvo_pmap == kernel_pmap)
+				isync();
+		}
+		PMAP_UNLOCK(pmap);
+	}
+	UNLOCK_TABLE_RD();
+	m->md.mdpg_cache_attrs = ma;
+}
+
+/*
+ * Map a wired page into kernel virtual address space.
+ */
+void
+moea64_kenter_attr(mmu_t mmu, vm_offset_t va, vm_offset_t pa, vm_memattr_t ma)
+{
+	uint64_t	pte_lo;
+	int		error;	
+
+	pte_lo = moea64_calc_wimg(pa, ma);
+
+	LOCK_TABLE_WR();
+	PMAP_LOCK(kernel_pmap);
+	error = moea64_pvo_enter(mmu, kernel_pmap, moea64_upvo_zone,
+	    NULL, va, pa, pte_lo, PVO_WIRED, 0);
+	PMAP_UNLOCK(kernel_pmap);
+	UNLOCK_TABLE_WR();
+
+	if (error != 0 && error != ENOENT)
+		panic("moea64_kenter: failed to enter va %#zx pa %#zx: %d", va,
+		    pa, error);
+}
+
+void
+moea64_kenter(mmu_t mmu, vm_offset_t va, vm_paddr_t pa)
+{
+
+	moea64_kenter_attr(mmu, va, pa, VM_MEMATTR_DEFAULT);
+}
+
+/*
+ * Extract the physical page address associated with the given kernel virtual
+ * address.
+ */
+vm_paddr_t
+moea64_kextract(mmu_t mmu, vm_offset_t va)
+{
+	struct		pvo_entry *pvo;
+	vm_paddr_t pa;
+
+	/*
+	 * Shortcut the direct-mapped case when applicable.  We never put
+	 * anything but 1:1 mappings below VM_MIN_KERNEL_ADDRESS.
+	 */
+	if (va < VM_MIN_KERNEL_ADDRESS)
+		return (va);
+
+	PMAP_LOCK(kernel_pmap);
+	pvo = moea64_pvo_find_va(kernel_pmap, va);
+	KASSERT(pvo != NULL, ("moea64_kextract: no addr found for %#" PRIxPTR,
+	    va));
+	pa = (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) | (va - PVO_VADDR(pvo));
+	PMAP_UNLOCK(kernel_pmap);
+	return (pa);
+}
+
+/*
+ * Remove a wired page from kernel virtual address space.
+ */
+void
+moea64_kremove(mmu_t mmu, vm_offset_t va)
+{
+	moea64_remove(mmu, kernel_pmap, va, va + PAGE_SIZE);
+}
+
+/*
+ * Map a range of physical addresses into kernel virtual address space.
+ *
+ * The value passed in *virt is a suggested virtual address for the mapping.
+ * Architectures which can support a direct-mapped physical to virtual region
+ * can return the appropriate address within that region, leaving '*virt'
+ * unchanged.  We cannot and therefore do not; *virt is updated with the
+ * first usable address after the mapped region.
+ */
+vm_offset_t
+moea64_map(mmu_t mmu, vm_offset_t *virt, vm_paddr_t pa_start,
+    vm_paddr_t pa_end, int prot)
+{
+	vm_offset_t	sva, va;
+
+	sva = *virt;
+	va = sva;
+	for (; pa_start < pa_end; pa_start += PAGE_SIZE, va += PAGE_SIZE)
+		moea64_kenter(mmu, va, pa_start);
+	*virt = va;
+
+	return (sva);
+}
+
+/*
+ * Returns true if the pmap's pv is one of the first
+ * 16 pvs linked to from this page.  This count may
+ * be changed upwards or downwards in the future; it
+ * is only necessary that true be returned for a small
+ * subset of pmaps for proper page aging.
+ */
+boolean_t
+moea64_page_exists_quick(mmu_t mmu, pmap_t pmap, vm_page_t m)
+{
+        int loops;
+	struct pvo_entry *pvo;
+	boolean_t rv;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("moea64_page_exists_quick: page %p is not managed", m));
+	loops = 0;
+	rv = FALSE;
+	LOCK_TABLE_RD();
+	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+		if (pvo->pvo_pmap == pmap) {
+			rv = TRUE;
+			break;
+		}
+		if (++loops >= 16)
+			break;
+	}
+	UNLOCK_TABLE_RD();
+	return (rv);
+}
+
+/*
+ * Return the number of managed mappings to the given physical page
+ * that are wired.
+ */
+int
+moea64_page_wired_mappings(mmu_t mmu, vm_page_t m)
+{
+	struct pvo_entry *pvo;
+	int count;
+
+	count = 0;
+	if ((m->oflags & VPO_UNMANAGED) != 0)
+		return (count);
+	LOCK_TABLE_RD();
+	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink)
+		if ((pvo->pvo_vaddr & PVO_WIRED) != 0)
+			count++;
+	UNLOCK_TABLE_RD();
+	return (count);
+}
+
+static uintptr_t	moea64_vsidcontext;
+
+uintptr_t
+moea64_get_unique_vsid(void) {
+	u_int entropy;
+	register_t hash;
+	uint32_t mask;
+	int i;
+
+	entropy = 0;
+	__asm __volatile("mftb %0" : "=r"(entropy));
+
+	mtx_lock(&moea64_slb_mutex);
+	for (i = 0; i < NVSIDS; i += VSID_NBPW) {
+		u_int	n;
+
+		/*
+		 * Create a new value by mutiplying by a prime and adding in
+		 * entropy from the timebase register.  This is to make the
+		 * VSID more random so that the PT hash function collides
+		 * less often.  (Note that the prime casues gcc to do shifts
+		 * instead of a multiply.)
+		 */
+		moea64_vsidcontext = (moea64_vsidcontext * 0x1105) + entropy;
+		hash = moea64_vsidcontext & (NVSIDS - 1);
+		if (hash == 0)		/* 0 is special, avoid it */
+			continue;
+		n = hash >> 5;
+		mask = 1 << (hash & (VSID_NBPW - 1));
+		hash = (moea64_vsidcontext & VSID_HASHMASK);
+		if (moea64_vsid_bitmap[n] & mask) {	/* collision? */
+			/* anything free in this bucket? */
+			if (moea64_vsid_bitmap[n] == 0xffffffff) {
+				entropy = (moea64_vsidcontext >> 20);
+				continue;
+			}
+			i = ffs(~moea64_vsid_bitmap[n]) - 1;
+			mask = 1 << i;
+			hash &= VSID_HASHMASK & ~(VSID_NBPW - 1);
+			hash |= i;
+		}
+		KASSERT(!(moea64_vsid_bitmap[n] & mask),
+		    ("Allocating in-use VSID %#zx\n", hash));
+		moea64_vsid_bitmap[n] |= mask;
+		mtx_unlock(&moea64_slb_mutex);
+		return (hash);
+	}
+
+	mtx_unlock(&moea64_slb_mutex);
+	panic("%s: out of segments",__func__);
+}
+
+#ifdef __powerpc64__
+void
+moea64_pinit(mmu_t mmu, pmap_t pmap)
+{
+
+	RB_INIT(&pmap->pmap_pvo);
+
+	pmap->pm_slb_tree_root = slb_alloc_tree();
+	pmap->pm_slb = slb_alloc_user_cache();
+	pmap->pm_slb_len = 0;
+}
+#else
+void
+moea64_pinit(mmu_t mmu, pmap_t pmap)
+{
+	int	i;
+	uint32_t hash;
+
+	RB_INIT(&pmap->pmap_pvo);
+
+	if (pmap_bootstrapped)
+		pmap->pmap_phys = (pmap_t)moea64_kextract(mmu,
+		    (vm_offset_t)pmap);
+	else
+		pmap->pmap_phys = pmap;
+
+	/*
+	 * Allocate some segment registers for this pmap.
+	 */
+	hash = moea64_get_unique_vsid();
+
+	for (i = 0; i < 16; i++) 
+		pmap->pm_sr[i] = VSID_MAKE(i, hash);
+
+	KASSERT(pmap->pm_sr[0] != 0, ("moea64_pinit: pm_sr[0] = 0"));
+}
+#endif
+
+/*
+ * Initialize the pmap associated with process 0.
+ */
+void
+moea64_pinit0(mmu_t mmu, pmap_t pm)
+{
+
+	PMAP_LOCK_INIT(pm);
+	moea64_pinit(mmu, pm);
+	bzero(&pm->pm_stats, sizeof(pm->pm_stats));
+}
+
+/*
+ * Set the physical protection on the specified range of this map as requested.
+ */
+static void
+moea64_pvo_protect(mmu_t mmu,  pmap_t pm, struct pvo_entry *pvo, vm_prot_t prot)
+{
+	uintptr_t pt;
+	struct	vm_page *pg;
+	uint64_t oldlo;
+
+	PMAP_LOCK_ASSERT(pm, MA_OWNED);
+
+	/*
+	 * Grab the PTE pointer before we diddle with the cached PTE
+	 * copy.
+	 */
+	pt = MOEA64_PVO_TO_PTE(mmu, pvo);
+
+	/*
+	 * Change the protection of the page.
+	 */
+	oldlo = pvo->pvo_pte.lpte.pte_lo;
+	pvo->pvo_pte.lpte.pte_lo &= ~LPTE_PP;
+	pvo->pvo_pte.lpte.pte_lo &= ~LPTE_NOEXEC;
+	if ((prot & VM_PROT_EXECUTE) == 0) 
+		pvo->pvo_pte.lpte.pte_lo |= LPTE_NOEXEC;
+	if (prot & VM_PROT_WRITE) 
+		pvo->pvo_pte.lpte.pte_lo |= LPTE_BW;
+	else
+		pvo->pvo_pte.lpte.pte_lo |= LPTE_BR;
+
+	pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);
+
+	/*
+	 * If the PVO is in the page table, update that pte as well.
+	 */
+	if (pt != -1)
+		MOEA64_PTE_CHANGE(mmu, pt, &pvo->pvo_pte.lpte,
+		    pvo->pvo_vpn);
+	if (pm != kernel_pmap && pg != NULL && !(pg->aflags & PGA_EXECUTABLE) &&
+	    (pvo->pvo_pte.lpte.pte_lo & (LPTE_I | LPTE_G | LPTE_NOEXEC)) == 0) {
+		if ((pg->oflags & VPO_UNMANAGED) == 0)
+			vm_page_aflag_set(pg, PGA_EXECUTABLE);
+		moea64_syncicache(mmu, pm, PVO_VADDR(pvo),
+		    pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN, PAGE_SIZE);
+	}
+
+	/*
+	 * Update vm about the REF/CHG bits if the page is managed and we have
+	 * removed write access.
+	 */
+	if ((pvo->pvo_vaddr & PVO_MANAGED) == PVO_MANAGED && 
+	    (oldlo & LPTE_PP) != LPTE_BR && !(prot & VM_PROT_WRITE)) {
+		if (pg != NULL) {
+			if (pvo->pvo_pte.lpte.pte_lo & LPTE_CHG)
+				vm_page_dirty(pg);
+			if (pvo->pvo_pte.lpte.pte_lo & LPTE_REF)
+				vm_page_aflag_set(pg, PGA_REFERENCED);
+		}
+	}
+}
+
+void
+moea64_protect(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva,
+    vm_prot_t prot)
+{
+	struct	pvo_entry *pvo, *tpvo, key;
+
+	CTR4(KTR_PMAP, "moea64_protect: pm=%p sva=%#x eva=%#x prot=%#x", pm,
+	    sva, eva, prot);
+
+	KASSERT(pm == &curproc->p_vmspace->vm_pmap || pm == kernel_pmap,
+	    ("moea64_protect: non current pmap"));
+
+	if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+		moea64_remove(mmu, pm, sva, eva);
+		return;
+	}
+
+	LOCK_TABLE_RD();
+	PMAP_LOCK(pm);
+	key.pvo_vaddr = sva;
+	for (pvo = RB_NFIND(pvo_tree, &pm->pmap_pvo, &key);
+	    pvo != NULL && PVO_VADDR(pvo) < eva; pvo = tpvo) {
+		tpvo = RB_NEXT(pvo_tree, &pm->pmap_pvo, pvo);
+		moea64_pvo_protect(mmu, pm, pvo, prot);
+	}
+	UNLOCK_TABLE_RD();
+	PMAP_UNLOCK(pm);
+}
+
+/*
+ * Map a list of wired pages into kernel virtual address space.  This is
+ * intended for temporary mappings which do not need page modification or
+ * references recorded.  Existing mappings in the region are overwritten.
+ */
+void
+moea64_qenter(mmu_t mmu, vm_offset_t va, vm_page_t *m, int count)
+{
+	while (count-- > 0) {
+		moea64_kenter(mmu, va, VM_PAGE_TO_PHYS(*m));
+		va += PAGE_SIZE;
+		m++;
+	}
+}
+
+/*
+ * Remove page mappings from kernel virtual address space.  Intended for
+ * temporary mappings entered by moea64_qenter.
+ */
+void
+moea64_qremove(mmu_t mmu, vm_offset_t va, int count)
+{
+	while (count-- > 0) {
+		moea64_kremove(mmu, va);
+		va += PAGE_SIZE;
+	}
+}
+
+void
+moea64_release_vsid(uint64_t vsid)
+{
+	int idx, mask;
+
+	mtx_lock(&moea64_slb_mutex);
+	idx = vsid & (NVSIDS-1);
+	mask = 1 << (idx % VSID_NBPW);
+	idx /= VSID_NBPW;
+	KASSERT(moea64_vsid_bitmap[idx] & mask,
+	    ("Freeing unallocated VSID %#jx", vsid));
+	moea64_vsid_bitmap[idx] &= ~mask;
+	mtx_unlock(&moea64_slb_mutex);
+}
+	
+
+void
+moea64_release(mmu_t mmu, pmap_t pmap)
+{
+        
+	/*
+	 * Free segment registers' VSIDs
+	 */
+    #ifdef __powerpc64__
+	slb_free_tree(pmap);
+	slb_free_user_cache(pmap->pm_slb);
+    #else
+	KASSERT(pmap->pm_sr[0] != 0, ("moea64_release: pm_sr[0] = 0"));
+
+	moea64_release_vsid(VSID_TO_HASH(pmap->pm_sr[0]));
+    #endif
+}
+
+/*
+ * Remove all pages mapped by the specified pmap
+ */
+void
+moea64_remove_pages(mmu_t mmu, pmap_t pm)
+{
+	struct	pvo_entry *pvo, *tpvo;
+
+	LOCK_TABLE_WR();
+	PMAP_LOCK(pm);
+	RB_FOREACH_SAFE(pvo, pvo_tree, &pm->pmap_pvo, tpvo) {
+		if (!(pvo->pvo_vaddr & PVO_WIRED))
+			moea64_pvo_remove(mmu, pvo);
+	}
+	UNLOCK_TABLE_WR();
+	PMAP_UNLOCK(pm);
+}
+
+/*
+ * Remove the given range of addresses from the specified map.
+ */
+void
+moea64_remove(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva)
+{
+	struct	pvo_entry *pvo, *tpvo, key;
+
+	/*
+	 * Perform an unsynchronized read.  This is, however, safe.
+	 */
+	if (pm->pm_stats.resident_count == 0)
+		return;
+
+	LOCK_TABLE_WR();
+	PMAP_LOCK(pm);
+	key.pvo_vaddr = sva;
+	for (pvo = RB_NFIND(pvo_tree, &pm->pmap_pvo, &key);
+	    pvo != NULL && PVO_VADDR(pvo) < eva; pvo = tpvo) {
+		tpvo = RB_NEXT(pvo_tree, &pm->pmap_pvo, pvo);
+		moea64_pvo_remove(mmu, pvo);
+	}
+	UNLOCK_TABLE_WR();
+	PMAP_UNLOCK(pm);
+}
+
+/*
+ * Remove physical page from all pmaps in which it resides. moea64_pvo_remove()
+ * will reflect changes in pte's back to the vm_page.
+ */
+void
+moea64_remove_all(mmu_t mmu, vm_page_t m)
+{
+	struct	pvo_entry *pvo, *next_pvo;
+	pmap_t	pmap;
+
+	LOCK_TABLE_WR();
+	LIST_FOREACH_SAFE(pvo, vm_page_to_pvoh(m), pvo_vlink, next_pvo) {
+		pmap = pvo->pvo_pmap;
+		PMAP_LOCK(pmap);
+		moea64_pvo_remove(mmu, pvo);
+		PMAP_UNLOCK(pmap);
+	}
+	UNLOCK_TABLE_WR();
+	if ((m->aflags & PGA_WRITEABLE) && moea64_is_modified(mmu, m))
+		vm_page_dirty(m);
+	vm_page_aflag_clear(m, PGA_WRITEABLE);
+	vm_page_aflag_clear(m, PGA_EXECUTABLE);
+}
+
+/*
+ * Allocate a physical page of memory directly from the phys_avail map.
+ * Can only be called from moea64_bootstrap before avail start and end are
+ * calculated.
+ */
+vm_offset_t
+moea64_bootstrap_alloc(vm_size_t size, u_int align)
+{
+	vm_offset_t	s, e;
+	int		i, j;
+
+	size = round_page(size);
+	for (i = 0; phys_avail[i + 1] != 0; i += 2) {
+		if (align != 0)
+			s = (phys_avail[i] + align - 1) & ~(align - 1);
+		else
+			s = phys_avail[i];
+		e = s + size;
+
+		if (s < phys_avail[i] || e > phys_avail[i + 1])
+			continue;
+
+		if (s + size > platform_real_maxaddr())
+			continue;
+
+		if (s == phys_avail[i]) {
+			phys_avail[i] += size;
+		} else if (e == phys_avail[i + 1]) {
+			phys_avail[i + 1] -= size;
+		} else {
+			for (j = phys_avail_count * 2; j > i; j -= 2) {
+				phys_avail[j] = phys_avail[j - 2];
+				phys_avail[j + 1] = phys_avail[j - 1];
+			}
+
+			phys_avail[i + 3] = phys_avail[i + 1];
+			phys_avail[i + 1] = s;
+			phys_avail[i + 2] = e;
+			phys_avail_count++;
+		}
+
+		return (s);
+	}
+	panic("moea64_bootstrap_alloc: could not allocate memory");
+}
+
+static int
+moea64_pvo_enter(mmu_t mmu, pmap_t pm, uma_zone_t zone,
+    struct pvo_head *pvo_head, vm_offset_t va, vm_offset_t pa,
+    uint64_t pte_lo, int flags, int8_t psind __unused)
+{
+	struct	 pvo_entry *pvo;
+	uintptr_t pt;
+	uint64_t vsid;
+	int	 first;
+	u_int	 ptegidx;
+	int	 i;
+	int      bootstrap;
+
+	/*
+	 * One nasty thing that can happen here is that the UMA calls to
+	 * allocate new PVOs need to map more memory, which calls pvo_enter(),
+	 * which calls UMA...
+	 *
+	 * We break the loop by detecting recursion and allocating out of
+	 * the bootstrap pool.
+	 */
+
+	first = 0;
+	bootstrap = (flags & PVO_BOOTSTRAP);
+
+	if (!moea64_initialized)
+		bootstrap = 1;
+
+	PMAP_LOCK_ASSERT(pm, MA_OWNED);
+	rw_assert(&moea64_table_lock, RA_WLOCKED);
+
+	/*
+	 * Compute the PTE Group index.
+	 */
+	va &= ~ADDR_POFF;
+	vsid = va_to_vsid(pm, va);
+	ptegidx = va_to_pteg(vsid, va, flags & PVO_LARGE);
+
+	/*
+	 * Remove any existing mapping for this page.  Reuse the pvo entry if
+	 * there is a mapping.
+	 */
+	moea64_pvo_enter_calls++;
+
+	LIST_FOREACH(pvo, &moea64_pvo_table[ptegidx], pvo_olink) {
+		if (pvo->pvo_pmap == pm && PVO_VADDR(pvo) == va) {
+			if ((pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) == pa &&
+			    (pvo->pvo_pte.lpte.pte_lo & (LPTE_NOEXEC | LPTE_PP))
+			    == (pte_lo & (LPTE_NOEXEC | LPTE_PP))) {
+				/*
+				 * The physical page and protection are not
+				 * changing.  Instead, this may be a request
+				 * to change the mapping's wired attribute.
+				 */
+				pt = -1;
+				if ((flags & PVO_WIRED) != 0 &&
+				    (pvo->pvo_vaddr & PVO_WIRED) == 0) {
+					pt = MOEA64_PVO_TO_PTE(mmu, pvo);
+					pvo->pvo_vaddr |= PVO_WIRED;
+					pvo->pvo_pte.lpte.pte_hi |= LPTE_WIRED;
+					pm->pm_stats.wired_count++;
+				} else if ((flags & PVO_WIRED) == 0 &&
+				    (pvo->pvo_vaddr & PVO_WIRED) != 0) {
+					pt = MOEA64_PVO_TO_PTE(mmu, pvo);
+					pvo->pvo_vaddr &= ~PVO_WIRED;
+					pvo->pvo_pte.lpte.pte_hi &= ~LPTE_WIRED;
+					pm->pm_stats.wired_count--;
+				}
+			    	if (!(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID)) {
+					KASSERT(pt == -1,
+					    ("moea64_pvo_enter: valid pt"));
+					/* Re-insert if spilled */
+					i = MOEA64_PTE_INSERT(mmu, ptegidx,
+					    &pvo->pvo_pte.lpte);
+					if (i >= 0)
+						PVO_PTEGIDX_SET(pvo, i);
+					moea64_pte_overflow--;
+				} else if (pt != -1) {
+					/*
+					 * The PTE's wired attribute is not a
+					 * hardware feature, so there is no
+					 * need to invalidate any TLB entries.
+					 */
+					MOEA64_PTE_CHANGE(mmu, pt,
+					    &pvo->pvo_pte.lpte, pvo->pvo_vpn);
+				}
+				return (0);
+			}
+			moea64_pvo_remove(mmu, pvo);
+			break;
+		}
+	}
+
+	/*
+	 * If we aren't overwriting a mapping, try to allocate.
+	 */
+	if (bootstrap) {
+		if (moea64_bpvo_pool_index >= BPVO_POOL_SIZE) {
+			panic("moea64_enter: bpvo pool exhausted, %d, %d, %zd",
+			      moea64_bpvo_pool_index, BPVO_POOL_SIZE, 
+			      BPVO_POOL_SIZE * sizeof(struct pvo_entry));
+		}
+		pvo = &moea64_bpvo_pool[moea64_bpvo_pool_index];
+		moea64_bpvo_pool_index++;
+		bootstrap = 1;
+	} else {
+		pvo = uma_zalloc(zone, M_NOWAIT);
+	}
+
+	if (pvo == NULL)
+		return (ENOMEM);
+
+	moea64_pvo_entries++;
+	pvo->pvo_vaddr = va;
+	pvo->pvo_vpn = (uint64_t)((va & ADDR_PIDX) >> ADDR_PIDX_SHFT)
+	    | (vsid << 16);
+	pvo->pvo_pmap = pm;
+	LIST_INSERT_HEAD(&moea64_pvo_table[ptegidx], pvo, pvo_olink);
+	pvo->pvo_vaddr &= ~ADDR_POFF;
+
+	if (flags & PVO_WIRED)
+		pvo->pvo_vaddr |= PVO_WIRED;
+	if (pvo_head != NULL)
+		pvo->pvo_vaddr |= PVO_MANAGED;
+	if (bootstrap)
+		pvo->pvo_vaddr |= PVO_BOOTSTRAP;
+	if (flags & PVO_LARGE)
+		pvo->pvo_vaddr |= PVO_LARGE;
+
+	moea64_pte_create(&pvo->pvo_pte.lpte, vsid, va, 
+	    (uint64_t)(pa) | pte_lo, flags);
+
+	/*
+	 * Add to pmap list
+	 */
+	RB_INSERT(pvo_tree, &pm->pmap_pvo, pvo);
+
+	/*
+	 * Remember if the list was empty and therefore will be the first
+	 * item.
+	 */
+	if (pvo_head != NULL) {
+		if (LIST_FIRST(pvo_head) == NULL)
+			first = 1;
+		LIST_INSERT_HEAD(pvo_head, pvo, pvo_vlink);
+	}
+
+	if (pvo->pvo_vaddr & PVO_WIRED) {
+		pvo->pvo_pte.lpte.pte_hi |= LPTE_WIRED;
+		pm->pm_stats.wired_count++;
+	}
+	pm->pm_stats.resident_count++;
+
+	/*
+	 * We hope this succeeds but it isn't required.
+	 */
+	i = MOEA64_PTE_INSERT(mmu, ptegidx, &pvo->pvo_pte.lpte);
+	if (i >= 0) {
+		PVO_PTEGIDX_SET(pvo, i);
+	} else {
+		panic("moea64_pvo_enter: overflow");
+		moea64_pte_overflow++;
+	}
+
+	if (pm == kernel_pmap)
+		isync();
+
+#ifdef __powerpc64__
+	/*
+	 * Make sure all our bootstrap mappings are in the SLB as soon
+	 * as virtual memory is switched on.
+	 */
+	if (!pmap_bootstrapped)
+		moea64_bootstrap_slb_prefault(va, flags & PVO_LARGE);
+#endif
+
+	return (first ? ENOENT : 0);
+}
+
+static void
+moea64_pvo_remove(mmu_t mmu, struct pvo_entry *pvo)
+{
+	struct	vm_page *pg;
+	uintptr_t pt;
+
+	PMAP_LOCK_ASSERT(pvo->pvo_pmap, MA_OWNED);
+	rw_assert(&moea64_table_lock, RA_WLOCKED);
+
+	/*
+	 * If there is an active pte entry, we need to deactivate it (and
+	 * save the ref & cfg bits).
+	 */
+	pt = MOEA64_PVO_TO_PTE(mmu, pvo);
+	if (pt != -1) {
+		MOEA64_PTE_UNSET(mmu, pt, &pvo->pvo_pte.lpte, pvo->pvo_vpn);
+		PVO_PTEGIDX_CLR(pvo);
+	} else {
+		moea64_pte_overflow--;
+	}
+
+	/*
+	 * Update our statistics.
+	 */
+	pvo->pvo_pmap->pm_stats.resident_count--;
+	if (pvo->pvo_vaddr & PVO_WIRED)
+		pvo->pvo_pmap->pm_stats.wired_count--;
+
+	/*
+	 * Remove this PVO from the pmap list.
+	 */
+	RB_REMOVE(pvo_tree, &pvo->pvo_pmap->pmap_pvo, pvo);
+
+	/*
+	 * Remove this from the overflow list and return it to the pool
+	 * if we aren't going to reuse it.
+	 */
+	LIST_REMOVE(pvo, pvo_olink);
+
+	/*
+	 * Update vm about the REF/CHG bits if the page is managed.
+	 */
+	pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);
+
+	if ((pvo->pvo_vaddr & PVO_MANAGED) == PVO_MANAGED && pg != NULL) {
+		LIST_REMOVE(pvo, pvo_vlink);
+		if ((pvo->pvo_pte.lpte.pte_lo & LPTE_PP) != LPTE_BR) {
+			if (pvo->pvo_pte.lpte.pte_lo & LPTE_CHG)
+				vm_page_dirty(pg);
+			if (pvo->pvo_pte.lpte.pte_lo & LPTE_REF)
+				vm_page_aflag_set(pg, PGA_REFERENCED);
+			if (LIST_EMPTY(vm_page_to_pvoh(pg)))
+				vm_page_aflag_clear(pg, PGA_WRITEABLE);
+		}
+		if (LIST_EMPTY(vm_page_to_pvoh(pg)))
+			vm_page_aflag_clear(pg, PGA_EXECUTABLE);
+	}
+
+	moea64_pvo_entries--;
+	moea64_pvo_remove_calls++;
+
+	if (!(pvo->pvo_vaddr & PVO_BOOTSTRAP))
+		uma_zfree((pvo->pvo_vaddr & PVO_MANAGED) ? moea64_mpvo_zone :
+		    moea64_upvo_zone, pvo);
+}
+
+static struct pvo_entry *
+moea64_pvo_find_va(pmap_t pm, vm_offset_t va)
+{
+	struct pvo_entry key;
+
+	key.pvo_vaddr = va & ~ADDR_POFF;
+	return (RB_FIND(pvo_tree, &pm->pmap_pvo, &key));
+}
+
+static boolean_t
+moea64_query_bit(mmu_t mmu, vm_page_t m, u_int64_t ptebit)
+{
+	struct	pvo_entry *pvo;
+	uintptr_t pt;
+
+	LOCK_TABLE_RD();
+	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+		/*
+		 * See if we saved the bit off.  If so, return success.
+		 */
+		if (pvo->pvo_pte.lpte.pte_lo & ptebit) {
+			UNLOCK_TABLE_RD();
+			return (TRUE);
+		}
+	}
+
+	/*
+	 * No luck, now go through the hard part of looking at the PTEs
+	 * themselves.  Sync so that any pending REF/CHG bits are flushed to
+	 * the PTEs.
+	 */
+	powerpc_sync();
+	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+
+		/*
+		 * See if this pvo has a valid PTE.  if so, fetch the
+		 * REF/CHG bits from the valid PTE.  If the appropriate
+		 * ptebit is set, return success.
+		 */
+		PMAP_LOCK(pvo->pvo_pmap);
+		pt = MOEA64_PVO_TO_PTE(mmu, pvo);
+		if (pt != -1) {
+			MOEA64_PTE_SYNCH(mmu, pt, &pvo->pvo_pte.lpte);
+			if (pvo->pvo_pte.lpte.pte_lo & ptebit) {
+				PMAP_UNLOCK(pvo->pvo_pmap);
+				UNLOCK_TABLE_RD();
+				return (TRUE);
+			}
+		}
+		PMAP_UNLOCK(pvo->pvo_pmap);
+	}
+
+	UNLOCK_TABLE_RD();
+	return (FALSE);
+}
+
+static u_int
+moea64_clear_bit(mmu_t mmu, vm_page_t m, u_int64_t ptebit)
+{
+	u_int	count;
+	struct	pvo_entry *pvo;
+	uintptr_t pt;
+
+	/*
+	 * Sync so that any pending REF/CHG bits are flushed to the PTEs (so
+	 * we can reset the right ones).  note that since the pvo entries and
+	 * list heads are accessed via BAT0 and are never placed in the page
+	 * table, we don't have to worry about further accesses setting the
+	 * REF/CHG bits.
+	 */
+	powerpc_sync();
+
+	/*
+	 * For each pvo entry, clear the pvo's ptebit.  If this pvo has a
+	 * valid pte clear the ptebit from the valid pte.
+	 */
+	count = 0;
+	LOCK_TABLE_RD();
+	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+		PMAP_LOCK(pvo->pvo_pmap);
+		pt = MOEA64_PVO_TO_PTE(mmu, pvo);
+		if (pt != -1) {
+			MOEA64_PTE_SYNCH(mmu, pt, &pvo->pvo_pte.lpte);
+			if (pvo->pvo_pte.lpte.pte_lo & ptebit) {
+				count++;
+				MOEA64_PTE_CLEAR(mmu, pt, &pvo->pvo_pte.lpte,
+				    pvo->pvo_vpn, ptebit);
+			}
+		}
+		pvo->pvo_pte.lpte.pte_lo &= ~ptebit;
+		PMAP_UNLOCK(pvo->pvo_pmap);
+	}
+
+	UNLOCK_TABLE_RD();
+	return (count);
+}
+
+boolean_t
+moea64_dev_direct_mapped(mmu_t mmu, vm_paddr_t pa, vm_size_t size)
+{
+	struct pvo_entry *pvo, key;
+	vm_offset_t ppa;
+	int error = 0;
+
+	PMAP_LOCK(kernel_pmap);
+	key.pvo_vaddr = ppa = pa & ~ADDR_POFF;
+	for (pvo = RB_FIND(pvo_tree, &kernel_pmap->pmap_pvo, &key);
+	    ppa < pa + size; ppa += PAGE_SIZE,
+	    pvo = RB_NEXT(pvo_tree, &kernel_pmap->pmap_pvo, pvo)) {
+		if (pvo == NULL ||
+		    (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) != ppa) {
+			error = EFAULT;
+			break;
+		}
+	}
+	PMAP_UNLOCK(kernel_pmap);
+
+	return (error);
+}
+
+/*
+ * Map a set of physical memory pages into the kernel virtual
+ * address space. Return a pointer to where it is mapped. This
+ * routine is intended to be used for mapping device memory,
+ * NOT real memory.
+ */
+void *
+moea64_mapdev_attr(mmu_t mmu, vm_offset_t pa, vm_size_t size, vm_memattr_t ma)
+{
+	vm_offset_t va, tmpva, ppa, offset;
+
+	ppa = trunc_page(pa);
+	offset = pa & PAGE_MASK;
+	size = roundup2(offset + size, PAGE_SIZE);
+
+	va = kva_alloc(size);
+
+	if (!va)
+		panic("moea64_mapdev: Couldn't alloc kernel virtual memory");
+
+	for (tmpva = va; size > 0;) {
+		moea64_kenter_attr(mmu, tmpva, ppa, ma);
+		size -= PAGE_SIZE;
+		tmpva += PAGE_SIZE;
+		ppa += PAGE_SIZE;
+	}
+
+	return ((void *)(va + offset));
+}
+
+void *
+moea64_mapdev(mmu_t mmu, vm_paddr_t pa, vm_size_t size)
+{
+
+	return moea64_mapdev_attr(mmu, pa, size, VM_MEMATTR_DEFAULT);
+}
+
+void
+moea64_unmapdev(mmu_t mmu, vm_offset_t va, vm_size_t size)
+{
+	vm_offset_t base, offset;
+
+	base = trunc_page(va);
+	offset = va & PAGE_MASK;
+	size = roundup2(offset + size, PAGE_SIZE);
+
+	kva_free(base, size);
+}
+
+void
+moea64_sync_icache(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_size_t sz)
+{
+	struct pvo_entry *pvo;
+	vm_offset_t lim;
+	vm_paddr_t pa;
+	vm_size_t len;
+
+	PMAP_LOCK(pm);
+	while (sz > 0) {
+		lim = round_page(va);
+		len = MIN(lim - va, sz);
+		pvo = moea64_pvo_find_va(pm, va & ~ADDR_POFF);
+		if (pvo != NULL && !(pvo->pvo_pte.lpte.pte_lo & LPTE_I)) {
+			pa = (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) |
+			    (va & ADDR_POFF);
+			moea64_syncicache(mmu, pm, va, pa, len);
+		}
+		va += len;
+		sz -= len;
+	}
+	PMAP_UNLOCK(pm);
+}
+
+vm_offset_t
+moea64_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
+    vm_size_t *sz)
+{
+	if (md->md_vaddr == ~0UL)
+	    return (md->md_paddr + ofs);
+	else
+	    return (md->md_vaddr + ofs);
+}
+
+struct pmap_md *
+moea64_scan_md(mmu_t mmu, struct pmap_md *prev)
+{
+	static struct pmap_md md;
+	struct pvo_entry *pvo;
+	vm_offset_t va;
+ 
+	if (dumpsys_minidump) {
+		md.md_paddr = ~0UL;	/* Minidumps use virtual addresses. */
+		if (prev == NULL) {
+			/* 1st: kernel .data and .bss. */
+			md.md_index = 1;
+			md.md_vaddr = trunc_page((uintptr_t)_etext);
+			md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
+			return (&md);
+		}
+		switch (prev->md_index) {
+		case 1:
+			/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
+			md.md_index = 2;
+			md.md_vaddr = (vm_offset_t)msgbufp->msg_ptr;
+			md.md_size = round_page(msgbufp->msg_size);
+			break;
+		case 2:
+			/* 3rd: kernel VM. */
+			va = prev->md_vaddr + prev->md_size;
+			/* Find start of next chunk (from va). */
+			while (va < virtual_end) {
+				/* Don't dump the buffer cache. */
+				if (va >= kmi.buffer_sva &&
+				    va < kmi.buffer_eva) {
+					va = kmi.buffer_eva;
+					continue;
+				}
+				pvo = moea64_pvo_find_va(kernel_pmap,
+				    va & ~ADDR_POFF);
+				if (pvo != NULL &&
+				    (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID))
+					break;
+				va += PAGE_SIZE;
+			}
+			if (va < virtual_end) {
+				md.md_vaddr = va;
+				va += PAGE_SIZE;
+				/* Find last page in chunk. */
+				while (va < virtual_end) {
+					/* Don't run into the buffer cache. */
+					if (va == kmi.buffer_sva)
+						break;
+					pvo = moea64_pvo_find_va(kernel_pmap,
+					    va & ~ADDR_POFF);
+					if (pvo == NULL ||
+					    !(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID))
+						break;
+					va += PAGE_SIZE;
+				}
+				md.md_size = va - md.md_vaddr;
+				break;
+			}
+			md.md_index = 3;
+			/* FALLTHROUGH */
+		default:
+			return (NULL);
+		}
+	} else { /* minidumps */
+		if (prev == NULL) {
+			/* first physical chunk. */
+			md.md_paddr = pregions[0].mr_start;
+			md.md_size = pregions[0].mr_size;
+			md.md_vaddr = ~0UL;
+			md.md_index = 1;
+		} else if (md.md_index < pregions_sz) {
+			md.md_paddr = pregions[md.md_index].mr_start;
+			md.md_size = pregions[md.md_index].mr_size;
+			md.md_vaddr = ~0UL;
+			md.md_index++;
+		} else {
+			/* There's no next physical chunk. */
+			return (NULL);
+		}
+	}
+
+	return (&md);
+}


Property changes on: trunk/sys/powerpc/aim/mmu_oea64.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/mmu_oea64.h
===================================================================
--- trunk/sys/powerpc/aim/mmu_oea64.h	                        (rev 0)
+++ trunk/sys/powerpc/aim/mmu_oea64.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,79 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2010 Nathan Whitehorn
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/aim/mmu_oea64.h 255418 2013-09-09 12:51:24Z nwhitehorn $
+ */
+
+#ifndef _POWERPC_AIM_MMU_OEA64_H
+#define _POWERPC_AIM_MMU_OEA64_H
+
+#include <machine/mmuvar.h>
+
+extern mmu_def_t oea64_mmu;
+
+/*
+ * Helper routines
+ */
+
+/* Allocate physical memory for use in moea64_bootstrap. */
+vm_offset_t	moea64_bootstrap_alloc(vm_size_t, u_int);
+
+/*
+ * Bootstrap subroutines
+ *
+ * An MMU_BOOTSTRAP() implementation looks like this:
+ *   moea64_early_bootstrap();
+ *   Allocate Page Table
+ *   moea64_mid_bootstrap();
+ *   Add mappings for MMU resources
+ *   moea64_late_bootstrap();
+ */
+
+void		moea64_early_bootstrap(mmu_t mmup, vm_offset_t kernelstart,
+		    vm_offset_t kernelend);
+void		moea64_mid_bootstrap(mmu_t mmup, vm_offset_t kernelstart,
+		    vm_offset_t kernelend);
+void		moea64_late_bootstrap(mmu_t mmup, vm_offset_t kernelstart,
+		    vm_offset_t kernelend);
+
+/*
+ * Statistics
+ */
+
+extern u_int	moea64_pte_valid;
+extern u_int	moea64_pte_overflow;
+
+/*
+ * State variables
+ */
+
+extern struct pvo_head *moea64_pvo_table;
+extern int		moea64_large_page_shift;
+extern uint64_t		moea64_large_page_size;
+extern u_int		moea64_pteg_count;
+extern u_int		moea64_pteg_mask;
+
+#endif /* _POWERPC_AIM_MMU_OEA64_H */
+


Property changes on: trunk/sys/powerpc/aim/mmu_oea64.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/moea64_if.m
===================================================================
--- trunk/sys/powerpc/aim/moea64_if.m	                        (rev 0)
+++ trunk/sys/powerpc/aim/moea64_if.m	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,115 @@
+#-
+# Copyright (c) 2010 Nathan Whitehorn
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD: stable/10/sys/powerpc/aim/moea64_if.m 216174 2010-12-04 02:42:52Z nwhitehorn $
+# $MidnightBSD$
+
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+        
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+#include <machine/mmuvar.h>
+
+/**
+ * MOEA64 kobj methods for 64-bit Book-S page table
+ * manipulation routines used, for example, by hypervisors.
+ */
+
+INTERFACE moea64;
+
+
+/**
+ * Copy ref/changed bits from PTE referenced by _pt_cookie to _pvo_pt.
+ */
+METHOD void pte_synch {
+	mmu_t		_mmu;
+	uintptr_t	_pt_cookie;
+	struct lpte	*_pvo_pt;
+};
+
+/**
+ * Clear bits ptebit (a mask) from the low word of the PTE referenced by
+ * _pt_cookie. Note that _pvo_pt is for reference use only -- the bit should
+ * NOT be cleared there.
+ */
+METHOD void pte_clear {
+	mmu_t		_mmu;
+	uintptr_t	_pt_cookie;
+	struct lpte	*_pvo_pt;
+	uint64_t	_vpn;
+	uint64_t	_ptebit;
+};
+
+/**
+ * Invalidate the PTE referenced by _pt_cookie, synchronizing its validity
+ * and ref/changed bits after completion.
+ */
+METHOD void pte_unset {
+	mmu_t		_mmu;
+	uintptr_t	_pt_cookie;
+	struct lpte	*_pvo_pt;
+	uint64_t	_vpn;
+};
+
+/**
+ * Update the PTE referenced by _pt_cookie with the values in _pvo_pt,
+ * making sure that the values of ref/changed bits are preserved and
+ * synchronized back to _pvo_pt.
+ */
+METHOD void pte_change {
+	mmu_t		_mmu;
+	uintptr_t	_pt_cookie;
+	struct lpte	*_pvo_pt;
+	uint64_t	_vpn;
+};
+	
+
+/**
+ * Insert the PTE _pvo_pt into the PTEG group _ptegidx, returning the index
+ * of the PTE in its group at completion, or -1 if no slots were free. Must
+ * not replace PTEs marked LPTE_WIRED or LPTE_LOCKED, and must set LPTE_HID
+ * and LPTE_VALID appropriately in _pvo_pt.
+ */
+METHOD int pte_insert {
+	mmu_t		_mmu;
+	u_int		_ptegidx;
+	struct lpte	*_pvo_pt;
+};
+
+/**
+ * Return the page table reference cookie corresponding to _pvo, or -1 if
+ * the _pvo is not currently in the page table.
+ */
+METHOD uintptr_t pvo_to_pte {
+	mmu_t		_mmu;
+	const struct pvo_entry *_pvo;
+};
+
+


Property changes on: trunk/sys/powerpc/aim/moea64_if.m
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/aim/moea64_native.c
===================================================================
--- trunk/sys/powerpc/aim/moea64_native.c	                        (rev 0)
+++ trunk/sys/powerpc/aim/moea64_native.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,627 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt at 3am-software.com> of Allegro Networks, Inc.
+ *
+ * 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.
+ *
+ * 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.
+ */
+/*-
+ * 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.
+ *
+ * $NetBSD: pmap.c,v 1.28 2000/03/26 20:42:36 kleink Exp $
+ */
+/*-
+ * Copyright (C) 2001 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/aim/moea64_native.c 263687 2014-03-24 13:48:04Z emaste $");
+
+/*
+ * Native 64-bit page table operations for running without a hypervisor.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+
+#include <sys/kdb.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_pageout.h>
+
+#include <machine/md_var.h>
+#include <machine/mmuvar.h>
+
+#include "mmu_oea64.h"
+#include "mmu_if.h"
+#include "moea64_if.h"
+
+#define	PTESYNC()	__asm __volatile("ptesync");
+#define	TLBSYNC()	__asm __volatile("tlbsync; ptesync");
+#define	SYNC()		__asm __volatile("sync");
+#define	EIEIO()		__asm __volatile("eieio");
+
+#define	VSID_HASH_MASK	0x0000007fffffffffULL
+
+static __inline void
+TLBIE(uint64_t vpn) {
+#ifndef __powerpc64__
+	register_t vpn_hi, vpn_lo;
+	register_t msr;
+	register_t scratch, intr;
+#endif
+
+	static volatile u_int tlbie_lock = 0;
+
+	vpn <<= ADDR_PIDX_SHFT;
+	vpn &= ~(0xffffULL << 48);
+
+	/* Hobo spinlock: we need stronger guarantees than mutexes provide */
+	while (!atomic_cmpset_int(&tlbie_lock, 0, 1));
+	isync(); /* Flush instruction queue once lock acquired */
+
+#ifdef __powerpc64__
+	__asm __volatile("tlbie %0" :: "r"(vpn) : "memory");
+	__asm __volatile("eieio; tlbsync; ptesync" ::: "memory");
+#else
+	vpn_hi = (uint32_t)(vpn >> 32);
+	vpn_lo = (uint32_t)vpn;
+
+	intr = intr_disable();
+	__asm __volatile("\
+	    mfmsr %0; \
+	    mr %1, %0; \
+	    insrdi %1,%5,1,0; \
+	    mtmsrd %1; isync; \
+	    \
+	    sld %1,%2,%4; \
+	    or %1,%1,%3; \
+	    tlbie %1; \
+	    \
+	    mtmsrd %0; isync; \
+	    eieio; \
+	    tlbsync; \
+	    ptesync;" 
+	: "=r"(msr), "=r"(scratch) : "r"(vpn_hi), "r"(vpn_lo), "r"(32), "r"(1)
+	    : "memory");
+	intr_restore(intr);
+#endif
+
+	/* No barriers or special ops -- taken care of by ptesync above */
+	tlbie_lock = 0;
+}
+
+#define DISABLE_TRANS(msr)	msr = mfmsr(); mtmsr(msr & ~PSL_DR)
+#define ENABLE_TRANS(msr)	mtmsr(msr)
+
+/*
+ * PTEG data.
+ */
+static struct	lpteg *moea64_pteg_table;
+
+/*
+ * PTE calls.
+ */
+static int	moea64_pte_insert_native(mmu_t, u_int, struct lpte *);
+static uintptr_t moea64_pvo_to_pte_native(mmu_t, const struct pvo_entry *);
+static void	moea64_pte_synch_native(mmu_t, uintptr_t pt,
+		    struct lpte *pvo_pt);
+static void	moea64_pte_clear_native(mmu_t, uintptr_t pt,
+		    struct lpte *pvo_pt, uint64_t vpn, uint64_t ptebit);
+static void	moea64_pte_change_native(mmu_t, uintptr_t pt,
+		    struct lpte *pvo_pt, uint64_t vpn);
+static void	moea64_pte_unset_native(mmu_t mmu, uintptr_t pt,
+		    struct lpte *pvo_pt, uint64_t vpn);
+
+/*
+ * Utility routines.
+ */
+static void		moea64_bootstrap_native(mmu_t mmup, 
+			    vm_offset_t kernelstart, vm_offset_t kernelend);
+static void		moea64_cpu_bootstrap_native(mmu_t, int ap);
+static void		tlbia(void);
+
+static mmu_method_t moea64_native_methods[] = {
+	/* Internal interfaces */
+	MMUMETHOD(mmu_bootstrap,	moea64_bootstrap_native),
+	MMUMETHOD(mmu_cpu_bootstrap,	moea64_cpu_bootstrap_native),
+
+	MMUMETHOD(moea64_pte_synch,	moea64_pte_synch_native),
+	MMUMETHOD(moea64_pte_clear,	moea64_pte_clear_native),	
+	MMUMETHOD(moea64_pte_unset,	moea64_pte_unset_native),	
+	MMUMETHOD(moea64_pte_change,	moea64_pte_change_native),	
+	MMUMETHOD(moea64_pte_insert,	moea64_pte_insert_native),	
+	MMUMETHOD(moea64_pvo_to_pte,	moea64_pvo_to_pte_native),	
+
+	{ 0, 0 }
+};
+
+MMU_DEF_INHERIT(oea64_mmu_native, MMU_TYPE_G5, moea64_native_methods,
+    0, oea64_mmu);
+
+static __inline u_int
+va_to_pteg(uint64_t vsid, vm_offset_t addr, int large)
+{
+	uint64_t hash;
+	int shift;
+
+	shift = large ? moea64_large_page_shift : ADDR_PIDX_SHFT;
+	hash = (vsid & VSID_HASH_MASK) ^ (((uint64_t)addr & ADDR_PIDX) >>
+	    shift);
+	return (hash & moea64_pteg_mask);
+}
+
+static void
+moea64_pte_synch_native(mmu_t mmu, uintptr_t pt_cookie, struct lpte *pvo_pt)
+{
+	struct lpte *pt = (struct lpte *)pt_cookie;
+
+	pvo_pt->pte_lo |= pt->pte_lo & (LPTE_REF | LPTE_CHG);
+}
+
+static void
+moea64_pte_clear_native(mmu_t mmu, uintptr_t pt_cookie, struct lpte *pvo_pt,
+    uint64_t vpn, uint64_t ptebit)
+{
+	struct lpte *pt = (struct lpte *)pt_cookie;
+
+	/*
+	 * As shown in Section 7.6.3.2.3
+	 */
+	pt->pte_lo &= ~ptebit;
+	critical_enter();
+	TLBIE(vpn);
+	critical_exit();
+}
+
+static void
+moea64_pte_set_native(struct lpte *pt, struct lpte *pvo_pt)
+{
+
+	pvo_pt->pte_hi |= LPTE_VALID;
+
+	/*
+	 * Update the PTE as defined in section 7.6.3.1.
+	 * Note that the REF/CHG bits are from pvo_pt and thus should have
+	 * been saved so this routine can restore them (if desired).
+	 */
+	pt->pte_lo = pvo_pt->pte_lo;
+	EIEIO();
+	pt->pte_hi = pvo_pt->pte_hi;
+	PTESYNC();
+
+	/* Keep statistics for unlocked pages */
+	if (!(pvo_pt->pte_hi & LPTE_LOCKED))
+		moea64_pte_valid++;
+}
+
+static void
+moea64_pte_unset_native(mmu_t mmu, uintptr_t pt_cookie, struct lpte *pvo_pt,
+    uint64_t vpn)
+{
+	struct lpte *pt = (struct lpte *)pt_cookie;
+
+	/*
+	 * Invalidate the pte.
+	 */
+	isync();
+	critical_enter();
+	pvo_pt->pte_hi &= ~LPTE_VALID;
+	pt->pte_hi &= ~LPTE_VALID;
+	PTESYNC();
+	TLBIE(vpn);
+	critical_exit();
+
+	/*
+	 * Save the reg & chg bits.
+	 */
+	moea64_pte_synch_native(mmu, pt_cookie, pvo_pt);
+
+	/* Keep statistics for unlocked pages */
+	if (!(pvo_pt->pte_hi & LPTE_LOCKED))
+		moea64_pte_valid--;
+}
+
+static void
+moea64_pte_change_native(mmu_t mmu, uintptr_t pt, struct lpte *pvo_pt,
+    uint64_t vpn)
+{
+
+	/*
+	 * Invalidate the PTE
+	 */
+	moea64_pte_unset_native(mmu, pt, pvo_pt, vpn);
+	moea64_pte_set_native((struct lpte *)pt, pvo_pt);
+}
+
+static void
+moea64_cpu_bootstrap_native(mmu_t mmup, int ap)
+{
+	int i = 0;
+	#ifdef __powerpc64__
+	struct slb *slb = PCPU_GET(slb);
+	register_t seg0;
+	#endif
+
+	/*
+	 * Initialize segment registers and MMU
+	 */
+
+	mtmsr(mfmsr() & ~PSL_DR & ~PSL_IR);
+
+	/*
+	 * Install kernel SLB entries
+	 */
+
+	#ifdef __powerpc64__
+		__asm __volatile ("slbia");
+		__asm __volatile ("slbmfee %0,%1; slbie %0;" : "=r"(seg0) :
+		    "r"(0));
+
+		for (i = 0; i < 64; i++) {
+			if (!(slb[i].slbe & SLBE_VALID))
+				continue;
+
+			__asm __volatile ("slbmte %0, %1" :: 
+			    "r"(slb[i].slbv), "r"(slb[i].slbe)); 
+		}
+	#else
+		for (i = 0; i < 16; i++)
+			mtsrin(i << ADDR_SR_SHFT, kernel_pmap->pm_sr[i]);
+	#endif
+
+	/*
+	 * Install page table
+	 */
+
+	__asm __volatile ("ptesync; mtsdr1 %0; isync"
+	    :: "r"((uintptr_t)moea64_pteg_table 
+		     | (uintptr_t)(flsl(moea64_pteg_mask >> 11))));
+	tlbia();
+}
+
+static void
+moea64_bootstrap_native(mmu_t mmup, vm_offset_t kernelstart,
+    vm_offset_t kernelend)
+{
+	vm_size_t	size;
+	vm_offset_t	off;
+	vm_paddr_t	pa;
+	register_t	msr;
+
+	moea64_early_bootstrap(mmup, kernelstart, kernelend);
+
+	/*
+	 * Allocate PTEG table.
+	 */
+
+	size = moea64_pteg_count * sizeof(struct lpteg);
+	CTR2(KTR_PMAP, "moea64_bootstrap: %d PTEGs, %d bytes", 
+	    moea64_pteg_count, size);
+
+	/*
+	 * We now need to allocate memory. This memory, to be allocated,
+	 * has to reside in a page table. The page table we are about to
+	 * allocate. We don't have BAT. So drop to data real mode for a minute
+	 * as a measure of last resort. We do this a couple times.
+	 */
+
+	moea64_pteg_table = (struct lpteg *)moea64_bootstrap_alloc(size, size);
+	DISABLE_TRANS(msr);
+	bzero((void *)moea64_pteg_table, moea64_pteg_count * sizeof(struct lpteg));
+	ENABLE_TRANS(msr);
+
+	CTR1(KTR_PMAP, "moea64_bootstrap: PTEG table at %p", moea64_pteg_table);
+
+	moea64_mid_bootstrap(mmup, kernelstart, kernelend);
+
+	/*
+	 * Add a mapping for the page table itself if there is no direct map.
+	 */
+	if (!hw_direct_map) {
+		size = moea64_pteg_count * sizeof(struct lpteg);
+		off = (vm_offset_t)(moea64_pteg_table);
+		DISABLE_TRANS(msr);
+		for (pa = off; pa < off + size; pa += PAGE_SIZE)
+			pmap_kenter(pa, pa);
+		ENABLE_TRANS(msr);
+	}
+
+	/* Bring up virtual memory */
+	moea64_late_bootstrap(mmup, kernelstart, kernelend);
+}
+
+static void
+tlbia(void)
+{
+	vm_offset_t i;
+	#ifndef __powerpc64__
+	register_t msr, scratch;
+	#endif
+
+	TLBSYNC();
+
+	for (i = 0; i < 0xFF000; i += 0x00001000) {
+		#ifdef __powerpc64__
+		__asm __volatile("tlbiel %0" :: "r"(i));
+		#else
+		__asm __volatile("\
+		    mfmsr %0; \
+		    mr %1, %0; \
+		    insrdi %1,%3,1,0; \
+		    mtmsrd %1; \
+		    isync; \
+		    \
+		    tlbiel %2; \
+		    \
+		    mtmsrd %0; \
+		    isync;" 
+		: "=r"(msr), "=r"(scratch) : "r"(i), "r"(1));
+		#endif
+	}
+
+	EIEIO();
+	TLBSYNC();
+}
+
+static uintptr_t
+moea64_pvo_to_pte_native(mmu_t mmu, const struct pvo_entry *pvo)
+{
+	struct lpte 	*pt;
+	int		pteidx, ptegidx;
+	uint64_t	vsid;
+
+	/* If the PTEG index is not set, then there is no page table entry */
+	if (!PVO_PTEGIDX_ISSET(pvo))
+		return (-1);
+
+	/*
+	 * Calculate the ptegidx
+	 */
+	vsid = PVO_VSID(pvo);
+	ptegidx = va_to_pteg(vsid, PVO_VADDR(pvo),
+	    pvo->pvo_vaddr & PVO_LARGE);
+
+	/*
+	 * We can find the actual pte entry without searching by grabbing
+	 * the PTEG index from 3 unused bits in pvo_vaddr and by
+	 * noticing the HID bit.
+	 */
+	if (pvo->pvo_pte.lpte.pte_hi & LPTE_HID)
+		ptegidx ^= moea64_pteg_mask;
+
+	pteidx = (ptegidx << 3) | PVO_PTEGIDX_GET(pvo);
+
+	if ((pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) && 
+	    !PVO_PTEGIDX_ISSET(pvo)) {
+		panic("moea64_pvo_to_pte: pvo %p has valid pte in pvo but no "
+		    "valid pte index", pvo);
+	}
+
+	if ((pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) == 0 && 
+	    PVO_PTEGIDX_ISSET(pvo)) {
+		panic("moea64_pvo_to_pte: pvo %p has valid pte index in pvo "
+		    "pvo but no valid pte", pvo);
+	}
+
+	pt = &moea64_pteg_table[pteidx >> 3].pt[pteidx & 7];
+	if ((pt->pte_hi ^ (pvo->pvo_pte.lpte.pte_hi & ~LPTE_VALID)) == 
+	    LPTE_VALID) {
+		if ((pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) == 0) {
+			panic("moea64_pvo_to_pte: pvo %p has valid pte in "
+			    "moea64_pteg_table %p but invalid in pvo", pvo, pt);
+		}
+
+		if (((pt->pte_lo ^ pvo->pvo_pte.lpte.pte_lo) & 
+		    ~(LPTE_M|LPTE_CHG|LPTE_REF)) != 0) {
+			panic("moea64_pvo_to_pte: pvo %p pte does not match "
+			    "pte %p in moea64_pteg_table difference is %#x", 
+			    pvo, pt,
+			    (uint32_t)(pt->pte_lo ^ pvo->pvo_pte.lpte.pte_lo));
+		}
+
+		return ((uintptr_t)pt);
+	}
+
+	if (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) {
+		panic("moea64_pvo_to_pte: pvo %p has invalid pte %p in "
+		    "moea64_pteg_table but valid in pvo", pvo, pt);
+	}
+
+	return (-1);
+}
+
+static __inline int
+moea64_pte_spillable_ident(u_int ptegidx)
+{
+	struct	lpte *pt;
+	int	i, j, k;
+
+	/* Start at a random slot */
+	i = mftb() % 8;
+	k = -1;
+	for (j = 0; j < 8; j++) {
+		pt = &moea64_pteg_table[ptegidx].pt[(i + j) % 8];
+		if (pt->pte_hi & (LPTE_LOCKED | LPTE_WIRED))
+			continue;
+
+		/* This is a candidate, so remember it */
+		k = (i + j) % 8;
+
+		/* Try to get a page that has not been used lately */
+		if (!(pt->pte_lo & LPTE_REF))
+			return (k);
+	}
+	
+	return (k);
+}
+
+static int
+moea64_pte_insert_native(mmu_t mmu, u_int ptegidx, struct lpte *pvo_pt)
+{
+	struct	lpte *pt;
+	struct	pvo_entry *pvo;
+	u_int	pteg_bktidx;
+	int	i;
+
+	/*
+	 * First try primary hash.
+	 */
+	pteg_bktidx = ptegidx;
+	for (pt = moea64_pteg_table[pteg_bktidx].pt, i = 0; i < 8; i++, pt++) {
+		if ((pt->pte_hi & (LPTE_VALID | LPTE_LOCKED)) == 0) {
+			pvo_pt->pte_hi &= ~LPTE_HID;
+			moea64_pte_set_native(pt, pvo_pt);
+			return (i);
+		}
+	}
+
+	/*
+	 * Now try secondary hash.
+	 */
+	pteg_bktidx ^= moea64_pteg_mask;
+	for (pt = moea64_pteg_table[pteg_bktidx].pt, i = 0; i < 8; i++, pt++) {
+		if ((pt->pte_hi & (LPTE_VALID | LPTE_LOCKED)) == 0) {
+			pvo_pt->pte_hi |= LPTE_HID;
+			moea64_pte_set_native(pt, pvo_pt);
+			return (i);
+		}
+	}
+
+	/*
+	 * Out of luck. Find a PTE to sacrifice.
+	 */
+	pteg_bktidx = ptegidx;
+	i = moea64_pte_spillable_ident(pteg_bktidx);
+	if (i < 0) {
+		pteg_bktidx ^= moea64_pteg_mask;
+		i = moea64_pte_spillable_ident(pteg_bktidx);
+	}
+
+	if (i < 0) {
+		/* No freeable slots in either PTEG? We're hosed. */
+		panic("moea64_pte_insert: overflow");
+		return (-1);
+	}
+
+	if (pteg_bktidx == ptegidx)
+		pvo_pt->pte_hi &= ~LPTE_HID;
+	else
+		pvo_pt->pte_hi |= LPTE_HID;
+
+	/*
+	 * Synchronize the sacrifice PTE with its PVO, then mark both
+	 * invalid. The PVO will be reused when/if the VM system comes
+	 * here after a fault.
+	 */
+	pt = &moea64_pteg_table[pteg_bktidx].pt[i];
+
+	if (pt->pte_hi & LPTE_HID)
+		pteg_bktidx ^= moea64_pteg_mask; /* PTEs indexed by primary */
+
+	LIST_FOREACH(pvo, &moea64_pvo_table[pteg_bktidx], pvo_olink) {
+		if (pvo->pvo_pte.lpte.pte_hi == pt->pte_hi) {
+			KASSERT(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID, 
+			    ("Invalid PVO for valid PTE!"));
+			moea64_pte_unset_native(mmu, (uintptr_t)pt,
+			    &pvo->pvo_pte.lpte, pvo->pvo_vpn);
+			PVO_PTEGIDX_CLR(pvo);
+			moea64_pte_overflow++;
+			break;
+		}
+	}
+
+	KASSERT(pvo->pvo_pte.lpte.pte_hi == pt->pte_hi,
+	   ("Unable to find PVO for spilled PTE"));
+
+	/*
+	 * Set the new PTE.
+	 */
+	moea64_pte_set_native(pt, pvo_pt);
+
+	return (i);
+}
+


Property changes on: trunk/sys/powerpc/aim/moea64_native.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/mp_cpudep.c
===================================================================
--- trunk/sys/powerpc/aim/mp_cpudep.c	                        (rev 0)
+++ trunk/sys/powerpc/aim/mp_cpudep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,376 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Marcel Moolenaar
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/aim/mp_cpudep.c 265974 2014-05-13 19:12:53Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/hid.h>
+#include <machine/intr_machdep.h>
+#include <machine/pcb.h>
+#include <machine/psl.h>
+#include <machine/smp.h>
+#include <machine/spr.h>
+#include <machine/trap.h>
+
+#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
+
+void *ap_pcpu;
+
+static register_t bsp_state[8] __aligned(8);
+
+static void cpudep_save_config(void *dummy);
+SYSINIT(cpu_save_config, SI_SUB_CPU, SI_ORDER_ANY, cpudep_save_config, NULL);
+
+void
+cpudep_ap_early_bootstrap(void)
+{
+	register_t reg;
+
+	__asm __volatile("mtsprg 0, %0" :: "r"(ap_pcpu));
+	powerpc_sync();
+
+	switch (mfpvr() >> 16) {
+	case IBM970:
+	case IBM970FX:
+	case IBM970MP:
+		/* Restore HID4 and HID5, which are necessary for the MMU */
+
+		__asm __volatile("ld %0, 16(%2); sync; isync;	\
+		    mtspr %1, %0; sync; isync;"
+		    : "=r"(reg) : "K"(SPR_HID4), "r"(bsp_state));
+		__asm __volatile("ld %0, 24(%2); sync; isync;	\
+		    mtspr %1, %0; sync; isync;"
+		    : "=r"(reg) : "K"(SPR_HID5), "r"(bsp_state));
+		powerpc_sync();
+		break;
+	}
+}
+
+uintptr_t
+cpudep_ap_bootstrap(void)
+{
+	register_t msr, sp;
+
+	msr = PSL_KERNSET & ~PSL_EE;
+	mtmsr(msr);
+
+	pcpup->pc_curthread = pcpup->pc_idlethread;
+#ifdef __powerpc64__
+	__asm __volatile("mr 13,%0" :: "r"(pcpup->pc_curthread));
+#else
+	__asm __volatile("mr 2,%0" :: "r"(pcpup->pc_curthread));
+#endif
+	pcpup->pc_curpcb = pcpup->pc_curthread->td_pcb;
+	sp = pcpup->pc_curpcb->pcb_sp;
+
+	return (sp);
+}
+
+static register_t
+mpc74xx_l2_enable(register_t l2cr_config)
+{
+	register_t ccr, bit;
+	uint16_t	vers;
+
+	vers = mfpvr() >> 16;
+	switch (vers) {
+	case MPC7400:
+	case MPC7410:
+		bit = L2CR_L2IP;
+		break;
+	default:
+		bit = L2CR_L2I;
+		break;
+	}
+
+	ccr = mfspr(SPR_L2CR);
+	if (ccr & L2CR_L2E)
+		return (ccr);
+
+	/* Configure L2 cache. */
+	ccr = l2cr_config & ~L2CR_L2E;
+	mtspr(SPR_L2CR, ccr | L2CR_L2I);
+	do {
+		ccr = mfspr(SPR_L2CR);
+	} while (ccr & bit);
+	powerpc_sync();
+	mtspr(SPR_L2CR, l2cr_config);
+	powerpc_sync();
+
+	return (l2cr_config);
+}
+
+static register_t
+mpc745x_l3_enable(register_t l3cr_config)
+{
+	register_t ccr;
+
+	ccr = mfspr(SPR_L3CR);
+	if (ccr & L3CR_L3E)
+		return (ccr);
+
+	/* Configure L3 cache. */
+	ccr = l3cr_config & ~(L3CR_L3E | L3CR_L3I | L3CR_L3PE | L3CR_L3CLKEN);
+	mtspr(SPR_L3CR, ccr);
+	ccr |= 0x4000000;       /* Magic, but documented. */
+	mtspr(SPR_L3CR, ccr);
+	ccr |= L3CR_L3CLKEN;
+	mtspr(SPR_L3CR, ccr);
+	mtspr(SPR_L3CR, ccr | L3CR_L3I);
+	while (mfspr(SPR_L3CR) & L3CR_L3I)
+		;
+	mtspr(SPR_L3CR, ccr & ~L3CR_L3CLKEN);
+	powerpc_sync();
+	DELAY(100);
+	mtspr(SPR_L3CR, ccr);
+	powerpc_sync();
+	DELAY(100);
+	ccr |= L3CR_L3E;
+	mtspr(SPR_L3CR, ccr);
+	powerpc_sync();
+
+	return(ccr);
+}
+
+static register_t
+mpc74xx_l1d_enable(void)
+{
+	register_t hid;
+
+	hid = mfspr(SPR_HID0);
+	if (hid & HID0_DCE)
+		return (hid);
+
+	/* Enable L1 D-cache */
+	hid |= HID0_DCE;
+	powerpc_sync();
+	mtspr(SPR_HID0, hid | HID0_DCFI);
+	powerpc_sync();
+
+	return (hid);
+}
+
+static register_t
+mpc74xx_l1i_enable(void)
+{
+	register_t hid;
+
+	hid = mfspr(SPR_HID0);
+	if (hid & HID0_ICE)
+		return (hid);
+
+	/* Enable L1 I-cache */
+	hid |= HID0_ICE;
+	isync();
+	mtspr(SPR_HID0, hid | HID0_ICFI);
+	isync();
+
+	return (hid);
+}
+
+static void
+cpudep_save_config(void *dummy)
+{
+	uint16_t	vers;
+
+	vers = mfpvr() >> 16;
+
+	switch(vers) {
+	case IBM970:
+	case IBM970FX:
+	case IBM970MP:
+		#ifdef __powerpc64__
+		bsp_state[0] = mfspr(SPR_HID0);
+		bsp_state[1] = mfspr(SPR_HID1);
+		bsp_state[2] = mfspr(SPR_HID4);
+		bsp_state[3] = mfspr(SPR_HID5);
+		#else
+		__asm __volatile ("mfspr %0,%2; mr %1,%0; srdi %0,%0,32"
+		    : "=r" (bsp_state[0]),"=r" (bsp_state[1]) : "K" (SPR_HID0));
+		__asm __volatile ("mfspr %0,%2; mr %1,%0; srdi %0,%0,32"
+		    : "=r" (bsp_state[2]),"=r" (bsp_state[3]) : "K" (SPR_HID1));
+		__asm __volatile ("mfspr %0,%2; mr %1,%0; srdi %0,%0,32"
+		    : "=r" (bsp_state[4]),"=r" (bsp_state[5]) : "K" (SPR_HID4));
+		__asm __volatile ("mfspr %0,%2; mr %1,%0; srdi %0,%0,32"
+		    : "=r" (bsp_state[6]),"=r" (bsp_state[7]) : "K" (SPR_HID5));
+		#endif
+
+		powerpc_sync();
+
+		break;
+	case IBMCELLBE:
+		#ifdef NOTYET /* Causes problems if in instruction stream on 970 */
+		if (mfmsr() & PSL_HV) {
+			bsp_state[0] = mfspr(SPR_HID0);
+			bsp_state[1] = mfspr(SPR_HID1);
+			bsp_state[2] = mfspr(SPR_HID4);
+			bsp_state[3] = mfspr(SPR_HID6);
+
+			bsp_state[4] = mfspr(SPR_CELL_TSCR);
+		}
+		#endif
+
+		bsp_state[5] = mfspr(SPR_CELL_TSRL);
+
+		break;
+	case MPC7450:
+	case MPC7455:
+	case MPC7457:
+		/* Only MPC745x CPUs have an L3 cache. */
+		bsp_state[3] = mfspr(SPR_L3CR);
+
+		/* Fallthrough */
+	case MPC7400:
+	case MPC7410:
+	case MPC7447A:
+	case MPC7448:
+		bsp_state[2] = mfspr(SPR_L2CR);
+		bsp_state[1] = mfspr(SPR_HID1);
+		bsp_state[0] = mfspr(SPR_HID0);
+		break;
+	}
+}
+
+void
+cpudep_ap_setup()
+{ 
+	register_t	reg;
+	uint16_t	vers;
+
+	vers = mfpvr() >> 16;
+
+	/* The following is needed for restoring from sleep. */
+#ifdef __powerpc64__
+	/* Writing to the time base register is hypervisor-privileged */
+	if (mfmsr() & PSL_HV)
+		mttb(0);
+#else
+	mttb(0);
+#endif
+	switch(vers) {
+	case IBM970:
+	case IBM970FX:
+	case IBM970MP:
+		/* Set HIOR to 0 */
+		__asm __volatile("mtspr 311,%0" :: "r"(0));
+		powerpc_sync();
+
+		/*
+		 * The 970 has strange rules about how to update HID registers.
+		 * See Table 2-3, 970MP manual
+		 */
+
+		__asm __volatile("mtasr %0; sync" :: "r"(0));
+		__asm __volatile(" \
+			ld	%0,0(%2);				\
+			sync; isync;					\
+			mtspr	%1, %0;					\
+			mfspr	%0, %1;	mfspr	%0, %1;	mfspr	%0, %1;	\
+			mfspr	%0, %1;	mfspr	%0, %1;	mfspr	%0, %1; \
+			sync; isync" 
+		    : "=r"(reg) : "K"(SPR_HID0), "r"(bsp_state));
+		__asm __volatile("ld %0, 8(%2); sync; isync;	\
+		    mtspr %1, %0; mtspr %1, %0; sync; isync"
+		    : "=r"(reg) : "K"(SPR_HID1), "r"(bsp_state));
+		__asm __volatile("ld %0, 16(%2); sync; isync;	\
+		    mtspr %1, %0; sync; isync;"
+		    : "=r"(reg) : "K"(SPR_HID4), "r"(bsp_state));
+		__asm __volatile("ld %0, 24(%2); sync; isync;	\
+		    mtspr %1, %0; sync; isync;"
+		    : "=r"(reg) : "K"(SPR_HID5), "r"(bsp_state));
+
+		powerpc_sync();
+		break;
+	case IBMCELLBE:
+		#ifdef NOTYET /* Causes problems if in instruction stream on 970 */
+		if (mfmsr() & PSL_HV) {
+			mtspr(SPR_HID0, bsp_state[0]);
+			mtspr(SPR_HID1, bsp_state[1]);
+			mtspr(SPR_HID4, bsp_state[2]);
+			mtspr(SPR_HID6, bsp_state[3]);
+
+			mtspr(SPR_CELL_TSCR, bsp_state[4]);
+		}
+		#endif
+
+		mtspr(SPR_CELL_TSRL, bsp_state[5]);
+
+		break;
+	case MPC7400:
+	case MPC7410:
+	case MPC7447A:
+	case MPC7448:
+	case MPC7450:
+	case MPC7455:
+	case MPC7457:
+		/* XXX: Program the CPU ID into PIR */
+		__asm __volatile("mtspr 1023,%0" :: "r"(PCPU_GET(cpuid)));
+
+		powerpc_sync();
+		isync();
+
+		mtspr(SPR_HID0, bsp_state[0]); isync();
+		mtspr(SPR_HID1, bsp_state[1]); isync();
+
+		/* Now enable the L3 cache. */
+		switch (vers) {
+		case MPC7450:
+		case MPC7455:
+		case MPC7457:
+			/* Only MPC745x CPUs have an L3 cache. */
+			reg = mpc745x_l3_enable(bsp_state[3]);
+		default:
+			break;
+		}
+		
+		reg = mpc74xx_l2_enable(bsp_state[2]);
+		reg = mpc74xx_l1d_enable();
+		reg = mpc74xx_l1i_enable();
+
+		break;
+	default:
+#ifdef __powerpc64__
+		if (!(mfmsr() & PSL_HV)) /* Rely on HV to have set things up */
+			break;
+#endif
+		printf("WARNING: Unknown CPU type. Cache performace may be "
+		    "suboptimal.\n");
+		break;
+	}
+}
+


Property changes on: trunk/sys/powerpc/aim/mp_cpudep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/slb.c
===================================================================
--- trunk/sys/powerpc/aim/slb.c	                        (rev 0)
+++ trunk/sys/powerpc/aim/slb.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,538 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 Nathan Whitehorn
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/aim/slb.c 287945 2015-09-17 23:31:44Z rstone $
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/uma.h>
+#include <vm/vm.h>
+#include <vm/vm_map.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+
+#include <machine/md_var.h>
+#include <machine/platform.h>
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+
+uintptr_t moea64_get_unique_vsid(void);
+void moea64_release_vsid(uint64_t vsid);
+static void slb_zone_init(void *);
+
+static uma_zone_t slbt_zone;
+static uma_zone_t slb_cache_zone;
+int n_slbs = 64;
+
+SYSINIT(slb_zone_init, SI_SUB_KMEM, SI_ORDER_ANY, slb_zone_init, NULL);
+
+struct slbtnode {
+	uint16_t	ua_alloc;
+	uint8_t		ua_level;
+	/* Only 36 bits needed for full 64-bit address space. */
+	uint64_t	ua_base;
+	union {
+		struct slbtnode	*ua_child[16];
+		struct slb	slb_entries[16];
+	} u;
+};
+
+/*
+ * For a full 64-bit address space, there are 36 bits in play in an
+ * esid, so 8 levels, with the leaf being at level 0.
+ *
+ * |3333|3322|2222|2222|1111|1111|11  |    |    |  esid
+ * |5432|1098|7654|3210|9876|5432|1098|7654|3210|  bits
+ * +----+----+----+----+----+----+----+----+----+--------
+ * | 8  | 7  | 6  | 5  | 4  | 3  | 2  | 1  | 0  | level
+ */
+#define UAD_ROOT_LEVEL  8
+#define UAD_LEAF_LEVEL  0
+
+static inline int
+esid2idx(uint64_t esid, int level)
+{
+	int shift;
+
+	shift = level * 4;
+	return ((esid >> shift) & 0xF);
+}
+
+/*
+ * The ua_base field should have 0 bits after the first 4*(level+1)
+ * bits; i.e. only
+ */
+#define uad_baseok(ua)                          \
+	(esid2base(ua->ua_base, ua->ua_level) == ua->ua_base)
+
+
+static inline uint64_t
+esid2base(uint64_t esid, int level)
+{
+	uint64_t mask;
+	int shift;
+
+	shift = (level + 1) * 4;
+	mask = ~((1ULL << shift) - 1);
+	return (esid & mask);
+}
+
+/*
+ * Allocate a new leaf node for the specified esid/vmhandle from the
+ * parent node.
+ */
+static struct slb *
+make_new_leaf(uint64_t esid, uint64_t slbv, struct slbtnode *parent)
+{
+	struct slbtnode *child;
+	struct slb *retval;
+	int idx;
+
+	idx = esid2idx(esid, parent->ua_level);
+	KASSERT(parent->u.ua_child[idx] == NULL, ("Child already exists!"));
+
+	/* unlock and M_WAITOK and loop? */
+	child = uma_zalloc(slbt_zone, M_NOWAIT | M_ZERO);
+	KASSERT(child != NULL, ("unhandled NULL case"));
+
+	child->ua_level = UAD_LEAF_LEVEL;
+	child->ua_base = esid2base(esid, child->ua_level);
+	idx = esid2idx(esid, child->ua_level);
+	child->u.slb_entries[idx].slbv = slbv;
+	child->u.slb_entries[idx].slbe = (esid << SLBE_ESID_SHIFT) | SLBE_VALID;
+	setbit(&child->ua_alloc, idx);
+
+	retval = &child->u.slb_entries[idx];
+
+	/*
+	 * The above stores must be visible before the next one, so
+	 * that a lockless searcher always sees a valid path through
+	 * the tree.
+	 */
+	mb();
+
+	idx = esid2idx(esid, parent->ua_level);
+	parent->u.ua_child[idx] = child;
+	setbit(&parent->ua_alloc, idx);
+
+	return (retval);
+}
+
+/*
+ * Allocate a new intermediate node to fit between the parent and
+ * esid.
+ */
+static struct slbtnode*
+make_intermediate(uint64_t esid, struct slbtnode *parent)
+{
+	struct slbtnode *child, *inter;
+	int idx, level;
+
+	idx = esid2idx(esid, parent->ua_level);
+	child = parent->u.ua_child[idx];
+	KASSERT(esid2base(esid, child->ua_level) != child->ua_base,
+	    ("No need for an intermediate node?"));
+
+	/*
+	 * Find the level where the existing child and our new esid
+	 * meet.  It must be lower than parent->ua_level or we would
+	 * have chosen a different index in parent.
+	 */
+	level = child->ua_level + 1;
+	while (esid2base(esid, level) !=
+	    esid2base(child->ua_base, level))
+		level++;
+	KASSERT(level < parent->ua_level,
+	    ("Found splitting level %d for %09jx and %09jx, "
+	    "but it's the same as %p's",
+	    level, esid, child->ua_base, parent));
+
+	/* unlock and M_WAITOK and loop? */
+	inter = uma_zalloc(slbt_zone, M_NOWAIT | M_ZERO);
+	KASSERT(inter != NULL, ("unhandled NULL case"));
+
+	/* Set up intermediate node to point to child ... */
+	inter->ua_level = level;
+	inter->ua_base = esid2base(esid, inter->ua_level);
+	idx = esid2idx(child->ua_base, inter->ua_level);
+	inter->u.ua_child[idx] = child;
+	setbit(&inter->ua_alloc, idx);
+	mb();
+
+	/* Set up parent to point to intermediate node ... */
+	idx = esid2idx(inter->ua_base, parent->ua_level);
+	parent->u.ua_child[idx] = inter;
+	setbit(&parent->ua_alloc, idx);
+
+	return (inter);
+}
+
+uint64_t
+kernel_va_to_slbv(vm_offset_t va)
+{
+	uint64_t slbv;
+
+	/* Set kernel VSID to deterministic value */
+	slbv = (KERNEL_VSID((uintptr_t)va >> ADDR_SR_SHFT)) << SLBV_VSID_SHIFT;
+
+	/* Figure out if this is a large-page mapping */
+	if (hw_direct_map && va < VM_MIN_KERNEL_ADDRESS) {
+		/*
+		 * XXX: If we have set up a direct map, assumes
+		 * all physical memory is mapped with large pages.
+		 */
+		if (mem_valid(va, 0) == 0)
+			slbv |= SLBV_L;
+	}
+		
+	return (slbv);
+}
+
+struct slb *
+user_va_to_slb_entry(pmap_t pm, vm_offset_t va)
+{
+	uint64_t esid = va >> ADDR_SR_SHFT;
+	struct slbtnode *ua;
+	int idx;
+
+	ua = pm->pm_slb_tree_root;
+
+	for (;;) {
+		KASSERT(uad_baseok(ua), ("uad base %016jx level %d bad!",
+		    ua->ua_base, ua->ua_level));
+		idx = esid2idx(esid, ua->ua_level);
+
+		/*
+		 * This code is specific to ppc64 where a load is
+		 * atomic, so no need for atomic_load macro.
+		 */
+		if (ua->ua_level == UAD_LEAF_LEVEL)
+			return ((ua->u.slb_entries[idx].slbe & SLBE_VALID) ?
+			    &ua->u.slb_entries[idx] : NULL);
+
+		ua = ua->u.ua_child[idx];
+		if (ua == NULL ||
+		    esid2base(esid, ua->ua_level) != ua->ua_base)
+			return (NULL);
+	}
+
+	return (NULL);
+}
+
+uint64_t
+va_to_vsid(pmap_t pm, vm_offset_t va)
+{
+	struct slb *entry;
+
+	/* Shortcut kernel case */
+	if (pm == kernel_pmap)
+		return (KERNEL_VSID((uintptr_t)va >> ADDR_SR_SHFT));
+
+	/*
+	 * If there is no vsid for this VA, we need to add a new entry
+	 * to the PMAP's segment table.
+	 */
+
+	entry = user_va_to_slb_entry(pm, va);
+
+	if (entry == NULL)
+		return (allocate_user_vsid(pm,
+		    (uintptr_t)va >> ADDR_SR_SHFT, 0));
+
+	return ((entry->slbv & SLBV_VSID_MASK) >> SLBV_VSID_SHIFT);
+}
+
+uint64_t
+allocate_user_vsid(pmap_t pm, uint64_t esid, int large)
+{
+	uint64_t vsid, slbv;
+	struct slbtnode *ua, *next, *inter;
+	struct slb *slb;
+	int idx;
+
+	KASSERT(pm != kernel_pmap, ("Attempting to allocate a kernel VSID"));
+
+	PMAP_LOCK_ASSERT(pm, MA_OWNED);
+	vsid = moea64_get_unique_vsid();
+
+	slbv = vsid << SLBV_VSID_SHIFT;
+	if (large)
+		slbv |= SLBV_L;
+
+	ua = pm->pm_slb_tree_root;
+
+	/* Descend to the correct leaf or NULL pointer. */
+	for (;;) {
+		KASSERT(uad_baseok(ua),
+		   ("uad base %09jx level %d bad!", ua->ua_base, ua->ua_level));
+		idx = esid2idx(esid, ua->ua_level);
+
+		if (ua->ua_level == UAD_LEAF_LEVEL) {
+			ua->u.slb_entries[idx].slbv = slbv;
+			eieio();
+			ua->u.slb_entries[idx].slbe = (esid << SLBE_ESID_SHIFT)
+			    | SLBE_VALID;
+			setbit(&ua->ua_alloc, idx);
+			slb = &ua->u.slb_entries[idx];
+			break;
+		}
+
+		next = ua->u.ua_child[idx];
+		if (next == NULL) {
+			slb = make_new_leaf(esid, slbv, ua);
+			break;
+                }
+
+		/*
+		 * Check if the next item down has an okay ua_base.
+		 * If not, we need to allocate an intermediate node.
+		 */
+		if (esid2base(esid, next->ua_level) != next->ua_base) {
+			inter = make_intermediate(esid, ua);
+			slb = make_new_leaf(esid, slbv, inter);
+			break;
+		}
+
+		ua = next;
+	}
+
+	/*
+	 * Someone probably wants this soon, and it may be a wired
+	 * SLB mapping, so pre-spill this entry.
+	 */
+	eieio();
+	slb_insert_user(pm, slb);
+
+	return (vsid);
+}
+
+void
+free_vsid(pmap_t pm, uint64_t esid, int large)
+{
+	struct slbtnode *ua;
+	int idx;
+
+	PMAP_LOCK_ASSERT(pm, MA_OWNED);
+
+	ua = pm->pm_slb_tree_root;
+	/* Descend to the correct leaf. */
+	for (;;) {
+		KASSERT(uad_baseok(ua),
+		   ("uad base %09jx level %d bad!", ua->ua_base, ua->ua_level));
+		
+		idx = esid2idx(esid, ua->ua_level);
+		if (ua->ua_level == UAD_LEAF_LEVEL) {
+			ua->u.slb_entries[idx].slbv = 0;
+			eieio();
+			ua->u.slb_entries[idx].slbe = 0;
+			clrbit(&ua->ua_alloc, idx);
+			return;
+		}
+
+		ua = ua->u.ua_child[idx];
+		if (ua == NULL ||
+		    esid2base(esid, ua->ua_level) != ua->ua_base) {
+			/* Perhaps just return instead of assert? */
+			KASSERT(0,
+			    ("Asked to remove an entry that was never inserted!"));
+			return;
+		}
+	}
+}
+
+static void
+free_slb_tree_node(struct slbtnode *ua)
+{
+	int idx;
+
+	for (idx = 0; idx < 16; idx++) {
+		if (ua->ua_level != UAD_LEAF_LEVEL) {
+			if (ua->u.ua_child[idx] != NULL)
+				free_slb_tree_node(ua->u.ua_child[idx]);
+		} else {
+			if (ua->u.slb_entries[idx].slbv != 0)
+				moea64_release_vsid(ua->u.slb_entries[idx].slbv
+				    >> SLBV_VSID_SHIFT);
+		}
+	}
+
+	uma_zfree(slbt_zone, ua);
+}
+
+void
+slb_free_tree(pmap_t pm)
+{
+
+	free_slb_tree_node(pm->pm_slb_tree_root);
+}
+
+struct slbtnode *
+slb_alloc_tree(void)
+{
+	struct slbtnode *root;
+
+	root = uma_zalloc(slbt_zone, M_NOWAIT | M_ZERO);
+	root->ua_level = UAD_ROOT_LEVEL;
+
+	return (root);
+}
+
+/* Lock entries mapping kernel text and stacks */
+
+void
+slb_insert_kernel(uint64_t slbe, uint64_t slbv)
+{
+	struct slb *slbcache;
+	int i;
+
+	/* We don't want to be preempted while modifying the kernel map */
+	critical_enter();
+
+	slbcache = PCPU_GET(slb);
+
+	/* Check for an unused slot, abusing the user slot as a full flag */
+	if (slbcache[USER_SLB_SLOT].slbe == 0) {
+		for (i = 0; i < n_slbs; i++) {
+			if (i == USER_SLB_SLOT)
+				continue;
+			if (!(slbcache[i].slbe & SLBE_VALID)) 
+				goto fillkernslb;
+		}
+
+		if (i == n_slbs)
+			slbcache[USER_SLB_SLOT].slbe = 1;
+	}
+
+	i = mftb() % n_slbs;
+	if (i == USER_SLB_SLOT)
+			i = (i+1) % n_slbs;
+
+fillkernslb:
+	KASSERT(i != USER_SLB_SLOT,
+	    ("Filling user SLB slot with a kernel mapping"));
+	slbcache[i].slbv = slbv;
+	slbcache[i].slbe = slbe | (uint64_t)i;
+
+	/* If it is for this CPU, put it in the SLB right away */
+	if (pmap_bootstrapped) {
+		/* slbie not required */
+		__asm __volatile ("slbmte %0, %1" :: 
+		    "r"(slbcache[i].slbv), "r"(slbcache[i].slbe)); 
+	}
+
+	critical_exit();
+}
+
+void
+slb_insert_user(pmap_t pm, struct slb *slb)
+{
+	int i;
+
+	PMAP_LOCK_ASSERT(pm, MA_OWNED);
+
+	if (pm->pm_slb_len < n_slbs) {
+		i = pm->pm_slb_len;
+		pm->pm_slb_len++;
+	} else {
+		i = mftb() % n_slbs;
+	}
+
+	/* Note that this replacement is atomic with respect to trap_subr */
+	pm->pm_slb[i] = slb;
+}
+
+static void *
+slb_uma_real_alloc(uma_zone_t zone, vm_size_t bytes, u_int8_t *flags, int wait)
+{
+	static vm_offset_t realmax = 0;
+	void *va;
+	vm_page_t m;
+	int pflags;
+
+	if (realmax == 0)
+		realmax = platform_real_maxaddr();
+
+	*flags = UMA_SLAB_PRIV;
+	pflags = malloc2vm_flags(wait) | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED;
+
+	for (;;) {
+		m = vm_page_alloc_contig(NULL, 0, pflags, 1, 0, realmax,
+		    PAGE_SIZE, PAGE_SIZE, VM_MEMATTR_DEFAULT);
+		if (m == NULL) {
+			if (wait & M_NOWAIT)
+				return (NULL);
+			VM_WAIT;
+		} else
+                        break;
+        }
+
+	va = (void *) VM_PAGE_TO_PHYS(m);
+
+	if (!hw_direct_map)
+		pmap_kenter((vm_offset_t)va, VM_PAGE_TO_PHYS(m));
+
+	if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0)
+		bzero(va, PAGE_SIZE);
+
+	return (va);
+}
+
+static void
+slb_zone_init(void *dummy)
+{
+
+	slbt_zone = uma_zcreate("SLB tree node", sizeof(struct slbtnode),
+	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
+	slb_cache_zone = uma_zcreate("SLB cache",
+	    (n_slbs + 1)*sizeof(struct slb *), NULL, NULL, NULL, NULL,
+	    UMA_ALIGN_PTR, UMA_ZONE_VM);
+
+	if (platform_real_maxaddr() != VM_MAX_ADDRESS) {
+		uma_zone_set_allocf(slb_cache_zone, slb_uma_real_alloc);
+		uma_zone_set_allocf(slbt_zone, slb_uma_real_alloc);
+	}
+}
+
+struct slb **
+slb_alloc_user_cache(void)
+{
+	return (uma_zalloc(slb_cache_zone, M_ZERO));
+}
+
+void
+slb_free_user_cache(struct slb **slb)
+{
+	uma_zfree(slb_cache_zone, slb);
+}


Property changes on: trunk/sys/powerpc/aim/slb.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/trap.c
===================================================================
--- trunk/sys/powerpc/aim/trap.c	                        (rev 0)
+++ trunk/sys/powerpc/aim/trap.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,754 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ * $NetBSD: trap.c,v 1.58 2002/03/04 04:07:35 dbj Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/aim/trap.c 333205 2018-05-03 07:57:08Z avg $");
+
+#include "opt_kdtrace.h"
+
+#include <sys/param.h>
+#include <sys/kdb.h>
+#include <sys/proc.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/pioctl.h>
+#include <sys/ptrace.h>
+#include <sys/reboot.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/uio.h>
+#include <sys/signalvar.h>
+#include <sys/vmmeter.h>
+
+#include <security/audit/audit.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_page.h>
+
+#include <machine/_inttypes.h>
+#include <machine/altivec.h>
+#include <machine/cpu.h>
+#include <machine/db_machdep.h>
+#include <machine/fpu.h>
+#include <machine/frame.h>
+#include <machine/pcb.h>
+#include <machine/pmap.h>
+#include <machine/psl.h>
+#include <machine/trap.h>
+#include <machine/spr.h>
+#include <machine/sr.h>
+
+static void	trap_fatal(struct trapframe *frame);
+static void	printtrap(u_int vector, struct trapframe *frame, int isfatal,
+		    int user);
+static int	trap_pfault(struct trapframe *frame, int user);
+static int	fix_unaligned(struct thread *td, struct trapframe *frame);
+static int	handle_onfault(struct trapframe *frame);
+static void	syscall(struct trapframe *frame);
+
+#ifdef __powerpc64__
+       void	handle_kernel_slb_spill(int, register_t, register_t);
+static int	handle_user_slb_spill(pmap_t pm, vm_offset_t addr);
+extern int	n_slbs;
+#endif
+
+struct powerpc_exception {
+	u_int	vector;
+	char	*name;
+};
+
+#ifdef KDTRACE_HOOKS
+#include <sys/dtrace_bsd.h>
+
+int (*dtrace_invop_jump_addr)(struct trapframe *);
+#endif
+
+static struct powerpc_exception powerpc_exceptions[] = {
+	{ 0x0100, "system reset" },
+	{ 0x0200, "machine check" },
+	{ 0x0300, "data storage interrupt" },
+	{ 0x0380, "data segment exception" },
+	{ 0x0400, "instruction storage interrupt" },
+	{ 0x0480, "instruction segment exception" },
+	{ 0x0500, "external interrupt" },
+	{ 0x0600, "alignment" },
+	{ 0x0700, "program" },
+	{ 0x0800, "floating-point unavailable" },
+	{ 0x0900, "decrementer" },
+	{ 0x0c00, "system call" },
+	{ 0x0d00, "trace" },
+	{ 0x0e00, "floating-point assist" },
+	{ 0x0f00, "performance monitoring" },
+	{ 0x0f20, "altivec unavailable" },
+	{ 0x1000, "instruction tlb miss" },
+	{ 0x1100, "data load tlb miss" },
+	{ 0x1200, "data store tlb miss" },
+	{ 0x1300, "instruction breakpoint" },
+	{ 0x1400, "system management" },
+	{ 0x1600, "altivec assist" },
+	{ 0x1700, "thermal management" },
+	{ 0x2000, "run mode/trace" },
+	{ 0x3000, NULL }
+};
+
+static const char *
+trapname(u_int vector)
+{
+	struct	powerpc_exception *pe;
+
+	for (pe = powerpc_exceptions; pe->vector != 0x3000; pe++) {
+		if (pe->vector == vector)
+			return (pe->name);
+	}
+
+	return ("unknown");
+}
+
+void
+trap(struct trapframe *frame)
+{
+	struct thread	*td;
+	struct proc	*p;
+#ifdef KDTRACE_HOOKS
+	uint32_t inst;
+#endif
+	int		sig, type, user;
+	u_int		ucode;
+	ksiginfo_t	ksi;
+
+	PCPU_INC(cnt.v_trap);
+
+	td = curthread;
+	p = td->td_proc;
+
+	type = ucode = frame->exc;
+	sig = 0;
+	user = frame->srr1 & PSL_PR;
+
+	CTR3(KTR_TRAP, "trap: %s type=%s (%s)", td->td_name,
+	    trapname(type), user ? "user" : "kernel");
+
+#ifdef KDTRACE_HOOKS
+	/*
+	 * A trap can occur while DTrace executes a probe. Before
+	 * executing the probe, DTrace blocks re-scheduling and sets
+	 * a flag in it's per-cpu flags to indicate that it doesn't
+	 * want to fault. On returning from the probe, the no-fault
+	 * flag is cleared and finally re-scheduling is enabled.
+	 *
+	 * If the DTrace kernel module has registered a trap handler,
+	 * call it and if it returns non-zero, assume that it has
+	 * handled the trap and modified the trap frame so that this
+	 * function can return normally.
+	 */
+	/*
+	 * XXXDTRACE: add pid probe handler here (if ever)
+	 */
+	if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
+		return;
+#endif
+
+	if (user) {
+		td->td_pticks = 0;
+		td->td_frame = frame;
+		if (td->td_ucred != p->p_ucred)
+			cred_update_thread(td);
+
+		/* User Mode Traps */
+		switch (type) {
+		case EXC_RUNMODETRC:
+		case EXC_TRC:
+			frame->srr1 &= ~PSL_SE;
+			sig = SIGTRAP;
+			ucode = TRAP_TRACE;
+			break;
+
+#ifdef __powerpc64__
+		case EXC_ISE:
+		case EXC_DSE:
+			if (handle_user_slb_spill(&p->p_vmspace->vm_pmap,
+			    (type == EXC_ISE) ? frame->srr0 :
+			    frame->cpu.aim.dar) != 0) {
+				sig = SIGSEGV;
+				ucode = SEGV_MAPERR;
+			}
+			break;
+#endif
+		case EXC_DSI:
+		case EXC_ISI:
+			sig = trap_pfault(frame, 1);
+			if (sig == SIGSEGV)
+				ucode = SEGV_MAPERR;
+			break;
+
+		case EXC_SC:
+			syscall(frame);
+			break;
+
+		case EXC_FPU:
+			KASSERT((td->td_pcb->pcb_flags & PCB_FPU) != PCB_FPU,
+			    ("FPU already enabled for thread"));
+			enable_fpu(td);
+			break;
+
+		case EXC_VEC:
+			KASSERT((td->td_pcb->pcb_flags & PCB_VEC) != PCB_VEC,
+			    ("Altivec already enabled for thread"));
+			enable_vec(td);
+			break;
+
+		case EXC_VECAST_G4:
+		case EXC_VECAST_G5:
+			/*
+			 * We get a VPU assist exception for IEEE mode
+			 * vector operations on denormalized floats.
+			 * Emulating this is a giant pain, so for now,
+			 * just switch off IEEE mode and treat them as
+			 * zero.
+			 */
+
+			save_vec(td);
+			td->td_pcb->pcb_vec.vscr |= ALTIVEC_VSCR_NJ;
+			enable_vec(td);
+			break;
+
+		case EXC_ALI:
+			if (fix_unaligned(td, frame) != 0) {
+				sig = SIGBUS;
+				ucode = BUS_ADRALN;
+			}
+			else
+				frame->srr0 += 4;
+			break;
+
+		case EXC_PGM:
+			/* Identify the trap reason */
+			if (frame->srr1 & EXC_PGM_TRAP) {
+#ifdef KDTRACE_HOOKS
+				inst = fuword32((const void *)frame->srr0);
+				if (inst == 0x0FFFDDDD && dtrace_pid_probe_ptr != NULL) {
+					struct reg regs;
+					fill_regs(td, &regs);
+					(*dtrace_pid_probe_ptr)(&regs);
+					break;
+				}
+#endif
+ 				sig = SIGTRAP;
+				ucode = TRAP_BRKPT;
+			} else {
+				sig = ppc_instr_emulate(frame, td->td_pcb);
+				if (sig == SIGILL) {
+					if (frame->srr1 & EXC_PGM_PRIV)
+						ucode = ILL_PRVOPC;
+					else if (frame->srr1 & EXC_PGM_ILLEGAL)
+						ucode = ILL_ILLOPC;
+				} else if (sig == SIGFPE)
+					ucode = FPE_FLTINV;	/* Punt for now, invalid operation. */
+			}
+			break;
+
+		case EXC_MCHK:
+			/*
+			 * Note that this may not be recoverable for the user
+			 * process, depending on the type of machine check,
+			 * but it at least prevents the kernel from dying.
+			 */
+			sig = SIGBUS;
+			ucode = BUS_OBJERR;
+			break;
+
+		default:
+			trap_fatal(frame);
+		}
+	} else {
+		/* Kernel Mode Traps */
+
+		KASSERT(cold || td->td_ucred != NULL,
+		    ("kernel trap doesn't have ucred"));
+		switch (type) {
+#ifdef KDTRACE_HOOKS
+		case EXC_PGM:
+			if (frame->srr1 & EXC_PGM_TRAP) {
+				if (*(uint32_t *)frame->srr0 == 0x7c810808) {
+					if (dtrace_invop_jump_addr != NULL) {
+						dtrace_invop_jump_addr(frame);
+						return;
+					}
+				}
+			}
+			break;
+#endif
+#ifdef __powerpc64__
+		case EXC_DSE:
+			if ((frame->cpu.aim.dar & SEGMENT_MASK) == USER_ADDR) {
+				__asm __volatile ("slbmte %0, %1" ::
+					"r"(td->td_pcb->pcb_cpu.aim.usr_vsid),
+					"r"(USER_SLB_SLBE));
+				return;
+			}
+			break;
+#endif
+		case EXC_DSI:
+			if (trap_pfault(frame, 0) == 0)
+ 				return;
+			break;
+		case EXC_MCHK:
+			if (handle_onfault(frame))
+ 				return;
+			break;
+		default:
+			break;
+		}
+		trap_fatal(frame);
+	}
+
+	if (sig != 0) {
+		if (p->p_sysent->sv_transtrap != NULL)
+			sig = (p->p_sysent->sv_transtrap)(sig, type);
+		ksiginfo_init_trap(&ksi);
+		ksi.ksi_signo = sig;
+		ksi.ksi_code = (int) ucode; /* XXX, not POSIX */
+		/* ksi.ksi_addr = ? */
+		ksi.ksi_trapno = type;
+		trapsignal(td, &ksi);
+	}
+
+	userret(td, frame);
+}
+
+static void
+trap_fatal(struct trapframe *frame)
+{
+#ifdef KDB
+	bool handled;
+#endif
+
+	printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR));
+#ifdef KDB
+	if (debugger_on_panic) {
+		kdb_why = KDB_WHY_TRAP;
+		handled = kdb_trap(frame->exc, 0, frame);
+		kdb_why = KDB_WHY_UNSET;
+		if (handled)
+			return;
+	}
+#endif
+	panic("%s trap", trapname(frame->exc));
+}
+
+static void
+printtrap(u_int vector, struct trapframe *frame, int isfatal, int user)
+{
+
+	printf("\n");
+	printf("%s %s trap:\n", isfatal ? "fatal" : "handled",
+	    user ? "user" : "kernel");
+	printf("\n");
+	printf("   exception       = 0x%x (%s)\n", vector, trapname(vector));
+	switch (vector) {
+	case EXC_DSE:
+	case EXC_DSI:
+		printf("   virtual address = 0x%" PRIxPTR "\n",
+		    frame->cpu.aim.dar);
+		printf("   dsisr           = 0x%" PRIxPTR "\n",
+		    frame->cpu.aim.dsisr);
+		break;
+	case EXC_ISE:
+	case EXC_ISI:
+		printf("   virtual address = 0x%" PRIxPTR "\n", frame->srr0);
+		break;
+	}
+	printf("   srr0            = 0x%" PRIxPTR "\n", frame->srr0);
+	printf("   srr1            = 0x%" PRIxPTR "\n", frame->srr1);
+	printf("   lr              = 0x%" PRIxPTR "\n", frame->lr);
+	printf("   curthread       = %p\n", curthread);
+	if (curthread != NULL)
+		printf("          pid = %d, comm = %s\n",
+		    curthread->td_proc->p_pid, curthread->td_name);
+	printf("\n");
+}
+
+/*
+ * Handles a fatal fault when we have onfault state to recover.  Returns
+ * non-zero if there was onfault recovery state available.
+ */
+static int
+handle_onfault(struct trapframe *frame)
+{
+	struct		thread *td;
+	faultbuf	*fb;
+
+	td = curthread;
+	fb = td->td_pcb->pcb_onfault;
+	if (fb != NULL) {
+		frame->srr0 = (*fb)[0];
+		frame->fixreg[1] = (*fb)[1];
+		frame->fixreg[2] = (*fb)[2];
+		frame->fixreg[3] = 1;
+		frame->cr = (*fb)[3];
+		bcopy(&(*fb)[4], &frame->fixreg[13],
+		    19 * sizeof(register_t));
+		return (1);
+	}
+	return (0);
+}
+
+int
+cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+{
+	struct proc *p;
+	struct trapframe *frame;
+	caddr_t	params;
+	size_t argsz;
+	int error, n, i;
+
+	p = td->td_proc;
+	frame = td->td_frame;
+
+	sa->code = frame->fixreg[0];
+	params = (caddr_t)(frame->fixreg + FIRSTARG);
+	n = NARGREG;
+
+	if (sa->code == SYS_syscall) {
+		/*
+		 * code is first argument,
+		 * followed by actual args.
+		 */
+		sa->code = *(register_t *) params;
+		params += sizeof(register_t);
+		n -= 1;
+	} else if (sa->code == SYS___syscall) {
+		/*
+		 * Like syscall, but code is a quad,
+		 * so as to maintain quad alignment
+		 * for the rest of the args.
+		 */
+		if (SV_PROC_FLAG(p, SV_ILP32)) {
+			params += sizeof(register_t);
+			sa->code = *(register_t *) params;
+			params += sizeof(register_t);
+			n -= 2;
+		} else {
+			sa->code = *(register_t *) params;
+			params += sizeof(register_t);
+			n -= 1;
+		}
+	}
+
+ 	if (p->p_sysent->sv_mask)
+		sa->code &= p->p_sysent->sv_mask;
+	if (sa->code >= p->p_sysent->sv_size)
+		sa->callp = &p->p_sysent->sv_table[0];
+	else
+		sa->callp = &p->p_sysent->sv_table[sa->code];
+
+	sa->narg = sa->callp->sy_narg;
+
+	if (SV_PROC_FLAG(p, SV_ILP32)) {
+		argsz = sizeof(uint32_t);
+
+		for (i = 0; i < n; i++)
+			sa->args[i] = ((u_register_t *)(params))[i] &
+			    0xffffffff;
+	} else {
+		argsz = sizeof(uint64_t);
+
+		for (i = 0; i < n; i++)
+			sa->args[i] = ((u_register_t *)(params))[i];
+	}
+
+	if (sa->narg > n)
+		error = copyin(MOREARGS(frame->fixreg[1]), sa->args + n,
+			       (sa->narg - n) * argsz);
+	else
+		error = 0;
+
+#ifdef __powerpc64__
+	if (SV_PROC_FLAG(p, SV_ILP32) && sa->narg > n) {
+		/* Expand the size of arguments copied from the stack */
+
+		for (i = sa->narg; i >= n; i--)
+			sa->args[i] = ((uint32_t *)(&sa->args[n]))[i-n];
+	}
+#endif
+
+	if (error == 0) {
+		td->td_retval[0] = 0;
+		td->td_retval[1] = frame->fixreg[FIRSTARG + 1];
+	}
+	return (error);
+}
+
+#include "../../kern/subr_syscall.c"
+
+void
+syscall(struct trapframe *frame)
+{
+	struct thread *td;
+	struct syscall_args sa;
+	int error;
+
+	td = curthread;
+	td->td_frame = frame;
+
+#ifdef __powerpc64__
+	/*
+	 * Speculatively restore last user SLB segment, which we know is
+	 * invalid already, since we are likely to do copyin()/copyout().
+	 */
+	__asm __volatile ("slbmte %0, %1; isync" ::
+            "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), "r"(USER_SLB_SLBE));
+#endif
+
+	error = syscallenter(td, &sa);
+	syscallret(td, error, &sa);
+}
+
+#ifdef __powerpc64__
+/* Handle kernel SLB faults -- runs in real mode, all seat belts off */
+void
+handle_kernel_slb_spill(int type, register_t dar, register_t srr0)
+{
+	struct slb *slbcache;
+	uint64_t slbe, slbv;
+	uint64_t esid, addr;
+	int i;
+
+	addr = (type == EXC_ISE) ? srr0 : dar;
+	slbcache = PCPU_GET(slb);
+	esid = (uintptr_t)addr >> ADDR_SR_SHFT;
+	slbe = (esid << SLBE_ESID_SHIFT) | SLBE_VALID;
+	
+	/* See if the hardware flushed this somehow (can happen in LPARs) */
+	for (i = 0; i < n_slbs; i++)
+		if (slbcache[i].slbe == (slbe | (uint64_t)i))
+			return;
+
+	/* Not in the map, needs to actually be added */
+	slbv = kernel_va_to_slbv(addr);
+	if (slbcache[USER_SLB_SLOT].slbe == 0) {
+		for (i = 0; i < n_slbs; i++) {
+			if (i == USER_SLB_SLOT)
+				continue;
+			if (!(slbcache[i].slbe & SLBE_VALID))
+				goto fillkernslb;
+		}
+
+		if (i == n_slbs)
+			slbcache[USER_SLB_SLOT].slbe = 1;
+	}
+
+	/* Sacrifice a random SLB entry that is not the user entry */
+	i = mftb() % n_slbs;
+	if (i == USER_SLB_SLOT)
+		i = (i+1) % n_slbs;
+
+fillkernslb:
+	/* Write new entry */
+	slbcache[i].slbv = slbv;
+	slbcache[i].slbe = slbe | (uint64_t)i;
+
+	/* Trap handler will restore from cache on exit */
+}
+
+static int 
+handle_user_slb_spill(pmap_t pm, vm_offset_t addr)
+{
+	struct slb *user_entry;
+	uint64_t esid;
+	int i;
+
+	esid = (uintptr_t)addr >> ADDR_SR_SHFT;
+
+	PMAP_LOCK(pm);
+	user_entry = user_va_to_slb_entry(pm, addr);
+
+	if (user_entry == NULL) {
+		/* allocate_vsid auto-spills it */
+		(void)allocate_user_vsid(pm, esid, 0);
+	} else {
+		/*
+		 * Check that another CPU has not already mapped this.
+		 * XXX: Per-thread SLB caches would be better.
+		 */
+		for (i = 0; i < pm->pm_slb_len; i++)
+			if (pm->pm_slb[i] == user_entry)
+				break;
+
+		if (i == pm->pm_slb_len)
+			slb_insert_user(pm, user_entry);
+	}
+	PMAP_UNLOCK(pm);
+
+	return (0);
+}
+#endif
+
+static int
+trap_pfault(struct trapframe *frame, int user)
+{
+	vm_offset_t	eva, va;
+	struct		thread *td;
+	struct		proc *p;
+	vm_map_t	map;
+	vm_prot_t	ftype;
+	int		rv;
+	register_t	user_sr;
+
+	td = curthread;
+	p = td->td_proc;
+	if (frame->exc == EXC_ISI) {
+		eva = frame->srr0;
+		ftype = VM_PROT_EXECUTE;
+		if (frame->srr1 & SRR1_ISI_PFAULT)
+			ftype |= VM_PROT_READ;
+	} else {
+		eva = frame->cpu.aim.dar;
+		if (frame->cpu.aim.dsisr & DSISR_STORE)
+			ftype = VM_PROT_WRITE;
+		else
+			ftype = VM_PROT_READ;
+	}
+
+	if (user) {
+		map = &p->p_vmspace->vm_map;
+	} else {
+		if ((eva >> ADDR_SR_SHFT) == (USER_ADDR >> ADDR_SR_SHFT)) {
+			if (p->p_vmspace == NULL)
+				return (SIGSEGV);
+
+			map = &p->p_vmspace->vm_map;
+
+			user_sr = td->td_pcb->pcb_cpu.aim.usr_segm;
+			eva &= ADDR_PIDX | ADDR_POFF;
+			eva |= user_sr << ADDR_SR_SHFT;
+		} else {
+			map = kernel_map;
+		}
+	}
+	va = trunc_page(eva);
+
+	if (map != kernel_map) {
+		/*
+		 * Keep swapout from messing with us during this
+		 *	critical time.
+		 */
+		PROC_LOCK(p);
+		++p->p_lock;
+		PROC_UNLOCK(p);
+
+		/* Fault in the user page: */
+		rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
+
+		PROC_LOCK(p);
+		--p->p_lock;
+		PROC_UNLOCK(p);
+		/*
+		 * XXXDTRACE: add dtrace_doubletrap_func here?
+		 */
+	} else {
+		/*
+		 * Don't have to worry about process locking or stacks in the
+		 * kernel.
+		 */
+		rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
+	}
+
+	if (rv == KERN_SUCCESS)
+		return (0);
+
+	if (!user && handle_onfault(frame))
+		return (0);
+
+	return (SIGSEGV);
+}
+
+/*
+ * For now, this only deals with the particular unaligned access case
+ * that gcc tends to generate.  Eventually it should handle all of the
+ * possibilities that can happen on a 32-bit PowerPC in big-endian mode.
+ */
+
+static int
+fix_unaligned(struct thread *td, struct trapframe *frame)
+{
+	struct thread	*fputhread;
+	int		indicator, reg;
+	double		*fpr;
+
+	indicator = EXC_ALI_OPCODE_INDICATOR(frame->cpu.aim.dsisr);
+
+	switch (indicator) {
+	case EXC_ALI_LFD:
+	case EXC_ALI_STFD:
+		reg = EXC_ALI_RST(frame->cpu.aim.dsisr);
+		fpr = &td->td_pcb->pcb_fpu.fpr[reg];
+		fputhread = PCPU_GET(fputhread);
+
+		/* Juggle the FPU to ensure that we've initialized
+		 * the FPRs, and that their current state is in
+		 * the PCB.
+		 */
+		if (fputhread != td) {
+			if (fputhread)
+				save_fpu(fputhread);
+			enable_fpu(td);
+		}
+		save_fpu(td);
+
+		if (indicator == EXC_ALI_LFD) {
+			if (copyin((void *)frame->cpu.aim.dar, fpr,
+			    sizeof(double)) != 0)
+				return -1;
+			enable_fpu(td);
+		} else {
+			if (copyout(fpr, (void *)frame->cpu.aim.dar,
+			    sizeof(double)) != 0)
+				return -1;
+		}
+		return 0;
+		break;
+	}
+
+	return -1;
+}
+


Property changes on: trunk/sys/powerpc/aim/trap.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/trap_subr32.S
===================================================================
--- trunk/sys/powerpc/aim/trap_subr32.S	                        (rev 0)
+++ trunk/sys/powerpc/aim/trap_subr32.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,928 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/aim/trap_subr32.S 266532 2014-05-22 05:20:21Z jhibbits $ */
+/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink 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.
+ */
+
+/*
+ * NOTICE: This is not a standalone file.  to use it, #include it in
+ * your port's locore.S, like so:
+ *
+ *	#include <powerpc/aim/trap_subr.S>
+ */
+
+/*
+ * Save/restore segment registers
+ */
+#define RESTORE_SRS(pmap,sr)	mtsr    0,sr; \
+	lwz	sr,1*4(pmap);	mtsr	1,sr; \
+	lwz	sr,2*4(pmap);	mtsr	2,sr; \
+	lwz	sr,3*4(pmap);	mtsr	3,sr; \
+	lwz	sr,4*4(pmap);	mtsr	4,sr; \
+	lwz	sr,5*4(pmap);	mtsr	5,sr; \
+	lwz	sr,6*4(pmap);	mtsr	6,sr; \
+	lwz	sr,7*4(pmap);	mtsr	7,sr; \
+	lwz	sr,8*4(pmap);	mtsr	8,sr; \
+	lwz	sr,9*4(pmap);	mtsr	9,sr; \
+	lwz	sr,10*4(pmap);	mtsr	10,sr; \
+	lwz	sr,11*4(pmap);	mtsr	11,sr; \
+	/* Skip segment 12 (USER_SR), which is restored differently */ \
+	lwz	sr,13*4(pmap);	mtsr	13,sr; \
+	lwz	sr,14*4(pmap);	mtsr	14,sr; \
+	lwz	sr,15*4(pmap);	mtsr	15,sr; isync;
+
+/*
+ * User SRs are loaded through a pointer to the current pmap.
+ */
+#define RESTORE_USER_SRS(pmap,sr) \
+	GET_CPUINFO(pmap); \
+	lwz	pmap,PC_CURPMAP(pmap); \
+	lwzu	sr,PM_SR(pmap); \
+	RESTORE_SRS(pmap,sr) \
+	/* Restore SR 12 */ \
+	lwz	sr,12*4(pmap);	mtsr	12,sr
+
+/*
+ * Kernel SRs are loaded directly from kernel_pmap_
+ */
+#define RESTORE_KERN_SRS(pmap,sr) \
+	lis	pmap,CNAME(kernel_pmap_store)@ha; \
+	lwzu	sr,CNAME(kernel_pmap_store)+PM_SR at l(pmap); \
+	RESTORE_SRS(pmap,sr)
+
+/*
+ * FRAME_SETUP assumes:
+ *	SPRG1		SP (1)
+ * 	SPRG3		trap type
+ *	savearea	r28-r31,DAR,DSISR   (DAR & DSISR only for DSI traps)
+ *	r28		LR
+ *	r29		CR
+ *	r30		scratch
+ *	r31		scratch
+ *	r1		kernel stack
+ *	SRR0/1		as at start of trap
+ */
+#define	FRAME_SETUP(savearea)						\
+/* Have to enable translation to allow access of kernel stack: */	\
+	GET_CPUINFO(%r31);						\
+	mfsrr0	%r30;							\
+	stw	%r30,(savearea+CPUSAVE_SRR0)(%r31);	/* save SRR0 */	\
+	mfsrr1	%r30;							\
+	stw	%r30,(savearea+CPUSAVE_SRR1)(%r31);	/* save SRR1 */	\
+	mfmsr	%r30;							\
+	ori	%r30,%r30,(PSL_DR|PSL_IR|PSL_RI)@l; /* relocation on */	\
+	mtmsr	%r30;			/* stack can now be accessed */	\
+	isync;								\
+	mfsprg1	%r31;			/* get saved SP */		\
+	stwu	%r31,-FRAMELEN(%r1);	/* save it in the callframe */	\
+	stw	%r0, FRAME_0+8(%r1);	/* save r0 in the trapframe */	\
+	stw	%r31,FRAME_1+8(%r1);	/* save SP   "      "       */	\
+	stw	%r2, FRAME_2+8(%r1);	/* save r2   "      "       */	\
+	stw	%r28,FRAME_LR+8(%r1);	/* save LR   "      "       */	\
+	stw	%r29,FRAME_CR+8(%r1);	/* save CR   "      "       */	\
+	GET_CPUINFO(%r2);						\
+	lwz	%r28,(savearea+CPUSAVE_R28)(%r2); /* get saved r28 */	\
+	lwz	%r29,(savearea+CPUSAVE_R29)(%r2); /* get saved r29 */	\
+	lwz	%r30,(savearea+CPUSAVE_R30)(%r2); /* get saved r30 */	\
+	lwz	%r31,(savearea+CPUSAVE_R31)(%r2); /* get saved r31 */	\
+	stw	%r3,  FRAME_3+8(%r1);	/* save r3-r31 */		\
+	stw	%r4,  FRAME_4+8(%r1);					\
+	stw	%r5,  FRAME_5+8(%r1);					\
+	stw	%r6,  FRAME_6+8(%r1);					\
+	stw	%r7,  FRAME_7+8(%r1);					\
+	stw	%r8,  FRAME_8+8(%r1);					\
+	stw	%r9,  FRAME_9+8(%r1);					\
+	stw	%r10, FRAME_10+8(%r1);					\
+	stw	%r11, FRAME_11+8(%r1);					\
+	stw	%r12, FRAME_12+8(%r1);					\
+	stw	%r13, FRAME_13+8(%r1);					\
+	stw	%r14, FRAME_14+8(%r1);					\
+	stw	%r15, FRAME_15+8(%r1);					\
+	stw	%r16, FRAME_16+8(%r1);					\
+	stw	%r17, FRAME_17+8(%r1);					\
+	stw	%r18, FRAME_18+8(%r1);					\
+	stw	%r19, FRAME_19+8(%r1);					\
+	stw	%r20, FRAME_20+8(%r1);					\
+	stw	%r21, FRAME_21+8(%r1);					\
+	stw	%r22, FRAME_22+8(%r1);					\
+	stw	%r23, FRAME_23+8(%r1);					\
+	stw	%r24, FRAME_24+8(%r1);					\
+	stw	%r25, FRAME_25+8(%r1);					\
+	stw	%r26, FRAME_26+8(%r1);					\
+	stw	%r27, FRAME_27+8(%r1);					\
+	stw	%r28, FRAME_28+8(%r1);					\
+	stw	%r29, FRAME_29+8(%r1);					\
+	stw	%r30, FRAME_30+8(%r1);					\
+	stw	%r31, FRAME_31+8(%r1);					\
+	lwz	%r28,(savearea+CPUSAVE_AIM_DAR)(%r2);  /* saved DAR */	\
+	lwz	%r29,(savearea+CPUSAVE_AIM_DSISR)(%r2);/* saved DSISR */\
+	lwz	%r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */	\
+	lwz	%r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */	\
+	mfxer	%r3;							\
+	mfctr	%r4;							\
+	mfsprg3	%r5;							\
+	stw	%r3, FRAME_XER+8(1);	/* save xer/ctr/exc */		\
+	stw	%r4, FRAME_CTR+8(1);					\
+	stw	%r5, FRAME_EXC+8(1);					\
+	stw	%r28,FRAME_AIM_DAR+8(1);				\
+	stw	%r29,FRAME_AIM_DSISR+8(1); /* save dsisr/srr0/srr1 */	\
+	stw	%r30,FRAME_SRR0+8(1);					\
+	stw	%r31,FRAME_SRR1+8(1);					\
+	lwz	%r2,PC_CURTHREAD(%r2)	/* set curthread pointer */
+
+#define	FRAME_LEAVE(savearea)						\
+/* Disable exceptions: */						\
+	mfmsr	%r2;							\
+	andi.	%r2,%r2,~PSL_EE at l;					\
+	mtmsr	%r2;							\
+	isync;								\
+/* Now restore regs: */							\
+	lwz	%r2,FRAME_SRR0+8(%r1);					\
+	lwz	%r3,FRAME_SRR1+8(%r1);					\
+	lwz	%r4,FRAME_CTR+8(%r1);					\
+	lwz	%r5,FRAME_XER+8(%r1);					\
+	lwz	%r6,FRAME_LR+8(%r1);					\
+	GET_CPUINFO(%r7);						\
+	stw	%r2,(savearea+CPUSAVE_SRR0)(%r7); /* save SRR0 */	\
+	stw	%r3,(savearea+CPUSAVE_SRR1)(%r7); /* save SRR1 */	\
+	lwz	%r7,FRAME_CR+8(%r1);					\
+	mtctr	%r4;							\
+	mtxer	%r5;							\
+	mtlr	%r6;							\
+	mtsprg1	%r7;			/* save cr */			\
+	lwz	%r31,FRAME_31+8(%r1);   /* restore r0-31 */		\
+	lwz	%r30,FRAME_30+8(%r1);					\
+	lwz	%r29,FRAME_29+8(%r1);					\
+	lwz	%r28,FRAME_28+8(%r1);					\
+	lwz	%r27,FRAME_27+8(%r1);					\
+	lwz	%r26,FRAME_26+8(%r1);					\
+	lwz	%r25,FRAME_25+8(%r1);					\
+	lwz	%r24,FRAME_24+8(%r1);					\
+	lwz	%r23,FRAME_23+8(%r1);					\
+	lwz	%r22,FRAME_22+8(%r1);					\
+	lwz	%r21,FRAME_21+8(%r1);					\
+	lwz	%r20,FRAME_20+8(%r1);					\
+	lwz	%r19,FRAME_19+8(%r1);					\
+	lwz	%r18,FRAME_18+8(%r1);					\
+	lwz	%r17,FRAME_17+8(%r1);					\
+	lwz	%r16,FRAME_16+8(%r1);					\
+	lwz	%r15,FRAME_15+8(%r1);					\
+	lwz	%r14,FRAME_14+8(%r1);					\
+	lwz	%r13,FRAME_13+8(%r1);					\
+	lwz	%r12,FRAME_12+8(%r1);					\
+	lwz	%r11,FRAME_11+8(%r1);					\
+	lwz	%r10,FRAME_10+8(%r1);					\
+	lwz	%r9, FRAME_9+8(%r1);					\
+	lwz	%r8, FRAME_8+8(%r1);					\
+	lwz	%r7, FRAME_7+8(%r1);					\
+	lwz	%r6, FRAME_6+8(%r1);					\
+	lwz	%r5, FRAME_5+8(%r1);					\
+	lwz	%r4, FRAME_4+8(%r1);					\
+	lwz	%r3, FRAME_3+8(%r1);					\
+	lwz	%r2, FRAME_2+8(%r1);					\
+	lwz	%r0, FRAME_0+8(%r1);					\
+	lwz	%r1, FRAME_1+8(%r1);					\
+/* Can't touch %r1 from here on */					\
+	mtsprg2	%r2;			/* save r2 & r3 */		\
+	mtsprg3	%r3;							\
+/* Disable translation, machine check and recoverability: */		\
+	mfmsr	%r2;							\
+	andi.	%r2,%r2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l;	\
+	mtmsr	%r2;							\
+	isync;								\
+/* Decide whether we return to user mode: */				\
+	GET_CPUINFO(%r2);						\
+	lwz	%r3,(savearea+CPUSAVE_SRR1)(%r2);			\
+	mtcr	%r3;							\
+	bf	17,1f;			/* branch if PSL_PR is false */	\
+/* Restore user SRs */							\
+	RESTORE_USER_SRS(%r2,%r3);					\
+1:	mfsprg1	%r2;			/* restore cr */		\
+	mtcr	%r2;							\
+	GET_CPUINFO(%r2);						\
+	lwz	%r3,(savearea+CPUSAVE_SRR0)(%r2); /* restore srr0 */	\
+	mtsrr0	%r3;							\
+	lwz	%r3,(savearea+CPUSAVE_SRR1)(%r2); /* restore srr1 */	\
+									\
+	/* Make sure HV bit of MSR propagated to SRR1 */		\
+	mfmsr	%r2;							\
+	or	%r3,%r2,%r3;						\
+									\
+	mtsrr1	%r3;							\
+	mfsprg2	%r2;			/* restore r2 & r3 */		\
+	mfsprg3	%r3
+
+#ifdef KDTRACE_HOOKS
+	.data
+	.globl	dtrace_invop_calltrap_addr
+	.align	4
+	.type	dtrace_invop_calltrap_addr, @object
+        .size	dtrace_invop_calltrap_addr, 4
+dtrace_invop_calltrap_addr:
+	.word	0
+	.word	0
+
+	.text
+#endif
+
+/*
+ * The next two routines are 64-bit glue code. The first is used to test if
+ * we are on a 64-bit system. By copying it to the illegal instruction
+ * handler, we can test for 64-bit mode by trying to execute a 64-bit
+ * instruction and seeing what happens. The second gets copied in front
+ * of all the other handlers to restore 32-bit bridge mode when traps
+ * are taken.
+ */
+
+/* 64-bit test code. Sets SPRG2 to 0 if an illegal instruction is executed */
+
+	.globl	CNAME(testppc64),CNAME(testppc64size)
+CNAME(testppc64):
+	mtsprg1 %r31
+	mfsrr0  %r31
+	addi	%r31, %r31, 4
+	mtsrr0  %r31
+
+	li	%r31, 0
+	mtsprg2 %r31
+	mfsprg1 %r31
+
+	rfi
+CNAME(testppc64size) = .-CNAME(testppc64)
+
+
+/* 64-bit bridge mode restore snippet. Gets copied in front of everything else
+ * on 64-bit systems. */
+
+	.globl	CNAME(restorebridge),CNAME(restorebridgesize)
+CNAME(restorebridge):
+	mtsprg1	%r31
+	mfmsr	%r31
+	clrldi	%r31,%r31,1
+	mtmsrd	%r31
+	mfsprg1	%r31
+	isync
+CNAME(restorebridgesize) = .-CNAME(restorebridge)
+
+/*
+ * Processor reset exception handler. These are typically
+ * the first instructions the processor executes after a
+ * software reset. We do this in two bits so that we are
+ * not still hanging around in the trap handling region
+ * once the MMU is turned on.
+ */
+	.globl	CNAME(rstcode), CNAME(rstsize)
+CNAME(rstcode):
+	ba	cpu_reset
+CNAME(rstsize) = . - CNAME(rstcode)
+
+cpu_reset:
+	bl	1f
+
+	.space	124
+
+1:
+	mflr	%r1
+	addi	%r1,%r1,(124-16)@l
+
+	lis	%r3,1 at l
+	bla	CNAME(cpudep_ap_early_bootstrap)
+	lis	%r3,1 at l
+	bla	CNAME(pmap_cpu_bootstrap)
+	bla	CNAME(cpudep_ap_bootstrap)
+	mr	%r1,%r3
+	bla	CNAME(cpudep_ap_setup)
+	GET_CPUINFO(%r5)
+	lwz	%r3,(PC_RESTORE)(%r5)
+	cmplwi	%cr0,%r3,0
+	beq	%cr0,2f
+	li	%r4, 1
+	b	CNAME(longjmp)
+2:
+#ifdef SMP
+	bla	CNAME(machdep_ap_bootstrap)
+#endif
+
+	/* Should not be reached */
+9:
+	b	9b
+
+/*
+ * This code gets copied to all the trap vectors
+ * (except ISI/DSI, ALI, and the interrupts)
+ */
+
+	.globl	CNAME(trapcode),CNAME(trapsize)
+CNAME(trapcode):
+	mtsprg1	%r1			/* save SP */
+	mflr	%r1			/* Save the old LR in r1 */
+	mtsprg2 %r1			/* And then in SPRG2 */
+	li	%r1, 0x20		/* How to get the vector from LR */
+	bla	generictrap		/* LR & SPRG3 is exception # */
+CNAME(trapsize) = .-CNAME(trapcode)
+
+/*
+ * 64-bit version of trapcode. Identical, except it calls generictrap64.
+ */
+	.globl	CNAME(trapcode64)
+CNAME(trapcode64):
+	mtsprg1	%r1			/* save SP */
+	mflr	%r1			/* Save the old LR in r1 */
+	mtsprg2 %r1			/* And then in SPRG2 */
+	li	%r1, 0x20		/* How to get the vector from LR */
+	bla	generictrap64		/* LR & SPRG3 is exception # */
+
+/*
+ * For ALI: has to save DSISR and DAR
+ */
+	.globl	CNAME(alitrap),CNAME(alisize)
+CNAME(alitrap):
+	mtsprg1	%r1			/* save SP */
+	GET_CPUINFO(%r1)
+	stw	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)	/* free r28-r31 */
+	stw	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
+	stw	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
+	stw	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
+	mfdar	%r30
+	mfdsisr	%r31
+	stw	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
+	stw	%r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
+	mfsprg1	%r1			/* restore SP, in case of branch */
+	mflr	%r28			/* save LR */
+	mfcr	%r29			/* save CR */
+
+	/* Put our exception vector in SPRG3 */
+	li	%r31, EXC_ALI
+	mtsprg3	%r31
+
+	/* Test whether we already had PR set */
+	mfsrr1	%r31
+	mtcr	%r31
+	bla	s_trap
+CNAME(alisize) = .-CNAME(alitrap)
+
+/*
+ * G2 specific: instuction TLB miss.
+ */
+	.globl	CNAME(imisstrap),CNAME(imisssize)
+CNAME(imisstrap):
+	mfspr %r2, SPR_HASH1		/* get first pointer */
+	addi %r1, 0, 8			/* load 8 for counter */
+	mfctr %r0			/* save counter */
+	mfspr %r3, SPR_ICMP		/* get first compare value */
+	addi %r2, %r2, -8		/* pre dec the pointer */
+im0:
+	mtctr %r1			/* load counter */
+im1:
+	lwzu %r1, 8(%r2)		/* get next pte */
+	cmp 0, %r1, %r3			/* see if found pte */
+	bdnzf 2, im1			/* dec count br if cmp ne and if
+					 * count not zero */
+	bne instr_sec_hash		/* if not found set up second hash
+					 * or exit */
+	lwz %r1, +4(%r2)		/* load tlb entry lower-word */
+	andi. %r3, %r1, 8		/* check G bit */
+	bne do_isi_prot			/* if guarded, take an ISI */
+	mtctr %r0			/* restore counter */
+	mfspr %r0, SPR_IMISS		/* get the miss address for the tlbli */
+	mfspr %r3, SPR_SRR1		/* get the saved cr0 bits */
+	mtcrf 0x80, %r3			/* restore CR0 */
+	mtspr SPR_RPA, %r1		/* set the pte */
+	ori %r1, %r1, 0x100		/* set reference bit */
+	srwi %r1, %r1, 8		/* get byte 7 of pte */
+	tlbli %r0 			/* load the itlb */
+	stb %r1, +6(%r2)		/* update page table */
+	rfi				/* return to executing program */
+
+instr_sec_hash:
+	andi. %r1, %r3, 0x0040		/* see if we have done second hash */
+	bne do_isi			/* if so, go to ISI interrupt */
+	mfspr %r2, SPR_HASH2		/* get the second pointer */
+	ori %r3, %r3, 0x0040		/* change the compare value */
+	addi %r1, %r0, 8		/* load 8 for counter */
+	addi %r2, %r2, -8		/* pre dec for update on load */
+	b im0				/* try second hash */
+
+/* Create a faked ISI interrupt as the address was not found */ 
+do_isi_prot:
+	mfspr %r3, SPR_SRR1		/* get srr1 */
+	andi. %r2, %r3, 0xffff		/* clean upper srr1 */
+	addis %r2, %r2, 0x0800		/* or in srr<4> = 1 to flag prot
+					 * violation */
+	b isi1
+do_isi:
+	mfspr %r3, SPR_SRR1		/* get srr1 */
+	andi. %r2, %r3, 0xffff		/* clean srr1 */
+	addis %r2, %r2, 0x4000		/* or in srr1<1> = 1 to flag pte
+					 * not found */
+isi1: 
+	mtctr %r0			/* restore counter */
+	mtspr SPR_SRR1, %r2		/* set srr1 */
+	mfmsr %r0			/* get msr */
+	xoris %r0, %r0, 0x2		/* flip the msr<tgpr> bit */
+	mtcrf 0x80, %r3			/* restore CR0 */
+	mtmsr %r0			/* flip back to the native gprs */
+	ba EXC_ISI			/* go to instr. access interrupt */
+
+CNAME(imisssize) = .-CNAME(imisstrap)
+
+/*
+ * G2 specific: data load TLB miss.
+ */
+	.globl	CNAME(dlmisstrap),CNAME(dlmisssize)
+CNAME(dlmisstrap):
+	mfspr %r2, SPR_HASH1		/* get first pointer */
+	addi %r1, 0, 8			/* load 8 for counter */
+	mfctr %r0			/* save counter */
+	mfspr %r3, SPR_DCMP		/* get first compare value */
+	addi %r2, %r2, -8		/* pre dec the pointer */
+dm0: 
+	mtctr %r1			/* load counter */
+dm1:	
+	lwzu %r1, 8(%r2)		/* get next pte */
+	cmp 0, 0, %r1, %r3		/* see if found pte */
+	bdnzf 2, dm1			/* dec count br if cmp ne and if
+					 * count not zero */
+	bne data_sec_hash		/* if not found set up second hash
+					 * or exit */
+	lwz %r1, +4(%r2)		/* load tlb entry lower-word */
+	mtctr %r0			/* restore counter */
+	mfspr %r0, SPR_DMISS		/* get the miss address for the tlbld */
+	mfspr %r3, SPR_SRR1		/* get the saved cr0 bits */
+	mtcrf 0x80, %r3			/* restore CR0 */
+	mtspr SPR_RPA, %r1		/* set the pte */
+	ori %r1, %r1, 0x100		/* set reference bit */
+	srwi %r1, %r1, 8		/* get byte 7 of pte */
+	tlbld %r0			/* load the dtlb */
+	stb %r1, +6(%r2)		/* update page table */
+	rfi				/* return to executing program */
+ 
+data_sec_hash:
+	andi. %r1, %r3, 0x0040		/* see if we have done second hash */
+	bne do_dsi			/* if so, go to DSI interrupt */
+	mfspr %r2, SPR_HASH2		/* get the second pointer */
+	ori %r3, %r3, 0x0040		/* change the compare value */
+	addi %r1, 0, 8			/* load 8 for counter */
+	addi %r2, %r2, -8		/* pre dec for update on load */
+	b dm0				/* try second hash */
+
+CNAME(dlmisssize) = .-CNAME(dlmisstrap)
+
+/*
+ *  G2 specific: data store TLB miss.
+ */
+	.globl	CNAME(dsmisstrap),CNAME(dsmisssize)
+CNAME(dsmisstrap):
+	mfspr %r2, SPR_HASH1		/* get first pointer */
+	addi %r1, 0, 8			/* load 8 for counter */
+	mfctr %r0			/* save counter */
+	mfspr %r3, SPR_DCMP		/* get first compare value */
+	addi %r2, %r2, -8		/* pre dec the pointer */
+ds0:
+	mtctr %r1			/* load counter */
+ds1:
+	lwzu %r1, 8(%r2)		/* get next pte */
+	cmp 0, 0, %r1, %r3		/* see if found pte */
+	bdnzf 2, ds1			/* dec count br if cmp ne and if
+					 * count not zero */
+	bne data_store_sec_hash		/* if not found set up second hash
+					 * or exit */
+	lwz %r1, +4(%r2)		/* load tlb entry lower-word */
+	andi. %r3, %r1, 0x80		/* check the C-bit */
+	beq data_store_chk_prot		/* if (C==0)
+					 *     go check protection modes */
+ds2:
+	mtctr %r0			/* restore counter */
+	mfspr %r0, SPR_DMISS		/* get the miss address for the tlbld */
+	mfspr %r3, SPR_SRR1		/* get the saved cr0 bits */
+	mtcrf 0x80, %r3			/* restore CR0 */
+	mtspr SPR_RPA, %r1		/* set the pte */
+	tlbld %r0			/* load the dtlb */
+	rfi				/* return to executing program */
+
+data_store_sec_hash:
+	andi. %r1, %r3, 0x0040		/* see if we have done second hash */
+	bne do_dsi			/* if so, go to DSI interrupt */
+	mfspr %r2, SPR_HASH2		/* get the second pointer */
+	ori %r3, %r3, 0x0040		/* change the compare value */
+	addi %r1, 0, 8			/* load 8 for counter */
+	addi %r2, %r2, -8		/* pre dec for update on load */
+	b ds0				/* try second hash */
+	
+/* Check the protection before setting PTE(c-bit) */
+data_store_chk_prot:
+	rlwinm. %r3,%r1,30,0,1		/* test PP */
+	bge- chk0			/* if (PP == 00 or PP == 01)
+					 *     goto chk0: */
+	andi. %r3, %r1, 1		/* test PP[0] */
+	beq+ chk2			/* return if PP[0] == 0 */
+	b do_dsi_prot			/* else DSIp */
+chk0:
+	mfspr %r3,SPR_SRR1		/* get old msr */
+	andis. %r3,%r3,0x0008		/* test the KEY bit (SRR1-bit 12) */
+	beq chk2			/* if (KEY==0) goto chk2: */
+	b do_dsi_prot			/* else do_dsi_prot */
+chk2:
+	ori %r1, %r1, 0x180		/* set reference and change bit */
+	sth %r1, 6(%r2)			/* update page table */
+	b ds2				/* and back we go */
+	
+/* Create a faked DSI interrupt as the address was not found */ 
+do_dsi:
+	mfspr %r3, SPR_SRR1		/* get srr1 */
+	rlwinm %r1,%r3,9,6,6		/* get srr1<flag> to bit 6 for
+					 * load/store, zero rest */
+	addis %r1, %r1, 0x4000		/* or in dsisr<1> = 1 to flag pte
+					 * not found */
+	b dsi1
+
+do_dsi_prot:
+	mfspr %r3, SPR_SRR1		/* get srr1 */
+	rlwinm %r1,%r3,9,6,6		/* get srr1<flag> to bit 6 for
+					   *load/store, zero rest */
+	addis %r1, %r1, 0x0800		/* or in dsisr<4> = 1 to flag prot
+					 * violation */
+
+dsi1:
+	mtctr %r0			/* restore counter */
+	andi. %r2, %r3, 0xffff		/* clear upper bits of srr1 */
+	mtspr SPR_SRR1, %r2		/* set srr1 */
+	mtspr SPR_DSISR, %r1		/* load the dsisr */
+	mfspr %r1, SPR_DMISS		/* get miss address */
+	rlwinm. %r2,%r2,0,31,31		/* test LE bit */
+	beq dsi2			/* if little endian then: */
+	xor %r1, %r1, 0x07		/* de-mung the data address */
+dsi2:
+	mtspr SPR_DAR, %r1		/* put in dar */
+	mfmsr %r0			/* get msr */
+	xoris %r0, %r0, 0x2		/* flip the msr<tgpr> bit */
+	mtcrf 0x80, %r3			/* restore CR0 */
+	mtmsr %r0			/* flip back to the native gprs */
+	ba EXC_DSI			/* branch to DSI interrupt */
+
+CNAME(dsmisssize) = .-CNAME(dsmisstrap)
+
+/*
+ * Similar to the above for DSI
+ * Has to handle BAT spills
+ * and standard pagetable spills
+ */
+	.globl	CNAME(dsitrap),CNAME(dsisize)
+CNAME(dsitrap):
+	mtsprg1	%r1			/* save SP */
+	GET_CPUINFO(%r1)
+	stw	%r28,(PC_DISISAVE+CPUSAVE_R28)(%r1)	/* free r28-r31 */
+	stw	%r29,(PC_DISISAVE+CPUSAVE_R29)(%r1)
+	stw	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
+	stw	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
+	mfsprg1	%r1			/* restore SP */
+	mfcr	%r29			/* save CR */
+	mfxer	%r30			/* save XER */
+	mtsprg2	%r30			/* in SPRG2 */
+	mfsrr1	%r31			/* test kernel mode */
+	mtcr	%r31
+	bt	17,1f			/* branch if PSL_PR is set */
+	mfdar	%r31			/* get fault address */
+	rlwinm	%r31,%r31,7,25,28	/* get segment * 8 */
+
+	/* get batu */
+	addis	%r31,%r31,CNAME(battable)@ha
+	lwz	%r30,CNAME(battable)@l(31)
+	mtcr	%r30
+	bf	30,1f			/* branch if supervisor valid is
+					   false */
+	/* get batl */
+	lwz	%r31,CNAME(battable)+4 at l(31)
+/* We randomly use the highest two bat registers here */
+	mftb	%r28
+	andi.	%r28,%r28,1
+	bne	2f
+	mtdbatu	2,%r30
+	mtdbatl	2,%r31
+	b	3f
+2:
+	mtdbatu	3,%r30
+	mtdbatl	3,%r31
+3:
+	mfsprg2	%r30			/* restore XER */
+	mtxer	%r30
+	mtcr	%r29			/* restore CR */
+	mtsprg1	%r1
+	GET_CPUINFO(%r1)
+	lwz	%r28,(PC_DISISAVE+CPUSAVE_R28)(%r1)	/* restore r28-r31 */
+	lwz	%r29,(PC_DISISAVE+CPUSAVE_R29)(%r1)
+	lwz	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
+	lwz	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
+	mfsprg1	%r1
+	rfi				/* return to trapped code */
+1:
+	mflr	%r28			/* save LR (SP already saved) */
+	bla	disitrap
+CNAME(dsisize) = .-CNAME(dsitrap)
+
+/*
+ * Preamble code for DSI/ISI traps
+ */
+disitrap:
+	/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
+	mflr	%r1
+	andi.	%r1,%r1,0xff00
+	mtsprg3	%r1
+	
+	GET_CPUINFO(%r1)
+	lwz	%r30,(PC_DISISAVE+CPUSAVE_R28)(%r1)
+	stw	%r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
+	lwz	%r31,(PC_DISISAVE+CPUSAVE_R29)(%r1)
+	stw	%r31,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
+	lwz	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
+	stw	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
+	lwz	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
+	stw	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
+	mfdar	%r30
+	mfdsisr	%r31
+	stw	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
+	stw	%r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
+
+#ifdef KDB
+	/* Try to detect a kernel stack overflow */
+	mfsrr1	%r31
+	mtcr	%r31
+	bt	17,realtrap		/* branch is user mode */
+	mfsprg1	%r31			/* get old SP */
+	clrrwi	%r31,%r31,12		/* Round SP down to nearest page */
+	sub.	%r30,%r31,%r30		/* SP - DAR */
+	bge	1f
+	neg	%r30,%r30		/* modulo value */
+1:	cmplwi	%cr0,%r30,4096		/* is DAR within a page of SP? */
+	bge	%cr0,realtrap		/* no, too far away. */
+
+	/* Now convert this DSI into a DDB trap.  */
+	GET_CPUINFO(%r1)
+	lwz	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) /* get DAR */
+	stw	%r30,(PC_DBSAVE  +CPUSAVE_AIM_DAR)(%r1) /* save DAR */
+	lwz	%r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) /* get DSISR */
+	stw	%r31,(PC_DBSAVE  +CPUSAVE_AIM_DSISR)(%r1) /* save DSISR */
+	lwz	%r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* get  r28 */
+	stw	%r30,(PC_DBSAVE  +CPUSAVE_R28)(%r1) /* save r28 */
+	lwz	%r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) /* get  r29 */
+	stw	%r31,(PC_DBSAVE  +CPUSAVE_R29)(%r1) /* save r29 */
+	lwz	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) /* get  r30 */
+	stw	%r30,(PC_DBSAVE  +CPUSAVE_R30)(%r1) /* save r30 */
+	lwz	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get  r31 */
+	stw	%r31,(PC_DBSAVE  +CPUSAVE_R31)(%r1) /* save r31 */
+	b	dbtrap
+#endif
+
+	/* XXX need stack probe here */
+realtrap:
+/* Test whether we already had PR set */
+	mfsrr1	%r1
+	mtcr	%r1
+	mfsprg1	%r1			/* restore SP (might have been
+					   overwritten) */
+	bf	17,k_trap		/* branch if PSL_PR is false */
+	GET_CPUINFO(%r1)
+	lwz	%r1,PC_CURPCB(%r1)
+	RESTORE_KERN_SRS(%r30,%r31)	/* enable kernel mapping */
+	ba s_trap
+
+/*
+ * generictrap does some standard setup for trap handling to minimize
+ * the code that need be installed in the actual vectors. It expects
+ * the following conditions.
+ * 
+ * R1 - Trap vector = LR & (0xff00 | R1)
+ * SPRG1 - Original R1 contents
+ * SPRG2 - Original LR
+ */
+
+generictrap64:
+	mtsprg3	%r31
+	mfmsr	%r31
+	clrldi	%r31,%r31,1
+	mtmsrd	%r31
+	mfsprg3	%r31
+	isync
+
+generictrap:
+	/* Save R1 for computing the exception vector */
+	mtsprg3 %r1
+
+	/* Save interesting registers */
+	GET_CPUINFO(%r1)
+	stw	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)	/* free r28-r31 */
+	stw	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
+	stw	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
+	stw	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
+	mfsprg1	%r1			/* restore SP, in case of branch */
+	mfsprg2	%r28			/* save LR */
+	mfcr	%r29			/* save CR */
+
+	/* Compute the exception vector from the link register */
+	mfsprg3 %r31
+	ori	%r31,%r31,0xff00
+	mflr	%r30
+	and	%r30,%r30,%r31
+	mtsprg3	%r30
+
+	/* Test whether we already had PR set */
+	mfsrr1	%r31
+	mtcr	%r31
+
+s_trap:
+	bf	17,k_trap		/* branch if PSL_PR is false */
+	GET_CPUINFO(%r1)
+u_trap:
+	lwz	%r1,PC_CURPCB(%r1)
+	RESTORE_KERN_SRS(%r30,%r31)	/* enable kernel mapping */
+
+/*
+ * Now the common trap catching code.
+ */
+k_trap:
+	FRAME_SETUP(PC_TEMPSAVE)
+	/* Restore USER_SR */
+	GET_CPUINFO(%r30)
+	lwz	%r30,PC_CURPCB(%r30)
+	lwz	%r30,PCB_AIM_USR_VSID(%r30)
+	mtsr	USER_SR,%r30; sync; isync
+/* Call C interrupt dispatcher: */
+trapagain:
+	addi	%r3,%r1,8
+	bl	CNAME(powerpc_interrupt)
+	.globl	CNAME(trapexit)		/* backtrace code sentinel */
+CNAME(trapexit):
+
+/* Disable interrupts: */
+	mfmsr	%r3
+	andi.	%r3,%r3,~PSL_EE at l
+	mtmsr	%r3
+/* Test AST pending: */
+	lwz	%r5,FRAME_SRR1+8(%r1)
+	mtcr	%r5
+	bf	17,1f			/* branch if PSL_PR is false */
+
+	GET_CPUINFO(%r3)		/* get per-CPU pointer */
+	lwz	%r4, TD_FLAGS(%r2)	/* get thread flags value
+					 * (r2 is curthread) */
+	lis	%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h
+	ori	%r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l
+	and.	%r4,%r4,%r5
+	beq	1f
+	mfmsr	%r3			/* re-enable interrupts */
+	ori	%r3,%r3,PSL_EE at l
+	mtmsr	%r3
+	isync
+	addi	%r3,%r1,8
+	bl	CNAME(ast)
+	.globl	CNAME(asttrapexit)	/* backtrace code sentinel #2 */
+CNAME(asttrapexit):
+	b	trapexit		/* test ast ret value ? */
+1:
+	FRAME_LEAVE(PC_TEMPSAVE)
+
+	.globl	CNAME(rfi_patch1)	/* replace rfi with rfid on ppc64 */
+CNAME(rfi_patch1):
+	rfi
+
+	.globl	CNAME(rfid_patch)
+CNAME(rfid_patch):
+	rfid
+
+#if defined(KDB)
+/*
+ * Deliberate entry to dbtrap
+ */
+	.globl	CNAME(breakpoint)
+CNAME(breakpoint):
+	mtsprg1	%r1
+	mfmsr	%r3
+	mtsrr1	%r3
+	andi.	%r3,%r3,~(PSL_EE|PSL_ME)@l
+	mtmsr	%r3			/* disable interrupts */
+	isync
+	GET_CPUINFO(%r3)
+	stw	%r28,(PC_DBSAVE+CPUSAVE_R28)(%r3)
+	stw	%r29,(PC_DBSAVE+CPUSAVE_R29)(%r3)
+	stw	%r30,(PC_DBSAVE+CPUSAVE_R30)(%r3)
+	stw	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r3)
+	mflr	%r28
+	li	%r29,EXC_BPT
+	mtlr	%r29
+	mfcr	%r29
+	mtsrr0	%r28
+
+/*
+ * Now the kdb trap catching code.
+ */
+dbtrap:
+	/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
+	mflr	%r1
+	andi.	%r1,%r1,0xff00
+	mtsprg3	%r1
+
+	lis	%r1,(tmpstk+TMPSTKSZ-16)@ha	/* get new SP */
+	addi	%r1,%r1,(tmpstk+TMPSTKSZ-16)@l
+
+	FRAME_SETUP(PC_DBSAVE)
+/* Call C trap code: */
+	addi	%r3,%r1,8
+	bl	CNAME(db_trap_glue)
+	or.	%r3,%r3,%r3
+	bne	dbleave
+/* This wasn't for KDB, so switch to real trap: */
+	lwz	%r3,FRAME_EXC+8(%r1)	/* save exception */
+	GET_CPUINFO(%r4)
+	stw	%r3,(PC_DBSAVE+CPUSAVE_R31)(%r4)
+	FRAME_LEAVE(PC_DBSAVE)
+	mtsprg1	%r1			/* prepare for entrance to realtrap */
+	GET_CPUINFO(%r1)
+	stw	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
+	stw	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
+	stw	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
+	stw	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
+	mflr	%r28
+	mfcr	%r29
+	lwz	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)
+	mtsprg3	%r31			/* SPRG3 was clobbered by FRAME_LEAVE */
+	mfsprg1	%r1
+	b	realtrap
+dbleave:
+	FRAME_LEAVE(PC_DBSAVE)
+	.globl	CNAME(rfi_patch2)	/* replace rfi with rfid on ppc64 */
+CNAME(rfi_patch2):
+	rfi
+
+/*
+ * In case of KDB we want a separate trap catcher for it
+ */
+	.globl	CNAME(dblow),CNAME(dbsize)
+CNAME(dblow):
+	mtsprg1	%r1			/* save SP */
+	mtsprg2	%r29			/* save r29 */
+	mfcr	%r29			/* save CR in r29 */
+	mfsrr1	%r1
+	mtcr	%r1
+	bf	17,2f			/* branch if privileged */
+1:
+	/* Unprivileged case */
+	mtcr	%r29			/* put the condition register back */
+        mfsprg2	%r29			/* ... and r29 */
+        mflr	%r1			/* save LR */
+	mtsprg2 %r1			/* And then in SPRG2 */
+	li	%r1, 0	 		/* How to get the vector from LR */
+
+        bla     generictrap		/* and we look like a generic trap */
+2:
+#ifdef KDTRACE_HOOKS
+	/* Privileged, so drop to KDB */
+	mfsrr0	%r1
+	mtsprg3	%r3
+	lwz	%r1,0(%r1)
+	/* Check if it's a DTrace trap. */
+	li	%r3,0x0808
+	addis	%r3,%r3,0x7c81
+	cmplw	%cr0,%r3,%r1
+	mfsprg3	%r3
+	beq	%cr0,1b
+#endif
+	/* Privileged, so drop to KDB */
+	GET_CPUINFO(%r1)
+	stw	%r28,(PC_DBSAVE+CPUSAVE_R28)(%r1)	/* free r28 */
+        mfsprg2	%r28				/* r29 holds cr...  */
+        stw	%r28,(PC_DBSAVE+CPUSAVE_R29)(%r1)	/* free r29 */
+        stw	%r30,(PC_DBSAVE+CPUSAVE_R30)(%r1)	/* free r30 */
+        stw	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)	/* free r31 */
+        mflr	%r28					/* save LR */
+	bla	dbtrap
+CNAME(dbsize) = .-CNAME(dblow)
+#endif /* KDB */


Property changes on: trunk/sys/powerpc/aim/trap_subr32.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/trap_subr64.S
===================================================================
--- trunk/sys/powerpc/aim/trap_subr64.S	                        (rev 0)
+++ trunk/sys/powerpc/aim/trap_subr64.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,838 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/aim/trap_subr64.S 266532 2014-05-22 05:20:21Z jhibbits $ */
+/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink 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.
+ */
+
+/*
+ * NOTICE: This is not a standalone file.  to use it, #include it in
+ * your port's locore.S, like so:
+ *
+ *	#include <powerpc/aim/trap_subr.S>
+ */
+
+/*
+ * Save/restore segment registers
+ */
+
+/*
+ * Restore SRs for a pmap
+ *
+ * Requires that r28-r31 be scratch, with r28 initialized to the SLB cache
+ */
+
+/*
+ * User SRs are loaded through a pointer to the current pmap.
+ */
+restore_usersrs:
+	GET_CPUINFO(%r28)
+	ld	%r28,PC_USERSLB(%r28)
+	li	%r29, 0			/* Set the counter to zero */
+
+	slbia
+	slbmfee	%r31,%r29		
+	clrrdi	%r31,%r31,28
+	slbie	%r31
+1:	ld	%r31, 0(%r28)		/* Load SLB entry pointer */
+	cmpli	0, %r31, 0		/* If NULL, stop */
+	beqlr
+
+	ld	%r30, 0(%r31)		/* Load SLBV */
+	ld	%r31, 8(%r31)		/* Load SLBE */
+	or	%r31, %r31, %r29	/*  Set SLBE slot */
+	slbmte	%r30, %r31		/* Install SLB entry */
+
+	addi	%r28, %r28, 8		/* Advance pointer */
+	addi	%r29, %r29, 1
+	b	1b			/* Repeat */
+
+/*
+ * Kernel SRs are loaded directly from the PCPU fields
+ */
+restore_kernsrs:
+	GET_CPUINFO(%r28)
+	addi	%r28,%r28,PC_KERNSLB
+	li	%r29, 0			/* Set the counter to zero */
+
+	slbia
+	slbmfee	%r31,%r29		
+	clrrdi	%r31,%r31,28
+	slbie	%r31
+1:	cmpli	0, %r29, USER_SLB_SLOT	/* Skip the user slot */
+	beq-	2f
+
+	ld	%r31, 8(%r28)		/* Load SLBE */
+	cmpli	0, %r31, 0		/* If SLBE is not valid, stop */
+	beqlr
+	ld	%r30, 0(%r28)		/* Load SLBV  */
+	slbmte	%r30, %r31		/* Install SLB entry */
+
+2:	addi	%r28, %r28, 16		/* Advance pointer */
+	addi	%r29, %r29, 1
+	cmpli	0, %r29, 64		/* Repeat if we are not at the end */
+	blt	1b 
+	blr
+
+/*
+ * FRAME_SETUP assumes:
+ *	SPRG1		SP (1)
+ * 	SPRG3		trap type
+ *	savearea	r27-r31,DAR,DSISR   (DAR & DSISR only for DSI traps)
+ *	r28		LR
+ *	r29		CR
+ *	r30		scratch
+ *	r31		scratch
+ *	r1		kernel stack
+ *	SRR0/1		as at start of trap
+ *
+ * NOTE: SPRG1 is never used while the MMU is on, making it safe to reuse
+ * in any real-mode fault handler, including those handling double faults.
+ */
+#define	FRAME_SETUP(savearea)						\
+/* Have to enable translation to allow access of kernel stack: */	\
+	GET_CPUINFO(%r31);						\
+	mfsrr0	%r30;							\
+	std	%r30,(savearea+CPUSAVE_SRR0)(%r31);	/* save SRR0 */	\
+	mfsrr1	%r30;							\
+	std	%r30,(savearea+CPUSAVE_SRR1)(%r31);	/* save SRR1 */	\
+	mfsprg1	%r31;			/* get saved SP (clears SPRG1) */ \
+	mfmsr	%r30;							\
+	ori	%r30,%r30,(PSL_DR|PSL_IR|PSL_RI)@l; /* relocation on */	\
+	mtmsr	%r30;			/* stack can now be accessed */	\
+	isync;								\
+	stdu	%r31,-(FRAMELEN+288)(%r1); /* save it in the callframe */ \
+	std	%r0, FRAME_0+48(%r1);	/* save r0 in the trapframe */	\
+	std	%r31,FRAME_1+48(%r1);	/* save SP   "      "       */	\
+	std	%r2, FRAME_2+48(%r1);	/* save r2   "      "       */	\
+	std	%r28,FRAME_LR+48(%r1);	/* save LR   "      "       */	\
+	std	%r29,FRAME_CR+48(%r1);	/* save CR   "      "       */	\
+	GET_CPUINFO(%r2);						\
+	ld	%r27,(savearea+CPUSAVE_R27)(%r2); /* get saved r27 */	\
+	ld	%r28,(savearea+CPUSAVE_R28)(%r2); /* get saved r28 */	\
+	ld	%r29,(savearea+CPUSAVE_R29)(%r2); /* get saved r29 */	\
+	ld	%r30,(savearea+CPUSAVE_R30)(%r2); /* get saved r30 */	\
+	ld	%r31,(savearea+CPUSAVE_R31)(%r2); /* get saved r31 */	\
+	std	%r3,  FRAME_3+48(%r1);	/* save r3-r31 */		\
+	std	%r4,  FRAME_4+48(%r1);					\
+	std	%r5,  FRAME_5+48(%r1);					\
+	std	%r6,  FRAME_6+48(%r1);					\
+	std	%r7,  FRAME_7+48(%r1);					\
+	std	%r8,  FRAME_8+48(%r1);					\
+	std	%r9,  FRAME_9+48(%r1);					\
+	std	%r10, FRAME_10+48(%r1);					\
+	std	%r11, FRAME_11+48(%r1);					\
+	std	%r12, FRAME_12+48(%r1);					\
+	std	%r13, FRAME_13+48(%r1);					\
+	std	%r14, FRAME_14+48(%r1);					\
+	std	%r15, FRAME_15+48(%r1);					\
+	std	%r16, FRAME_16+48(%r1);					\
+	std	%r17, FRAME_17+48(%r1);					\
+	std	%r18, FRAME_18+48(%r1);					\
+	std	%r19, FRAME_19+48(%r1);					\
+	std	%r20, FRAME_20+48(%r1);					\
+	std	%r21, FRAME_21+48(%r1);					\
+	std	%r22, FRAME_22+48(%r1);					\
+	std	%r23, FRAME_23+48(%r1);					\
+	std	%r24, FRAME_24+48(%r1);					\
+	std	%r25, FRAME_25+48(%r1);					\
+	std	%r26, FRAME_26+48(%r1);					\
+	std	%r27, FRAME_27+48(%r1);					\
+	std	%r28, FRAME_28+48(%r1);					\
+	std	%r29, FRAME_29+48(%r1);					\
+	std	%r30, FRAME_30+48(%r1);					\
+	std	%r31, FRAME_31+48(%r1);					\
+	ld	%r28,(savearea+CPUSAVE_AIM_DAR)(%r2);  /* saved DAR */	\
+	ld	%r29,(savearea+CPUSAVE_AIM_DSISR)(%r2);/* saved DSISR */\
+	ld	%r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */	\
+	ld	%r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */	\
+	mfxer	%r3;							\
+	mfctr	%r4;							\
+	mfsprg3	%r5;							\
+	std	%r3, FRAME_XER+48(1);	/* save xer/ctr/exc */		\
+	std	%r4, FRAME_CTR+48(1);					\
+	std	%r5, FRAME_EXC+48(1);					\
+	std	%r28,FRAME_AIM_DAR+48(1);				\
+	std	%r29,FRAME_AIM_DSISR+48(1); /* save dsisr/srr0/srr1 */	\
+	std	%r30,FRAME_SRR0+48(1);					\
+	std	%r31,FRAME_SRR1+48(1);					\
+	ld	%r13,PC_CURTHREAD(%r2)	/* set kernel curthread */
+
+#define	FRAME_LEAVE(savearea)						\
+/* Disable exceptions: */						\
+	mfmsr	%r2;							\
+	andi.	%r2,%r2,~PSL_EE at l;					\
+	mtmsr	%r2;							\
+	isync;								\
+/* Now restore regs: */							\
+	ld	%r2,FRAME_SRR0+48(%r1);					\
+	ld	%r3,FRAME_SRR1+48(%r1);					\
+	ld	%r4,FRAME_CTR+48(%r1);					\
+	ld	%r5,FRAME_XER+48(%r1);					\
+	ld	%r6,FRAME_LR+48(%r1);					\
+	GET_CPUINFO(%r7);						\
+	std	%r2,(savearea+CPUSAVE_SRR0)(%r7); /* save SRR0 */	\
+	std	%r3,(savearea+CPUSAVE_SRR1)(%r7); /* save SRR1 */	\
+	ld	%r7,FRAME_CR+48(%r1);					\
+	mtctr	%r4;							\
+	mtxer	%r5;							\
+	mtlr	%r6;							\
+	mtsprg2	%r7;			/* save cr */			\
+	ld	%r31,FRAME_31+48(%r1);   /* restore r0-31 */		\
+	ld	%r30,FRAME_30+48(%r1);					\
+	ld	%r29,FRAME_29+48(%r1);					\
+	ld	%r28,FRAME_28+48(%r1);					\
+	ld	%r27,FRAME_27+48(%r1);					\
+	ld	%r26,FRAME_26+48(%r1);					\
+	ld	%r25,FRAME_25+48(%r1);					\
+	ld	%r24,FRAME_24+48(%r1);					\
+	ld	%r23,FRAME_23+48(%r1);					\
+	ld	%r22,FRAME_22+48(%r1);					\
+	ld	%r21,FRAME_21+48(%r1);					\
+	ld	%r20,FRAME_20+48(%r1);					\
+	ld	%r19,FRAME_19+48(%r1);					\
+	ld	%r18,FRAME_18+48(%r1);					\
+	ld	%r17,FRAME_17+48(%r1);					\
+	ld	%r16,FRAME_16+48(%r1);					\
+	ld	%r15,FRAME_15+48(%r1);					\
+	ld	%r14,FRAME_14+48(%r1);					\
+	ld	%r13,FRAME_13+48(%r1);					\
+	ld	%r12,FRAME_12+48(%r1);					\
+	ld	%r11,FRAME_11+48(%r1);					\
+	ld	%r10,FRAME_10+48(%r1);					\
+	ld	%r9, FRAME_9+48(%r1);					\
+	ld	%r8, FRAME_8+48(%r1);					\
+	ld	%r7, FRAME_7+48(%r1);					\
+	ld	%r6, FRAME_6+48(%r1);					\
+	ld	%r5, FRAME_5+48(%r1);					\
+	ld	%r4, FRAME_4+48(%r1);					\
+	ld	%r3, FRAME_3+48(%r1);					\
+	ld	%r2, FRAME_2+48(%r1);					\
+	ld	%r0, FRAME_0+48(%r1);					\
+	ld	%r1, FRAME_1+48(%r1);					\
+/* Can't touch %r1 from here on */					\
+	mtsprg3	%r3;			/* save r3 */			\
+/* Disable translation, machine check and recoverability: */		\
+	mfmsr	%r3;							\
+	andi.	%r3,%r3,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l;		\
+	mtmsr	%r3;							\
+	isync;								\
+/* Decide whether we return to user mode: */				\
+	GET_CPUINFO(%r3);						\
+	ld	%r3,(savearea+CPUSAVE_SRR1)(%r3);			\
+	mtcr	%r3;							\
+	bf	17,1f;			/* branch if PSL_PR is false */	\
+/* Restore user SRs */							\
+	GET_CPUINFO(%r3);						\
+	std	%r27,(savearea+CPUSAVE_R27)(%r3);			\
+	std	%r28,(savearea+CPUSAVE_R28)(%r3);			\
+	std	%r29,(savearea+CPUSAVE_R29)(%r3);			\
+	std	%r30,(savearea+CPUSAVE_R30)(%r3);			\
+	std	%r31,(savearea+CPUSAVE_R31)(%r3);			\
+	mflr	%r27;			/* preserve LR */		\
+	bl	restore_usersrs;	/* uses r28-r31 */		\
+	mtlr	%r27;							\
+	ld	%r31,(savearea+CPUSAVE_R31)(%r3);			\
+	ld	%r30,(savearea+CPUSAVE_R30)(%r3);			\
+	ld	%r29,(savearea+CPUSAVE_R29)(%r3);			\
+	ld	%r28,(savearea+CPUSAVE_R28)(%r3);			\
+	ld	%r27,(savearea+CPUSAVE_R27)(%r3);			\
+1:	mfsprg2	%r3;			/* restore cr */		\
+	mtcr	%r3;							\
+	GET_CPUINFO(%r3);						\
+	ld	%r3,(savearea+CPUSAVE_SRR0)(%r3); /* restore srr0 */	\
+	mtsrr0	%r3;							\
+	GET_CPUINFO(%r3);						\
+	ld	%r3,(savearea+CPUSAVE_SRR1)(%r3); /* restore srr1 */	\
+	mtsrr1	%r3;							\
+	mfsprg3	%r3			/* restore r3 */
+
+#ifdef KDTRACE_HOOKS
+	.data
+	.globl	dtrace_invop_calltrap_addr
+	.align	8
+	.type	dtrace_invop_calltrap_addr, @object
+        .size	dtrace_invop_calltrap_addr, 8
+dtrace_invop_calltrap_addr:
+	.word	0
+	.word	0
+
+	.text
+#endif
+
+/*
+ * Processor reset exception handler. These are typically
+ * the first instructions the processor executes after a
+ * software reset. We do this in two bits so that we are
+ * not still hanging around in the trap handling region
+ * once the MMU is turned on.
+ */
+	.globl	CNAME(rstcode), CNAME(rstsize)
+CNAME(rstcode):
+	/* Explicitly set MSR[SF] */
+	mfmsr	%r9
+	li	%r8,1
+	insrdi	%r9,%r8,1,0
+	mtmsrd	%r9
+	isync
+
+	ba	cpu_reset
+CNAME(rstsize) = . - CNAME(rstcode)
+
+cpu_reset:
+	lis	%r1,(tmpstk+TMPSTKSZ-48)@ha	/* get new SP */
+	addi	%r1,%r1,(tmpstk+TMPSTKSZ-48)@l
+
+	lis	%r3,tocbase at ha
+	ld	%r2,tocbase at l(%r3)
+	lis	%r3,1 at l
+	bl	CNAME(cpudep_ap_early_bootstrap) /* Set PCPU */
+	nop
+	lis	%r3,1 at l
+	bl	CNAME(pmap_cpu_bootstrap)	/* Turn on virtual memory */
+	nop
+	bl	CNAME(cpudep_ap_bootstrap)	/* Set up PCPU and stack */
+	nop
+	mr	%r1,%r3				/* Use new stack */
+	bl	CNAME(cpudep_ap_setup)
+	nop
+	GET_CPUINFO(%r5)
+	ld	%r3,(PC_RESTORE)(%r5)
+	cmpldi	%cr0,%r3,0
+	beq	%cr0,2f
+	nop
+	li	%r4,1
+	b	CNAME(longjmp)
+	nop
+2:
+#ifdef SMP
+	bl	CNAME(machdep_ap_bootstrap)	/* And away! */
+	nop
+#endif
+
+	/* Should not be reached */
+9:
+	b	9b
+
+/*
+ * This code gets copied to all the trap vectors
+ * (except ISI/DSI, ALI, and the interrupts)
+ */
+
+	.globl	CNAME(trapcode),CNAME(trapsize)
+CNAME(trapcode):
+	mtsprg1	%r1			/* save SP */
+	mflr	%r1			/* Save the old LR in r1 */
+	mtsprg2 %r1			/* And then in SPRG2 */
+	li	%r1, 0xA0		/* How to get the vector from LR */
+	bla	generictrap		/* LR & SPRG3 is exception # */
+CNAME(trapsize) = .-CNAME(trapcode)
+
+/*
+ * For SLB misses: do special things for the kernel
+ *
+ * Note: SPRG1 is always safe to overwrite any time the MMU is on, which is
+ * the only time this can be called.
+ */
+	.globl	CNAME(slbtrap),CNAME(slbtrapsize)
+CNAME(slbtrap):
+	mtsprg1	%r1			/* save SP */
+	GET_CPUINFO(%r1)
+	std	%r2,(PC_SLBSAVE+16)(%r1)
+	mfcr	%r2			/* save CR */
+	std	%r2,(PC_SLBSAVE+104)(%r1)
+	mfsrr1	%r2			/* test kernel mode */
+	mtcr	%r2
+	bf	17,1f			/* branch if PSL_PR is false */
+	/* User mode */
+	ld	%r2,(PC_SLBSAVE+104)(%r1) /* Restore CR */
+	mtcr	%r2
+	ld	%r2,(PC_SLBSAVE+16)(%r1) /* Restore R2 */
+	mflr	%r1			/* Save the old LR in r1 */
+	mtsprg2 %r1			/* And then in SPRG2 */
+	li	%r1, 0x80		/* How to get the vector from LR */
+	bla	generictrap		/* LR & SPRG3 is exception # */
+1:	mflr	%r2			/* Save the old LR in r2 */
+	bla	kern_slbtrap
+CNAME(slbtrapsize) = .-CNAME(slbtrap)
+
+kern_slbtrap:
+	std	%r2,(PC_SLBSAVE+136)(%r1) /* old LR */
+	std	%r3,(PC_SLBSAVE+24)(%r1) /* save R3 */
+
+	/* Check if this needs to be handled as a regular trap (userseg miss) */
+	mflr	%r2
+	andi.	%r2,%r2,0xff80
+	cmpwi	%r2,0x380
+	bne	1f
+	mfdar	%r2
+	b	2f
+1:	mfsrr0	%r2
+2:	/* r2 now contains the fault address */
+	lis	%r3,SEGMENT_MASK at highesta
+	ori	%r3,%r3,SEGMENT_MASK at highera
+	sldi	%r3,%r3,32
+	oris	%r3,%r3,SEGMENT_MASK at ha
+	ori	%r3,%r3,SEGMENT_MASK at l
+	and	%r2,%r2,%r3	/* R2 = segment base address */
+	lis	%r3,USER_ADDR at highesta
+	ori	%r3,%r3,USER_ADDR at highera
+	sldi	%r3,%r3,32
+	oris	%r3,%r3,USER_ADDR at ha
+	ori	%r3,%r3,USER_ADDR at l
+	cmpd	%r2,%r3		/* Compare fault base to USER_ADDR */
+	bne	3f
+
+	/* User seg miss, handle as a regular trap */
+	ld	%r2,(PC_SLBSAVE+104)(%r1) /* Restore CR */
+	mtcr	%r2
+	ld	%r2,(PC_SLBSAVE+16)(%r1) /* Restore R2,R3 */
+	ld	%r3,(PC_SLBSAVE+24)(%r1)
+	ld	%r1,(PC_SLBSAVE+136)(%r1) /* Save the old LR in r1 */
+	mtsprg2 %r1			/* And then in SPRG2 */
+	li	%r1, 0x80		/* How to get the vector from LR */
+	b	generictrap		/* Retain old LR using b */
+	
+3:	/* Real kernel SLB miss */
+	std	%r0,(PC_SLBSAVE+0)(%r1)	/* free all volatile regs */
+	mfsprg1	%r2			/* Old R1 */
+	std	%r2,(PC_SLBSAVE+8)(%r1)
+	/* R2,R3 already saved */
+	std	%r4,(PC_SLBSAVE+32)(%r1)
+	std	%r5,(PC_SLBSAVE+40)(%r1)
+	std	%r6,(PC_SLBSAVE+48)(%r1)
+	std	%r7,(PC_SLBSAVE+56)(%r1)
+	std	%r8,(PC_SLBSAVE+64)(%r1)
+	std	%r9,(PC_SLBSAVE+72)(%r1)
+	std	%r10,(PC_SLBSAVE+80)(%r1)
+	std	%r11,(PC_SLBSAVE+88)(%r1)
+	std	%r12,(PC_SLBSAVE+96)(%r1)
+	/* CR already saved */
+	mfxer	%r2			/* save XER */
+	std	%r2,(PC_SLBSAVE+112)(%r1)
+	mflr	%r2			/* save LR (SP already saved) */
+	std	%r2,(PC_SLBSAVE+120)(%r1)
+	mfctr	%r2			/* save CTR */
+	std	%r2,(PC_SLBSAVE+128)(%r1)
+
+	/* Call handler */
+	addi	%r1,%r1,PC_SLBSTACK-48+1024
+	li	%r2,~15
+	and	%r1,%r1,%r2
+	lis	%r3,tocbase at ha
+	ld	%r2,tocbase at l(%r3)
+	mflr	%r3
+	andi.	%r3,%r3,0xff80
+	mfdar	%r4
+	mfsrr0	%r5
+	bl	handle_kernel_slb_spill
+	nop
+
+	/* Save r28-31, restore r4-r12 */
+	GET_CPUINFO(%r1)
+	ld	%r4,(PC_SLBSAVE+32)(%r1)
+	ld	%r5,(PC_SLBSAVE+40)(%r1)
+	ld	%r6,(PC_SLBSAVE+48)(%r1)
+	ld	%r7,(PC_SLBSAVE+56)(%r1)
+	ld	%r8,(PC_SLBSAVE+64)(%r1)
+	ld	%r9,(PC_SLBSAVE+72)(%r1)
+	ld	%r10,(PC_SLBSAVE+80)(%r1)
+	ld	%r11,(PC_SLBSAVE+88)(%r1)
+	ld	%r12,(PC_SLBSAVE+96)(%r1)
+	std	%r28,(PC_SLBSAVE+64)(%r1)
+	std	%r29,(PC_SLBSAVE+72)(%r1)
+	std	%r30,(PC_SLBSAVE+80)(%r1)
+	std	%r31,(PC_SLBSAVE+88)(%r1)
+
+	/* Restore kernel mapping */
+	bl	restore_kernsrs
+
+	/* Restore remaining registers */
+	ld	%r28,(PC_SLBSAVE+64)(%r1)
+	ld	%r29,(PC_SLBSAVE+72)(%r1)
+	ld	%r30,(PC_SLBSAVE+80)(%r1)
+	ld	%r31,(PC_SLBSAVE+88)(%r1)
+
+	ld	%r2,(PC_SLBSAVE+104)(%r1)
+	mtcr	%r2
+	ld	%r2,(PC_SLBSAVE+112)(%r1)
+	mtxer	%r2
+	ld	%r2,(PC_SLBSAVE+120)(%r1)
+	mtlr	%r2
+	ld	%r2,(PC_SLBSAVE+128)(%r1)
+	mtctr	%r2
+	ld	%r2,(PC_SLBSAVE+136)(%r1)
+	mtlr	%r2
+
+	/* Restore r0-r3 */
+	ld	%r0,(PC_SLBSAVE+0)(%r1)
+	ld	%r2,(PC_SLBSAVE+16)(%r1)
+	ld	%r3,(PC_SLBSAVE+24)(%r1)
+	mfsprg1	%r1
+
+	/* Back to whatever we were doing */
+	rfid
+
+/*
+ * For ALI: has to save DSISR and DAR
+ */
+	.globl	CNAME(alitrap),CNAME(alisize)
+CNAME(alitrap):
+	mtsprg1	%r1			/* save SP */
+	GET_CPUINFO(%r1)
+	std	%r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)	/* free r27-r31 */
+	std	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
+	std	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
+	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
+	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
+	mfdar	%r30
+	mfdsisr	%r31
+	std	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
+	std	%r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
+	mfsprg1	%r1			/* restore SP, in case of branch */
+	mflr	%r28			/* save LR */
+	mfcr	%r29			/* save CR */
+
+	/* Put our exception vector in SPRG3 */
+	li	%r31, EXC_ALI
+	mtsprg3	%r31
+
+	/* Test whether we already had PR set */
+	mfsrr1	%r31
+	mtcr	%r31
+	bla	s_trap
+CNAME(alisize) = .-CNAME(alitrap)
+
+/*
+ * Similar to the above for DSI
+ * Has to handle BAT spills
+ * and standard pagetable spills
+ */
+	.globl	CNAME(dsitrap),CNAME(dsisize)
+CNAME(dsitrap):
+	mtsprg1	%r1			/* save SP */
+	GET_CPUINFO(%r1)
+	std	%r27,(PC_DISISAVE+CPUSAVE_R27)(%r1)	/* free r27-r31 */
+	std	%r28,(PC_DISISAVE+CPUSAVE_R28)(%r1)
+	std	%r29,(PC_DISISAVE+CPUSAVE_R29)(%r1)
+	std	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
+	std	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
+	mfsprg1	%r1			/* restore SP */
+	mfcr	%r29			/* save CR */
+	mfxer	%r30			/* save XER */
+	mtsprg2	%r30			/* in SPRG2 */
+	mfsrr1	%r31			/* test kernel mode */
+	mtcr	%r31
+	mflr	%r28			/* save LR (SP already saved) */
+	bla	disitrap
+CNAME(dsisize) = .-CNAME(dsitrap)
+
+/*
+ * Preamble code for DSI/ISI traps
+ */
+disitrap:
+	/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
+	mflr	%r1
+	andi.	%r1,%r1,0xff00
+	mtsprg3	%r1
+	
+	GET_CPUINFO(%r1)
+	ld	%r31,(PC_DISISAVE+CPUSAVE_R27)(%r1)
+	std	%r31,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)
+	ld	%r30,(PC_DISISAVE+CPUSAVE_R28)(%r1)
+	std	%r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
+	ld	%r31,(PC_DISISAVE+CPUSAVE_R29)(%r1)
+	std	%r31,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
+	ld	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
+	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
+	ld	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
+	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
+	mfdar	%r30
+	mfdsisr	%r31
+	std	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
+	std	%r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
+
+#ifdef KDB
+	/* Try to detect a kernel stack overflow */
+	mfsrr1	%r31
+	mtcr	%r31
+	bt	17,realtrap		/* branch is user mode */
+	mfsprg1	%r31			/* get old SP */
+	clrrdi	%r31,%r31,12		/* Round SP down to nearest page */
+	sub.	%r30,%r31,%r30		/* SP - DAR */
+	bge	1f
+	neg	%r30,%r30		/* modulo value */
+1:	cmpldi	%cr0,%r30,4096		/* is DAR within a page of SP? */
+	bge	%cr0,realtrap		/* no, too far away. */
+
+	/* Now convert this DSI into a DDB trap.  */
+	GET_CPUINFO(%r1)
+	ld	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) /* get DAR */
+	std	%r30,(PC_DBSAVE  +CPUSAVE_AIM_DAR)(%r1) /* save DAR */
+	ld	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) /* get DSISR */
+	std	%r30,(PC_DBSAVE  +CPUSAVE_AIM_DSISR)(%r1) /* save DSISR */
+	ld	%r31,(PC_DISISAVE+CPUSAVE_R27)(%r1) /* get  r27 */
+	std	%r31,(PC_DBSAVE  +CPUSAVE_R27)(%r1) /* save r27 */
+	ld	%r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* get  r28 */
+	std	%r30,(PC_DBSAVE  +CPUSAVE_R28)(%r1) /* save r28 */
+	ld	%r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) /* get  r29 */
+	std	%r31,(PC_DBSAVE  +CPUSAVE_R29)(%r1) /* save r29 */
+	ld	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) /* get  r30 */
+	std	%r30,(PC_DBSAVE  +CPUSAVE_R30)(%r1) /* save r30 */
+	ld	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get  r31 */
+	std	%r31,(PC_DBSAVE  +CPUSAVE_R31)(%r1) /* save r31 */
+	b	dbtrap
+#endif
+
+	/* XXX need stack probe here */
+realtrap:
+/* Test whether we already had PR set */
+	mfsrr1	%r1
+	mtcr	%r1
+	mfsprg1	%r1			/* restore SP (might have been
+					   overwritten) */
+	bf	17,k_trap		/* branch if PSL_PR is false */
+	GET_CPUINFO(%r1)
+	ld	%r1,PC_CURPCB(%r1)
+	mr	%r27,%r28		/* Save LR, r29 */
+	mtsprg2	%r29
+	bl	restore_kernsrs		/* enable kernel mapping */
+	mfsprg2	%r29
+	mr	%r28,%r27
+	ba s_trap
+
+/*
+ * generictrap does some standard setup for trap handling to minimize
+ * the code that need be installed in the actual vectors. It expects
+ * the following conditions.
+ * 
+ * R1 - Trap vector = LR & (0xff00 | R1)
+ * SPRG1 - Original R1 contents
+ * SPRG2 - Original LR
+ */
+
+generictrap:
+	/* Save R1 for computing the exception vector */
+	mtsprg3 %r1
+
+	/* Save interesting registers */
+	GET_CPUINFO(%r1)
+	std	%r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)	/* free r27-r31 */
+	std	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
+	std	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
+	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
+	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
+	mfdar	%r30
+	std	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
+	mfsprg1	%r1			/* restore SP, in case of branch */
+	mfsprg2	%r28			/* save LR */
+	mfcr	%r29			/* save CR */
+
+	/* Compute the exception vector from the link register */
+	mfsprg3 %r31
+	ori	%r31,%r31,0xff00
+	mflr	%r30
+	and	%r30,%r30,%r31
+	mtsprg3	%r30
+
+	/* Test whether we already had PR set */
+	mfsrr1	%r31
+	mtcr	%r31
+
+s_trap:
+	bf	17,k_trap		/* branch if PSL_PR is false */
+	GET_CPUINFO(%r1)
+u_trap:
+	ld	%r1,PC_CURPCB(%r1)
+	mr	%r27,%r28		/* Save LR, r29 */
+	mtsprg2	%r29
+	bl	restore_kernsrs		/* enable kernel mapping */
+	mfsprg2	%r29
+	mr	%r28,%r27
+
+/*
+ * Now the common trap catching code.
+ */
+k_trap:
+	FRAME_SETUP(PC_TEMPSAVE)
+/* Call C interrupt dispatcher: */
+trapagain:
+	lis	%r3,tocbase at ha
+	ld	%r2,tocbase at l(%r3)
+	addi	%r3,%r1,48
+	bl	CNAME(powerpc_interrupt)
+	nop
+
+	.globl	CNAME(trapexit)	/* backtrace code sentinel */
+CNAME(trapexit):
+/* Disable interrupts: */
+	mfmsr	%r3
+	andi.	%r3,%r3,~PSL_EE at l
+	mtmsr	%r3
+	isync
+/* Test AST pending: */
+	ld	%r5,FRAME_SRR1+48(%r1)
+	mtcr	%r5
+	bf	17,1f			/* branch if PSL_PR is false */
+
+	GET_CPUINFO(%r3)		/* get per-CPU pointer */
+	lwz	%r4, TD_FLAGS(%r13)	/* get thread flags value */
+	lis	%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h
+	ori	%r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l
+	and.	%r4,%r4,%r5
+	beq	1f
+	mfmsr	%r3			/* re-enable interrupts */
+	ori	%r3,%r3,PSL_EE at l
+	mtmsr	%r3
+	isync
+	lis	%r3,tocbase at ha
+	ld	%r2,tocbase at l(%r3)
+	addi	%r3,%r1,48
+	bl	CNAME(ast)
+	nop
+	.globl	CNAME(asttrapexit)	/* backtrace code sentinel #2 */
+CNAME(asttrapexit):
+	b	trapexit		/* test ast ret value ? */
+1:
+	FRAME_LEAVE(PC_TEMPSAVE)
+	rfid
+
+#if defined(KDB)
+/*
+ * Deliberate entry to dbtrap
+ */
+ASENTRY_NOPROF(breakpoint)
+	mtsprg1	%r1
+	mfmsr	%r3
+	mtsrr1	%r3
+	andi.	%r3,%r3,~(PSL_EE|PSL_ME)@l
+	mtmsr	%r3			/* disable interrupts */
+	isync
+	GET_CPUINFO(%r3)
+	std	%r27,(PC_DBSAVE+CPUSAVE_R27)(%r3)
+	std	%r28,(PC_DBSAVE+CPUSAVE_R28)(%r3)
+	std	%r29,(PC_DBSAVE+CPUSAVE_R29)(%r3)
+	std	%r30,(PC_DBSAVE+CPUSAVE_R30)(%r3)
+	std	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r3)
+	mflr	%r28
+	li	%r29,EXC_BPT
+	mtlr	%r29
+	mfcr	%r29
+	mtsrr0	%r28
+
+/*
+ * Now the kdb trap catching code.
+ */
+dbtrap:
+	/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
+	mflr	%r1
+	andi.	%r1,%r1,0xff00
+	mtsprg3	%r1
+
+	lis	%r1,(tmpstk+TMPSTKSZ-48)@ha	/* get new SP */
+	addi	%r1,%r1,(tmpstk+TMPSTKSZ-48)@l
+
+	FRAME_SETUP(PC_DBSAVE)
+/* Call C trap code: */
+	lis	%r3,tocbase at ha
+	ld	%r2,tocbase at l(%r3)
+	addi	%r3,%r1,48
+	bl	CNAME(db_trap_glue)
+	nop
+	or.	%r3,%r3,%r3
+	bne	dbleave
+/* This wasn't for KDB, so switch to real trap: */
+	ld	%r3,FRAME_EXC+48(%r1)	/* save exception */
+	GET_CPUINFO(%r4)
+	std	%r3,(PC_DBSAVE+CPUSAVE_R31)(%r4)
+	FRAME_LEAVE(PC_DBSAVE)
+	mtsprg1	%r1			/* prepare for entrance to realtrap */
+	GET_CPUINFO(%r1)
+	std	%r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)
+	std	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
+	std	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
+	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
+	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
+	mflr	%r28
+	mfcr	%r29
+	ld	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)
+	mtsprg3	%r31			/* SPRG3 was clobbered by FRAME_LEAVE */
+	mfsprg1	%r1
+	b	realtrap
+dbleave:
+	FRAME_LEAVE(PC_DBSAVE)
+	rfid
+
+/*
+ * In case of KDB we want a separate trap catcher for it
+ */
+	.globl	CNAME(dblow),CNAME(dbsize)
+CNAME(dblow):
+	mtsprg1	%r1			/* save SP */
+	mtsprg2	%r29			/* save r29 */
+	mfcr	%r29			/* save CR in r29 */
+	mfsrr1	%r1
+	mtcr	%r1
+	bf	17,2f			/* branch if privileged */
+
+1:
+	/* Unprivileged case */
+	mtcr	%r29			/* put the condition register back */
+        mfsprg2	%r29			/* ... and r29 */
+        mflr	%r1			/* save LR */
+	mtsprg2 %r1			/* And then in SPRG2 */
+	li	%r1, 0	 		/* How to get the vector from LR */
+
+        bla     generictrap		/* and we look like a generic trap */
+2:
+#ifdef KDTRACE_HOOKS
+	/* Privileged, so drop to KDB */
+	mfsrr0	%r1
+	mtsprg3	%r3
+	lwz	%r1,0(%r1)
+	/* Check if it's a DTrace trap. */
+	li	%r3,0x0808
+	addis	%r3,%r3,0x7c81
+	cmplw	%cr0,%r3,%r1
+	mfsprg3	%r3
+	beq	%cr0,1b
+#endif
+	GET_CPUINFO(%r1)
+	std	%r27,(PC_DBSAVE+CPUSAVE_R27)(%r1)	/* free r27 */
+	std	%r28,(PC_DBSAVE+CPUSAVE_R28)(%r1)	/* free r28 */
+        mfsprg2	%r28				/* r29 holds cr...  */
+        std	%r28,(PC_DBSAVE+CPUSAVE_R29)(%r1)	/* free r29 */
+        std	%r30,(PC_DBSAVE+CPUSAVE_R30)(%r1)	/* free r30 */
+        std	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)	/* free r31 */
+        mflr	%r28					/* save LR */
+	bla	dbtrap
+CNAME(dbsize) = .-CNAME(dblow)
+#endif /* KDB */


Property changes on: trunk/sys/powerpc/aim/trap_subr64.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/aim/uma_machdep.c
===================================================================
--- trunk/sys/powerpc/aim/uma_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/aim/uma_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,99 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 The FreeBSD Project
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/aim/uma_machdep.c 287945 2015-09-17 23:31:44Z rstone $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_pageout.h>
+#include <vm/vm_extern.h>
+#include <vm/uma.h>
+#include <vm/uma.h>
+#include <vm/uma_int.h>
+#include <machine/md_var.h>
+#include <machine/vmparam.h>
+
+static int hw_uma_mdpages;
+SYSCTL_INT(_hw, OID_AUTO, uma_mdpages, CTLFLAG_RD, &hw_uma_mdpages, 0,
+	   "UMA MD pages in use");
+
+void *
+uma_small_alloc(uma_zone_t zone, vm_size_t bytes, u_int8_t *flags, int wait)
+{
+	void *va;
+	vm_page_t m;
+	int pflags;
+	
+	*flags = UMA_SLAB_PRIV;
+	pflags = malloc2vm_flags(wait) | VM_ALLOC_WIRED;
+
+	for (;;) {
+		m = vm_page_alloc(NULL, 0, pflags | VM_ALLOC_NOOBJ);
+		if (m == NULL) {
+			if (wait & M_NOWAIT)
+				return (NULL);
+			VM_WAIT;
+		} else
+			break;
+	}
+
+	va = (void *) VM_PAGE_TO_PHYS(m);
+
+	if (!hw_direct_map)
+		pmap_kenter((vm_offset_t)va, VM_PAGE_TO_PHYS(m));
+
+	if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0)
+		bzero(va, PAGE_SIZE);
+	atomic_add_int(&hw_uma_mdpages, 1);
+
+	return (va);
+}
+
+void
+uma_small_free(void *mem, vm_size_t size, u_int8_t flags)
+{
+	vm_page_t m;
+
+	if (!hw_direct_map)
+		pmap_remove(kernel_pmap,(vm_offset_t)mem,
+		    (vm_offset_t)mem + PAGE_SIZE);
+
+	m = PHYS_TO_VM_PAGE((vm_offset_t)mem);
+	m->wire_count--;
+	vm_page_free(m);
+	atomic_subtract_int(&cnt.v_wire_count, 1);
+	atomic_subtract_int(&hw_uma_mdpages, 1);
+}


Property changes on: trunk/sys/powerpc/aim/uma_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/booke/interrupt.c
===================================================================
--- trunk/sys/powerpc/booke/interrupt.c	                        (rev 0)
+++ trunk/sys/powerpc/booke/interrupt.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,145 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2006 Semihalf, Rafal Jaworowski <raj at semihalf.com>
+ * Copyright 2002 by Peter Grehan.
+ * 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. 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.
+ *
+ */
+
+/*
+ * Interrupts are dispatched to here from locore asm
+ */
+
+#include <sys/cdefs.h>                  /* RCS ID & Copyright macro defns */
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/booke/interrupt.c 223485 2011-06-23 22:21:28Z nwhitehorn $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+#include <sys/unistd.h>
+#include <sys/vmmeter.h>
+
+#include <machine/cpu.h>
+#include <machine/db_machdep.h>
+#include <machine/frame.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+#include <machine/psl.h>
+#include <machine/trap.h>
+
+#include "pic_if.h"
+
+extern void decr_intr(struct trapframe *);
+
+void powerpc_decr_interrupt(struct trapframe *);
+void powerpc_extr_interrupt(struct trapframe *);
+void powerpc_crit_interrupt(struct trapframe *);
+void powerpc_mchk_interrupt(struct trapframe *);
+
+static void dump_frame(struct trapframe *framep);
+
+static void
+dump_frame(struct trapframe *frame)
+{
+	int i;
+
+	printf("\n*** *** STACK FRAME DUMP *** ***\n");
+	printf("  exc  = 0x%x\n", frame->exc);
+	printf("  srr0 = 0x%08x\n", frame->srr0);
+	printf("  srr1 = 0x%08x\n", frame->srr1);
+	printf("  dear = 0x%08x\n", frame->cpu.booke.dear);
+	printf("  esr  = 0x%08x\n", frame->cpu.booke.esr);
+	printf("  lr   = 0x%08x\n", frame->lr);
+	printf("  cr   = 0x%08x\n", frame->cr);
+	printf("  sp   = 0x%08x\n", frame->fixreg[1]);
+
+	for (i = 0; i < 32; i++) {
+		printf("  R%02d = 0x%08x", i, frame->fixreg[i]);
+		if ((i & 0x3) == 3)
+			printf("\n");
+	}
+	printf("\n");
+}
+
+void powerpc_crit_interrupt(struct trapframe *framep)
+{
+
+	printf("powerpc_crit_interrupt: critical interrupt!\n");
+	dump_frame(framep);
+	trap(framep);
+}
+
+void powerpc_mchk_interrupt(struct trapframe *framep)
+{
+
+	printf("powerpc_mchk_interrupt: machine check interrupt!\n");
+	dump_frame(framep);
+	trap(framep);
+}
+
+/*
+ * Decrementer interrupt routine
+ */
+void
+powerpc_decr_interrupt(struct trapframe *framep)
+{
+	struct thread *td;
+	struct trapframe *oldframe;
+
+	td = curthread;
+	critical_enter();
+	atomic_add_int(&td->td_intr_nesting_level, 1);
+	oldframe = td->td_intr_frame;
+	td->td_intr_frame = framep;
+	decr_intr(framep);
+	td->td_intr_frame = oldframe;
+	atomic_subtract_int(&td->td_intr_nesting_level, 1);
+	critical_exit();
+	framep->srr1 &= ~PSL_WE;
+}
+
+/*
+ * External input interrupt routine
+ */
+void
+powerpc_extr_interrupt(struct trapframe *framep)
+{
+
+	critical_enter();
+	PIC_DISPATCH(root_pic, framep);
+	critical_exit();
+	framep->srr1 &= ~PSL_WE;
+}


Property changes on: trunk/sys/powerpc/booke/interrupt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/booke/locore.S
===================================================================
--- trunk/sys/powerpc/booke/locore.S	                        (rev 0)
+++ trunk/sys/powerpc/booke/locore.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,784 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2007-2009 Semihalf, Rafal Jaworowski <raj at semihalf.com>
+ * Copyright (C) 2006 Semihalf, Marian Balakowicz <m8 at semihalf.com>
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/booke/locore.S 266001 2014-05-14 03:09:37Z ian $
+ */
+
+#include "assym.s"
+
+#include <machine/asm.h>
+#include <machine/hid.h>
+#include <machine/param.h>
+#include <machine/spr.h>
+#include <machine/pte.h>
+#include <machine/trap.h>
+#include <machine/vmparam.h>
+#include <machine/tlb.h>
+
+#define TMPSTACKSZ	16384
+
+	.text
+	.globl	btext
+btext:
+
+/*
+ * This symbol is here for the benefit of kvm_mkdb, and is supposed to
+ * mark the start of kernel text.
+ */
+	.globl	kernel_text
+kernel_text:
+
+/*
+ * Startup entry.  Note, this must be the first thing in the text segment!
+ */
+	.text
+	.globl	__start
+__start:
+
+/*
+ * Assumptions on the boot loader:
+ *  - system memory starts from physical address 0
+ *  - it's mapped by a single TBL1 entry
+ *  - TLB1 mapping is 1:1 pa to va
+ *  - kernel is loaded at 16MB boundary
+ *  - all PID registers are set to the same value
+ *  - CPU is running in AS=0
+ *
+ * Registers contents provided by the loader(8):
+ *	r1	: stack pointer
+ *	r3	: metadata pointer
+ *
+ * We rearrange the TLB1 layout as follows:
+ *  - find TLB1 entry we started in
+ *  - make sure it's protected, ivalidate other entries
+ *  - create temp entry in the second AS (make sure it's not TLB[1])
+ *  - switch to temp mapping
+ *  - map 16MB of RAM in TLB1[1]
+ *  - use AS=1, set EPN to KERNBASE and RPN to kernel load address
+ *  - switch to to TLB1[1] mapping
+ *  - invalidate temp mapping
+ *
+ * locore registers use:
+ *	r1	: stack pointer
+ *	r2	: trace pointer (AP only, for early diagnostics)
+ *	r3-r27	: scratch registers
+ *	r28	: temp TLB1 entry
+ *	r29	: initial TLB1 entry we started in
+ *	r30-r31	: arguments (metadata pointer)
+ */
+
+/*
+ * Keep arguments in r30 & r31 for later use.
+ */
+	mr	%r30, %r3
+	mr	%r31, %r4
+
+/*
+ * Initial cleanup
+ */
+	li	%r3, PSL_DE	/* Keep debug exceptions for CodeWarrior. */
+	mtmsr	%r3
+	isync
+
+	lis	%r3, HID0_E500_DEFAULT_SET at h
+	ori	%r3, %r3, HID0_E500_DEFAULT_SET at l
+	mtspr	SPR_HID0, %r3
+	isync
+	lis	%r3, HID1_E500_DEFAULT_SET at h
+	ori	%r3, %r3, HID1_E500_DEFAULT_SET at l
+	mtspr	SPR_HID1, %r3
+	isync
+
+	/* Invalidate all entries in TLB0 */
+	li	%r3, 0
+	bl	tlb_inval_all
+
+	cmpwi	%r30, 0
+	beq	done_mapping
+
+/*
+ * Locate the TLB1 entry that maps this code
+ */
+	bl	1f
+1:	mflr	%r3
+	bl	tlb1_find_current	/* the entry found is returned in r29 */
+
+	bl	tlb1_inval_all_but_current
+
+/*
+ * Create temporary mapping in AS=1 and switch to it
+ */
+	addi	%r3, %r29, 1
+	bl	tlb1_temp_mapping_as1
+
+	mfmsr	%r3
+	ori	%r3, %r3, (PSL_IS | PSL_DS)
+	bl	2f
+2:	mflr	%r4
+	addi	%r4, %r4, 20
+	mtspr	SPR_SRR0, %r4
+	mtspr	SPR_SRR1, %r3
+	rfi				/* Switch context */
+
+/*
+ * Invalidate initial entry
+ */
+	mr	%r3, %r29
+	bl	tlb1_inval_entry
+
+/*
+ * Setup final mapping in TLB1[1] and switch to it
+ */
+	/* Final kernel mapping, map in 16 MB of RAM */
+	lis	%r3, MAS0_TLBSEL1 at h	/* Select TLB1 */
+	li	%r4, 0			/* Entry 0 */
+	rlwimi	%r3, %r4, 16, 12, 15
+	mtspr	SPR_MAS0, %r3
+	isync
+
+	li	%r3, (TLB_SIZE_64M << MAS1_TSIZE_SHIFT)@l
+	oris	%r3, %r3, (MAS1_VALID | MAS1_IPROT)@h
+	mtspr	SPR_MAS1, %r3		/* note TS was not filled, so it's TS=0 */
+	isync
+
+	lis	%r3, KERNBASE at h
+	ori	%r3, %r3, KERNBASE at l	/* EPN = KERNBASE */
+#ifdef SMP
+	ori	%r3, %r3, MAS2_M at l	/* WIMGE = 0b00100 */
+#endif
+	mtspr	SPR_MAS2, %r3
+	isync
+
+	/* Discover phys load address */
+	bl	3f
+3:	mflr	%r4			/* Use current address */
+	rlwinm	%r4, %r4, 0, 0, 7	/* 16MB alignment mask */
+	ori	%r4, %r4, (MAS3_SX | MAS3_SW | MAS3_SR)@l
+	mtspr	SPR_MAS3, %r4		/* Set RPN and protection */
+	isync
+	tlbwe
+	isync
+	msync
+
+	/* Switch to the above TLB1[1] mapping */
+	bl	4f
+4:	mflr	%r4
+	rlwinm	%r4, %r4, 0, 8, 31	/* Current offset from kernel load address */
+	rlwinm	%r3, %r3, 0, 0, 19
+	add	%r4, %r4, %r3		/* Convert to kernel virtual address */
+	addi	%r4, %r4, 36
+	li	%r3, PSL_DE		/* Note AS=0 */
+	mtspr   SPR_SRR0, %r4
+	mtspr   SPR_SRR1, %r3
+	rfi
+
+/*
+ * Invalidate temp mapping
+ */
+	mr	%r3, %r28
+	bl	tlb1_inval_entry
+
+done_mapping:
+
+/*
+ * Setup a temporary stack
+ */
+	lis	%r1, tmpstack at ha
+	addi	%r1, %r1, tmpstack at l
+	addi	%r1, %r1, (TMPSTACKSZ - 8)
+
+/*
+ * Initialise exception vector offsets
+ */
+	bl	ivor_setup
+
+/*
+ * Set up arguments and jump to system initialization code
+ */
+	mr	%r3, %r30
+	mr	%r4, %r31
+
+	/* Prepare core */
+	bl	booke_init
+
+	/* Switch to thread0.td_kstack now */
+	mr	%r1, %r3
+	li	%r3, 0
+	stw	%r3, 0(%r1)
+
+	/* Machine independet part, does not return */
+	bl	mi_startup
+	/* NOT REACHED */
+5:	b	5b
+
+
+#ifdef SMP
+/************************************************************************/
+/* AP Boot page */
+/************************************************************************/
+	.text
+	.globl	__boot_page
+	.align	12
+__boot_page:
+	bl	1f
+
+	.globl	bp_ntlb1s
+bp_ntlb1s:
+	.long	0
+
+	.globl	bp_tlb1
+bp_tlb1:
+	.space	4 * 3 * 16
+
+	.globl	bp_tlb1_end
+bp_tlb1_end:
+
+/*
+ * Initial configuration
+ */
+1:	mflr	%r31		/* r31 hold the address of bp_ntlb1s */
+
+	/* Set HIDs */
+	lis	%r3, HID0_E500_DEFAULT_SET at h
+	ori	%r3, %r3, HID0_E500_DEFAULT_SET at l
+	mtspr	SPR_HID0, %r3
+	isync
+	lis	%r3, HID1_E500_DEFAULT_SET at h
+	ori	%r3, %r3, HID1_E500_DEFAULT_SET at l
+	mtspr	SPR_HID1, %r3
+	isync
+
+	/* Enable branch prediction */
+	li	%r3, BUCSR_BPEN
+	mtspr	SPR_BUCSR, %r3
+	isync
+
+	/* Invalidate all entries in TLB0 */
+	li	%r3, 0
+	bl	tlb_inval_all
+
+/*
+ * Find TLB1 entry which is translating us now
+ */
+	bl	2f
+2:	mflr	%r3
+	bl	tlb1_find_current	/* the entry number found is in r29 */
+
+	bl	tlb1_inval_all_but_current
+
+/*
+ * Create temporary translation in AS=1 and switch to it
+ */
+	lwz	%r3, 0(%r31)
+	bl	tlb1_temp_mapping_as1
+
+	mfmsr	%r3
+	ori	%r3, %r3, (PSL_IS | PSL_DS)
+	bl	3f
+3:	mflr	%r4
+	addi	%r4, %r4, 20
+	mtspr	SPR_SRR0, %r4
+	mtspr	SPR_SRR1, %r3
+	rfi				/* Switch context */
+
+/*
+ * Invalidate initial entry
+ */
+	mr	%r3, %r29
+	bl	tlb1_inval_entry
+
+/*
+ * Setup final mapping in TLB1[1] and switch to it
+ */
+	lwz	%r6, 0(%r31)
+	addi	%r5, %r31, 4
+	li	%r4, 0
+
+4:	lis	%r3, MAS0_TLBSEL1 at h
+	rlwimi	%r3, %r4, 16, 12, 15
+	mtspr	SPR_MAS0, %r3
+	isync
+	lwz	%r3, 0(%r5)
+	mtspr	SPR_MAS1, %r3
+	isync
+	lwz	%r3, 4(%r5)
+	mtspr	SPR_MAS2, %r3
+	isync
+	lwz	%r3, 8(%r5)
+	mtspr	SPR_MAS3, %r3
+	isync
+	tlbwe
+	isync
+	msync
+	addi	%r5, %r5, 12
+	addi	%r4, %r4, 1
+	cmpw	%r4, %r6
+	blt	4b
+
+	/* Switch to the final mapping */
+	lis	%r5, __boot_page at ha
+	ori	%r5, %r5, __boot_page at l
+	bl	5f
+5:	mflr	%r3
+	rlwinm	%r3, %r3, 0, 0xfff	/* Offset from boot page start */
+	add	%r3, %r3, %r5		/* Make this virtual address */
+	addi	%r3, %r3, 32
+	li	%r4, 0			/* Note AS=0 */
+	mtspr	SPR_SRR0, %r3
+	mtspr	SPR_SRR1, %r4
+	rfi
+
+/*
+ * At this point we're running at virtual addresses KERNBASE and beyond so
+ * it's allowed to directly access all locations the kernel was linked
+ * against.
+ */
+
+/*
+ * Invalidate temp mapping
+ */
+	mr	%r3, %r28
+	bl	tlb1_inval_entry
+
+/*
+ * Setup a temporary stack
+ */
+	lis	%r1, tmpstack at ha
+	addi	%r1, %r1, tmpstack at l
+	addi	%r1, %r1, (TMPSTACKSZ - 8)
+
+/*
+ * Initialise exception vector offsets
+ */
+	bl	ivor_setup
+
+	/*
+	 * Assign our pcpu instance
+	 */
+	lis	%r3, ap_pcpu at h
+	ori	%r3, %r3, ap_pcpu at l
+	lwz	%r3, 0(%r3)
+	mtsprg0	%r3
+
+	bl	pmap_bootstrap_ap
+
+	bl	cpudep_ap_bootstrap
+	/* Switch to the idle thread's kstack */
+	mr	%r1, %r3
+	
+	bl	machdep_ap_bootstrap
+
+	/* NOT REACHED */
+6:	b	6b
+#endif /* SMP */
+
+/*
+ * Invalidate all entries in the given TLB.
+ *
+ * r3	TLBSEL
+ */
+tlb_inval_all:
+	rlwinm	%r3, %r3, 3, 0x18	/* TLBSEL */
+	ori	%r3, %r3, 0x4		/* INVALL */
+	tlbivax	0, %r3
+	isync
+	msync
+
+	tlbsync
+	msync
+	blr
+
+/*
+ * expects address to look up in r3, returns entry number in r29
+ *
+ * FIXME: the hidden assumption is we are now running in AS=0, but we should
+ * retrieve actual AS from MSR[IS|DS] and put it in MAS6[SAS]
+ */
+tlb1_find_current:
+	mfspr	%r17, SPR_PID0
+	slwi	%r17, %r17, MAS6_SPID0_SHIFT
+	mtspr	SPR_MAS6, %r17
+	isync
+	tlbsx	0, %r3
+	mfspr	%r17, SPR_MAS0
+	rlwinm	%r29, %r17, 16, 20, 31		/* MAS0[ESEL] -> r29 */
+
+	/* Make sure we have IPROT set on the entry */
+	mfspr	%r17, SPR_MAS1
+	oris	%r17, %r17, MAS1_IPROT at h
+	mtspr	SPR_MAS1, %r17
+	isync
+	tlbwe
+	isync
+	msync
+	blr
+
+/*
+ * Invalidates a single entry in TLB1.
+ *
+ * r3		ESEL
+ * r4-r5	scratched
+ */
+tlb1_inval_entry:
+	lis	%r4, MAS0_TLBSEL1 at h	/* Select TLB1 */
+	rlwimi	%r4, %r3, 16, 12, 15	/* Select our entry */
+	mtspr	SPR_MAS0, %r4
+	isync
+	tlbre
+	li	%r5, 0			/* MAS1[V] = 0 */
+	mtspr	SPR_MAS1, %r5
+	isync
+	tlbwe
+	isync
+	msync
+	blr
+
+/*
+ * r3		entry of temp translation
+ * r29		entry of current translation
+ * r28		returns temp entry passed in r3
+ * r4-r5	scratched
+ */
+tlb1_temp_mapping_as1:
+	mr	%r28, %r3
+
+	/* Read our current translation */
+	lis	%r3, MAS0_TLBSEL1 at h	/* Select TLB1 */
+	rlwimi	%r3, %r29, 16, 12, 15	/* Select our current entry */
+	mtspr	SPR_MAS0, %r3
+	isync
+	tlbre
+
+	/* Prepare and write temp entry */
+	lis	%r3, MAS0_TLBSEL1 at h	/* Select TLB1 */
+	rlwimi	%r3, %r28, 16, 12, 15	/* Select temp entry */
+	mtspr	SPR_MAS0, %r3
+	isync
+	mfspr	%r5, SPR_MAS1
+	li	%r4, 1			/* AS=1 */
+	rlwimi	%r5, %r4, 12, 19, 19
+	li	%r4, 0			/* Global mapping, TID=0 */
+	rlwimi	%r5, %r4, 16, 8, 15
+	oris	%r5, %r5, (MAS1_VALID | MAS1_IPROT)@h
+	mtspr	SPR_MAS1, %r5
+	isync
+	tlbwe
+	isync
+	msync
+	blr
+
+/*
+ * Loops over TLB1, invalidates all entries skipping the one which currently
+ * maps this code.
+ *
+ * r29		current entry
+ * r3-r5	scratched
+ */
+tlb1_inval_all_but_current:
+	mr	%r6, %r3
+	mfspr	%r3, SPR_TLB1CFG	/* Get number of entries */
+	andi.	%r3, %r3, TLBCFG_NENTRY_MASK at l
+	li	%r4, 0			/* Start from Entry 0 */
+1:	lis	%r5, MAS0_TLBSEL1 at h
+	rlwimi	%r5, %r4, 16, 12, 15
+	mtspr	SPR_MAS0, %r5
+	isync
+	tlbre
+	mfspr	%r5, SPR_MAS1
+	cmpw	%r4, %r29		/* our current entry? */
+	beq	2f
+	rlwinm	%r5, %r5, 0, 2, 31	/* clear VALID and IPROT bits */
+	mtspr	SPR_MAS1, %r5
+	isync
+	tlbwe
+	isync
+	msync
+2:	addi	%r4, %r4, 1
+	cmpw	%r4, %r3		/* Check if this is the last entry */
+	bne	1b
+	blr
+
+#ifdef SMP
+__boot_page_padding:
+	/*
+	 * Boot page needs to be exactly 4K, with the last word of this page
+	 * acting as the reset vector, so we need to stuff the remainder.
+	 * Upon release from holdoff CPU fetches the last word of the boot
+	 * page.
+	 */
+	.space	4092 - (__boot_page_padding - __boot_page)
+	b	__boot_page
+#endif /* SMP */
+
+/************************************************************************/
+/* locore subroutines */
+/************************************************************************/
+
+ivor_setup:
+	/* Set base address of interrupt handler routines */
+	lis	%r3, interrupt_vector_base at h
+	mtspr	SPR_IVPR, %r3
+
+	/* Assign interrupt handler routines offsets */
+	li	%r3, int_critical_input at l
+	mtspr	SPR_IVOR0, %r3
+	li	%r3, int_machine_check at l
+	mtspr	SPR_IVOR1, %r3
+	li	%r3, int_data_storage at l
+	mtspr	SPR_IVOR2, %r3
+	li	%r3, int_instr_storage at l
+	mtspr	SPR_IVOR3, %r3
+	li	%r3, int_external_input at l
+	mtspr	SPR_IVOR4, %r3
+	li	%r3, int_alignment at l
+	mtspr	SPR_IVOR5, %r3
+	li	%r3, int_program at l
+	mtspr	SPR_IVOR6, %r3
+	li	%r3, int_syscall at l
+	mtspr	SPR_IVOR8, %r3
+	li	%r3, int_decrementer at l
+	mtspr	SPR_IVOR10, %r3
+	li	%r3, int_fixed_interval_timer at l
+	mtspr	SPR_IVOR11, %r3
+	li	%r3, int_watchdog at l
+	mtspr	SPR_IVOR12, %r3
+	li	%r3, int_data_tlb_error at l
+	mtspr	SPR_IVOR13, %r3
+	li	%r3, int_inst_tlb_error at l
+	mtspr	SPR_IVOR14, %r3
+	li	%r3, int_debug at l
+	mtspr	SPR_IVOR15, %r3
+	blr
+
+/*
+ * void tid_flush(tlbtid_t tid);
+ *
+ * Invalidate all TLB0 entries which match the given TID. Note this is
+ * dedicated for cases when invalidation(s) should NOT be propagated to other
+ * CPUs.
+ *
+ * Global vars tlb0_ways, tlb0_entries_per_way are assumed to have been set up
+ * correctly (by tlb0_get_tlbconf()).
+ *
+ */
+ENTRY(tid_flush)
+	cmpwi	%r3, TID_KERNEL
+	beq	tid_flush_end	/* don't evict kernel translations */
+
+	/* Number of TLB0 ways */
+	lis	%r4, tlb0_ways at h
+	ori	%r4, %r4, tlb0_ways at l
+	lwz	%r4, 0(%r4)
+
+	/* Number of entries / way */
+	lis	%r5, tlb0_entries_per_way at h
+	ori	%r5, %r5, tlb0_entries_per_way at l
+	lwz	%r5, 0(%r5)
+
+	/* Disable interrupts */
+	mfmsr	%r10
+	wrteei	0
+
+	li	%r6, 0		/* ways counter */
+loop_ways:
+	li	%r7, 0		/* entries [per way] counter */
+loop_entries:
+	/* Select TLB0 and ESEL (way) */
+	lis	%r8, MAS0_TLBSEL0 at h
+	rlwimi	%r8, %r6, 16, 14, 15
+	mtspr	SPR_MAS0, %r8
+	isync
+
+	/* Select EPN (entry within the way) */
+	rlwinm	%r8, %r7, 12, 13, 19
+	mtspr	SPR_MAS2, %r8
+	isync
+	tlbre
+
+	/* Check if valid entry */
+	mfspr	%r8, SPR_MAS1
+	andis.	%r9, %r8, MAS1_VALID at h
+	beq	next_entry	/* invalid entry */
+
+	/* Check if this is our TID */
+	rlwinm	%r9, %r8, 16, 24, 31
+
+	cmplw	%r9, %r3
+	bne	next_entry	/* not our TID */
+
+	/* Clear VALID bit */
+	rlwinm	%r8, %r8, 0, 1, 31
+	mtspr	SPR_MAS1, %r8
+	isync
+	tlbwe
+	isync
+	msync
+
+next_entry:
+	addi	%r7, %r7, 1
+	cmpw	%r7, %r5
+	bne	loop_entries
+
+	/* Next way */
+	addi	%r6, %r6, 1
+	cmpw	%r6, %r4
+	bne	loop_ways
+
+	/* Restore MSR (possibly re-enable interrupts) */
+	mtmsr	%r10
+	isync
+
+tid_flush_end:
+	blr
+
+/*
+ * Cache disable/enable/inval sequences according
+ * to section 2.16 of E500CORE RM.
+ */
+ENTRY(dcache_inval)
+	/* Invalidate d-cache */
+	mfspr	%r3, SPR_L1CSR0
+	ori	%r3, %r3, (L1CSR0_DCFI | L1CSR0_DCLFR)@l
+	msync
+	isync
+	mtspr	SPR_L1CSR0, %r3
+	isync
+1:	mfspr	%r3, SPR_L1CSR0
+	andi.	%r3, %r3, L1CSR0_DCFI
+	bne	1b
+	blr
+
+ENTRY(dcache_disable)
+	/* Disable d-cache */
+	mfspr	%r3, SPR_L1CSR0
+	li	%r4, L1CSR0_DCE at l
+	not	%r4, %r4
+	and	%r3, %r3, %r4
+	msync
+	isync
+	mtspr	SPR_L1CSR0, %r3
+	isync
+	blr
+
+ENTRY(dcache_enable)
+	/* Enable d-cache */
+	mfspr	%r3, SPR_L1CSR0
+	oris	%r3, %r3, (L1CSR0_DCPE | L1CSR0_DCE)@h
+	ori	%r3, %r3, (L1CSR0_DCPE | L1CSR0_DCE)@l
+	msync
+	isync
+	mtspr	SPR_L1CSR0, %r3
+	isync
+	blr
+
+ENTRY(icache_inval)
+	/* Invalidate i-cache */
+	mfspr	%r3, SPR_L1CSR1
+	ori	%r3, %r3, (L1CSR1_ICFI | L1CSR1_ICLFR)@l
+	isync
+	mtspr	SPR_L1CSR1, %r3
+	isync
+1:	mfspr	%r3, SPR_L1CSR1
+	andi.	%r3, %r3, L1CSR1_ICFI
+	bne	1b
+	blr
+
+ENTRY(icache_disable)
+	/* Disable i-cache */
+	mfspr	%r3, SPR_L1CSR1
+	li	%r4, L1CSR1_ICE at l
+	not	%r4, %r4
+	and	%r3, %r3, %r4
+	isync
+	mtspr	SPR_L1CSR1, %r3
+	isync
+	blr
+
+ENTRY(icache_enable)
+	/* Enable i-cache */
+	mfspr	%r3, SPR_L1CSR1
+	oris	%r3, %r3, (L1CSR1_ICPE | L1CSR1_ICE)@h
+	ori	%r3, %r3, (L1CSR1_ICPE | L1CSR1_ICE)@l
+	isync
+	mtspr	SPR_L1CSR1, %r3
+	isync
+	blr
+
+/*
+ * int setfault()
+ *
+ * Similar to setjmp to setup for handling faults on accesses to user memory.
+ * Any routine using this may only call bcopy, either the form below,
+ * or the (currently used) C code optimized, so it doesn't use any non-volatile
+ * registers.
+ */
+	.globl	setfault
+setfault:
+	mflr	%r0
+	mfsprg0	%r4
+	lwz	%r4, TD_PCB(%r2)
+	stw	%r3, PCB_ONFAULT(%r4)
+	mfcr	%r10
+	mfctr	%r11
+	mfxer	%r12
+	stw	%r0, 0(%r3)
+	stw	%r1, 4(%r3)
+	stw	%r2, 8(%r3)
+	stmw	%r10, 12(%r3)		/* store CR, CTR, XER, [r13 .. r31] */
+	li	%r3, 0			/* return FALSE */
+	blr
+
+/************************************************************************/
+/* Data section								*/
+/************************************************************************/
+	.data
+	.align	4
+tmpstack:
+	.space	TMPSTACKSZ
+
+/*
+ * Compiled KERNBASE locations
+ */
+	.globl	kernbase
+	.set	kernbase, KERNBASE
+
+/*
+ * Globals
+ */
+#define	INTRCNT_COUNT	256		/* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
+
+GLOBAL(intrnames)
+	.space	INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+GLOBAL(sintrnames)
+	.long	INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+
+	.align 4
+GLOBAL(intrcnt)
+	.space	INTRCNT_COUNT * 4 * 2
+GLOBAL(sintrcnt)
+	.long	INTRCNT_COUNT * 4 * 2
+
+#include <powerpc/booke/trap_subr.S>


Property changes on: trunk/sys/powerpc/booke/locore.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/booke/machdep.c
===================================================================
--- trunk/sys/powerpc/booke/machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/booke/machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,663 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2006-2012 Semihalf
+ * 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.
+ *
+ * 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.
+ */
+/*-
+ * Copyright (C) 2001 Benno Rice
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/booke/machdep.c 266003 2014-05-14 04:14:58Z ian $");
+
+#include "opt_compat.h"
+#include "opt_ddb.h"
+#include "opt_kstack_pages.h"
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <sys/cpu.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rwlock.h>
+#include <sys/sysctl.h>
+#include <sys/exec.h>
+#include <sys/ktr.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/signalvar.h>
+#include <sys/sysent.h>
+#include <sys/imgact.h>
+#include <sys/msgbuf.h>
+#include <sys/ptrace.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_page.h>
+#include <vm/vm_object.h>
+#include <vm/vm_pager.h>
+
+#include <machine/cpu.h>
+#include <machine/kdb.h>
+#include <machine/reg.h>
+#include <machine/vmparam.h>
+#include <machine/spr.h>
+#include <machine/hid.h>
+#include <machine/psl.h>
+#include <machine/trap.h>
+#include <machine/md_var.h>
+#include <machine/mmuvar.h>
+#include <machine/sigframe.h>
+#include <machine/machdep.h>
+#include <machine/metadata.h>
+#include <machine/platform.h>
+
+#include <sys/linker.h>
+#include <sys/reboot.h>
+
+#include <contrib/libfdt/libfdt.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#ifdef DDB
+extern vm_offset_t ksym_start, ksym_end;
+#endif
+
+#ifdef  DEBUG
+#define debugf(fmt, args...) printf(fmt, ##args)
+#else
+#define debugf(fmt, args...)
+#endif
+
+extern unsigned char kernel_text[];
+extern unsigned char _etext[];
+extern unsigned char _edata[];
+extern unsigned char __bss_start[];
+extern unsigned char __sbss_start[];
+extern unsigned char __sbss_end[];
+extern unsigned char _end[];
+
+/*
+ * Bootinfo is passed to us by legacy loaders. Save the address of the
+ * structure to handle backward compatibility.
+ */
+uint32_t *bootinfo;
+
+struct kva_md_info kmi;
+struct pcpu __pcpu[MAXCPU];
+struct trapframe frame0;
+int cold = 1;
+long realmem = 0;
+long Maxmem = 0;
+char machine[] = "powerpc";
+SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
+
+int cacheline_size = 32;
+
+SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
+	   CTLFLAG_RD, &cacheline_size, 0, "");
+
+int hw_direct_map = 0;
+
+static void cpu_booke_startup(void *);
+SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_booke_startup, NULL);
+
+void print_kernel_section_addr(void);
+void print_kenv(void);
+u_int booke_init(uint32_t, uint32_t);
+
+extern int elf32_nxstack;
+
+static void
+cpu_booke_startup(void *dummy)
+{
+	int indx;
+	unsigned long size;
+
+	/* Initialise the decrementer-based clock. */
+	decr_init();
+
+	/* Good {morning,afternoon,evening,night}. */
+	cpu_setup(PCPU_GET(cpuid));
+
+	printf("real memory  = %lu (%ld MB)\n", ptoa(physmem),
+	    ptoa(physmem) / 1048576);
+	realmem = physmem;
+
+	/* Display any holes after the first chunk of extended memory. */
+	if (bootverbose) {
+		printf("Physical memory chunk(s):\n");
+		for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
+			size = phys_avail[indx + 1] - phys_avail[indx];
+
+			printf("0x%08x - 0x%08x, %lu bytes (%lu pages)\n",
+			    phys_avail[indx], phys_avail[indx + 1] - 1,
+			    size, size / PAGE_SIZE);
+		}
+	}
+
+	vm_ksubmap_init(&kmi);
+
+	printf("avail memory = %lu (%ld MB)\n", ptoa(cnt.v_free_count),
+	    ptoa(cnt.v_free_count) / 1048576);
+
+	/* Set up buffers, so they can be used to read disk labels. */
+	bufinit();
+	vm_pager_bufferinit();
+
+	/* Cpu supports execution permissions on the pages. */
+	elf32_nxstack = 1;
+}
+
+static char *
+kenv_next(char *cp)
+{
+
+	if (cp != NULL) {
+		while (*cp != 0)
+			cp++;
+		cp++;
+		if (*cp == 0)
+			cp = NULL;
+	}
+	return (cp);
+}
+
+void
+print_kenv(void)
+{
+	int len;
+	char *cp;
+
+	debugf("loader passed (static) kenv:\n");
+	if (kern_envp == NULL) {
+		debugf(" no env, null ptr\n");
+		return;
+	}
+	debugf(" kern_envp = 0x%08x\n", (u_int32_t)kern_envp);
+
+	len = 0;
+	for (cp = kern_envp; cp != NULL; cp = kenv_next(cp))
+		debugf(" %x %s\n", (u_int32_t)cp, cp);
+}
+
+void
+print_kernel_section_addr(void)
+{
+
+	debugf("kernel image addresses:\n");
+	debugf(" kernel_text    = 0x%08x\n", (uint32_t)kernel_text);
+	debugf(" _etext (sdata) = 0x%08x\n", (uint32_t)_etext);
+	debugf(" _edata         = 0x%08x\n", (uint32_t)_edata);
+	debugf(" __sbss_start   = 0x%08x\n", (uint32_t)__sbss_start);
+	debugf(" __sbss_end     = 0x%08x\n", (uint32_t)__sbss_end);
+	debugf(" __sbss_start   = 0x%08x\n", (uint32_t)__bss_start);
+	debugf(" _end           = 0x%08x\n", (uint32_t)_end);
+}
+
+static int
+booke_check_for_fdt(uint32_t arg1, vm_offset_t *dtbp)
+{
+	void *ptr;
+
+	if (arg1 % 8 != 0)
+		return (-1);
+
+	ptr = (void *)pmap_early_io_map(arg1, PAGE_SIZE);
+	if (fdt_check_header(ptr) != 0)
+		return (-1);
+
+	*dtbp = (vm_offset_t)ptr;
+
+	return (0);
+}
+
+u_int
+booke_init(uint32_t arg1, uint32_t arg2)
+{
+	struct pcpu *pc;
+	void *kmdp, *mdp;
+	vm_offset_t dtbp, end;
+
+	kmdp = NULL;
+
+	end = (uintptr_t)_end;
+	dtbp = (vm_offset_t)NULL;
+
+	/* Set up TLB initially */
+	bootinfo = NULL;
+	tlb1_init();
+
+	/*
+	 * Handle the various ways we can get loaded and started:
+	 *  -	FreeBSD's loader passes the pointer to the metadata
+	 *	in arg1, with arg2 undefined. arg1 has a value that's
+	 *	relative to the kernel's link address (i.e. larger
+	 *	than 0xc0000000).
+	 *  -	Juniper's loader passes the metadata pointer in arg2
+	 *	and sets arg1 to zero. This is to signal that the
+	 *	loader maps the kernel and starts it at its link
+	 *	address (unlike the FreeBSD loader).
+	 *  -	U-Boot passes the standard argc and argv parameters
+	 *	in arg1 and arg2 (resp). arg1 is between 1 and some
+	 *	relatively small number, such as 64K. arg2 is the
+	 *	physical address of the argv vector.
+	 *  -   ePAPR loaders pass an FDT blob in r3 (arg1) and the magic hex
+	 *      string 0x45504150 ('ePAP') in r6 (which has been lost by now).
+	 *      r4 (arg2) is supposed to be set to zero, but is not always.
+	 */
+	
+	if (arg1 == 0)				/* Juniper loader */
+		mdp = (void *)arg2;
+	else if (booke_check_for_fdt(arg1, &dtbp) == 0) { /* ePAPR */
+		end = roundup(end, 8);
+		memmove((void *)end, (void *)dtbp, fdt_totalsize((void *)dtbp));
+		dtbp = end;
+		end += fdt_totalsize((void *)dtbp);
+		mdp = NULL;
+	} else if (arg1 > (uintptr_t)kernel_text)	/* FreeBSD loader */
+		mdp = (void *)arg1;
+	else					/* U-Boot */
+		mdp = NULL;
+
+	/*
+	 * Parse metadata and fetch parameters.
+	 */
+	if (mdp != NULL) {
+		preload_metadata = mdp;
+		kmdp = preload_search_by_type("elf kernel");
+		if (kmdp != NULL) {
+			boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
+			kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
+			dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t);
+			end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
+
+			bootinfo = (uint32_t *)preload_search_info(kmdp,
+			    MODINFO_METADATA | MODINFOMD_BOOTINFO);
+
+#ifdef DDB
+			ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
+			ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
+#endif
+		}
+	} else {
+		bzero(__sbss_start, __sbss_end - __sbss_start);
+		bzero(__bss_start, _end - __bss_start);
+	}
+
+#if defined(FDT_DTB_STATIC)
+	/*
+	 * In case the device tree blob was not retrieved (from metadata) try
+	 * to use the statically embedded one.
+	 */
+	if (dtbp == (vm_offset_t)NULL)
+		dtbp = (vm_offset_t)&fdt_static_dtb;
+#endif
+
+	if (OF_install(OFW_FDT, 0) == FALSE)
+		while (1);
+
+	if (OF_init((void *)dtbp) != 0)
+		while (1);
+
+	OF_interpret("perform-fixup", 0);
+	
+	/* Reset TLB1 to get rid of temporary mappings */
+	tlb1_init();
+
+	/* Reset Time Base */
+	mttb(0);
+
+	/* Init params/tunables that can be overridden by the loader. */
+	init_param1();
+
+	/* Start initializing proc0 and thread0. */
+	proc_linkup0(&proc0, &thread0);
+	thread0.td_frame = &frame0;
+
+	/* Set up per-cpu data and store the pointer in SPR general 0. */
+	pc = &__pcpu[0];
+	pcpu_init(pc, 0, sizeof(struct pcpu));
+	pc->pc_curthread = &thread0;
+#ifdef __powerpc64__
+	__asm __volatile("mr 13,%0" :: "r"(pc->pc_curthread));
+#else
+	__asm __volatile("mr 2,%0" :: "r"(pc->pc_curthread));
+#endif
+	__asm __volatile("mtsprg 0, %0" :: "r"(pc));
+
+	/* Initialize system mutexes. */
+	mutex_init();
+
+	/* Initialize the console before printing anything. */
+	cninit();
+
+	/* Print out some debug info... */
+	debugf("%s: console initialized\n", __func__);
+	debugf(" arg3 mdp = 0x%08x\n", (u_int32_t)mdp);
+	debugf(" end = 0x%08x\n", (u_int32_t)end);
+	debugf(" boothowto = 0x%08x\n", boothowto);
+	debugf(" kernel ccsrbar = 0x%08x\n", CCSRBAR_VA);
+	debugf(" MSR = 0x%08x\n", mfmsr());
+#if defined(BOOKE_E500)
+	debugf(" HID0 = 0x%08x\n", mfspr(SPR_HID0));
+	debugf(" HID1 = 0x%08x\n", mfspr(SPR_HID1));
+	debugf(" BUCSR = 0x%08x\n", mfspr(SPR_BUCSR));
+#endif
+
+	debugf(" dtbp = 0x%08x\n", (uint32_t)dtbp);
+
+	print_kernel_section_addr();
+	print_kenv();
+#if defined(BOOKE_E500)
+	//tlb1_print_entries();
+	//tlb1_print_tlbentries();
+#endif
+
+	kdb_init();
+
+#ifdef KDB
+	if (boothowto & RB_KDB)
+		kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
+#endif
+
+	/* Initialise platform module */
+	platform_probe_and_attach();
+
+	/* Initialise virtual memory. */
+	pmap_mmu_install(MMU_TYPE_BOOKE, 0);
+	pmap_bootstrap((uintptr_t)kernel_text, end);
+	pmap_bootstrapped = 1;
+	debugf("MSR = 0x%08x\n", mfmsr());
+#if defined(BOOKE_E500)
+	//tlb1_print_entries();
+	//tlb1_print_tlbentries();
+#endif
+
+	/* Initialize params/tunables that are derived from memsize. */
+	init_param2(physmem);
+
+	/* Finish setting up thread0. */
+	thread0.td_pcb = (struct pcb *)
+	    ((thread0.td_kstack + thread0.td_kstack_pages * PAGE_SIZE -
+	    sizeof(struct pcb)) & ~15);
+	bzero((void *)thread0.td_pcb, sizeof(struct pcb));
+	pc->pc_curpcb = thread0.td_pcb;
+
+	/* Initialise the message buffer. */
+	msgbufinit(msgbufp, msgbufsize);
+
+	/* Enable Machine Check interrupt. */
+	mtmsr(mfmsr() | PSL_ME);
+	isync();
+
+	/* Enable L1 caches */
+	booke_enable_l1_cache();
+
+	debugf("%s: SP = 0x%08x\n", __func__,
+	    ((uintptr_t)thread0.td_pcb - 16) & ~15);
+
+	return (((uintptr_t)thread0.td_pcb - 16) & ~15);
+}
+
+#define RES_GRANULE 32
+extern uint32_t tlb0_miss_locks[];
+
+/* Initialise a struct pcpu. */
+void
+cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
+{
+
+	pcpu->pc_tid_next = TID_MIN;
+
+#ifdef SMP
+	uint32_t *ptr;
+	int words_per_gran = RES_GRANULE / sizeof(uint32_t);
+
+	ptr = &tlb0_miss_locks[cpuid * words_per_gran];
+	pcpu->pc_booke_tlb_lock = ptr;
+	*ptr = TLB_UNLOCKED;
+	*(ptr + 1) = 0;		/* recurse counter */
+#endif
+}
+
+/*
+ * Flush the D-cache for non-DMA I/O so that the I-cache can
+ * be made coherent later.
+ */
+void
+cpu_flush_dcache(void *ptr, size_t len)
+{
+	register_t addr, off;
+
+	/*
+	 * Align the address to a cacheline and adjust the length
+	 * accordingly. Then round the length to a multiple of the
+	 * cacheline for easy looping.
+	 */
+	addr = (uintptr_t)ptr;
+	off = addr & (cacheline_size - 1);
+	addr -= off;
+	len = (len + off + cacheline_size - 1) & ~(cacheline_size - 1);
+
+	while (len > 0) {
+		__asm __volatile ("dcbf 0,%0" :: "r"(addr));
+		__asm __volatile ("sync");
+		addr += cacheline_size;
+		len -= cacheline_size;
+	}
+}
+
+void
+spinlock_enter(void)
+{
+	struct thread *td;
+	register_t msr;
+
+	td = curthread;
+	if (td->td_md.md_spinlock_count == 0) {
+		msr = intr_disable();
+		td->td_md.md_spinlock_count = 1;
+		td->td_md.md_saved_msr = msr;
+	} else
+		td->td_md.md_spinlock_count++;
+	critical_enter();
+}
+
+void
+spinlock_exit(void)
+{
+	struct thread *td;
+	register_t msr;
+
+	td = curthread;
+	critical_exit();
+	msr = td->td_md.md_saved_msr;
+	td->td_md.md_spinlock_count--;
+	if (td->td_md.md_spinlock_count == 0)
+		intr_restore(msr);
+}
+
+/* Shutdown the CPU as much as possible. */
+void
+cpu_halt(void)
+{
+
+	mtmsr(mfmsr() & ~(PSL_CE | PSL_EE | PSL_ME | PSL_DE));
+	while (1)
+		;
+}
+
+int
+ptrace_set_pc(struct thread *td, unsigned long addr)
+{
+	struct trapframe *tf;
+
+	tf = td->td_frame;
+	tf->srr0 = (register_t)addr;
+
+	return (0);
+}
+
+int
+ptrace_single_step(struct thread *td)
+{
+	struct trapframe *tf;
+
+	tf = td->td_frame;
+	tf->srr1 |= PSL_DE;
+	tf->cpu.booke.dbcr0 |= (DBCR0_IDM | DBCR0_IC);
+	return (0);
+}
+
+int
+ptrace_clear_single_step(struct thread *td)
+{
+	struct trapframe *tf;
+
+	tf = td->td_frame;
+	tf->srr1 &= ~PSL_DE;
+	tf->cpu.booke.dbcr0 &= ~(DBCR0_IDM | DBCR0_IC);
+	return (0);
+}
+
+void
+kdb_cpu_clear_singlestep(void)
+{
+	register_t r;
+
+	r = mfspr(SPR_DBCR0);
+	mtspr(SPR_DBCR0, r & ~DBCR0_IC);
+	kdb_frame->srr1 &= ~PSL_DE;
+}
+
+void
+kdb_cpu_set_singlestep(void)
+{
+	register_t r;
+
+	r = mfspr(SPR_DBCR0);
+	mtspr(SPR_DBCR0, r | DBCR0_IC | DBCR0_IDM);
+	kdb_frame->srr1 |= PSL_DE;
+}
+
+void
+bzero(void *buf, size_t len)
+{
+	caddr_t p;
+
+	p = buf;
+
+	while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
+		*p++ = 0;
+		len--;
+	}
+
+	while (len >= sizeof(u_long) * 8) {
+		*(u_long*) p = 0;
+		*((u_long*) p + 1) = 0;
+		*((u_long*) p + 2) = 0;
+		*((u_long*) p + 3) = 0;
+		len -= sizeof(u_long) * 8;
+		*((u_long*) p + 4) = 0;
+		*((u_long*) p + 5) = 0;
+		*((u_long*) p + 6) = 0;
+		*((u_long*) p + 7) = 0;
+		p += sizeof(u_long) * 8;
+	}
+
+	while (len >= sizeof(u_long)) {
+		*(u_long*) p = 0;
+		len -= sizeof(u_long);
+		p += sizeof(u_long);
+	}
+
+	while (len) {
+		*p++ = 0;
+		len--;
+	}
+}
+


Property changes on: trunk/sys/powerpc/booke/machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/booke/machdep_e500.c
===================================================================
--- trunk/sys/powerpc/booke/machdep_e500.c	                        (rev 0)
+++ trunk/sys/powerpc/booke/machdep_e500.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,157 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011-2012 Semihalf.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/booke/machdep_e500.c 265996 2014-05-14 00:51:26Z ian $");
+
+#include <sys/types.h>
+#include <sys/reboot.h>
+
+#include <machine/machdep.h>
+
+#include <dev/fdt/fdt_common.h>
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+extern void dcache_enable(void);
+extern void dcache_inval(void);
+extern void icache_enable(void);
+extern void icache_inval(void);
+extern void l2cache_enable(void);
+extern void l2cache_inval(void);
+
+void
+booke_init_tlb(vm_paddr_t fdt_immr_pa)
+{
+
+}
+
+void
+booke_enable_l1_cache(void)
+{
+	uint32_t csr;
+
+	/* Enable D-cache if applicable */
+	csr = mfspr(SPR_L1CSR0);
+	if ((csr & L1CSR0_DCE) == 0) {
+		dcache_inval();
+		dcache_enable();
+	}
+
+	csr = mfspr(SPR_L1CSR0);
+	if ((boothowto & RB_VERBOSE) != 0 || (csr & L1CSR0_DCE) == 0)
+		printf("L1 D-cache %sabled\n",
+		    (csr & L1CSR0_DCE) ? "en" : "dis");
+
+	/* Enable L1 I-cache if applicable. */
+	csr = mfspr(SPR_L1CSR1);
+	if ((csr & L1CSR1_ICE) == 0) {
+		icache_inval();
+		icache_enable();
+	}
+
+	csr = mfspr(SPR_L1CSR1);
+	if ((boothowto & RB_VERBOSE) != 0 || (csr & L1CSR1_ICE) == 0)
+		printf("L1 I-cache %sabled\n",
+		    (csr & L1CSR1_ICE) ? "en" : "dis");
+}
+
+#if 0
+void
+booke_enable_l2_cache(void)
+{
+	uint32_t csr;
+
+	/* Enable L2 cache on E500mc */
+	if ((((mfpvr() >> 16) & 0xFFFF) == FSL_E500mc) ||
+	    (((mfpvr() >> 16) & 0xFFFF) == FSL_E5500)) {
+		csr = mfspr(SPR_L2CSR0);
+		if ((csr & L2CSR0_L2E) == 0) {
+			l2cache_inval();
+			l2cache_enable();
+		}
+
+		csr = mfspr(SPR_L2CSR0);
+		if ((boothowto & RB_VERBOSE) != 0 || (csr & L2CSR0_L2E) == 0)
+			printf("L2 cache %sabled\n",
+			    (csr & L2CSR0_L2E) ? "en" : "dis");
+	}
+}
+
+void
+booke_enable_l3_cache(void)
+{
+	uint32_t csr, size, ver;
+
+	/* Enable L3 CoreNet Platform Cache (CPC) */
+	ver = SVR_VER(mfspr(SPR_SVR));
+	if (ver == SVR_P2041 || ver == SVR_P2041E || ver == SVR_P3041 ||
+	    ver == SVR_P3041E || ver == SVR_P5020 || ver == SVR_P5020E) {
+		csr = ccsr_read4(OCP85XX_CPC_CSR0);
+		if ((csr & OCP85XX_CPC_CSR0_CE) == 0) {
+			l3cache_inval();
+			l3cache_enable();
+		}
+
+		csr = ccsr_read4(OCP85XX_CPC_CSR0);
+		if ((boothowto & RB_VERBOSE) != 0 ||
+		    (csr & OCP85XX_CPC_CSR0_CE) == 0) {
+			size = OCP85XX_CPC_CFG0_SZ_K(ccsr_read4(OCP85XX_CPC_CFG0));
+			printf("L3 Corenet Platform Cache: %d KB %sabled\n",
+			    size, (csr & OCP85XX_CPC_CSR0_CE) == 0 ?
+			    "dis" : "en");
+		}
+	}
+}
+
+void
+booke_disable_l2_cache(void)
+{
+}
+
+static void
+l3cache_inval(void)
+{
+
+	/* Flash invalidate the CPC and clear all the locks */
+	ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_FI |
+	    OCP85XX_CPC_CSR0_LFC);
+	while (ccsr_read4(OCP85XX_CPC_CSR0) & (OCP85XX_CPC_CSR0_FI |
+	    OCP85XX_CPC_CSR0_LFC))
+		;
+}
+
+static void
+l3cache_enable(void)
+{
+
+	ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_CE |
+	    OCP85XX_CPC_CSR0_PE);
+	/* Read back to sync write */
+	ccsr_read4(OCP85XX_CPC_CSR0);
+}
+#endif


Property changes on: trunk/sys/powerpc/booke/machdep_e500.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/booke/machdep_ppc4xx.c
===================================================================
--- trunk/sys/powerpc/booke/machdep_ppc4xx.c	                        (rev 0)
+++ trunk/sys/powerpc/booke/machdep_ppc4xx.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,220 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011-2012 Semihalf.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/booke/machdep_ppc4xx.c 236324 2012-05-30 17:34:40Z raj $");
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/machdep.h>
+
+#include <powerpc/booke/dcr.h>
+#include <powerpc/apm86xxx/apm86xxx.h>
+
+#include <dev/fdt/fdt_common.h>
+
+#define OCP_ADDR_WORDLO(addr)	((uint32_t)((uint64_t)(addr) & 0xFFFFFFFF))
+#define OCP_ADDR_WORDHI(addr)	((uint32_t)((uint64_t)(addr) >> 32))
+
+extern void tlb_write(u_int, uint32_t, uint32_t, uint32_t, tlbtid_t, uint32_t,
+    uint32_t);
+extern void tlb_read(u_int, uint32_t *, uint32_t *, uint32_t *, uint32_t *,
+    uint32_t *, uint32_t *);
+
+unsigned int tlb_static_entries;
+unsigned int tlb_current_entry = TLB_SIZE;
+unsigned int tlb_misses = 0;
+unsigned int tlb_invals = 0;
+
+void tlb_map(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
+void tlb_map_mem(uint32_t, uint32_t, uint32_t);
+void tlb_dump(void);
+
+void
+booke_init_tlb(vm_paddr_t fdt_immr_pa)
+{
+
+	/* Map register space */
+	tlb_map(APM86XXX_DEEP_SLEEP_VA,
+	    OCP_ADDR_WORDLO(APM86XXX_DEEP_SLEEP_PA),
+	    OCP_ADDR_WORDHI(APM86XXX_DEEP_SLEEP_PA), TLB_VALID | TLB_SIZE_16M,
+	    TLB_SW | TLB_SR | TLB_I | TLB_G);
+
+	tlb_map(APM86XXX_CSR_VA, OCP_ADDR_WORDLO(APM86XXX_CSR_PA),
+	    OCP_ADDR_WORDHI(APM86XXX_CSR_PA), TLB_VALID | TLB_SIZE_16M,
+	    TLB_SW | TLB_SR | TLB_I | TLB_G);
+
+	tlb_map(APM86XXX_PRIMARY_FABRIC_VA,
+	    OCP_ADDR_WORDLO(APM86XXX_PRIMARY_FABRIC_PA),
+	    OCP_ADDR_WORDHI(APM86XXX_PRIMARY_FABRIC_PA),
+	    TLB_VALID | TLB_SIZE_16M,
+	    TLB_SW | TLB_SR | TLB_I | TLB_G);
+
+	tlb_map(APM86XXX_AHB_VA, OCP_ADDR_WORDLO(APM86XXX_AHB_PA),
+	    OCP_ADDR_WORDHI(APM86XXX_AHB_PA),
+	    TLB_VALID | TLB_SIZE_16M,
+	    TLB_SW | TLB_SR | TLB_I | TLB_G);
+
+	/* Map MailBox space */
+	tlb_map(APM86XXX_MBOX_VA, OCP_ADDR_WORDLO(APM86XXX_MBOX_PA),
+	    OCP_ADDR_WORDHI(APM86XXX_MBOX_PA),
+	    TLB_VALID | TLB_SIZE_4K,
+	    TLB_UX | TLB_UW | TLB_UR |
+	    TLB_SX | TLB_SW | TLB_SR |
+	    TLB_I | TLB_G);
+
+	tlb_map(APM86XXX_MBOX_VA + 0x1000,
+	    OCP_ADDR_WORDLO(APM86XXX_MBOX_PA) + 0x1000,
+	    OCP_ADDR_WORDHI(APM86XXX_MBOX_PA),
+	    TLB_VALID | TLB_SIZE_4K,
+	    TLB_UX | TLB_UW | TLB_UR |
+	    TLB_SX | TLB_SW | TLB_SR |
+	    TLB_I | TLB_G);
+
+	tlb_map(APM86XXX_MBOX_VA + 0x2000,
+	    OCP_ADDR_WORDLO(APM86XXX_MBOX_PA)+ 0x2000,
+	    OCP_ADDR_WORDHI(APM86XXX_MBOX_PA),
+	    TLB_VALID | TLB_SIZE_4K,
+	    TLB_UX | TLB_UW | TLB_UR |
+	    TLB_SX | TLB_SW | TLB_SR |
+	    TLB_I | TLB_G);
+}
+
+void
+booke_enable_l1_cache(void)
+{
+}
+
+void
+booke_enable_l2_cache(void)
+{
+}
+
+void
+booke_enable_l3_cache(void)
+{
+}
+
+void
+booke_disable_l2_cache(void)
+{
+	uint32_t ccr1,l2cr0;
+
+	/* Disable L2 cache op broadcast */
+	ccr1 = mfspr(SPR_CCR1);
+	ccr1 &= ~CCR1_L2COBE;
+	mtspr(SPR_CCR1, ccr1);
+
+	/* Set L2 array size to 0 i.e. disable L2 cache */
+	mtdcr(DCR_L2DCDCRAI, DCR_L2CR0);
+	l2cr0 = mfdcr(DCR_L2DCDCRDI);
+	l2cr0 &= ~L2CR0_AS;
+	mtdcr(DCR_L2DCDCRDI, l2cr0);
+}
+
+void tlb_map(uint32_t epn, uint32_t rpn, uint32_t erpn, uint32_t flags,
+    uint32_t perms)
+{
+
+	tlb_write(++tlb_static_entries, epn, rpn, erpn, 0, flags, perms);
+}
+
+static void tlb_dump_entry(u_int entry)
+{
+	uint32_t epn, rpn, erpn, tid, flags, perms;
+	const char *size;
+
+	tlb_read(entry, &epn, &rpn, &erpn, &tid, &flags, &perms);
+
+	switch (flags & TLB_SIZE_MASK) {
+	case TLB_SIZE_1K:
+		size = "  1k";
+		break;
+	case TLB_SIZE_4K:
+		size = "  4k";
+		break;
+	case TLB_SIZE_16K:
+		size = " 16k";
+		break;
+	case TLB_SIZE_256K:
+		size = "256k";
+		break;
+	case TLB_SIZE_1M:
+		size = "  1M";
+		break;
+	case TLB_SIZE_16M:
+		size = " 16M";
+		break;
+	case TLB_SIZE_256M:
+		size = "256M";
+		break;
+	case TLB_SIZE_1G:
+		size = "  1G";
+		break;
+	default:
+		size = "????";
+		break;
+	}
+
+
+	printf("TLB[%02u]: 0x%08X => "
+	    "0x%01X_%08X %s %c %c %s %s %s %s %s "
+	    "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c (%u)\n",
+	    entry, epn, erpn, rpn, size,
+	    (flags & TLB_TS)	? '1'		: '0',
+	    (flags & TLB_VALID)	?  'V'		: '.',
+	    (perms & TLB_WL1)	? "WL1"		: "___",
+	    (perms & TLB_IL1I)	? "IL1I"	: "____",
+	    (perms & TLB_IL1D)	? "IL1D"	: "____",
+	    (perms & TLB_IL2I)	? "IL2I"	: "____",
+	    (perms & TLB_IL2D)	? "IL2D"	: "____",
+	    (perms & TLB_U0)	? '1'		: '.',
+	    (perms & TLB_U1)	? '2'		: '.',
+	    (perms & TLB_U2)	? '3'		: '.',
+	    (perms & TLB_U3)	? '4'		: '.',
+	    (perms & TLB_W)		? 'W'		: '.',
+	    (perms & TLB_I)		? 'I'		: '.',
+	    (perms & TLB_M)		? 'M'		: '.',
+	    (perms & TLB_G)		? 'G'		: '.',
+	    (perms & TLB_E)		? 'E'		: '.',
+	    (perms & TLB_UX)	? 'x'		: '.',
+	    (perms & TLB_UW)	? 'w'		: '.',
+	    (perms & TLB_UR)	? 'r'		: '.',
+	    (perms & TLB_SX)	? 'X'		: '.',
+	    (perms & TLB_SW)	? 'W'		: '.',
+	    (perms & TLB_SR)	? 'R'		: '.',
+	    tid);
+}
+
+void tlb_dump(void)
+{
+	int i;
+
+	for (i = 0; i < TLB_SIZE; i++)
+		tlb_dump_entry(i);
+}


Property changes on: trunk/sys/powerpc/booke/machdep_ppc4xx.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/booke/mp_cpudep.c
===================================================================
--- trunk/sys/powerpc/booke/mp_cpudep.c	                        (rev 0)
+++ trunk/sys/powerpc/booke/mp_cpudep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,91 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008-2009 Semihalf, Rafal Jaworowski
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/booke/mp_cpudep.c 266001 2014-05-14 03:09:37Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+
+#include <machine/pcb.h>
+#include <machine/psl.h>
+#include <machine/smp.h>
+#include <machine/spr.h>
+
+extern void dcache_enable(void);
+extern void dcache_inval(void);
+extern void icache_enable(void);
+extern void icache_inval(void);
+
+volatile void *ap_pcpu;
+
+uintptr_t
+cpudep_ap_bootstrap()
+{
+	uint32_t msr, sp, csr;
+
+	/* Enable L1 caches */
+	csr = mfspr(SPR_L1CSR0);
+	if ((csr & L1CSR0_DCE) == 0) {
+		dcache_inval();
+		dcache_enable();
+	}
+
+	csr = mfspr(SPR_L1CSR1);
+	if ((csr & L1CSR1_ICE) == 0) {
+		icache_inval();
+		icache_enable();
+	}
+
+	/* Set MSR */
+	msr = PSL_ME;
+	mtmsr(msr);
+
+	/* Assign pcpu fields, return ptr to this AP's idle thread kstack */
+	pcpup->pc_curthread = pcpup->pc_idlethread;
+#ifdef __powerpc64__
+	__asm __volatile("mr 13,%0" :: "r"(pcpup->pc_curthread));
+#else
+	__asm __volatile("mr 2,%0" :: "r"(pcpup->pc_curthread));
+#endif
+	pcpup->pc_curpcb = pcpup->pc_curthread->td_pcb;
+	sp = pcpup->pc_curpcb->pcb_sp;
+
+	/* XXX shouldn't the pcb_sp be checked/forced for alignment here?? */
+
+	return (sp);
+}
+
+void
+cpudep_ap_setup()
+{
+}


Property changes on: trunk/sys/powerpc/booke/mp_cpudep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/booke/platform_bare.c
===================================================================
--- trunk/sys/powerpc/booke/platform_bare.c	                        (rev 0)
+++ trunk/sys/powerpc/booke/platform_bare.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,161 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008-2012 Semihalf.
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/booke/platform_bare.c 266020 2014-05-14 14:17:51Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <machine/platform.h>
+#include <machine/platformvar.h>
+
+#include "platform_if.h"
+
+extern uint32_t *bootinfo;
+
+static int bare_probe(platform_t);
+static void bare_mem_regions(platform_t, struct mem_region *phys, int *physsz,
+    struct mem_region *avail, int *availsz);
+static u_long bare_timebase_freq(platform_t, struct cpuref *cpuref);
+
+static void bare_reset(platform_t);
+
+static platform_method_t bare_methods[] = {
+	PLATFORMMETHOD(platform_probe,		bare_probe),
+	PLATFORMMETHOD(platform_mem_regions,	bare_mem_regions),
+	PLATFORMMETHOD(platform_timebase_freq,	bare_timebase_freq),
+
+	PLATFORMMETHOD(platform_reset,		bare_reset),
+
+	PLATFORMMETHOD_END
+};
+
+static platform_def_t bare_platform = {
+	"bare",
+	bare_methods,
+	0
+};
+
+PLATFORM_DEF(bare_platform);
+
+static int
+bare_probe(platform_t plat)
+{
+
+	if (OF_peer(0) == -1) /* Needs device tree to work */
+		return (ENXIO);
+
+	return (BUS_PROBE_GENERIC);
+}
+
+void
+bare_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
+    struct mem_region *avail, int *availsz)
+{
+
+	ofw_mem_regions(phys, physsz, avail, availsz);
+}
+
+static u_long
+bare_timebase_freq(platform_t plat, struct cpuref *cpuref)
+{
+	u_long ticks;
+	phandle_t cpus, child;
+	pcell_t freq;
+
+	if (bootinfo != NULL) {
+		if (bootinfo[0] == 1) {
+			/* Backward compatibility. See 8-STABLE. */
+			ticks = bootinfo[3] >> 3;
+		} else {
+			/* Compatibility with Juniper's loader. */
+			ticks = bootinfo[5] >> 3;
+		}
+	} else
+		ticks = 0;
+
+	if ((cpus = OF_finddevice("/cpus")) == -1)
+		goto out;
+
+	if ((child = OF_child(cpus)) == 0)
+		goto out;
+
+	switch (OF_getproplen(child, "timebase-frequency")) {
+	case 4:
+	{
+		uint32_t tbase;
+		OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase));
+		ticks = tbase;
+		return (ticks);
+	}
+	case 8:
+	{
+		uint64_t tbase;
+		OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase));
+		ticks = tbase;
+		return (ticks);
+	}
+	default:
+		break;
+	}
+
+	freq = 0;
+	if (OF_getprop(child, "bus-frequency", (void *)&freq,
+	    sizeof(freq)) <= 0)
+		goto out;
+
+	/*
+	 * Time Base and Decrementer are updated every 8 CCB bus clocks.
+	 * HID0[SEL_TBCLK] = 0
+	 */
+	if (freq != 0)
+		ticks = freq / 8;
+
+out:
+	if (ticks <= 0)
+		panic("Unable to determine timebase frequency!");
+
+	return (ticks);
+}
+
+static void
+bare_reset(platform_t plat)
+{
+
+	printf("Reset failed...\n");
+	while (1)
+		;
+}
+


Property changes on: trunk/sys/powerpc/booke/platform_bare.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/booke/pmap.c
===================================================================
--- trunk/sys/powerpc/booke/pmap.c	                        (rev 0)
+++ trunk/sys/powerpc/booke/pmap.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,3327 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2007-2009 Semihalf, Rafal Jaworowski <raj at semihalf.com>
+ * Copyright (C) 2006 Semihalf, Marian Balakowicz <m8 at semihalf.com>
+ * 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.
+ *
+ * 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.
+ *
+ * Some hw specific parts of this pmap were derived or influenced
+ * by NetBSD's ibm4xx pmap module. More generic code is shared with
+ * a few other pmap modules from the FreeBSD tree.
+ */
+
+ /*
+  * VM layout notes:
+  *
+  * Kernel and user threads run within one common virtual address space
+  * defined by AS=0.
+  *
+  * Virtual address space layout:
+  * -----------------------------
+  * 0x0000_0000 - 0xafff_ffff	: user process
+  * 0xb000_0000 - 0xbfff_ffff	: pmap_mapdev()-ed area (PCI/PCIE etc.)
+  * 0xc000_0000 - 0xc0ff_ffff	: kernel reserved
+  *   0xc000_0000 - data_end	: kernel code+data, env, metadata etc.
+  * 0xc100_0000 - 0xfeef_ffff	: KVA
+  *   0xc100_0000 - 0xc100_3fff : reserved for page zero/copy
+  *   0xc100_4000 - 0xc200_3fff : reserved for ptbl bufs
+  *   0xc200_4000 - 0xc200_8fff : guard page + kstack0
+  *   0xc200_9000 - 0xfeef_ffff	: actual free KVA space
+  * 0xfef0_0000 - 0xffff_ffff	: I/O devices region
+  */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/booke/pmap.c 270920 2014-09-01 07:58:15Z kib $");
+
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/ktr.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/linker.h>
+#include <sys/msgbuf.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rwlock.h>
+#include <sys/sched.h>
+#include <sys/smp.h>
+#include <sys/vmmeter.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_pageout.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_object.h>
+#include <vm/vm_param.h>
+#include <vm/vm_map.h>
+#include <vm/vm_pager.h>
+#include <vm/uma.h>
+
+#include <machine/cpu.h>
+#include <machine/pcb.h>
+#include <machine/platform.h>
+
+#include <machine/tlb.h>
+#include <machine/spr.h>
+#include <machine/md_var.h>
+#include <machine/mmuvar.h>
+#include <machine/pmap.h>
+#include <machine/pte.h>
+
+#include "mmu_if.h"
+
+#ifdef  DEBUG
+#define debugf(fmt, args...) printf(fmt, ##args)
+#else
+#define debugf(fmt, args...)
+#endif
+
+#define TODO			panic("%s: not implemented", __func__);
+
+extern int dumpsys_minidump;
+
+extern unsigned char _etext[];
+extern unsigned char _end[];
+
+extern uint32_t *bootinfo;
+
+#ifdef SMP
+extern uint32_t bp_ntlb1s;
+#endif
+
+vm_paddr_t kernload;
+vm_offset_t kernstart;
+vm_size_t kernsize;
+
+/* Message buffer and tables. */
+static vm_offset_t data_start;
+static vm_size_t data_end;
+
+/* Phys/avail memory regions. */
+static struct mem_region *availmem_regions;
+static int availmem_regions_sz;
+static struct mem_region *physmem_regions;
+static int physmem_regions_sz;
+
+/* Reserved KVA space and mutex for mmu_booke_zero_page. */
+static vm_offset_t zero_page_va;
+static struct mtx zero_page_mutex;
+
+static struct mtx tlbivax_mutex;
+
+/*
+ * Reserved KVA space for mmu_booke_zero_page_idle. This is used
+ * by idle thred only, no lock required.
+ */
+static vm_offset_t zero_page_idle_va;
+
+/* Reserved KVA space and mutex for mmu_booke_copy_page. */
+static vm_offset_t copy_page_src_va;
+static vm_offset_t copy_page_dst_va;
+static struct mtx copy_page_mutex;
+
+/**************************************************************************/
+/* PMAP */
+/**************************************************************************/
+
+static int mmu_booke_enter_locked(mmu_t, pmap_t, vm_offset_t, vm_page_t,
+    vm_prot_t, u_int flags, int8_t psind);
+
+unsigned int kptbl_min;		/* Index of the first kernel ptbl. */
+unsigned int kernel_ptbls;	/* Number of KVA ptbls. */
+
+/*
+ * If user pmap is processed with mmu_booke_remove and the resident count
+ * drops to 0, there are no more pages to remove, so we need not continue.
+ */
+#define PMAP_REMOVE_DONE(pmap) \
+	((pmap) != kernel_pmap && (pmap)->pm_stats.resident_count == 0)
+
+extern void tid_flush(tlbtid_t);
+
+/**************************************************************************/
+/* TLB and TID handling */
+/**************************************************************************/
+
+/* Translation ID busy table */
+static volatile pmap_t tidbusy[MAXCPU][TID_MAX + 1];
+
+/*
+ * TLB0 capabilities (entry, way numbers etc.). These can vary between e500
+ * core revisions and should be read from h/w registers during early config.
+ */
+uint32_t tlb0_entries;
+uint32_t tlb0_ways;
+uint32_t tlb0_entries_per_way;
+
+#define TLB0_ENTRIES		(tlb0_entries)
+#define TLB0_WAYS		(tlb0_ways)
+#define TLB0_ENTRIES_PER_WAY	(tlb0_entries_per_way)
+
+#define TLB1_ENTRIES 16
+
+/* In-ram copy of the TLB1 */
+static tlb_entry_t tlb1[TLB1_ENTRIES];
+
+/* Next free entry in the TLB1 */
+static unsigned int tlb1_idx;
+static vm_offset_t tlb1_map_base = VM_MAX_KERNEL_ADDRESS;
+
+static tlbtid_t tid_alloc(struct pmap *);
+
+static void tlb_print_entry(int, uint32_t, uint32_t, uint32_t, uint32_t);
+
+static int tlb1_set_entry(vm_offset_t, vm_offset_t, vm_size_t, uint32_t);
+static void tlb1_write_entry(unsigned int);
+static int tlb1_iomapped(int, vm_paddr_t, vm_size_t, vm_offset_t *);
+static vm_size_t tlb1_mapin_region(vm_offset_t, vm_paddr_t, vm_size_t);
+
+static vm_size_t tsize2size(unsigned int);
+static unsigned int size2tsize(vm_size_t);
+static unsigned int ilog2(unsigned int);
+
+static void set_mas4_defaults(void);
+
+static inline void tlb0_flush_entry(vm_offset_t);
+static inline unsigned int tlb0_tableidx(vm_offset_t, unsigned int);
+
+/**************************************************************************/
+/* Page table management */
+/**************************************************************************/
+
+static struct rwlock_padalign pvh_global_lock;
+
+/* Data for the pv entry allocation mechanism */
+static uma_zone_t pvzone;
+static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0;
+
+#define PV_ENTRY_ZONE_MIN	2048	/* min pv entries in uma zone */
+
+#ifndef PMAP_SHPGPERPROC
+#define PMAP_SHPGPERPROC	200
+#endif
+
+static void ptbl_init(void);
+static struct ptbl_buf *ptbl_buf_alloc(void);
+static void ptbl_buf_free(struct ptbl_buf *);
+static void ptbl_free_pmap_ptbl(pmap_t, pte_t *);
+
+static pte_t *ptbl_alloc(mmu_t, pmap_t, unsigned int, boolean_t);
+static void ptbl_free(mmu_t, pmap_t, unsigned int);
+static void ptbl_hold(mmu_t, pmap_t, unsigned int);
+static int ptbl_unhold(mmu_t, pmap_t, unsigned int);
+
+static vm_paddr_t pte_vatopa(mmu_t, pmap_t, vm_offset_t);
+static pte_t *pte_find(mmu_t, pmap_t, vm_offset_t);
+static int pte_enter(mmu_t, pmap_t, vm_page_t, vm_offset_t, uint32_t, boolean_t);
+static int pte_remove(mmu_t, pmap_t, vm_offset_t, uint8_t);
+
+static pv_entry_t pv_alloc(void);
+static void pv_free(pv_entry_t);
+static void pv_insert(pmap_t, vm_offset_t, vm_page_t);
+static void pv_remove(pmap_t, vm_offset_t, vm_page_t);
+
+/* Number of kva ptbl buffers, each covering one ptbl (PTBL_PAGES). */
+#define PTBL_BUFS		(128 * 16)
+
+struct ptbl_buf {
+	TAILQ_ENTRY(ptbl_buf) link;	/* list link */
+	vm_offset_t kva;		/* va of mapping */
+};
+
+/* ptbl free list and a lock used for access synchronization. */
+static TAILQ_HEAD(, ptbl_buf) ptbl_buf_freelist;
+static struct mtx ptbl_buf_freelist_lock;
+
+/* Base address of kva space allocated fot ptbl bufs. */
+static vm_offset_t ptbl_buf_pool_vabase;
+
+/* Pointer to ptbl_buf structures. */
+static struct ptbl_buf *ptbl_bufs;
+
+void pmap_bootstrap_ap(volatile uint32_t *);
+
+/*
+ * Kernel MMU interface
+ */
+static void		mmu_booke_clear_modify(mmu_t, vm_page_t);
+static void		mmu_booke_copy(mmu_t, pmap_t, pmap_t, vm_offset_t,
+    vm_size_t, vm_offset_t);
+static void		mmu_booke_copy_page(mmu_t, vm_page_t, vm_page_t);
+static void		mmu_booke_copy_pages(mmu_t, vm_page_t *,
+    vm_offset_t, vm_page_t *, vm_offset_t, int);
+static int		mmu_booke_enter(mmu_t, pmap_t, vm_offset_t, vm_page_t,
+    vm_prot_t, u_int flags, int8_t psind);
+static void		mmu_booke_enter_object(mmu_t, pmap_t, vm_offset_t, vm_offset_t,
+    vm_page_t, vm_prot_t);
+static void		mmu_booke_enter_quick(mmu_t, pmap_t, vm_offset_t, vm_page_t,
+    vm_prot_t);
+static vm_paddr_t	mmu_booke_extract(mmu_t, pmap_t, vm_offset_t);
+static vm_page_t	mmu_booke_extract_and_hold(mmu_t, pmap_t, vm_offset_t,
+    vm_prot_t);
+static void		mmu_booke_init(mmu_t);
+static boolean_t	mmu_booke_is_modified(mmu_t, vm_page_t);
+static boolean_t	mmu_booke_is_prefaultable(mmu_t, pmap_t, vm_offset_t);
+static boolean_t	mmu_booke_is_referenced(mmu_t, vm_page_t);
+static int		mmu_booke_ts_referenced(mmu_t, vm_page_t);
+static vm_offset_t	mmu_booke_map(mmu_t, vm_offset_t *, vm_paddr_t, vm_paddr_t,
+    int);
+static int		mmu_booke_mincore(mmu_t, pmap_t, vm_offset_t,
+    vm_paddr_t *);
+static void		mmu_booke_object_init_pt(mmu_t, pmap_t, vm_offset_t,
+    vm_object_t, vm_pindex_t, vm_size_t);
+static boolean_t	mmu_booke_page_exists_quick(mmu_t, pmap_t, vm_page_t);
+static void		mmu_booke_page_init(mmu_t, vm_page_t);
+static int		mmu_booke_page_wired_mappings(mmu_t, vm_page_t);
+static void		mmu_booke_pinit(mmu_t, pmap_t);
+static void		mmu_booke_pinit0(mmu_t, pmap_t);
+static void		mmu_booke_protect(mmu_t, pmap_t, vm_offset_t, vm_offset_t,
+    vm_prot_t);
+static void		mmu_booke_qenter(mmu_t, vm_offset_t, vm_page_t *, int);
+static void		mmu_booke_qremove(mmu_t, vm_offset_t, int);
+static void		mmu_booke_release(mmu_t, pmap_t);
+static void		mmu_booke_remove(mmu_t, pmap_t, vm_offset_t, vm_offset_t);
+static void		mmu_booke_remove_all(mmu_t, vm_page_t);
+static void		mmu_booke_remove_write(mmu_t, vm_page_t);
+static void		mmu_booke_unwire(mmu_t, pmap_t, vm_offset_t, vm_offset_t);
+static void		mmu_booke_zero_page(mmu_t, vm_page_t);
+static void		mmu_booke_zero_page_area(mmu_t, vm_page_t, int, int);
+static void		mmu_booke_zero_page_idle(mmu_t, vm_page_t);
+static void		mmu_booke_activate(mmu_t, struct thread *);
+static void		mmu_booke_deactivate(mmu_t, struct thread *);
+static void		mmu_booke_bootstrap(mmu_t, vm_offset_t, vm_offset_t);
+static void		*mmu_booke_mapdev(mmu_t, vm_paddr_t, vm_size_t);
+static void		*mmu_booke_mapdev_attr(mmu_t, vm_paddr_t, vm_size_t, vm_memattr_t);
+static void		mmu_booke_unmapdev(mmu_t, vm_offset_t, vm_size_t);
+static vm_paddr_t	mmu_booke_kextract(mmu_t, vm_offset_t);
+static void		mmu_booke_kenter(mmu_t, vm_offset_t, vm_paddr_t);
+static void		mmu_booke_kenter_attr(mmu_t, vm_offset_t, vm_paddr_t, vm_memattr_t);
+static void		mmu_booke_kremove(mmu_t, vm_offset_t);
+static boolean_t	mmu_booke_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
+static void		mmu_booke_sync_icache(mmu_t, pmap_t, vm_offset_t,
+    vm_size_t);
+static vm_offset_t	mmu_booke_dumpsys_map(mmu_t, struct pmap_md *,
+    vm_size_t, vm_size_t *);
+static void		mmu_booke_dumpsys_unmap(mmu_t, struct pmap_md *,
+    vm_size_t, vm_offset_t);
+static struct pmap_md	*mmu_booke_scan_md(mmu_t, struct pmap_md *);
+
+static mmu_method_t mmu_booke_methods[] = {
+	/* pmap dispatcher interface */
+	MMUMETHOD(mmu_clear_modify,	mmu_booke_clear_modify),
+	MMUMETHOD(mmu_copy,		mmu_booke_copy),
+	MMUMETHOD(mmu_copy_page,	mmu_booke_copy_page),
+	MMUMETHOD(mmu_copy_pages,	mmu_booke_copy_pages),
+	MMUMETHOD(mmu_enter,		mmu_booke_enter),
+	MMUMETHOD(mmu_enter_object,	mmu_booke_enter_object),
+	MMUMETHOD(mmu_enter_quick,	mmu_booke_enter_quick),
+	MMUMETHOD(mmu_extract,		mmu_booke_extract),
+	MMUMETHOD(mmu_extract_and_hold,	mmu_booke_extract_and_hold),
+	MMUMETHOD(mmu_init,		mmu_booke_init),
+	MMUMETHOD(mmu_is_modified,	mmu_booke_is_modified),
+	MMUMETHOD(mmu_is_prefaultable,	mmu_booke_is_prefaultable),
+	MMUMETHOD(mmu_is_referenced,	mmu_booke_is_referenced),
+	MMUMETHOD(mmu_ts_referenced,	mmu_booke_ts_referenced),
+	MMUMETHOD(mmu_map,		mmu_booke_map),
+	MMUMETHOD(mmu_mincore,		mmu_booke_mincore),
+	MMUMETHOD(mmu_object_init_pt,	mmu_booke_object_init_pt),
+	MMUMETHOD(mmu_page_exists_quick,mmu_booke_page_exists_quick),
+	MMUMETHOD(mmu_page_init,	mmu_booke_page_init),
+	MMUMETHOD(mmu_page_wired_mappings, mmu_booke_page_wired_mappings),
+	MMUMETHOD(mmu_pinit,		mmu_booke_pinit),
+	MMUMETHOD(mmu_pinit0,		mmu_booke_pinit0),
+	MMUMETHOD(mmu_protect,		mmu_booke_protect),
+	MMUMETHOD(mmu_qenter,		mmu_booke_qenter),
+	MMUMETHOD(mmu_qremove,		mmu_booke_qremove),
+	MMUMETHOD(mmu_release,		mmu_booke_release),
+	MMUMETHOD(mmu_remove,		mmu_booke_remove),
+	MMUMETHOD(mmu_remove_all,	mmu_booke_remove_all),
+	MMUMETHOD(mmu_remove_write,	mmu_booke_remove_write),
+	MMUMETHOD(mmu_sync_icache,	mmu_booke_sync_icache),
+	MMUMETHOD(mmu_unwire,		mmu_booke_unwire),
+	MMUMETHOD(mmu_zero_page,	mmu_booke_zero_page),
+	MMUMETHOD(mmu_zero_page_area,	mmu_booke_zero_page_area),
+	MMUMETHOD(mmu_zero_page_idle,	mmu_booke_zero_page_idle),
+	MMUMETHOD(mmu_activate,		mmu_booke_activate),
+	MMUMETHOD(mmu_deactivate,	mmu_booke_deactivate),
+
+	/* Internal interfaces */
+	MMUMETHOD(mmu_bootstrap,	mmu_booke_bootstrap),
+	MMUMETHOD(mmu_dev_direct_mapped,mmu_booke_dev_direct_mapped),
+	MMUMETHOD(mmu_mapdev,		mmu_booke_mapdev),
+	MMUMETHOD(mmu_mapdev_attr,	mmu_booke_mapdev_attr),
+	MMUMETHOD(mmu_kenter,		mmu_booke_kenter),
+	MMUMETHOD(mmu_kenter_attr,	mmu_booke_kenter_attr),
+	MMUMETHOD(mmu_kextract,		mmu_booke_kextract),
+/*	MMUMETHOD(mmu_kremove,		mmu_booke_kremove),	*/
+	MMUMETHOD(mmu_unmapdev,		mmu_booke_unmapdev),
+
+	/* dumpsys() support */
+	MMUMETHOD(mmu_dumpsys_map,	mmu_booke_dumpsys_map),
+	MMUMETHOD(mmu_dumpsys_unmap,	mmu_booke_dumpsys_unmap),
+	MMUMETHOD(mmu_scan_md,		mmu_booke_scan_md),
+
+	{ 0, 0 }
+};
+
+MMU_DEF(booke_mmu, MMU_TYPE_BOOKE, mmu_booke_methods, 0);
+
+static __inline uint32_t
+tlb_calc_wimg(vm_offset_t pa, vm_memattr_t ma)
+{
+	uint32_t attrib;
+	int i;
+
+	if (ma != VM_MEMATTR_DEFAULT) {
+		switch (ma) {
+		case VM_MEMATTR_UNCACHEABLE:
+			return (PTE_I | PTE_G);
+		case VM_MEMATTR_WRITE_COMBINING:
+		case VM_MEMATTR_WRITE_BACK:
+		case VM_MEMATTR_PREFETCHABLE:
+			return (PTE_I);
+		case VM_MEMATTR_WRITE_THROUGH:
+			return (PTE_W | PTE_M);
+		}
+	}
+
+	/*
+	 * Assume the page is cache inhibited and access is guarded unless
+	 * it's in our available memory array.
+	 */
+	attrib = _TLB_ENTRY_IO;
+	for (i = 0; i < physmem_regions_sz; i++) {
+		if ((pa >= physmem_regions[i].mr_start) &&
+		    (pa < (physmem_regions[i].mr_start +
+		     physmem_regions[i].mr_size))) {
+			attrib = _TLB_ENTRY_MEM;
+			break;
+		}
+	}
+
+	return (attrib);
+}
+
+static inline void
+tlb_miss_lock(void)
+{
+#ifdef SMP
+	struct pcpu *pc;
+
+	if (!smp_started)
+		return;
+
+	STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
+		if (pc != pcpup) {
+
+			CTR3(KTR_PMAP, "%s: tlb miss LOCK of CPU=%d, "
+			    "tlb_lock=%p", __func__, pc->pc_cpuid, pc->pc_booke_tlb_lock);
+
+			KASSERT((pc->pc_cpuid != PCPU_GET(cpuid)),
+			    ("tlb_miss_lock: tried to lock self"));
+
+			tlb_lock(pc->pc_booke_tlb_lock);
+
+			CTR1(KTR_PMAP, "%s: locked", __func__);
+		}
+	}
+#endif
+}
+
+static inline void
+tlb_miss_unlock(void)
+{
+#ifdef SMP
+	struct pcpu *pc;
+
+	if (!smp_started)
+		return;
+
+	STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
+		if (pc != pcpup) {
+			CTR2(KTR_PMAP, "%s: tlb miss UNLOCK of CPU=%d",
+			    __func__, pc->pc_cpuid);
+
+			tlb_unlock(pc->pc_booke_tlb_lock);
+
+			CTR1(KTR_PMAP, "%s: unlocked", __func__);
+		}
+	}
+#endif
+}
+
+/* Return number of entries in TLB0. */
+static __inline void
+tlb0_get_tlbconf(void)
+{
+	uint32_t tlb0_cfg;
+
+	tlb0_cfg = mfspr(SPR_TLB0CFG);
+	tlb0_entries = tlb0_cfg & TLBCFG_NENTRY_MASK;
+	tlb0_ways = (tlb0_cfg & TLBCFG_ASSOC_MASK) >> TLBCFG_ASSOC_SHIFT;
+	tlb0_entries_per_way = tlb0_entries / tlb0_ways;
+}
+
+/* Initialize pool of kva ptbl buffers. */
+static void
+ptbl_init(void)
+{
+	int i;
+
+	CTR3(KTR_PMAP, "%s: s (ptbl_bufs = 0x%08x size 0x%08x)", __func__,
+	    (uint32_t)ptbl_bufs, sizeof(struct ptbl_buf) * PTBL_BUFS);
+	CTR3(KTR_PMAP, "%s: s (ptbl_buf_pool_vabase = 0x%08x size = 0x%08x)",
+	    __func__, ptbl_buf_pool_vabase, PTBL_BUFS * PTBL_PAGES * PAGE_SIZE);
+
+	mtx_init(&ptbl_buf_freelist_lock, "ptbl bufs lock", NULL, MTX_DEF);
+	TAILQ_INIT(&ptbl_buf_freelist);
+
+	for (i = 0; i < PTBL_BUFS; i++) {
+		ptbl_bufs[i].kva = ptbl_buf_pool_vabase + i * PTBL_PAGES * PAGE_SIZE;
+		TAILQ_INSERT_TAIL(&ptbl_buf_freelist, &ptbl_bufs[i], link);
+	}
+}
+
+/* Get a ptbl_buf from the freelist. */
+static struct ptbl_buf *
+ptbl_buf_alloc(void)
+{
+	struct ptbl_buf *buf;
+
+	mtx_lock(&ptbl_buf_freelist_lock);
+	buf = TAILQ_FIRST(&ptbl_buf_freelist);
+	if (buf != NULL)
+		TAILQ_REMOVE(&ptbl_buf_freelist, buf, link);
+	mtx_unlock(&ptbl_buf_freelist_lock);
+
+	CTR2(KTR_PMAP, "%s: buf = %p", __func__, buf);
+
+	return (buf);
+}
+
+/* Return ptbl buff to free pool. */
+static void
+ptbl_buf_free(struct ptbl_buf *buf)
+{
+
+	CTR2(KTR_PMAP, "%s: buf = %p", __func__, buf);
+
+	mtx_lock(&ptbl_buf_freelist_lock);
+	TAILQ_INSERT_TAIL(&ptbl_buf_freelist, buf, link);
+	mtx_unlock(&ptbl_buf_freelist_lock);
+}
+
+/*
+ * Search the list of allocated ptbl bufs and find on list of allocated ptbls
+ */
+static void
+ptbl_free_pmap_ptbl(pmap_t pmap, pte_t *ptbl)
+{
+	struct ptbl_buf *pbuf;
+
+	CTR2(KTR_PMAP, "%s: ptbl = %p", __func__, ptbl);
+
+	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+
+	TAILQ_FOREACH(pbuf, &pmap->pm_ptbl_list, link)
+		if (pbuf->kva == (vm_offset_t)ptbl) {
+			/* Remove from pmap ptbl buf list. */
+			TAILQ_REMOVE(&pmap->pm_ptbl_list, pbuf, link);
+
+			/* Free corresponding ptbl buf. */
+			ptbl_buf_free(pbuf);
+			break;
+		}
+}
+
+/* Allocate page table. */
+static pte_t *
+ptbl_alloc(mmu_t mmu, pmap_t pmap, unsigned int pdir_idx, boolean_t nosleep)
+{
+	vm_page_t mtbl[PTBL_PAGES];
+	vm_page_t m;
+	struct ptbl_buf *pbuf;
+	unsigned int pidx;
+	pte_t *ptbl;
+	int i, j;
+
+	CTR4(KTR_PMAP, "%s: pmap = %p su = %d pdir_idx = %d", __func__, pmap,
+	    (pmap == kernel_pmap), pdir_idx);
+
+	KASSERT((pdir_idx <= (VM_MAXUSER_ADDRESS / PDIR_SIZE)),
+	    ("ptbl_alloc: invalid pdir_idx"));
+	KASSERT((pmap->pm_pdir[pdir_idx] == NULL),
+	    ("pte_alloc: valid ptbl entry exists!"));
+
+	pbuf = ptbl_buf_alloc();
+	if (pbuf == NULL)
+		panic("pte_alloc: couldn't alloc kernel virtual memory");
+		
+	ptbl = (pte_t *)pbuf->kva;
+
+	CTR2(KTR_PMAP, "%s: ptbl kva = %p", __func__, ptbl);
+
+	/* Allocate ptbl pages, this will sleep! */
+	for (i = 0; i < PTBL_PAGES; i++) {
+		pidx = (PTBL_PAGES * pdir_idx) + i;
+		while ((m = vm_page_alloc(NULL, pidx,
+		    VM_ALLOC_NOOBJ | VM_ALLOC_WIRED)) == NULL) {
+			PMAP_UNLOCK(pmap);
+			rw_wunlock(&pvh_global_lock);
+			if (nosleep) {
+				ptbl_free_pmap_ptbl(pmap, ptbl);
+				for (j = 0; j < i; j++)
+					vm_page_free(mtbl[j]);
+				atomic_subtract_int(&cnt.v_wire_count, i);
+				return (NULL);
+			}
+			VM_WAIT;
+			rw_wlock(&pvh_global_lock);
+			PMAP_LOCK(pmap);
+		}
+		mtbl[i] = m;
+	}
+
+	/* Map allocated pages into kernel_pmap. */
+	mmu_booke_qenter(mmu, (vm_offset_t)ptbl, mtbl, PTBL_PAGES);
+
+	/* Zero whole ptbl. */
+	bzero((caddr_t)ptbl, PTBL_PAGES * PAGE_SIZE);
+
+	/* Add pbuf to the pmap ptbl bufs list. */
+	TAILQ_INSERT_TAIL(&pmap->pm_ptbl_list, pbuf, link);
+
+	return (ptbl);
+}
+
+/* Free ptbl pages and invalidate pdir entry. */
+static void
+ptbl_free(mmu_t mmu, pmap_t pmap, unsigned int pdir_idx)
+{
+	pte_t *ptbl;
+	vm_paddr_t pa;
+	vm_offset_t va;
+	vm_page_t m;
+	int i;
+
+	CTR4(KTR_PMAP, "%s: pmap = %p su = %d pdir_idx = %d", __func__, pmap,
+	    (pmap == kernel_pmap), pdir_idx);
+
+	KASSERT((pdir_idx <= (VM_MAXUSER_ADDRESS / PDIR_SIZE)),
+	    ("ptbl_free: invalid pdir_idx"));
+
+	ptbl = pmap->pm_pdir[pdir_idx];
+
+	CTR2(KTR_PMAP, "%s: ptbl = %p", __func__, ptbl);
+
+	KASSERT((ptbl != NULL), ("ptbl_free: null ptbl"));
+
+	/*
+	 * Invalidate the pdir entry as soon as possible, so that other CPUs
+	 * don't attempt to look up the page tables we are releasing.
+	 */
+	mtx_lock_spin(&tlbivax_mutex);
+	tlb_miss_lock();
+	
+	pmap->pm_pdir[pdir_idx] = NULL;
+
+	tlb_miss_unlock();
+	mtx_unlock_spin(&tlbivax_mutex);
+
+	for (i = 0; i < PTBL_PAGES; i++) {
+		va = ((vm_offset_t)ptbl + (i * PAGE_SIZE));
+		pa = pte_vatopa(mmu, kernel_pmap, va);
+		m = PHYS_TO_VM_PAGE(pa);
+		vm_page_free_zero(m);
+		atomic_subtract_int(&cnt.v_wire_count, 1);
+		mmu_booke_kremove(mmu, va);
+	}
+
+	ptbl_free_pmap_ptbl(pmap, ptbl);
+}
+
+/*
+ * Decrement ptbl pages hold count and attempt to free ptbl pages.
+ * Called when removing pte entry from ptbl.
+ *
+ * Return 1 if ptbl pages were freed.
+ */
+static int
+ptbl_unhold(mmu_t mmu, pmap_t pmap, unsigned int pdir_idx)
+{
+	pte_t *ptbl;
+	vm_paddr_t pa;
+	vm_page_t m;
+	int i;
+
+	CTR4(KTR_PMAP, "%s: pmap = %p su = %d pdir_idx = %d", __func__, pmap,
+	    (pmap == kernel_pmap), pdir_idx);
+
+	KASSERT((pdir_idx <= (VM_MAXUSER_ADDRESS / PDIR_SIZE)),
+	    ("ptbl_unhold: invalid pdir_idx"));
+	KASSERT((pmap != kernel_pmap),
+	    ("ptbl_unhold: unholding kernel ptbl!"));
+
+	ptbl = pmap->pm_pdir[pdir_idx];
+
+	//debugf("ptbl_unhold: ptbl = 0x%08x\n", (u_int32_t)ptbl);
+	KASSERT(((vm_offset_t)ptbl >= VM_MIN_KERNEL_ADDRESS),
+	    ("ptbl_unhold: non kva ptbl"));
+
+	/* decrement hold count */
+	for (i = 0; i < PTBL_PAGES; i++) {
+		pa = pte_vatopa(mmu, kernel_pmap,
+		    (vm_offset_t)ptbl + (i * PAGE_SIZE));
+		m = PHYS_TO_VM_PAGE(pa);
+		m->wire_count--;
+	}
+
+	/*
+	 * Free ptbl pages if there are no pte etries in this ptbl.
+	 * wire_count has the same value for all ptbl pages, so check the last
+	 * page.
+	 */
+	if (m->wire_count == 0) {
+		ptbl_free(mmu, pmap, pdir_idx);
+
+		//debugf("ptbl_unhold: e (freed ptbl)\n");
+		return (1);
+	}
+
+	return (0);
+}
+
+/*
+ * Increment hold count for ptbl pages. This routine is used when a new pte
+ * entry is being inserted into the ptbl.
+ */
+static void
+ptbl_hold(mmu_t mmu, pmap_t pmap, unsigned int pdir_idx)
+{
+	vm_paddr_t pa;
+	pte_t *ptbl;
+	vm_page_t m;
+	int i;
+
+	CTR3(KTR_PMAP, "%s: pmap = %p pdir_idx = %d", __func__, pmap,
+	    pdir_idx);
+
+	KASSERT((pdir_idx <= (VM_MAXUSER_ADDRESS / PDIR_SIZE)),
+	    ("ptbl_hold: invalid pdir_idx"));
+	KASSERT((pmap != kernel_pmap),
+	    ("ptbl_hold: holding kernel ptbl!"));
+
+	ptbl = pmap->pm_pdir[pdir_idx];
+
+	KASSERT((ptbl != NULL), ("ptbl_hold: null ptbl"));
+
+	for (i = 0; i < PTBL_PAGES; i++) {
+		pa = pte_vatopa(mmu, kernel_pmap,
+		    (vm_offset_t)ptbl + (i * PAGE_SIZE));
+		m = PHYS_TO_VM_PAGE(pa);
+		m->wire_count++;
+	}
+}
+
+/* Allocate pv_entry structure. */
+pv_entry_t
+pv_alloc(void)
+{
+	pv_entry_t pv;
+
+	pv_entry_count++;
+	if (pv_entry_count > pv_entry_high_water)
+		pagedaemon_wakeup();
+	pv = uma_zalloc(pvzone, M_NOWAIT);
+
+	return (pv);
+}
+
+/* Free pv_entry structure. */
+static __inline void
+pv_free(pv_entry_t pve)
+{
+
+	pv_entry_count--;
+	uma_zfree(pvzone, pve);
+}
+
+
+/* Allocate and initialize pv_entry structure. */
+static void
+pv_insert(pmap_t pmap, vm_offset_t va, vm_page_t m)
+{
+	pv_entry_t pve;
+
+	//int su = (pmap == kernel_pmap);
+	//debugf("pv_insert: s (su = %d pmap = 0x%08x va = 0x%08x m = 0x%08x)\n", su,
+	//	(u_int32_t)pmap, va, (u_int32_t)m);
+
+	pve = pv_alloc();
+	if (pve == NULL)
+		panic("pv_insert: no pv entries!");
+
+	pve->pv_pmap = pmap;
+	pve->pv_va = va;
+
+	/* add to pv_list */
+	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
+
+	TAILQ_INSERT_TAIL(&m->md.pv_list, pve, pv_link);
+
+	//debugf("pv_insert: e\n");
+}
+
+/* Destroy pv entry. */
+static void
+pv_remove(pmap_t pmap, vm_offset_t va, vm_page_t m)
+{
+	pv_entry_t pve;
+
+	//int su = (pmap == kernel_pmap);
+	//debugf("pv_remove: s (su = %d pmap = 0x%08x va = 0x%08x)\n", su, (u_int32_t)pmap, va);
+
+	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
+
+	/* find pv entry */
+	TAILQ_FOREACH(pve, &m->md.pv_list, pv_link) {
+		if ((pmap == pve->pv_pmap) && (va == pve->pv_va)) {
+			/* remove from pv_list */
+			TAILQ_REMOVE(&m->md.pv_list, pve, pv_link);
+			if (TAILQ_EMPTY(&m->md.pv_list))
+				vm_page_aflag_clear(m, PGA_WRITEABLE);
+
+			/* free pv entry struct */
+			pv_free(pve);
+			break;
+		}
+	}
+
+	//debugf("pv_remove: e\n");
+}
+
+/*
+ * Clean pte entry, try to free page table page if requested.
+ *
+ * Return 1 if ptbl pages were freed, otherwise return 0.
+ */
+static int
+pte_remove(mmu_t mmu, pmap_t pmap, vm_offset_t va, uint8_t flags)
+{
+	unsigned int pdir_idx = PDIR_IDX(va);
+	unsigned int ptbl_idx = PTBL_IDX(va);
+	vm_page_t m;
+	pte_t *ptbl;
+	pte_t *pte;
+
+	//int su = (pmap == kernel_pmap);
+	//debugf("pte_remove: s (su = %d pmap = 0x%08x va = 0x%08x flags = %d)\n",
+	//		su, (u_int32_t)pmap, va, flags);
+
+	ptbl = pmap->pm_pdir[pdir_idx];
+	KASSERT(ptbl, ("pte_remove: null ptbl"));
+
+	pte = &ptbl[ptbl_idx];
+
+	if (pte == NULL || !PTE_ISVALID(pte))
+		return (0);
+
+	if (PTE_ISWIRED(pte))
+		pmap->pm_stats.wired_count--;
+
+	/* Handle managed entry. */
+	if (PTE_ISMANAGED(pte)) {
+		/* Get vm_page_t for mapped pte. */
+		m = PHYS_TO_VM_PAGE(PTE_PA(pte));
+
+		if (PTE_ISMODIFIED(pte))
+			vm_page_dirty(m);
+
+		if (PTE_ISREFERENCED(pte))
+			vm_page_aflag_set(m, PGA_REFERENCED);
+
+		pv_remove(pmap, va, m);
+	}
+
+	mtx_lock_spin(&tlbivax_mutex);
+	tlb_miss_lock();
+
+	tlb0_flush_entry(va);
+	pte->flags = 0;
+	pte->rpn = 0;
+
+	tlb_miss_unlock();
+	mtx_unlock_spin(&tlbivax_mutex);
+
+	pmap->pm_stats.resident_count--;
+
+	if (flags & PTBL_UNHOLD) {
+		//debugf("pte_remove: e (unhold)\n");
+		return (ptbl_unhold(mmu, pmap, pdir_idx));
+	}
+
+	//debugf("pte_remove: e\n");
+	return (0);
+}
+
+/*
+ * Insert PTE for a given page and virtual address.
+ */
+static int
+pte_enter(mmu_t mmu, pmap_t pmap, vm_page_t m, vm_offset_t va, uint32_t flags,
+    boolean_t nosleep)
+{
+	unsigned int pdir_idx = PDIR_IDX(va);
+	unsigned int ptbl_idx = PTBL_IDX(va);
+	pte_t *ptbl, *pte;
+
+	CTR4(KTR_PMAP, "%s: su = %d pmap = %p va = %p", __func__,
+	    pmap == kernel_pmap, pmap, va);
+
+	/* Get the page table pointer. */
+	ptbl = pmap->pm_pdir[pdir_idx];
+
+	if (ptbl == NULL) {
+		/* Allocate page table pages. */
+		ptbl = ptbl_alloc(mmu, pmap, pdir_idx, nosleep);
+		if (ptbl == NULL) {
+			KASSERT(nosleep, ("nosleep and NULL ptbl"));
+			return (ENOMEM);
+		}
+	} else {
+		/*
+		 * Check if there is valid mapping for requested
+		 * va, if there is, remove it.
+		 */
+		pte = &pmap->pm_pdir[pdir_idx][ptbl_idx];
+		if (PTE_ISVALID(pte)) {
+			pte_remove(mmu, pmap, va, PTBL_HOLD);
+		} else {
+			/*
+			 * pte is not used, increment hold count
+			 * for ptbl pages.
+			 */
+			if (pmap != kernel_pmap)
+				ptbl_hold(mmu, pmap, pdir_idx);
+		}
+	}
+
+	/*
+	 * Insert pv_entry into pv_list for mapped page if part of managed
+	 * memory.
+	 */
+	if ((m->oflags & VPO_UNMANAGED) == 0) {
+		flags |= PTE_MANAGED;
+
+		/* Create and insert pv entry. */
+		pv_insert(pmap, va, m);
+	}
+
+	pmap->pm_stats.resident_count++;
+	
+	mtx_lock_spin(&tlbivax_mutex);
+	tlb_miss_lock();
+
+	tlb0_flush_entry(va);
+	if (pmap->pm_pdir[pdir_idx] == NULL) {
+		/*
+		 * If we just allocated a new page table, hook it in
+		 * the pdir.
+		 */
+		pmap->pm_pdir[pdir_idx] = ptbl;
+	}
+	pte = &(pmap->pm_pdir[pdir_idx][ptbl_idx]);
+	pte->rpn = VM_PAGE_TO_PHYS(m) & ~PTE_PA_MASK;
+	pte->flags |= (PTE_VALID | flags);
+
+	tlb_miss_unlock();
+	mtx_unlock_spin(&tlbivax_mutex);
+	return (0);
+}
+
+/* Return the pa for the given pmap/va. */
+static vm_paddr_t
+pte_vatopa(mmu_t mmu, pmap_t pmap, vm_offset_t va)
+{
+	vm_paddr_t pa = 0;
+	pte_t *pte;
+
+	pte = pte_find(mmu, pmap, va);
+	if ((pte != NULL) && PTE_ISVALID(pte))
+		pa = (PTE_PA(pte) | (va & PTE_PA_MASK));
+	return (pa);
+}
+
+/* Get a pointer to a PTE in a page table. */
+static pte_t *
+pte_find(mmu_t mmu, pmap_t pmap, vm_offset_t va)
+{
+	unsigned int pdir_idx = PDIR_IDX(va);
+	unsigned int ptbl_idx = PTBL_IDX(va);
+
+	KASSERT((pmap != NULL), ("pte_find: invalid pmap"));
+
+	if (pmap->pm_pdir[pdir_idx])
+		return (&(pmap->pm_pdir[pdir_idx][ptbl_idx]));
+
+	return (NULL);
+}
+
+/**************************************************************************/
+/* PMAP related */
+/**************************************************************************/
+
+/*
+ * This is called during booke_init, before the system is really initialized.
+ */
+static void
+mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_offset_t kernelend)
+{
+	vm_offset_t phys_kernelend;
+	struct mem_region *mp, *mp1;
+	int cnt, i, j;
+	u_int s, e, sz;
+	u_int phys_avail_count;
+	vm_size_t physsz, hwphyssz, kstack0_sz;
+	vm_offset_t kernel_pdir, kstack0, va;
+	vm_paddr_t kstack0_phys;
+	void *dpcpu;
+	pte_t *pte;
+
+	debugf("mmu_booke_bootstrap: entered\n");
+
+	/* Initialize invalidation mutex */
+	mtx_init(&tlbivax_mutex, "tlbivax", NULL, MTX_SPIN);
+
+	/* Read TLB0 size and associativity. */
+	tlb0_get_tlbconf();
+
+	/*
+	 * Align kernel start and end address (kernel image).
+	 * Note that kernel end does not necessarily relate to kernsize.
+	 * kernsize is the size of the kernel that is actually mapped.
+	 * Also note that "start - 1" is deliberate. With SMP, the
+	 * entry point is exactly a page from the actual load address.
+	 * As such, trunc_page() has no effect and we're off by a page.
+	 * Since we always have the ELF header between the load address
+	 * and the entry point, we can safely subtract 1 to compensate.
+	 */
+	kernstart = trunc_page(start - 1);
+	data_start = round_page(kernelend);
+	data_end = data_start;
+
+	/*
+	 * Addresses of preloaded modules (like file systems) use
+	 * physical addresses. Make sure we relocate those into
+	 * virtual addresses.
+	 */
+	preload_addr_relocate = kernstart - kernload;
+
+	/* Allocate the dynamic per-cpu area. */
+	dpcpu = (void *)data_end;
+	data_end += DPCPU_SIZE;
+
+	/* Allocate space for the message buffer. */
+	msgbufp = (struct msgbuf *)data_end;
+	data_end += msgbufsize;
+	debugf(" msgbufp at 0x%08x end = 0x%08x\n", (uint32_t)msgbufp,
+	    data_end);
+
+	data_end = round_page(data_end);
+
+	/* Allocate space for ptbl_bufs. */
+	ptbl_bufs = (struct ptbl_buf *)data_end;
+	data_end += sizeof(struct ptbl_buf) * PTBL_BUFS;
+	debugf(" ptbl_bufs at 0x%08x end = 0x%08x\n", (uint32_t)ptbl_bufs,
+	    data_end);
+
+	data_end = round_page(data_end);
+
+	/* Allocate PTE tables for kernel KVA. */
+	kernel_pdir = data_end;
+	kernel_ptbls = (VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS +
+	    PDIR_SIZE - 1) / PDIR_SIZE;
+	data_end += kernel_ptbls * PTBL_PAGES * PAGE_SIZE;
+	debugf(" kernel ptbls: %d\n", kernel_ptbls);
+	debugf(" kernel pdir at 0x%08x end = 0x%08x\n", kernel_pdir, data_end);
+
+	debugf(" data_end: 0x%08x\n", data_end);
+	if (data_end - kernstart > kernsize) {
+		kernsize += tlb1_mapin_region(kernstart + kernsize,
+		    kernload + kernsize, (data_end - kernstart) - kernsize);
+	}
+	data_end = kernstart + kernsize;
+	debugf(" updated data_end: 0x%08x\n", data_end);
+
+	/*
+	 * Clear the structures - note we can only do it safely after the
+	 * possible additional TLB1 translations are in place (above) so that
+	 * all range up to the currently calculated 'data_end' is covered.
+	 */
+	dpcpu_init(dpcpu, 0);
+	memset((void *)ptbl_bufs, 0, sizeof(struct ptbl_buf) * PTBL_SIZE);
+	memset((void *)kernel_pdir, 0, kernel_ptbls * PTBL_PAGES * PAGE_SIZE);
+
+	/*******************************************************/
+	/* Set the start and end of kva. */
+	/*******************************************************/
+	virtual_avail = round_page(data_end);
+	virtual_end = VM_MAX_KERNEL_ADDRESS;
+
+	/* Allocate KVA space for page zero/copy operations. */
+	zero_page_va = virtual_avail;
+	virtual_avail += PAGE_SIZE;
+	zero_page_idle_va = virtual_avail;
+	virtual_avail += PAGE_SIZE;
+	copy_page_src_va = virtual_avail;
+	virtual_avail += PAGE_SIZE;
+	copy_page_dst_va = virtual_avail;
+	virtual_avail += PAGE_SIZE;
+	debugf("zero_page_va = 0x%08x\n", zero_page_va);
+	debugf("zero_page_idle_va = 0x%08x\n", zero_page_idle_va);
+	debugf("copy_page_src_va = 0x%08x\n", copy_page_src_va);
+	debugf("copy_page_dst_va = 0x%08x\n", copy_page_dst_va);
+
+	/* Initialize page zero/copy mutexes. */
+	mtx_init(&zero_page_mutex, "mmu_booke_zero_page", NULL, MTX_DEF);
+	mtx_init(&copy_page_mutex, "mmu_booke_copy_page", NULL, MTX_DEF);
+
+	/* Allocate KVA space for ptbl bufs. */
+	ptbl_buf_pool_vabase = virtual_avail;
+	virtual_avail += PTBL_BUFS * PTBL_PAGES * PAGE_SIZE;
+	debugf("ptbl_buf_pool_vabase = 0x%08x end = 0x%08x\n",
+	    ptbl_buf_pool_vabase, virtual_avail);
+
+	/* Calculate corresponding physical addresses for the kernel region. */
+	phys_kernelend = kernload + kernsize;
+	debugf("kernel image and allocated data:\n");
+	debugf(" kernload    = 0x%08x\n", kernload);
+	debugf(" kernstart   = 0x%08x\n", kernstart);
+	debugf(" kernsize    = 0x%08x\n", kernsize);
+
+	if (sizeof(phys_avail) / sizeof(phys_avail[0]) < availmem_regions_sz)
+		panic("mmu_booke_bootstrap: phys_avail too small");
+
+	/*
+	 * Remove kernel physical address range from avail regions list. Page
+	 * align all regions.  Non-page aligned memory isn't very interesting
+	 * to us.  Also, sort the entries for ascending addresses.
+	 */
+
+	/* Retrieve phys/avail mem regions */
+	mem_regions(&physmem_regions, &physmem_regions_sz,
+	    &availmem_regions, &availmem_regions_sz);
+	sz = 0;
+	cnt = availmem_regions_sz;
+	debugf("processing avail regions:\n");
+	for (mp = availmem_regions; mp->mr_size; mp++) {
+		s = mp->mr_start;
+		e = mp->mr_start + mp->mr_size;
+		debugf(" %08x-%08x -> ", s, e);
+		/* Check whether this region holds all of the kernel. */
+		if (s < kernload && e > phys_kernelend) {
+			availmem_regions[cnt].mr_start = phys_kernelend;
+			availmem_regions[cnt++].mr_size = e - phys_kernelend;
+			e = kernload;
+		}
+		/* Look whether this regions starts within the kernel. */
+		if (s >= kernload && s < phys_kernelend) {
+			if (e <= phys_kernelend)
+				goto empty;
+			s = phys_kernelend;
+		}
+		/* Now look whether this region ends within the kernel. */
+		if (e > kernload && e <= phys_kernelend) {
+			if (s >= kernload)
+				goto empty;
+			e = kernload;
+		}
+		/* Now page align the start and size of the region. */
+		s = round_page(s);
+		e = trunc_page(e);
+		if (e < s)
+			e = s;
+		sz = e - s;
+		debugf("%08x-%08x = %x\n", s, e, sz);
+
+		/* Check whether some memory is left here. */
+		if (sz == 0) {
+		empty:
+			memmove(mp, mp + 1,
+			    (cnt - (mp - availmem_regions)) * sizeof(*mp));
+			cnt--;
+			mp--;
+			continue;
+		}
+
+		/* Do an insertion sort. */
+		for (mp1 = availmem_regions; mp1 < mp; mp1++)
+			if (s < mp1->mr_start)
+				break;
+		if (mp1 < mp) {
+			memmove(mp1 + 1, mp1, (char *)mp - (char *)mp1);
+			mp1->mr_start = s;
+			mp1->mr_size = sz;
+		} else {
+			mp->mr_start = s;
+			mp->mr_size = sz;
+		}
+	}
+	availmem_regions_sz = cnt;
+
+	/*******************************************************/
+	/* Steal physical memory for kernel stack from the end */
+	/* of the first avail region                           */
+	/*******************************************************/
+	kstack0_sz = KSTACK_PAGES * PAGE_SIZE;
+	kstack0_phys = availmem_regions[0].mr_start +
+	    availmem_regions[0].mr_size;
+	kstack0_phys -= kstack0_sz;
+	availmem_regions[0].mr_size -= kstack0_sz;
+
+	/*******************************************************/
+	/* Fill in phys_avail table, based on availmem_regions */
+	/*******************************************************/
+	phys_avail_count = 0;
+	physsz = 0;
+	hwphyssz = 0;
+	TUNABLE_ULONG_FETCH("hw.physmem", (u_long *) &hwphyssz);
+
+	debugf("fill in phys_avail:\n");
+	for (i = 0, j = 0; i < availmem_regions_sz; i++, j += 2) {
+
+		debugf(" region: 0x%08x - 0x%08x (0x%08x)\n",
+		    availmem_regions[i].mr_start,
+		    availmem_regions[i].mr_start +
+		        availmem_regions[i].mr_size,
+		    availmem_regions[i].mr_size);
+
+		if (hwphyssz != 0 &&
+		    (physsz + availmem_regions[i].mr_size) >= hwphyssz) {
+			debugf(" hw.physmem adjust\n");
+			if (physsz < hwphyssz) {
+				phys_avail[j] = availmem_regions[i].mr_start;
+				phys_avail[j + 1] =
+				    availmem_regions[i].mr_start +
+				    hwphyssz - physsz;
+				physsz = hwphyssz;
+				phys_avail_count++;
+			}
+			break;
+		}
+
+		phys_avail[j] = availmem_regions[i].mr_start;
+		phys_avail[j + 1] = availmem_regions[i].mr_start +
+		    availmem_regions[i].mr_size;
+		phys_avail_count++;
+		physsz += availmem_regions[i].mr_size;
+	}
+	physmem = btoc(physsz);
+
+	/* Calculate the last available physical address. */
+	for (i = 0; phys_avail[i + 2] != 0; i += 2)
+		;
+	Maxmem = powerpc_btop(phys_avail[i + 1]);
+
+	debugf("Maxmem = 0x%08lx\n", Maxmem);
+	debugf("phys_avail_count = %d\n", phys_avail_count);
+	debugf("physsz = 0x%08x physmem = %ld (0x%08lx)\n", physsz, physmem,
+	    physmem);
+
+	/*******************************************************/
+	/* Initialize (statically allocated) kernel pmap. */
+	/*******************************************************/
+	PMAP_LOCK_INIT(kernel_pmap);
+	kptbl_min = VM_MIN_KERNEL_ADDRESS / PDIR_SIZE;
+
+	debugf("kernel_pmap = 0x%08x\n", (uint32_t)kernel_pmap);
+	debugf("kptbl_min = %d, kernel_ptbls = %d\n", kptbl_min, kernel_ptbls);
+	debugf("kernel pdir range: 0x%08x - 0x%08x\n",
+	    kptbl_min * PDIR_SIZE, (kptbl_min + kernel_ptbls) * PDIR_SIZE - 1);
+
+	/* Initialize kernel pdir */
+	for (i = 0; i < kernel_ptbls; i++)
+		kernel_pmap->pm_pdir[kptbl_min + i] =
+		    (pte_t *)(kernel_pdir + (i * PAGE_SIZE * PTBL_PAGES));
+
+	for (i = 0; i < MAXCPU; i++) {
+		kernel_pmap->pm_tid[i] = TID_KERNEL;
+		
+		/* Initialize each CPU's tidbusy entry 0 with kernel_pmap */
+		tidbusy[i][0] = kernel_pmap;
+	}
+
+	/*
+	 * Fill in PTEs covering kernel code and data. They are not required
+	 * for address translation, as this area is covered by static TLB1
+	 * entries, but for pte_vatopa() to work correctly with kernel area
+	 * addresses.
+	 */
+	for (va = kernstart; va < data_end; va += PAGE_SIZE) {
+		pte = &(kernel_pmap->pm_pdir[PDIR_IDX(va)][PTBL_IDX(va)]);
+		pte->rpn = kernload + (va - kernstart);
+		pte->flags = PTE_M | PTE_SR | PTE_SW | PTE_SX | PTE_WIRED |
+		    PTE_VALID;
+	}
+	/* Mark kernel_pmap active on all CPUs */
+	CPU_FILL(&kernel_pmap->pm_active);
+
+ 	/*
+	 * Initialize the global pv list lock.
+	 */
+	rw_init(&pvh_global_lock, "pmap pv global");
+
+	/*******************************************************/
+	/* Final setup */
+	/*******************************************************/
+
+	/* Enter kstack0 into kernel map, provide guard page */
+	kstack0 = virtual_avail + KSTACK_GUARD_PAGES * PAGE_SIZE;
+	thread0.td_kstack = kstack0;
+	thread0.td_kstack_pages = KSTACK_PAGES;
+
+	debugf("kstack_sz = 0x%08x\n", kstack0_sz);
+	debugf("kstack0_phys at 0x%08x - 0x%08x\n",
+	    kstack0_phys, kstack0_phys + kstack0_sz);
+	debugf("kstack0 at 0x%08x - 0x%08x\n", kstack0, kstack0 + kstack0_sz);
+	
+	virtual_avail += KSTACK_GUARD_PAGES * PAGE_SIZE + kstack0_sz;
+	for (i = 0; i < KSTACK_PAGES; i++) {
+		mmu_booke_kenter(mmu, kstack0, kstack0_phys);
+		kstack0 += PAGE_SIZE;
+		kstack0_phys += PAGE_SIZE;
+	}
+	
+	debugf("virtual_avail = %08x\n", virtual_avail);
+	debugf("virtual_end   = %08x\n", virtual_end);
+
+	debugf("mmu_booke_bootstrap: exit\n");
+}
+
+void
+pmap_bootstrap_ap(volatile uint32_t *trcp __unused)
+{
+	int i;
+
+	/*
+	 * Finish TLB1 configuration: the BSP already set up its TLB1 and we
+	 * have the snapshot of its contents in the s/w tlb1[] table, so use
+	 * these values directly to (re)program AP's TLB1 hardware.
+	 */
+	for (i = bp_ntlb1s; i < tlb1_idx; i++) {
+		/* Skip invalid entries */
+		if (!(tlb1[i].mas1 & MAS1_VALID))
+			continue;
+
+		tlb1_write_entry(i);
+	}
+
+	set_mas4_defaults();
+}
+
+/*
+ * Get the physical page address for the given pmap/virtual address.
+ */
+static vm_paddr_t
+mmu_booke_extract(mmu_t mmu, pmap_t pmap, vm_offset_t va)
+{
+	vm_paddr_t pa;
+
+	PMAP_LOCK(pmap);
+	pa = pte_vatopa(mmu, pmap, va);
+	PMAP_UNLOCK(pmap);
+
+	return (pa);
+}
+
+/*
+ * Extract the physical page address associated with the given
+ * kernel virtual address.
+ */
+static vm_paddr_t
+mmu_booke_kextract(mmu_t mmu, vm_offset_t va)
+{
+	int i;
+
+	/* Check TLB1 mappings */
+	for (i = 0; i < tlb1_idx; i++) {
+		if (!(tlb1[i].mas1 & MAS1_VALID))
+			continue;
+		if (va >= tlb1[i].virt && va < tlb1[i].virt + tlb1[i].size)
+			return (tlb1[i].phys + (va - tlb1[i].virt));
+	}
+
+	return (pte_vatopa(mmu, kernel_pmap, va));
+}
+
+/*
+ * Initialize the pmap module.
+ * Called by vm_init, to initialize any structures that the pmap
+ * system needs to map virtual memory.
+ */
+static void
+mmu_booke_init(mmu_t mmu)
+{
+	int shpgperproc = PMAP_SHPGPERPROC;
+
+	/*
+	 * Initialize the address space (zone) for the pv entries.  Set a
+	 * high water mark so that the system can recover from excessive
+	 * numbers of pv entries.
+	 */
+	pvzone = uma_zcreate("PV ENTRY", sizeof(struct pv_entry), NULL, NULL,
+	    NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
+
+	TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc);
+	pv_entry_max = shpgperproc * maxproc + cnt.v_page_count;
+
+	TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max);
+	pv_entry_high_water = 9 * (pv_entry_max / 10);
+
+	uma_zone_reserve_kva(pvzone, pv_entry_max);
+
+	/* Pre-fill pvzone with initial number of pv entries. */
+	uma_prealloc(pvzone, PV_ENTRY_ZONE_MIN);
+
+	/* Initialize ptbl allocation. */
+	ptbl_init();
+}
+
+/*
+ * Map a list of wired pages into kernel virtual address space.  This is
+ * intended for temporary mappings which do not need page modification or
+ * references recorded.  Existing mappings in the region are overwritten.
+ */
+static void
+mmu_booke_qenter(mmu_t mmu, vm_offset_t sva, vm_page_t *m, int count)
+{
+	vm_offset_t va;
+
+	va = sva;
+	while (count-- > 0) {
+		mmu_booke_kenter(mmu, va, VM_PAGE_TO_PHYS(*m));
+		va += PAGE_SIZE;
+		m++;
+	}
+}
+
+/*
+ * Remove page mappings from kernel virtual address space.  Intended for
+ * temporary mappings entered by mmu_booke_qenter.
+ */
+static void
+mmu_booke_qremove(mmu_t mmu, vm_offset_t sva, int count)
+{
+	vm_offset_t va;
+
+	va = sva;
+	while (count-- > 0) {
+		mmu_booke_kremove(mmu, va);
+		va += PAGE_SIZE;
+	}
+}
+
+/*
+ * Map a wired page into kernel virtual address space.
+ */
+static void
+mmu_booke_kenter(mmu_t mmu, vm_offset_t va, vm_paddr_t pa)
+{
+
+	mmu_booke_kenter_attr(mmu, va, pa, VM_MEMATTR_DEFAULT);
+}
+
+static void
+mmu_booke_kenter_attr(mmu_t mmu, vm_offset_t va, vm_paddr_t pa, vm_memattr_t ma)
+{
+	unsigned int pdir_idx = PDIR_IDX(va);
+	unsigned int ptbl_idx = PTBL_IDX(va);
+	uint32_t flags;
+	pte_t *pte;
+
+	KASSERT(((va >= VM_MIN_KERNEL_ADDRESS) &&
+	    (va <= VM_MAX_KERNEL_ADDRESS)), ("mmu_booke_kenter: invalid va"));
+
+	flags = PTE_SR | PTE_SW | PTE_SX | PTE_WIRED | PTE_VALID;
+	flags |= tlb_calc_wimg(pa, ma);
+
+	pte = &(kernel_pmap->pm_pdir[pdir_idx][ptbl_idx]);
+
+	mtx_lock_spin(&tlbivax_mutex);
+	tlb_miss_lock();
+	
+	if (PTE_ISVALID(pte)) {
+	
+		CTR1(KTR_PMAP, "%s: replacing entry!", __func__);
+
+		/* Flush entry from TLB0 */
+		tlb0_flush_entry(va);
+	}
+
+	pte->rpn = pa & ~PTE_PA_MASK;
+	pte->flags = flags;
+
+	//debugf("mmu_booke_kenter: pdir_idx = %d ptbl_idx = %d va=0x%08x "
+	//		"pa=0x%08x rpn=0x%08x flags=0x%08x\n",
+	//		pdir_idx, ptbl_idx, va, pa, pte->rpn, pte->flags);
+
+	/* Flush the real memory from the instruction cache. */
+	if ((flags & (PTE_I | PTE_G)) == 0) {
+		__syncicache((void *)va, PAGE_SIZE);
+	}
+
+	tlb_miss_unlock();
+	mtx_unlock_spin(&tlbivax_mutex);
+}
+
+/*
+ * Remove a page from kernel page table.
+ */
+static void
+mmu_booke_kremove(mmu_t mmu, vm_offset_t va)
+{
+	unsigned int pdir_idx = PDIR_IDX(va);
+	unsigned int ptbl_idx = PTBL_IDX(va);
+	pte_t *pte;
+
+//	CTR2(KTR_PMAP,("%s: s (va = 0x%08x)\n", __func__, va));
+
+	KASSERT(((va >= VM_MIN_KERNEL_ADDRESS) &&
+	    (va <= VM_MAX_KERNEL_ADDRESS)),
+	    ("mmu_booke_kremove: invalid va"));
+
+	pte = &(kernel_pmap->pm_pdir[pdir_idx][ptbl_idx]);
+
+	if (!PTE_ISVALID(pte)) {
+	
+		CTR1(KTR_PMAP, "%s: invalid pte", __func__);
+
+		return;
+	}
+
+	mtx_lock_spin(&tlbivax_mutex);
+	tlb_miss_lock();
+
+	/* Invalidate entry in TLB0, update PTE. */
+	tlb0_flush_entry(va);
+	pte->flags = 0;
+	pte->rpn = 0;
+
+	tlb_miss_unlock();
+	mtx_unlock_spin(&tlbivax_mutex);
+}
+
+/*
+ * Initialize pmap associated with process 0.
+ */
+static void
+mmu_booke_pinit0(mmu_t mmu, pmap_t pmap)
+{
+
+	PMAP_LOCK_INIT(pmap);
+	mmu_booke_pinit(mmu, pmap);
+	PCPU_SET(curpmap, pmap);
+}
+
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ */
+static void
+mmu_booke_pinit(mmu_t mmu, pmap_t pmap)
+{
+	int i;
+
+	CTR4(KTR_PMAP, "%s: pmap = %p, proc %d '%s'", __func__, pmap,
+	    curthread->td_proc->p_pid, curthread->td_proc->p_comm);
+
+	KASSERT((pmap != kernel_pmap), ("pmap_pinit: initializing kernel_pmap"));
+
+	for (i = 0; i < MAXCPU; i++)
+		pmap->pm_tid[i] = TID_NONE;
+	CPU_ZERO(&kernel_pmap->pm_active);
+	bzero(&pmap->pm_stats, sizeof(pmap->pm_stats));
+	bzero(&pmap->pm_pdir, sizeof(pte_t *) * PDIR_NENTRIES);
+	TAILQ_INIT(&pmap->pm_ptbl_list);
+}
+
+/*
+ * Release any resources held by the given physical map.
+ * Called when a pmap initialized by mmu_booke_pinit is being released.
+ * Should only be called if the map contains no valid mappings.
+ */
+static void
+mmu_booke_release(mmu_t mmu, pmap_t pmap)
+{
+
+	KASSERT(pmap->pm_stats.resident_count == 0,
+	    ("pmap_release: pmap resident count %ld != 0",
+	    pmap->pm_stats.resident_count));
+}
+
+/*
+ * Insert the given physical page at the specified virtual address in the
+ * target physical map with the protection requested. If specified the page
+ * will be wired down.
+ */
+static int
+mmu_booke_enter(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
+    vm_prot_t prot, u_int flags, int8_t psind)
+{
+	int error;
+
+	rw_wlock(&pvh_global_lock);
+	PMAP_LOCK(pmap);
+	error = mmu_booke_enter_locked(mmu, pmap, va, m, prot, flags, psind);
+	rw_wunlock(&pvh_global_lock);
+	PMAP_UNLOCK(pmap);
+	return (error);
+}
+
+static int
+mmu_booke_enter_locked(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
+    vm_prot_t prot, u_int pmap_flags, int8_t psind __unused)
+{
+	pte_t *pte;
+	vm_paddr_t pa;
+	uint32_t flags;
+	int error, su, sync;
+
+	pa = VM_PAGE_TO_PHYS(m);
+	su = (pmap == kernel_pmap);
+	sync = 0;
+
+	//debugf("mmu_booke_enter_locked: s (pmap=0x%08x su=%d tid=%d m=0x%08x va=0x%08x "
+	//		"pa=0x%08x prot=0x%08x flags=%#x)\n",
+	//		(u_int32_t)pmap, su, pmap->pm_tid,
+	//		(u_int32_t)m, va, pa, prot, flags);
+
+	if (su) {
+		KASSERT(((va >= virtual_avail) &&
+		    (va <= VM_MAX_KERNEL_ADDRESS)),
+		    ("mmu_booke_enter_locked: kernel pmap, non kernel va"));
+	} else {
+		KASSERT((va <= VM_MAXUSER_ADDRESS),
+		    ("mmu_booke_enter_locked: user pmap, non user va"));
+	}
+	if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
+		VM_OBJECT_ASSERT_LOCKED(m->object);
+
+	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+
+	/*
+	 * If there is an existing mapping, and the physical address has not
+	 * changed, must be protection or wiring change.
+	 */
+	if (((pte = pte_find(mmu, pmap, va)) != NULL) &&
+	    (PTE_ISVALID(pte)) && (PTE_PA(pte) == pa)) {
+	    
+		/*
+		 * Before actually updating pte->flags we calculate and
+		 * prepare its new value in a helper var.
+		 */
+		flags = pte->flags;
+		flags &= ~(PTE_UW | PTE_UX | PTE_SW | PTE_SX | PTE_MODIFIED);
+
+		/* Wiring change, just update stats. */
+		if ((pmap_flags & PMAP_ENTER_WIRED) != 0) {
+			if (!PTE_ISWIRED(pte)) {
+				flags |= PTE_WIRED;
+				pmap->pm_stats.wired_count++;
+			}
+		} else {
+			if (PTE_ISWIRED(pte)) {
+				flags &= ~PTE_WIRED;
+				pmap->pm_stats.wired_count--;
+			}
+		}
+
+		if (prot & VM_PROT_WRITE) {
+			/* Add write permissions. */
+			flags |= PTE_SW;
+			if (!su)
+				flags |= PTE_UW;
+
+			if ((flags & PTE_MANAGED) != 0)
+				vm_page_aflag_set(m, PGA_WRITEABLE);
+		} else {
+			/* Handle modified pages, sense modify status. */
+
+			/*
+			 * The PTE_MODIFIED flag could be set by underlying
+			 * TLB misses since we last read it (above), possibly
+			 * other CPUs could update it so we check in the PTE
+			 * directly rather than rely on that saved local flags
+			 * copy.
+			 */
+			if (PTE_ISMODIFIED(pte))
+				vm_page_dirty(m);
+		}
+
+		if (prot & VM_PROT_EXECUTE) {
+			flags |= PTE_SX;
+			if (!su)
+				flags |= PTE_UX;
+
+			/*
+			 * Check existing flags for execute permissions: if we
+			 * are turning execute permissions on, icache should
+			 * be flushed.
+			 */
+			if ((pte->flags & (PTE_UX | PTE_SX)) == 0)
+				sync++;
+		}
+
+		flags &= ~PTE_REFERENCED;
+
+		/*
+		 * The new flags value is all calculated -- only now actually
+		 * update the PTE.
+		 */
+		mtx_lock_spin(&tlbivax_mutex);
+		tlb_miss_lock();
+
+		tlb0_flush_entry(va);
+		pte->flags = flags;
+
+		tlb_miss_unlock();
+		mtx_unlock_spin(&tlbivax_mutex);
+
+	} else {
+		/*
+		 * If there is an existing mapping, but it's for a different
+		 * physical address, pte_enter() will delete the old mapping.
+		 */
+		//if ((pte != NULL) && PTE_ISVALID(pte))
+		//	debugf("mmu_booke_enter_locked: replace\n");
+		//else
+		//	debugf("mmu_booke_enter_locked: new\n");
+
+		/* Now set up the flags and install the new mapping. */
+		flags = (PTE_SR | PTE_VALID);
+		flags |= PTE_M;
+
+		if (!su)
+			flags |= PTE_UR;
+
+		if (prot & VM_PROT_WRITE) {
+			flags |= PTE_SW;
+			if (!su)
+				flags |= PTE_UW;
+
+			if ((m->oflags & VPO_UNMANAGED) == 0)
+				vm_page_aflag_set(m, PGA_WRITEABLE);
+		}
+
+		if (prot & VM_PROT_EXECUTE) {
+			flags |= PTE_SX;
+			if (!su)
+				flags |= PTE_UX;
+		}
+
+		/* If its wired update stats. */
+		if ((pmap_flags & PMAP_ENTER_WIRED) != 0)
+			flags |= PTE_WIRED;
+
+		error = pte_enter(mmu, pmap, m, va, flags,
+		    (pmap_flags & PMAP_ENTER_NOSLEEP) != 0);
+		if (error != 0)
+			return (KERN_RESOURCE_SHORTAGE);
+
+		if ((flags & PMAP_ENTER_WIRED) != 0)
+			pmap->pm_stats.wired_count++;
+
+		/* Flush the real memory from the instruction cache. */
+		if (prot & VM_PROT_EXECUTE)
+			sync++;
+	}
+
+	if (sync && (su || pmap == PCPU_GET(curpmap))) {
+		__syncicache((void *)va, PAGE_SIZE);
+		sync = 0;
+	}
+
+	return (KERN_SUCCESS);
+}
+
+/*
+ * Maps a sequence of resident pages belonging to the same object.
+ * The sequence begins with the given page m_start.  This page is
+ * mapped at the given virtual address start.  Each subsequent page is
+ * mapped at a virtual address that is offset from start by the same
+ * amount as the page is offset from m_start within the object.  The
+ * last page in the sequence is the page with the largest offset from
+ * m_start that can be mapped at a virtual address less than the given
+ * virtual address end.  Not every virtual page between start and end
+ * is mapped; only those for which a resident page exists with the
+ * corresponding offset from m_start are mapped.
+ */
+static void
+mmu_booke_enter_object(mmu_t mmu, pmap_t pmap, vm_offset_t start,
+    vm_offset_t end, vm_page_t m_start, vm_prot_t prot)
+{
+	vm_page_t m;
+	vm_pindex_t diff, psize;
+
+	VM_OBJECT_ASSERT_LOCKED(m_start->object);
+
+	psize = atop(end - start);
+	m = m_start;
+	rw_wlock(&pvh_global_lock);
+	PMAP_LOCK(pmap);
+	while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
+		mmu_booke_enter_locked(mmu, pmap, start + ptoa(diff), m,
+		    prot & (VM_PROT_READ | VM_PROT_EXECUTE),
+		    PMAP_ENTER_NOSLEEP, 0);
+		m = TAILQ_NEXT(m, listq);
+	}
+	rw_wunlock(&pvh_global_lock);
+	PMAP_UNLOCK(pmap);
+}
+
+static void
+mmu_booke_enter_quick(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
+    vm_prot_t prot)
+{
+
+	rw_wlock(&pvh_global_lock);
+	PMAP_LOCK(pmap);
+	mmu_booke_enter_locked(mmu, pmap, va, m,
+	    prot & (VM_PROT_READ | VM_PROT_EXECUTE), PMAP_ENTER_NOSLEEP,
+	    0);
+	rw_wunlock(&pvh_global_lock);
+	PMAP_UNLOCK(pmap);
+}
+
+/*
+ * Remove the given range of addresses from the specified map.
+ *
+ * It is assumed that the start and end are properly rounded to the page size.
+ */
+static void
+mmu_booke_remove(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_offset_t endva)
+{
+	pte_t *pte;
+	uint8_t hold_flag;
+
+	int su = (pmap == kernel_pmap);
+
+	//debugf("mmu_booke_remove: s (su = %d pmap=0x%08x tid=%d va=0x%08x endva=0x%08x)\n",
+	//		su, (u_int32_t)pmap, pmap->pm_tid, va, endva);
+
+	if (su) {
+		KASSERT(((va >= virtual_avail) &&
+		    (va <= VM_MAX_KERNEL_ADDRESS)),
+		    ("mmu_booke_remove: kernel pmap, non kernel va"));
+	} else {
+		KASSERT((va <= VM_MAXUSER_ADDRESS),
+		    ("mmu_booke_remove: user pmap, non user va"));
+	}
+
+	if (PMAP_REMOVE_DONE(pmap)) {
+		//debugf("mmu_booke_remove: e (empty)\n");
+		return;
+	}
+
+	hold_flag = PTBL_HOLD_FLAG(pmap);
+	//debugf("mmu_booke_remove: hold_flag = %d\n", hold_flag);
+
+	rw_wlock(&pvh_global_lock);
+	PMAP_LOCK(pmap);
+	for (; va < endva; va += PAGE_SIZE) {
+		pte = pte_find(mmu, pmap, va);
+		if ((pte != NULL) && PTE_ISVALID(pte))
+			pte_remove(mmu, pmap, va, hold_flag);
+	}
+	PMAP_UNLOCK(pmap);
+	rw_wunlock(&pvh_global_lock);
+
+	//debugf("mmu_booke_remove: e\n");
+}
+
+/*
+ * Remove physical page from all pmaps in which it resides.
+ */
+static void
+mmu_booke_remove_all(mmu_t mmu, vm_page_t m)
+{
+	pv_entry_t pv, pvn;
+	uint8_t hold_flag;
+
+	rw_wlock(&pvh_global_lock);
+	for (pv = TAILQ_FIRST(&m->md.pv_list); pv != NULL; pv = pvn) {
+		pvn = TAILQ_NEXT(pv, pv_link);
+
+		PMAP_LOCK(pv->pv_pmap);
+		hold_flag = PTBL_HOLD_FLAG(pv->pv_pmap);
+		pte_remove(mmu, pv->pv_pmap, pv->pv_va, hold_flag);
+		PMAP_UNLOCK(pv->pv_pmap);
+	}
+	vm_page_aflag_clear(m, PGA_WRITEABLE);
+	rw_wunlock(&pvh_global_lock);
+}
+
+/*
+ * Map a range of physical addresses into kernel virtual address space.
+ */
+static vm_offset_t
+mmu_booke_map(mmu_t mmu, vm_offset_t *virt, vm_paddr_t pa_start,
+    vm_paddr_t pa_end, int prot)
+{
+	vm_offset_t sva = *virt;
+	vm_offset_t va = sva;
+
+	//debugf("mmu_booke_map: s (sva = 0x%08x pa_start = 0x%08x pa_end = 0x%08x)\n",
+	//		sva, pa_start, pa_end);
+
+	while (pa_start < pa_end) {
+		mmu_booke_kenter(mmu, va, pa_start);
+		va += PAGE_SIZE;
+		pa_start += PAGE_SIZE;
+	}
+	*virt = va;
+
+	//debugf("mmu_booke_map: e (va = 0x%08x)\n", va);
+	return (sva);
+}
+
+/*
+ * The pmap must be activated before it's address space can be accessed in any
+ * way.
+ */
+static void
+mmu_booke_activate(mmu_t mmu, struct thread *td)
+{
+	pmap_t pmap;
+	u_int cpuid;
+
+	pmap = &td->td_proc->p_vmspace->vm_pmap;
+
+	CTR5(KTR_PMAP, "%s: s (td = %p, proc = '%s', id = %d, pmap = 0x%08x)",
+	    __func__, td, td->td_proc->p_comm, td->td_proc->p_pid, pmap);
+
+	KASSERT((pmap != kernel_pmap), ("mmu_booke_activate: kernel_pmap!"));
+
+	sched_pin();
+
+	cpuid = PCPU_GET(cpuid);
+	CPU_SET_ATOMIC(cpuid, &pmap->pm_active);
+	PCPU_SET(curpmap, pmap);
+	
+	if (pmap->pm_tid[cpuid] == TID_NONE)
+		tid_alloc(pmap);
+
+	/* Load PID0 register with pmap tid value. */
+	mtspr(SPR_PID0, pmap->pm_tid[cpuid]);
+	__asm __volatile("isync");
+
+	sched_unpin();
+
+	CTR3(KTR_PMAP, "%s: e (tid = %d for '%s')", __func__,
+	    pmap->pm_tid[PCPU_GET(cpuid)], td->td_proc->p_comm);
+}
+
+/*
+ * Deactivate the specified process's address space.
+ */
+static void
+mmu_booke_deactivate(mmu_t mmu, struct thread *td)
+{
+	pmap_t pmap;
+
+	pmap = &td->td_proc->p_vmspace->vm_pmap;
+	
+	CTR5(KTR_PMAP, "%s: td=%p, proc = '%s', id = %d, pmap = 0x%08x",
+	    __func__, td, td->td_proc->p_comm, td->td_proc->p_pid, pmap);
+
+	CPU_CLR_ATOMIC(PCPU_GET(cpuid), &pmap->pm_active);
+	PCPU_SET(curpmap, NULL);
+}
+
+/*
+ * Copy the range specified by src_addr/len
+ * from the source map to the range dst_addr/len
+ * in the destination map.
+ *
+ * This routine is only advisory and need not do anything.
+ */
+static void
+mmu_booke_copy(mmu_t mmu, pmap_t dst_pmap, pmap_t src_pmap,
+    vm_offset_t dst_addr, vm_size_t len, vm_offset_t src_addr)
+{
+
+}
+
+/*
+ * Set the physical protection on the specified range of this map as requested.
+ */
+static void
+mmu_booke_protect(mmu_t mmu, pmap_t pmap, vm_offset_t sva, vm_offset_t eva,
+    vm_prot_t prot)
+{
+	vm_offset_t va;
+	vm_page_t m;
+	pte_t *pte;
+
+	if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+		mmu_booke_remove(mmu, pmap, sva, eva);
+		return;
+	}
+
+	if (prot & VM_PROT_WRITE)
+		return;
+
+	PMAP_LOCK(pmap);
+	for (va = sva; va < eva; va += PAGE_SIZE) {
+		if ((pte = pte_find(mmu, pmap, va)) != NULL) {
+			if (PTE_ISVALID(pte)) {
+				m = PHYS_TO_VM_PAGE(PTE_PA(pte));
+
+				mtx_lock_spin(&tlbivax_mutex);
+				tlb_miss_lock();
+
+				/* Handle modified pages. */
+				if (PTE_ISMODIFIED(pte) && PTE_ISMANAGED(pte))
+					vm_page_dirty(m);
+
+				tlb0_flush_entry(va);
+				pte->flags &= ~(PTE_UW | PTE_SW | PTE_MODIFIED);
+
+				tlb_miss_unlock();
+				mtx_unlock_spin(&tlbivax_mutex);
+			}
+		}
+	}
+	PMAP_UNLOCK(pmap);
+}
+
+/*
+ * Clear the write and modified bits in each of the given page's mappings.
+ */
+static void
+mmu_booke_remove_write(mmu_t mmu, vm_page_t m)
+{
+	pv_entry_t pv;
+	pte_t *pte;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("mmu_booke_remove_write: page %p is not managed", m));
+
+	/*
+	 * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
+	 * set by another thread while the object is locked.  Thus,
+	 * if PGA_WRITEABLE is clear, no page table entries need updating.
+	 */
+	VM_OBJECT_ASSERT_WLOCKED(m->object);
+	if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
+		return;
+	rw_wlock(&pvh_global_lock);
+	TAILQ_FOREACH(pv, &m->md.pv_list, pv_link) {
+		PMAP_LOCK(pv->pv_pmap);
+		if ((pte = pte_find(mmu, pv->pv_pmap, pv->pv_va)) != NULL) {
+			if (PTE_ISVALID(pte)) {
+				m = PHYS_TO_VM_PAGE(PTE_PA(pte));
+
+				mtx_lock_spin(&tlbivax_mutex);
+				tlb_miss_lock();
+
+				/* Handle modified pages. */
+				if (PTE_ISMODIFIED(pte))
+					vm_page_dirty(m);
+
+				/* Flush mapping from TLB0. */
+				pte->flags &= ~(PTE_UW | PTE_SW | PTE_MODIFIED);
+
+				tlb_miss_unlock();
+				mtx_unlock_spin(&tlbivax_mutex);
+			}
+		}
+		PMAP_UNLOCK(pv->pv_pmap);
+	}
+	vm_page_aflag_clear(m, PGA_WRITEABLE);
+	rw_wunlock(&pvh_global_lock);
+}
+
+static void
+mmu_booke_sync_icache(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_size_t sz)
+{
+	pte_t *pte;
+	pmap_t pmap;
+	vm_page_t m;
+	vm_offset_t addr;
+	vm_paddr_t pa;
+	int active, valid;
+ 
+	va = trunc_page(va);
+	sz = round_page(sz);
+
+	rw_wlock(&pvh_global_lock);
+	pmap = PCPU_GET(curpmap);
+	active = (pm == kernel_pmap || pm == pmap) ? 1 : 0;
+	while (sz > 0) {
+		PMAP_LOCK(pm);
+		pte = pte_find(mmu, pm, va);
+		valid = (pte != NULL && PTE_ISVALID(pte)) ? 1 : 0;
+		if (valid)
+			pa = PTE_PA(pte);
+		PMAP_UNLOCK(pm);
+		if (valid) {
+			if (!active) {
+				/* Create a mapping in the active pmap. */
+				addr = 0;
+				m = PHYS_TO_VM_PAGE(pa);
+				PMAP_LOCK(pmap);
+				pte_enter(mmu, pmap, m, addr,
+				    PTE_SR | PTE_VALID | PTE_UR, FALSE);
+				__syncicache((void *)addr, PAGE_SIZE);
+				pte_remove(mmu, pmap, addr, PTBL_UNHOLD);
+				PMAP_UNLOCK(pmap);
+			} else
+				__syncicache((void *)va, PAGE_SIZE);
+		}
+		va += PAGE_SIZE;
+		sz -= PAGE_SIZE;
+	}
+	rw_wunlock(&pvh_global_lock);
+}
+
+/*
+ * Atomically extract and hold the physical page with the given
+ * pmap and virtual address pair if that mapping permits the given
+ * protection.
+ */
+static vm_page_t
+mmu_booke_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va,
+    vm_prot_t prot)
+{
+	pte_t *pte;
+	vm_page_t m;
+	uint32_t pte_wbit;
+	vm_paddr_t pa;
+	
+	m = NULL;
+	pa = 0;	
+	PMAP_LOCK(pmap);
+retry:
+	pte = pte_find(mmu, pmap, va);
+	if ((pte != NULL) && PTE_ISVALID(pte)) {
+		if (pmap == kernel_pmap)
+			pte_wbit = PTE_SW;
+		else
+			pte_wbit = PTE_UW;
+
+		if ((pte->flags & pte_wbit) || ((prot & VM_PROT_WRITE) == 0)) {
+			if (vm_page_pa_tryrelock(pmap, PTE_PA(pte), &pa))
+				goto retry;
+			m = PHYS_TO_VM_PAGE(PTE_PA(pte));
+			vm_page_hold(m);
+		}
+	}
+
+	PA_UNLOCK_COND(pa);
+	PMAP_UNLOCK(pmap);
+	return (m);
+}
+
+/*
+ * Initialize a vm_page's machine-dependent fields.
+ */
+static void
+mmu_booke_page_init(mmu_t mmu, vm_page_t m)
+{
+
+	TAILQ_INIT(&m->md.pv_list);
+}
+
+/*
+ * mmu_booke_zero_page_area zeros the specified hardware page by
+ * mapping it into virtual memory and using bzero to clear
+ * its contents.
+ *
+ * off and size must reside within a single page.
+ */
+static void
+mmu_booke_zero_page_area(mmu_t mmu, vm_page_t m, int off, int size)
+{
+	vm_offset_t va;
+
+	/* XXX KASSERT off and size are within a single page? */
+
+	mtx_lock(&zero_page_mutex);
+	va = zero_page_va;
+
+	mmu_booke_kenter(mmu, va, VM_PAGE_TO_PHYS(m));
+	bzero((caddr_t)va + off, size);
+	mmu_booke_kremove(mmu, va);
+
+	mtx_unlock(&zero_page_mutex);
+}
+
+/*
+ * mmu_booke_zero_page zeros the specified hardware page.
+ */
+static void
+mmu_booke_zero_page(mmu_t mmu, vm_page_t m)
+{
+
+	mmu_booke_zero_page_area(mmu, m, 0, PAGE_SIZE);
+}
+
+/*
+ * mmu_booke_copy_page copies the specified (machine independent) page by
+ * mapping the page into virtual memory and using memcopy to copy the page,
+ * one machine dependent page at a time.
+ */
+static void
+mmu_booke_copy_page(mmu_t mmu, vm_page_t sm, vm_page_t dm)
+{
+	vm_offset_t sva, dva;
+
+	sva = copy_page_src_va;
+	dva = copy_page_dst_va;
+
+	mtx_lock(&copy_page_mutex);
+	mmu_booke_kenter(mmu, sva, VM_PAGE_TO_PHYS(sm));
+	mmu_booke_kenter(mmu, dva, VM_PAGE_TO_PHYS(dm));
+	memcpy((caddr_t)dva, (caddr_t)sva, PAGE_SIZE);
+	mmu_booke_kremove(mmu, dva);
+	mmu_booke_kremove(mmu, sva);
+	mtx_unlock(&copy_page_mutex);
+}
+
+static inline void
+mmu_booke_copy_pages(mmu_t mmu, vm_page_t *ma, vm_offset_t a_offset,
+    vm_page_t *mb, vm_offset_t b_offset, int xfersize)
+{
+	void *a_cp, *b_cp;
+	vm_offset_t a_pg_offset, b_pg_offset;
+	int cnt;
+
+	mtx_lock(&copy_page_mutex);
+	while (xfersize > 0) {
+		a_pg_offset = a_offset & PAGE_MASK;
+		cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
+		mmu_booke_kenter(mmu, copy_page_src_va,
+		    VM_PAGE_TO_PHYS(ma[a_offset >> PAGE_SHIFT]));
+		a_cp = (char *)copy_page_src_va + a_pg_offset;
+		b_pg_offset = b_offset & PAGE_MASK;
+		cnt = min(cnt, PAGE_SIZE - b_pg_offset);
+		mmu_booke_kenter(mmu, copy_page_dst_va,
+		    VM_PAGE_TO_PHYS(mb[b_offset >> PAGE_SHIFT]));
+		b_cp = (char *)copy_page_dst_va + b_pg_offset;
+		bcopy(a_cp, b_cp, cnt);
+		mmu_booke_kremove(mmu, copy_page_dst_va);
+		mmu_booke_kremove(mmu, copy_page_src_va);
+		a_offset += cnt;
+		b_offset += cnt;
+		xfersize -= cnt;
+	}
+	mtx_unlock(&copy_page_mutex);
+}
+
+/*
+ * mmu_booke_zero_page_idle zeros the specified hardware page by mapping it
+ * into virtual memory and using bzero to clear its contents. This is intended
+ * to be called from the vm_pagezero process only and outside of Giant. No
+ * lock is required.
+ */
+static void
+mmu_booke_zero_page_idle(mmu_t mmu, vm_page_t m)
+{
+	vm_offset_t va;
+
+	va = zero_page_idle_va;
+	mmu_booke_kenter(mmu, va, VM_PAGE_TO_PHYS(m));
+	bzero((caddr_t)va, PAGE_SIZE);
+	mmu_booke_kremove(mmu, va);
+}
+
+/*
+ * Return whether or not the specified physical page was modified
+ * in any of physical maps.
+ */
+static boolean_t
+mmu_booke_is_modified(mmu_t mmu, vm_page_t m)
+{
+	pte_t *pte;
+	pv_entry_t pv;
+	boolean_t rv;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("mmu_booke_is_modified: page %p is not managed", m));
+	rv = FALSE;
+
+	/*
+	 * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
+	 * concurrently set while the object is locked.  Thus, if PGA_WRITEABLE
+	 * is clear, no PTEs can be modified.
+	 */
+	VM_OBJECT_ASSERT_WLOCKED(m->object);
+	if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
+		return (rv);
+	rw_wlock(&pvh_global_lock);
+	TAILQ_FOREACH(pv, &m->md.pv_list, pv_link) {
+		PMAP_LOCK(pv->pv_pmap);
+		if ((pte = pte_find(mmu, pv->pv_pmap, pv->pv_va)) != NULL &&
+		    PTE_ISVALID(pte)) {
+			if (PTE_ISMODIFIED(pte))
+				rv = TRUE;
+		}
+		PMAP_UNLOCK(pv->pv_pmap);
+		if (rv)
+			break;
+	}
+	rw_wunlock(&pvh_global_lock);
+	return (rv);
+}
+
+/*
+ * Return whether or not the specified virtual address is eligible
+ * for prefault.
+ */
+static boolean_t
+mmu_booke_is_prefaultable(mmu_t mmu, pmap_t pmap, vm_offset_t addr)
+{
+
+	return (FALSE);
+}
+
+/*
+ * Return whether or not the specified physical page was referenced
+ * in any physical maps.
+ */
+static boolean_t
+mmu_booke_is_referenced(mmu_t mmu, vm_page_t m)
+{
+	pte_t *pte;
+	pv_entry_t pv;
+	boolean_t rv;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("mmu_booke_is_referenced: page %p is not managed", m));
+	rv = FALSE;
+	rw_wlock(&pvh_global_lock);
+	TAILQ_FOREACH(pv, &m->md.pv_list, pv_link) {
+		PMAP_LOCK(pv->pv_pmap);
+		if ((pte = pte_find(mmu, pv->pv_pmap, pv->pv_va)) != NULL &&
+		    PTE_ISVALID(pte)) {
+			if (PTE_ISREFERENCED(pte))
+				rv = TRUE;
+		}
+		PMAP_UNLOCK(pv->pv_pmap);
+		if (rv)
+			break;
+	}
+	rw_wunlock(&pvh_global_lock);
+	return (rv);
+}
+
+/*
+ * Clear the modify bits on the specified physical page.
+ */
+static void
+mmu_booke_clear_modify(mmu_t mmu, vm_page_t m)
+{
+	pte_t *pte;
+	pv_entry_t pv;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("mmu_booke_clear_modify: page %p is not managed", m));
+	VM_OBJECT_ASSERT_WLOCKED(m->object);
+	KASSERT(!vm_page_xbusied(m),
+	    ("mmu_booke_clear_modify: page %p is exclusive busied", m));
+
+	/*
+	 * If the page is not PG_AWRITEABLE, then no PTEs can be modified.
+	 * If the object containing the page is locked and the page is not
+	 * exclusive busied, then PG_AWRITEABLE cannot be concurrently set.
+	 */
+	if ((m->aflags & PGA_WRITEABLE) == 0)
+		return;
+	rw_wlock(&pvh_global_lock);
+	TAILQ_FOREACH(pv, &m->md.pv_list, pv_link) {
+		PMAP_LOCK(pv->pv_pmap);
+		if ((pte = pte_find(mmu, pv->pv_pmap, pv->pv_va)) != NULL &&
+		    PTE_ISVALID(pte)) {
+			mtx_lock_spin(&tlbivax_mutex);
+			tlb_miss_lock();
+			
+			if (pte->flags & (PTE_SW | PTE_UW | PTE_MODIFIED)) {
+				tlb0_flush_entry(pv->pv_va);
+				pte->flags &= ~(PTE_SW | PTE_UW | PTE_MODIFIED |
+				    PTE_REFERENCED);
+			}
+
+			tlb_miss_unlock();
+			mtx_unlock_spin(&tlbivax_mutex);
+		}
+		PMAP_UNLOCK(pv->pv_pmap);
+	}
+	rw_wunlock(&pvh_global_lock);
+}
+
+/*
+ * Return a count of reference bits for a page, clearing those bits.
+ * It is not necessary for every reference bit to be cleared, but it
+ * is necessary that 0 only be returned when there are truly no
+ * reference bits set.
+ *
+ * XXX: The exact number of bits to check and clear is a matter that
+ * should be tested and standardized at some point in the future for
+ * optimal aging of shared pages.
+ */
+static int
+mmu_booke_ts_referenced(mmu_t mmu, vm_page_t m)
+{
+	pte_t *pte;
+	pv_entry_t pv;
+	int count;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("mmu_booke_ts_referenced: page %p is not managed", m));
+	count = 0;
+	rw_wlock(&pvh_global_lock);
+	TAILQ_FOREACH(pv, &m->md.pv_list, pv_link) {
+		PMAP_LOCK(pv->pv_pmap);
+		if ((pte = pte_find(mmu, pv->pv_pmap, pv->pv_va)) != NULL &&
+		    PTE_ISVALID(pte)) {
+			if (PTE_ISREFERENCED(pte)) {
+				mtx_lock_spin(&tlbivax_mutex);
+				tlb_miss_lock();
+
+				tlb0_flush_entry(pv->pv_va);
+				pte->flags &= ~PTE_REFERENCED;
+
+				tlb_miss_unlock();
+				mtx_unlock_spin(&tlbivax_mutex);
+
+				if (++count > 4) {
+					PMAP_UNLOCK(pv->pv_pmap);
+					break;
+				}
+			}
+		}
+		PMAP_UNLOCK(pv->pv_pmap);
+	}
+	rw_wunlock(&pvh_global_lock);
+	return (count);
+}
+
+/*
+ * Clear the wired attribute from the mappings for the specified range of
+ * addresses in the given pmap.  Every valid mapping within that range must
+ * have the wired attribute set.  In contrast, invalid mappings cannot have
+ * the wired attribute set, so they are ignored.
+ *
+ * The wired attribute of the page table entry is not a hardware feature, so
+ * there is no need to invalidate any TLB entries.
+ */
+static void
+mmu_booke_unwire(mmu_t mmu, pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
+{
+	vm_offset_t va;
+	pte_t *pte;
+
+	PMAP_LOCK(pmap);
+	for (va = sva; va < eva; va += PAGE_SIZE) {
+		if ((pte = pte_find(mmu, pmap, va)) != NULL &&
+		    PTE_ISVALID(pte)) {
+			if (!PTE_ISWIRED(pte))
+				panic("mmu_booke_unwire: pte %p isn't wired",
+				    pte);
+			pte->flags &= ~PTE_WIRED;
+			pmap->pm_stats.wired_count--;
+		}
+	}
+	PMAP_UNLOCK(pmap);
+
+}
+
+/*
+ * Return true if the pmap's pv is one of the first 16 pvs linked to from this
+ * page.  This count may be changed upwards or downwards in the future; it is
+ * only necessary that true be returned for a small subset of pmaps for proper
+ * page aging.
+ */
+static boolean_t
+mmu_booke_page_exists_quick(mmu_t mmu, pmap_t pmap, vm_page_t m)
+{
+	pv_entry_t pv;
+	int loops;
+	boolean_t rv;
+
+	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+	    ("mmu_booke_page_exists_quick: page %p is not managed", m));
+	loops = 0;
+	rv = FALSE;
+	rw_wlock(&pvh_global_lock);
+	TAILQ_FOREACH(pv, &m->md.pv_list, pv_link) {
+		if (pv->pv_pmap == pmap) {
+			rv = TRUE;
+			break;
+		}
+		if (++loops >= 16)
+			break;
+	}
+	rw_wunlock(&pvh_global_lock);
+	return (rv);
+}
+
+/*
+ * Return the number of managed mappings to the given physical page that are
+ * wired.
+ */
+static int
+mmu_booke_page_wired_mappings(mmu_t mmu, vm_page_t m)
+{
+	pv_entry_t pv;
+	pte_t *pte;
+	int count = 0;
+
+	if ((m->oflags & VPO_UNMANAGED) != 0)
+		return (count);
+	rw_wlock(&pvh_global_lock);
+	TAILQ_FOREACH(pv, &m->md.pv_list, pv_link) {
+		PMAP_LOCK(pv->pv_pmap);
+		if ((pte = pte_find(mmu, pv->pv_pmap, pv->pv_va)) != NULL)
+			if (PTE_ISVALID(pte) && PTE_ISWIRED(pte))
+				count++;
+		PMAP_UNLOCK(pv->pv_pmap);
+	}
+	rw_wunlock(&pvh_global_lock);
+	return (count);
+}
+
+static int
+mmu_booke_dev_direct_mapped(mmu_t mmu, vm_paddr_t pa, vm_size_t size)
+{
+	int i;
+	vm_offset_t va;
+
+	/*
+	 * This currently does not work for entries that
+	 * overlap TLB1 entries.
+	 */
+	for (i = 0; i < tlb1_idx; i ++) {
+		if (tlb1_iomapped(i, pa, size, &va) == 0)
+			return (0);
+	}
+
+	return (EFAULT);
+}
+
+vm_offset_t
+mmu_booke_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
+    vm_size_t *sz)
+{
+	vm_paddr_t pa, ppa;
+	vm_offset_t va;
+	vm_size_t gran;
+
+	/* Raw physical memory dumps don't have a virtual address. */
+	if (md->md_vaddr == ~0UL) {
+		/* We always map a 256MB page at 256M. */
+		gran = 256 * 1024 * 1024;
+		pa = md->md_paddr + ofs;
+		ppa = pa & ~(gran - 1);
+		ofs = pa - ppa;
+		va = gran;
+		tlb1_set_entry(va, ppa, gran, _TLB_ENTRY_IO);
+		if (*sz > (gran - ofs))
+			*sz = gran - ofs;
+		return (va + ofs);
+	}
+
+	/* Minidumps are based on virtual memory addresses. */
+	va = md->md_vaddr + ofs;
+	if (va >= kernstart + kernsize) {
+		gran = PAGE_SIZE - (va & PAGE_MASK);
+		if (*sz > gran)
+			*sz = gran;
+	}
+	return (va);
+}
+
+void
+mmu_booke_dumpsys_unmap(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
+    vm_offset_t va)
+{
+
+	/* Raw physical memory dumps don't have a virtual address. */
+	if (md->md_vaddr == ~0UL) {
+		tlb1_idx--;
+		tlb1[tlb1_idx].mas1 = 0;
+		tlb1[tlb1_idx].mas2 = 0;
+		tlb1[tlb1_idx].mas3 = 0;
+		tlb1_write_entry(tlb1_idx);
+		return;
+	}
+ 
+	/* Minidumps are based on virtual memory addresses. */
+	/* Nothing to do... */
+}
+
+struct pmap_md *
+mmu_booke_scan_md(mmu_t mmu, struct pmap_md *prev)
+{
+	static struct pmap_md md;
+	pte_t *pte;
+	vm_offset_t va;
+ 
+	if (dumpsys_minidump) {
+		md.md_paddr = ~0UL;	/* Minidumps use virtual addresses. */
+		if (prev == NULL) {
+			/* 1st: kernel .data and .bss. */
+			md.md_index = 1;
+			md.md_vaddr = trunc_page((uintptr_t)_etext);
+			md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
+			return (&md);
+		}
+		switch (prev->md_index) {
+		case 1:
+			/* 2nd: msgbuf and tables (see pmap_bootstrap()). */
+			md.md_index = 2;
+			md.md_vaddr = data_start;
+			md.md_size = data_end - data_start;
+			break;
+		case 2:
+			/* 3rd: kernel VM. */
+			va = prev->md_vaddr + prev->md_size;
+			/* Find start of next chunk (from va). */
+			while (va < virtual_end) {
+				/* Don't dump the buffer cache. */
+				if (va >= kmi.buffer_sva &&
+				    va < kmi.buffer_eva) {
+					va = kmi.buffer_eva;
+					continue;
+				}
+				pte = pte_find(mmu, kernel_pmap, va);
+				if (pte != NULL && PTE_ISVALID(pte))
+					break;
+				va += PAGE_SIZE;
+			}
+			if (va < virtual_end) {
+				md.md_vaddr = va;
+				va += PAGE_SIZE;
+				/* Find last page in chunk. */
+				while (va < virtual_end) {
+					/* Don't run into the buffer cache. */
+					if (va == kmi.buffer_sva)
+						break;
+					pte = pte_find(mmu, kernel_pmap, va);
+					if (pte == NULL || !PTE_ISVALID(pte))
+						break;
+					va += PAGE_SIZE;
+				}
+				md.md_size = va - md.md_vaddr;
+				break;
+			}
+			md.md_index = 3;
+			/* FALLTHROUGH */
+		default:
+			return (NULL);
+		}
+	} else { /* minidumps */
+		mem_regions(&physmem_regions, &physmem_regions_sz,
+		    &availmem_regions, &availmem_regions_sz);
+
+		if (prev == NULL) {
+			/* first physical chunk. */
+			md.md_paddr = physmem_regions[0].mr_start;
+			md.md_size = physmem_regions[0].mr_size;
+			md.md_vaddr = ~0UL;
+			md.md_index = 1;
+		} else if (md.md_index < physmem_regions_sz) {
+			md.md_paddr = physmem_regions[md.md_index].mr_start;
+			md.md_size = physmem_regions[md.md_index].mr_size;
+			md.md_vaddr = ~0UL;
+			md.md_index++;
+		} else {
+			/* There's no next physical chunk. */
+			return (NULL);
+		}
+	}
+
+	return (&md);
+}
+
+/*
+ * Map a set of physical memory pages into the kernel virtual address space.
+ * Return a pointer to where it is mapped. This routine is intended to be used
+ * for mapping device memory, NOT real memory.
+ */
+static void *
+mmu_booke_mapdev(mmu_t mmu, vm_paddr_t pa, vm_size_t size)
+{
+
+	return (mmu_booke_mapdev_attr(mmu, pa, size, VM_MEMATTR_DEFAULT));
+}
+
+static void *
+mmu_booke_mapdev_attr(mmu_t mmu, vm_paddr_t pa, vm_size_t size, vm_memattr_t ma)
+{
+	void *res;
+	uintptr_t va;
+	vm_size_t sz;
+	int i;
+
+	/*
+	 * Check if this is premapped in TLB1. Note: this should probably also
+	 * check whether a sequence of TLB1 entries exist that match the
+	 * requirement, but now only checks the easy case.
+	 */
+	if (ma == VM_MEMATTR_DEFAULT) {
+		for (i = 0; i < tlb1_idx; i++) {
+			if (!(tlb1[i].mas1 & MAS1_VALID))
+				continue;
+			if (pa >= tlb1[i].phys &&
+			    (pa + size) <= (tlb1[i].phys + tlb1[i].size))
+				return (void *)(tlb1[i].virt +
+				    (pa - tlb1[i].phys));
+		}
+	}
+
+	size = roundup(size, PAGE_SIZE);
+
+	/*
+	 * We leave a hole for device direct mapping between the maximum user
+	 * address (0x8000000) and the minimum KVA address (0xc0000000). If
+	 * devices are in there, just map them 1:1. If not, map them to the
+	 * device mapping area about VM_MAX_KERNEL_ADDRESS. These mapped
+	 * addresses should be pulled from an allocator, but since we do not
+	 * ever free TLB1 entries, it is safe just to increment a counter.
+	 * Note that there isn't a lot of address space here (128 MB) and it
+	 * is not at all difficult to imagine running out, since that is a 4:1
+	 * compression from the 0xc0000000 - 0xf0000000 address space that gets
+	 * mapped there.
+	 */
+	if (pa >= (VM_MAXUSER_ADDRESS + PAGE_SIZE) &&
+	    (pa + size - 1) < VM_MIN_KERNEL_ADDRESS) 
+		va = pa;
+	else
+		va = atomic_fetchadd_int(&tlb1_map_base, size);
+	res = (void *)va;
+
+	do {
+		sz = 1 << (ilog2(size) & ~1);
+		if (bootverbose)
+			printf("Wiring VA=%x to PA=%x (size=%x), "
+			    "using TLB1[%d]\n", va, pa, sz, tlb1_idx);
+		tlb1_set_entry(va, pa, sz, tlb_calc_wimg(pa, ma));
+		size -= sz;
+		pa += sz;
+		va += sz;
+	} while (size > 0);
+
+	return (res);
+}
+
+/*
+ * 'Unmap' a range mapped by mmu_booke_mapdev().
+ */
+static void
+mmu_booke_unmapdev(mmu_t mmu, vm_offset_t va, vm_size_t size)
+{
+#ifdef SUPPORTS_SHRINKING_TLB1
+	vm_offset_t base, offset;
+
+	/*
+	 * Unmap only if this is inside kernel virtual space.
+	 */
+	if ((va >= VM_MIN_KERNEL_ADDRESS) && (va <= VM_MAX_KERNEL_ADDRESS)) {
+		base = trunc_page(va);
+		offset = va & PAGE_MASK;
+		size = roundup(offset + size, PAGE_SIZE);
+		kva_free(base, size);
+	}
+#endif
+}
+
+/*
+ * mmu_booke_object_init_pt preloads the ptes for a given object into the
+ * specified pmap. This eliminates the blast of soft faults on process startup
+ * and immediately after an mmap.
+ */
+static void
+mmu_booke_object_init_pt(mmu_t mmu, pmap_t pmap, vm_offset_t addr,
+    vm_object_t object, vm_pindex_t pindex, vm_size_t size)
+{
+
+	VM_OBJECT_ASSERT_WLOCKED(object);
+	KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG,
+	    ("mmu_booke_object_init_pt: non-device object"));
+}
+
+/*
+ * Perform the pmap work for mincore.
+ */
+static int
+mmu_booke_mincore(mmu_t mmu, pmap_t pmap, vm_offset_t addr,
+    vm_paddr_t *locked_pa)
+{
+
+	/* XXX: this should be implemented at some point */
+	return (0);
+}
+
+/**************************************************************************/
+/* TID handling */
+/**************************************************************************/
+
+/*
+ * Allocate a TID. If necessary, steal one from someone else.
+ * The new TID is flushed from the TLB before returning.
+ */
+static tlbtid_t
+tid_alloc(pmap_t pmap)
+{
+	tlbtid_t tid;
+	int thiscpu;
+
+	KASSERT((pmap != kernel_pmap), ("tid_alloc: kernel pmap"));
+
+	CTR2(KTR_PMAP, "%s: s (pmap = %p)", __func__, pmap);
+
+	thiscpu = PCPU_GET(cpuid);
+
+	tid = PCPU_GET(tid_next);
+	if (tid > TID_MAX)
+		tid = TID_MIN;
+	PCPU_SET(tid_next, tid + 1);
+
+	/* If we are stealing TID then clear the relevant pmap's field */
+	if (tidbusy[thiscpu][tid] != NULL) {
+
+		CTR2(KTR_PMAP, "%s: warning: stealing tid %d", __func__, tid);
+		
+		tidbusy[thiscpu][tid]->pm_tid[thiscpu] = TID_NONE;
+
+		/* Flush all entries from TLB0 matching this TID. */
+		tid_flush(tid);
+	}
+
+	tidbusy[thiscpu][tid] = pmap;
+	pmap->pm_tid[thiscpu] = tid;
+	__asm __volatile("msync; isync");
+
+	CTR3(KTR_PMAP, "%s: e (%02d next = %02d)", __func__, tid,
+	    PCPU_GET(tid_next));
+
+	return (tid);
+}
+
+/**************************************************************************/
+/* TLB0 handling */
+/**************************************************************************/
+
+static void
+tlb_print_entry(int i, uint32_t mas1, uint32_t mas2, uint32_t mas3,
+    uint32_t mas7)
+{
+	int as;
+	char desc[3];
+	tlbtid_t tid;
+	vm_size_t size;
+	unsigned int tsize;
+
+	desc[2] = '\0';
+	if (mas1 & MAS1_VALID)
+		desc[0] = 'V';
+	else
+		desc[0] = ' ';
+
+	if (mas1 & MAS1_IPROT)
+		desc[1] = 'P';
+	else
+		desc[1] = ' ';
+
+	as = (mas1 & MAS1_TS_MASK) ? 1 : 0;
+	tid = MAS1_GETTID(mas1);
+
+	tsize = (mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
+	size = 0;
+	if (tsize)
+		size = tsize2size(tsize);
+
+	debugf("%3d: (%s) [AS=%d] "
+	    "sz = 0x%08x tsz = %d tid = %d mas1 = 0x%08x "
+	    "mas2(va) = 0x%08x mas3(pa) = 0x%08x mas7 = 0x%08x\n",
+	    i, desc, as, size, tsize, tid, mas1, mas2, mas3, mas7);
+}
+
+/* Convert TLB0 va and way number to tlb0[] table index. */
+static inline unsigned int
+tlb0_tableidx(vm_offset_t va, unsigned int way)
+{
+	unsigned int idx;
+
+	idx = (way * TLB0_ENTRIES_PER_WAY);
+	idx += (va & MAS2_TLB0_ENTRY_IDX_MASK) >> MAS2_TLB0_ENTRY_IDX_SHIFT;
+	return (idx);
+}
+
+/*
+ * Invalidate TLB0 entry.
+ */
+static inline void
+tlb0_flush_entry(vm_offset_t va)
+{
+
+	CTR2(KTR_PMAP, "%s: s va=0x%08x", __func__, va);
+
+	mtx_assert(&tlbivax_mutex, MA_OWNED);
+
+	__asm __volatile("tlbivax 0, %0" :: "r"(va & MAS2_EPN_MASK));
+	__asm __volatile("isync; msync");
+	__asm __volatile("tlbsync; msync");
+
+	CTR1(KTR_PMAP, "%s: e", __func__);
+}
+
+/* Print out contents of the MAS registers for each TLB0 entry */
+void
+tlb0_print_tlbentries(void)
+{
+	uint32_t mas0, mas1, mas2, mas3, mas7;
+	int entryidx, way, idx;
+
+	debugf("TLB0 entries:\n");
+	for (way = 0; way < TLB0_WAYS; way ++)
+		for (entryidx = 0; entryidx < TLB0_ENTRIES_PER_WAY; entryidx++) {
+
+			mas0 = MAS0_TLBSEL(0) | MAS0_ESEL(way);
+			mtspr(SPR_MAS0, mas0);
+			__asm __volatile("isync");
+
+			mas2 = entryidx << MAS2_TLB0_ENTRY_IDX_SHIFT;
+			mtspr(SPR_MAS2, mas2);
+
+			__asm __volatile("isync; tlbre");
+
+			mas1 = mfspr(SPR_MAS1);
+			mas2 = mfspr(SPR_MAS2);
+			mas3 = mfspr(SPR_MAS3);
+			mas7 = mfspr(SPR_MAS7);
+
+			idx = tlb0_tableidx(mas2, way);
+			tlb_print_entry(idx, mas1, mas2, mas3, mas7);
+		}
+}
+
+/**************************************************************************/
+/* TLB1 handling */
+/**************************************************************************/
+
+/*
+ * TLB1 mapping notes:
+ *
+ * TLB1[0]	Kernel text and data.
+ * TLB1[1-15]	Additional kernel text and data mappings (if required), PCI
+ *		windows, other devices mappings.
+ */
+
+/*
+ * Write given entry to TLB1 hardware.
+ * Use 32 bit pa, clear 4 high-order bits of RPN (mas7).
+ */
+static void
+tlb1_write_entry(unsigned int idx)
+{
+	uint32_t mas0, mas7;
+
+	//debugf("tlb1_write_entry: s\n");
+
+	/* Clear high order RPN bits */
+	mas7 = 0;
+
+	/* Select entry */
+	mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(idx);
+	//debugf("tlb1_write_entry: mas0 = 0x%08x\n", mas0);
+
+	mtspr(SPR_MAS0, mas0);
+	__asm __volatile("isync");
+	mtspr(SPR_MAS1, tlb1[idx].mas1);
+	__asm __volatile("isync");
+	mtspr(SPR_MAS2, tlb1[idx].mas2);
+	__asm __volatile("isync");
+	mtspr(SPR_MAS3, tlb1[idx].mas3);
+	__asm __volatile("isync");
+	mtspr(SPR_MAS7, mas7);
+	__asm __volatile("isync; tlbwe; isync; msync");
+
+	//debugf("tlb1_write_entry: e\n");
+}
+
+/*
+ * Return the largest uint value log such that 2^log <= num.
+ */
+static unsigned int
+ilog2(unsigned int num)
+{
+	int lz;
+
+	__asm ("cntlzw %0, %1" : "=r" (lz) : "r" (num));
+	return (31 - lz);
+}
+
+/*
+ * Convert TLB TSIZE value to mapped region size.
+ */
+static vm_size_t
+tsize2size(unsigned int tsize)
+{
+
+	/*
+	 * size = 4^tsize KB
+	 * size = 4^tsize * 2^10 = 2^(2 * tsize - 10)
+	 */
+
+	return ((1 << (2 * tsize)) * 1024);
+}
+
+/*
+ * Convert region size (must be power of 4) to TLB TSIZE value.
+ */
+static unsigned int
+size2tsize(vm_size_t size)
+{
+
+	return (ilog2(size) / 2 - 5);
+}
+
+/*
+ * Register permanent kernel mapping in TLB1.
+ *
+ * Entries are created starting from index 0 (current free entry is
+ * kept in tlb1_idx) and are not supposed to be invalidated.
+ */
+static int
+tlb1_set_entry(vm_offset_t va, vm_offset_t pa, vm_size_t size,
+    uint32_t flags)
+{
+	uint32_t ts, tid;
+	int tsize, index;
+
+	index = atomic_fetchadd_int(&tlb1_idx, 1);
+	if (index >= TLB1_ENTRIES) {
+		printf("tlb1_set_entry: TLB1 full!\n");
+		return (-1);
+	}
+
+	/* Convert size to TSIZE */
+	tsize = size2tsize(size);
+
+	tid = (TID_KERNEL << MAS1_TID_SHIFT) & MAS1_TID_MASK;
+	/* XXX TS is hard coded to 0 for now as we only use single address space */
+	ts = (0 << MAS1_TS_SHIFT) & MAS1_TS_MASK;
+
+	/*
+	 * Atomicity is preserved by the atomic increment above since nothing
+	 * is ever removed from tlb1.
+	 */
+
+	tlb1[index].phys = pa;
+	tlb1[index].virt = va;
+	tlb1[index].size = size;
+	tlb1[index].mas1 = MAS1_VALID | MAS1_IPROT | ts | tid;
+	tlb1[index].mas1 |= ((tsize << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK);
+	tlb1[index].mas2 = (va & MAS2_EPN_MASK) | flags;
+
+	/* Set supervisor RWX permission bits */
+	tlb1[index].mas3 = (pa & MAS3_RPN) | MAS3_SR | MAS3_SW | MAS3_SX;
+
+	tlb1_write_entry(index);
+
+	/*
+	 * XXX in general TLB1 updates should be propagated between CPUs,
+	 * since current design assumes to have the same TLB1 set-up on all
+	 * cores.
+	 */
+	return (0);
+}
+
+/*
+ * Map in contiguous RAM region into the TLB1 using maximum of
+ * KERNEL_REGION_MAX_TLB_ENTRIES entries.
+ *
+ * If necessary round up last entry size and return total size
+ * used by all allocated entries.
+ */
+vm_size_t
+tlb1_mapin_region(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
+{
+	vm_size_t pgs[KERNEL_REGION_MAX_TLB_ENTRIES];
+	vm_size_t mapped, pgsz, base, mask;
+	int idx, nents;
+
+	/* Round up to the next 1M */
+	size = (size + (1 << 20) - 1) & ~((1 << 20) - 1);
+
+	mapped = 0;
+	idx = 0;
+	base = va;
+	pgsz = 64*1024*1024;
+	while (mapped < size) {
+		while (mapped < size && idx < KERNEL_REGION_MAX_TLB_ENTRIES) {
+			while (pgsz > (size - mapped))
+				pgsz >>= 2;
+			pgs[idx++] = pgsz;
+			mapped += pgsz;
+		}
+
+		/* We under-map. Correct for this. */
+		if (mapped < size) {
+			while (pgs[idx - 1] == pgsz) {
+				idx--;
+				mapped -= pgsz;
+			}
+			/* XXX We may increase beyond out starting point. */
+			pgsz <<= 2;
+			pgs[idx++] = pgsz;
+			mapped += pgsz;
+		}
+	}
+
+	nents = idx;
+	mask = pgs[0] - 1;
+	/* Align address to the boundary */
+	if (va & mask) {
+		va = (va + mask) & ~mask;
+		pa = (pa + mask) & ~mask;
+	}
+
+	for (idx = 0; idx < nents; idx++) {
+		pgsz = pgs[idx];
+		debugf("%u: %x -> %x, size=%x\n", idx, pa, va, pgsz);
+		tlb1_set_entry(va, pa, pgsz, _TLB_ENTRY_MEM);
+		pa += pgsz;
+		va += pgsz;
+	}
+
+	mapped = (va - base);
+	printf("mapped size 0x%08x (wasted space 0x%08x)\n",
+	    mapped, mapped - size);
+	return (mapped);
+}
+
+/*
+ * TLB1 initialization routine, to be called after the very first
+ * assembler level setup done in locore.S.
+ */
+void
+tlb1_init()
+{
+	uint32_t mas0, mas1, mas2, mas3;
+	uint32_t tsz;
+	u_int i;
+
+	if (bootinfo != NULL && bootinfo[0] != 1) {
+		tlb1_idx = *((uint16_t *)(bootinfo + 8));
+	} else
+		tlb1_idx = 1;
+
+	/* The first entry/entries are used to map the kernel. */
+	for (i = 0; i < tlb1_idx; i++) {
+		mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(i);
+		mtspr(SPR_MAS0, mas0);
+		__asm __volatile("isync; tlbre");
+
+		mas1 = mfspr(SPR_MAS1);
+		if ((mas1 & MAS1_VALID) == 0)
+			continue;
+
+		mas2 = mfspr(SPR_MAS2);
+		mas3 = mfspr(SPR_MAS3);
+
+		tlb1[i].mas1 = mas1;
+		tlb1[i].mas2 = mfspr(SPR_MAS2);
+		tlb1[i].mas3 = mas3;
+		tlb1[i].virt = mas2 & MAS2_EPN_MASK;
+		tlb1[i].phys = mas3 & MAS3_RPN;
+
+		if (i == 0)
+			kernload = mas3 & MAS3_RPN;
+
+		tsz = (mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
+		tlb1[i].size = (tsz > 0) ? tsize2size(tsz) : 0;
+		kernsize += tlb1[i].size;
+	}
+
+#ifdef SMP
+	bp_ntlb1s = tlb1_idx;
+#endif
+
+	/* Purge the remaining entries */
+	for (i = tlb1_idx; i < TLB1_ENTRIES; i++)
+		tlb1_write_entry(i);
+
+	/* Setup TLB miss defaults */
+	set_mas4_defaults();
+}
+
+vm_offset_t 
+pmap_early_io_map(vm_paddr_t pa, vm_size_t size)
+{
+	vm_paddr_t pa_base;
+	vm_offset_t va, sz;
+	int i;
+
+	KASSERT(!pmap_bootstrapped, ("Do not use after PMAP is up!"));
+	
+	for (i = 0; i < tlb1_idx; i++) {
+		if (!(tlb1[i].mas1 & MAS1_VALID))
+			continue;
+		if (pa >= tlb1[i].phys && (pa + size) <=
+		    (tlb1[i].phys + tlb1[i].size))
+			return (tlb1[i].virt + (pa - tlb1[i].phys));
+	}
+
+	pa_base = trunc_page(pa);
+	size = roundup(size + (pa - pa_base), PAGE_SIZE);
+	tlb1_map_base = roundup2(tlb1_map_base, 1 << (ilog2(size) & ~1));
+	va = tlb1_map_base + (pa - pa_base);
+
+	do {
+		sz = 1 << (ilog2(size) & ~1);
+		tlb1_set_entry(tlb1_map_base, pa_base, sz, _TLB_ENTRY_IO);
+		size -= sz;
+		pa_base += sz;
+		tlb1_map_base += sz;
+	} while (size > 0);
+
+#ifdef SMP
+	bp_ntlb1s = tlb1_idx;
+#endif
+
+	return (va);
+}
+
+/*
+ * Setup MAS4 defaults.
+ * These values are loaded to MAS0-2 on a TLB miss.
+ */
+static void
+set_mas4_defaults(void)
+{
+	uint32_t mas4;
+
+	/* Defaults: TLB0, PID0, TSIZED=4K */
+	mas4 = MAS4_TLBSELD0;
+	mas4 |= (TLB_SIZE_4K << MAS4_TSIZED_SHIFT) & MAS4_TSIZED_MASK;
+#ifdef SMP
+	mas4 |= MAS4_MD;
+#endif
+	mtspr(SPR_MAS4, mas4);
+	__asm __volatile("isync");
+}
+
+/*
+ * Print out contents of the MAS registers for each TLB1 entry
+ */
+void
+tlb1_print_tlbentries(void)
+{
+	uint32_t mas0, mas1, mas2, mas3, mas7;
+	int i;
+
+	debugf("TLB1 entries:\n");
+	for (i = 0; i < TLB1_ENTRIES; i++) {
+
+		mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(i);
+		mtspr(SPR_MAS0, mas0);
+
+		__asm __volatile("isync; tlbre");
+
+		mas1 = mfspr(SPR_MAS1);
+		mas2 = mfspr(SPR_MAS2);
+		mas3 = mfspr(SPR_MAS3);
+		mas7 = mfspr(SPR_MAS7);
+
+		tlb_print_entry(i, mas1, mas2, mas3, mas7);
+	}
+}
+
+/*
+ * Print out contents of the in-ram tlb1 table.
+ */
+void
+tlb1_print_entries(void)
+{
+	int i;
+
+	debugf("tlb1[] table entries:\n");
+	for (i = 0; i < TLB1_ENTRIES; i++)
+		tlb_print_entry(i, tlb1[i].mas1, tlb1[i].mas2, tlb1[i].mas3, 0);
+}
+
+/*
+ * Return 0 if the physical IO range is encompassed by one of the
+ * the TLB1 entries, otherwise return related error code.
+ */
+static int
+tlb1_iomapped(int i, vm_paddr_t pa, vm_size_t size, vm_offset_t *va)
+{
+	uint32_t prot;
+	vm_paddr_t pa_start;
+	vm_paddr_t pa_end;
+	unsigned int entry_tsize;
+	vm_size_t entry_size;
+
+	*va = (vm_offset_t)NULL;
+
+	/* Skip invalid entries */
+	if (!(tlb1[i].mas1 & MAS1_VALID))
+		return (EINVAL);
+
+	/*
+	 * The entry must be cache-inhibited, guarded, and r/w
+	 * so it can function as an i/o page
+	 */
+	prot = tlb1[i].mas2 & (MAS2_I | MAS2_G);
+	if (prot != (MAS2_I | MAS2_G))
+		return (EPERM);
+
+	prot = tlb1[i].mas3 & (MAS3_SR | MAS3_SW);
+	if (prot != (MAS3_SR | MAS3_SW))
+		return (EPERM);
+
+	/* The address should be within the entry range. */
+	entry_tsize = (tlb1[i].mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
+	KASSERT((entry_tsize), ("tlb1_iomapped: invalid entry tsize"));
+
+	entry_size = tsize2size(entry_tsize);
+	pa_start = tlb1[i].mas3 & MAS3_RPN;
+	pa_end = pa_start + entry_size - 1;
+
+	if ((pa < pa_start) || ((pa + size) > pa_end))
+		return (ERANGE);
+
+	/* Return virtual address of this mapping. */
+	*va = (tlb1[i].mas2 & MAS2_EPN_MASK) + (pa - pa_start);
+	return (0);
+}


Property changes on: trunk/sys/powerpc/booke/pmap.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/booke/trap.c
===================================================================
--- trunk/sys/powerpc/booke/trap.c	                        (rev 0)
+++ trunk/sys/powerpc/booke/trap.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,527 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ * $NetBSD: trap.c,v 1.58 2002/03/04 04:07:35 dbj Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/booke/trap.c 333205 2018-05-03 07:57:08Z avg $");
+
+#include "opt_fpu_emu.h"
+
+#include <sys/param.h>
+#include <sys/kdb.h>
+#include <sys/proc.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/pioctl.h>
+#include <sys/ptrace.h>
+#include <sys/reboot.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/uio.h>
+#include <sys/signalvar.h>
+#include <sys/vmmeter.h>
+
+#include <security/audit/audit.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_page.h>
+
+#include <machine/cpu.h>
+#include <machine/db_machdep.h>
+#include <machine/frame.h>
+#include <machine/pcb.h>
+#include <machine/pmap.h>
+#include <machine/psl.h>
+#include <machine/trap.h>
+#include <machine/spr.h>
+
+#define	FAULTBUF_LR	0
+#define	FAULTBUF_R1	1
+#define	FAULTBUF_R2	2
+#define	FAULTBUF_CR	3
+#define	FAULTBUF_CTR	4
+#define	FAULTBUF_XER	5
+#define	FAULTBUF_R13	6
+
+static void	trap_fatal(struct trapframe *frame);
+static void	printtrap(u_int vector, struct trapframe *frame, int isfatal,
+    int user);
+static int	trap_pfault(struct trapframe *frame, int user);
+static int	fix_unaligned(struct thread *td, struct trapframe *frame);
+static int	handle_onfault(struct trapframe *frame);
+static void	syscall(struct trapframe *frame);
+
+struct powerpc_exception {
+	u_int	vector;
+	char	*name;
+};
+
+static struct powerpc_exception powerpc_exceptions[] = {
+	{ EXC_CRIT,	"critical input" },
+	{ EXC_MCHK,	"machine check" },
+	{ EXC_DSI,	"data storage interrupt" },
+	{ EXC_ISI,	"instruction storage interrupt" },
+	{ EXC_EXI,	"external interrupt" },
+	{ EXC_ALI,	"alignment" },
+	{ EXC_PGM,	"program" },
+	{ EXC_SC,	"system call" },
+	{ EXC_APU,	"auxiliary proc unavailable" },
+	{ EXC_DECR,	"decrementer" },
+	{ EXC_FIT,	"fixed-interval timer" },
+	{ EXC_WDOG,	"watchdog timer" },
+	{ EXC_DTMISS,	"data tlb miss" },
+	{ EXC_ITMISS,	"instruction tlb miss" },
+	{ EXC_DEBUG,	"debug" },
+	{ EXC_PERF,	"performance monitoring" },
+	{ EXC_LAST,	NULL }
+};
+
+static const char *
+trapname(u_int vector)
+{
+	struct	powerpc_exception *pe;
+
+	for (pe = powerpc_exceptions; pe->vector != EXC_LAST; pe++) {
+		if (pe->vector == vector)
+			return (pe->name);
+	}
+
+	return ("unknown");
+}
+
+void
+trap(struct trapframe *frame)
+{
+	struct thread	*td;
+	struct proc	*p;
+	int		sig, type, user;
+	ksiginfo_t	ksi;
+
+#ifdef KDB
+	if (kdb_active) {
+		kdb_reenter();
+		return;
+	}
+#endif
+
+	PCPU_INC(cnt.v_trap);
+
+	td = curthread;
+	p = td->td_proc;
+
+	type = frame->exc;
+	sig = 0;
+	user = (frame->srr1 & PSL_PR) ? 1 : 0;
+
+	CTR3(KTR_TRAP, "trap: %s type=%s (%s)", p->p_comm,
+	    trapname(type), user ? "user" : "kernel");
+
+	if (user) {
+		td->td_frame = frame;
+		if (td->td_ucred != p->p_ucred)
+			cred_update_thread(td);
+
+		/* User Mode Traps */
+		switch (type) {
+		case EXC_DSI:
+		case EXC_ISI:
+			sig = trap_pfault(frame, 1);
+			break;
+
+		case EXC_SC:
+			syscall(frame);
+			break;
+
+		case EXC_ALI:
+			if (fix_unaligned(td, frame) != 0)
+				sig = SIGBUS;
+			else
+				frame->srr0 += 4;
+			break;
+
+		case EXC_DEBUG:	/* Single stepping */
+			mtspr(SPR_DBSR, mfspr(SPR_DBSR));
+			frame->srr1 &= ~PSL_DE;
+			frame->cpu.booke.dbcr0 &= ~(DBCR0_IDM || DBCR0_IC);
+			sig = SIGTRAP;
+			break;
+
+		case EXC_PGM:	/* Program exception */
+			sig = ppc_instr_emulate(frame, td->td_pcb);
+			break;
+
+		default:
+			trap_fatal(frame);
+		}
+	} else {
+		/* Kernel Mode Traps */
+		KASSERT(cold || td->td_ucred != NULL,
+		    ("kernel trap doesn't have ucred"));
+
+		switch (type) {
+		case EXC_DEBUG:
+			mtspr(SPR_DBSR, mfspr(SPR_DBSR));
+			kdb_trap(frame->exc, 0, frame);
+			return;
+
+		case EXC_DSI:
+			if (trap_pfault(frame, 0) == 0)
+ 				return;
+			break;
+
+		case EXC_MCHK:
+			if (handle_onfault(frame))
+ 				return;
+			break;
+#ifdef KDB
+		case EXC_PGM:
+			if (frame->cpu.booke.esr & ESR_PTR)
+				kdb_trap(EXC_PGM, 0, frame);
+			return;
+#endif
+		default:
+			break;
+		}
+		trap_fatal(frame);
+	}
+
+	if (sig != 0) {
+		if (p->p_sysent->sv_transtrap != NULL)
+			sig = (p->p_sysent->sv_transtrap)(sig, type);
+		ksiginfo_init_trap(&ksi);
+		ksi.ksi_signo = sig;
+		ksi.ksi_code = type; /* XXX, not POSIX */
+		/* ksi.ksi_addr = ? */
+		ksi.ksi_trapno = type;
+		trapsignal(td, &ksi);
+	}
+
+	userret(td, frame);
+}
+
+static void
+trap_fatal(struct trapframe *frame)
+{
+#ifdef KDB
+	bool handled;
+#endif
+
+	printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR));
+#ifdef KDB
+	if (debugger_on_panic) {
+		kdb_why = KDB_WHY_TRAP;
+		handled = kdb_trap(frame->exc, 0, frame);
+		kdb_why = KDB_WHY_UNSET;
+		if (handled)
+			return;
+	}
+#endif
+	panic("%s trap", trapname(frame->exc));
+}
+
+static void
+printtrap(u_int vector, struct trapframe *frame, int isfatal, int user)
+{
+	register_t va = 0;
+
+	printf("\n");
+	printf("%s %s trap:\n", isfatal ? "fatal" : "handled",
+	    user ? "user" : "kernel");
+	printf("\n");
+	printf("   exception       = 0x%x (%s)\n", vector, trapname(vector));
+	
+	switch (vector) {
+	case EXC_DTMISS:
+	case EXC_DSI:
+		va = frame->cpu.booke.dear;
+		break;
+
+	case EXC_ITMISS:
+	case EXC_ISI:
+		va = frame->srr0;
+		break;
+	}
+
+	printf("   virtual address = 0x%08x\n", va);
+	printf("   srr0            = 0x%08x\n", frame->srr0);
+	printf("   srr1            = 0x%08x\n", frame->srr1);
+	printf("   curthread       = %p\n", curthread);
+	if (curthread != NULL)
+		printf("          pid = %d, comm = %s\n",
+		    curthread->td_proc->p_pid, curthread->td_proc->p_comm);
+	printf("\n");
+}
+
+/*
+ * Handles a fatal fault when we have onfault state to recover.  Returns
+ * non-zero if there was onfault recovery state available.
+ */
+static int
+handle_onfault(struct trapframe *frame)
+{
+	struct		thread *td;
+	faultbuf	*fb;
+
+	td = curthread;
+	fb = td->td_pcb->pcb_onfault;
+	if (fb != NULL) {
+		frame->srr0 = (*fb)[FAULTBUF_LR];
+		frame->fixreg[1] = (*fb)[FAULTBUF_R1];
+		frame->fixreg[2] = (*fb)[FAULTBUF_R2];
+		frame->fixreg[3] = 1;
+		frame->cr = (*fb)[FAULTBUF_CR];
+		frame->ctr = (*fb)[FAULTBUF_CTR];
+		frame->xer = (*fb)[FAULTBUF_XER];
+		bcopy(&(*fb)[FAULTBUF_R13], &frame->fixreg[13],
+		    19 * sizeof(register_t));
+		return (1);
+	}
+	return (0);
+}
+
+int
+cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
+{
+	struct proc *p;
+	struct trapframe *frame;
+	caddr_t	params;
+	int error, n;
+
+	p = td->td_proc;
+	frame = td->td_frame;
+
+	sa->code = frame->fixreg[0];
+	params = (caddr_t)(frame->fixreg + FIRSTARG);
+	n = NARGREG;
+
+	if (sa->code == SYS_syscall) {
+		/*
+		 * code is first argument,
+		 * followed by actual args.
+		 */
+		sa->code = *(u_int *) params;
+		params += sizeof(register_t);
+		n -= 1;
+	} else if (sa->code == SYS___syscall) {
+		/*
+		 * Like syscall, but code is a quad,
+		 * so as to maintain quad alignment
+		 * for the rest of the args.
+		 */
+		params += sizeof(register_t);
+		sa->code = *(u_int *) params;
+		params += sizeof(register_t);
+		n -= 2;
+	}
+
+	if (p->p_sysent->sv_mask)
+		sa->code &= p->p_sysent->sv_mask;
+	if (sa->code >= p->p_sysent->sv_size)
+		sa->callp = &p->p_sysent->sv_table[0];
+	else
+		sa->callp = &p->p_sysent->sv_table[sa->code];
+	sa->narg = sa->callp->sy_narg;
+
+	bcopy(params, sa->args, n * sizeof(register_t));
+	if (sa->narg > n) {
+		error = copyin(MOREARGS(frame->fixreg[1]), sa->args + n,
+		    (sa->narg - n) * sizeof(register_t));
+	} else
+		error = 0;
+
+	if (error == 0) {
+		td->td_retval[0] = 0;
+		td->td_retval[1] = frame->fixreg[FIRSTARG + 1];
+	}
+	return (error);
+}
+
+#include "../../kern/subr_syscall.c"
+
+void
+syscall(struct trapframe *frame)
+{
+	struct thread *td;
+	struct syscall_args sa;
+	int error;
+
+	td = curthread;
+	td->td_frame = frame;
+
+	error = syscallenter(td, &sa);
+	syscallret(td, error, &sa);
+}
+
+static int
+trap_pfault(struct trapframe *frame, int user)
+{
+	vm_offset_t	eva, va;
+	struct		thread *td;
+	struct		proc *p;
+	vm_map_t	map;
+	vm_prot_t	ftype;
+	int		rv;
+
+	td = curthread;
+	p = td->td_proc;
+
+	if (frame->exc == EXC_ISI) {
+		eva = frame->srr0;
+		ftype = VM_PROT_READ | VM_PROT_EXECUTE;
+
+	} else {
+		eva = frame->cpu.booke.dear;
+		if (frame->cpu.booke.esr & ESR_ST)
+			ftype = VM_PROT_WRITE;
+		else
+			ftype = VM_PROT_READ;
+	}
+
+	if (user) {
+		KASSERT(p->p_vmspace != NULL, ("trap_pfault: vmspace  NULL"));
+		map = &p->p_vmspace->vm_map;
+	} else {
+		if (eva < VM_MAXUSER_ADDRESS) {
+
+			if (p->p_vmspace == NULL)
+				return (SIGSEGV);
+
+			map = &p->p_vmspace->vm_map;
+
+		} else {
+			map = kernel_map;
+		}
+	}
+	va = trunc_page(eva);
+
+	if (map != kernel_map) {
+		/*
+		 * Keep swapout from messing with us during this
+		 *	critical time.
+		 */
+		PROC_LOCK(p);
+		++p->p_lock;
+		PROC_UNLOCK(p);
+
+		/* Fault in the user page: */
+		rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
+
+		PROC_LOCK(p);
+		--p->p_lock;
+		PROC_UNLOCK(p);
+	} else {
+		/*
+		 * Don't have to worry about process locking or stacks in the
+		 * kernel.
+		 */
+		rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
+	}
+
+	if (rv == KERN_SUCCESS)
+		return (0);
+
+	if (!user && handle_onfault(frame))
+		return (0);
+
+	return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
+}
+
+/*
+ * For now, this only deals with the particular unaligned access case
+ * that gcc tends to generate.  Eventually it should handle all of the
+ * possibilities that can happen on a 32-bit PowerPC in big-endian mode.
+ */
+
+static int
+fix_unaligned(struct thread *td, struct trapframe *frame)
+{
+#if 0
+	struct thread	*fputhread;
+	int		indicator, reg;
+	double		*fpr;
+
+	indicator = EXC_ALI_OPCODE_INDICATOR(frame->dsisr);
+
+	switch (indicator) {
+	case EXC_ALI_LFD:
+	case EXC_ALI_STFD:
+		reg = EXC_ALI_RST(frame->dsisr);
+		fpr = &td->td_pcb->pcb_fpu.fpr[reg];
+		fputhread = PCPU_GET(fputhread);
+		/* Juggle the FPU to ensure that we've initialized
+		 * the FPRs, and that their current state is in
+		 * the PCB.
+		 */
+		if (fputhread != td) {
+			if (fputhread)
+				save_fpu(fputhread);
+			enable_fpu(td);
+		}
+		save_fpu(td);
+
+		if (indicator == EXC_ALI_LFD) {
+			if (copyin((void *)frame->dar, fpr,
+			    sizeof(double)) != 0)
+				return -1;
+			enable_fpu(td);
+		} else {
+			if (copyout(fpr, (void *)frame->dar,
+			    sizeof(double)) != 0)
+				return -1;
+		}
+		return 0;
+		break;
+	}
+
+#endif
+	return (-1);
+}
+
+#ifdef KDB
+int db_trap_glue(struct trapframe *);
+int
+db_trap_glue(struct trapframe *tf)
+{
+	if (!(tf->srr1 & PSL_PR))
+		return (kdb_trap(tf->exc, 0, tf));
+	return (0);
+}
+#endif


Property changes on: trunk/sys/powerpc/booke/trap.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/booke/trap_subr.S
===================================================================
--- trunk/sys/powerpc/booke/trap_subr.S	                        (rev 0)
+++ trunk/sys/powerpc/booke/trap_subr.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,894 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2006-2009 Semihalf, Rafal Jaworowski <raj at semihalf.com>
+ * Copyright (C) 2006 Semihalf, Marian Balakowicz <m8 at semihalf.com>
+ * Copyright (C) 2006 Juniper Networks, Inc.
+ * 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/booke/trap_subr.S 266001 2014-05-14 03:09:37Z ian $
+ */
+/*-
+ * 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.
+ *
+ *	from: $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $
+ */
+
+/*
+ * NOTICE: This is not a standalone file.  to use it, #include it in
+ * your port's locore.S, like so:
+ *
+ *	#include <powerpc/booke/trap_subr.S>
+ */
+
+/*
+ * SPRG usage notes
+ *
+ * SPRG0 - pcpu pointer
+ * SPRG1 - all interrupts except TLB miss, critical, machine check
+ * SPRG2 - critical
+ * SPRG3 - machine check
+ * SPRG4-6 - scratch
+ *
+ */
+
+/* Get the per-CPU data structure */
+#define GET_CPUINFO(r) mfsprg0 r
+
+#define RES_GRANULE	32
+#define RES_LOCK	0	/* offset to the 'lock' word */
+#define RES_RECURSE	4	/* offset to the 'recurse' word */
+
+/*
+ * Standard interrupt prolog
+ *
+ * sprg_sp - SPRG{1-3} reg used to temporarily store the SP
+ * savearea - temp save area (pc_{tempsave, disisave, critsave, mchksave})
+ * isrr0-1 - save restore registers with CPU state at interrupt time (may be
+ *           SRR0-1, CSRR0-1, MCSRR0-1
+ *
+ * 1. saves in the given savearea:
+ *   - R30-31
+ *   - DEAR, ESR
+ *   - xSRR0-1
+ *
+ * 2. saves CR -> R30
+ *
+ * 3. switches to kstack if needed
+ *
+ * 4. notes:
+ *   - R31 can be used as scratch register until a new frame is layed on
+ *     the stack with FRAME_SETUP
+ *
+ *   - potential TLB miss: NO. Saveareas are always acessible via TLB1 
+ *     permanent entries, and within this prolog we do not dereference any
+ *     locations potentially not in the TLB
+ */
+#define STANDARD_PROLOG(sprg_sp, savearea, isrr0, isrr1)		\
+	mtspr	sprg_sp, %r1;		/* Save SP */			\
+	GET_CPUINFO(%r1);		/* Per-cpu structure */		\
+	stw	%r30, (savearea+CPUSAVE_R30)(%r1);			\
+	stw	%r31, (savearea+CPUSAVE_R31)(%r1); 			\
+	mfdear	%r30;		 					\
+	mfesr	%r31;							\
+	stw	%r30, (savearea+CPUSAVE_BOOKE_DEAR)(%r1); 		\
+	stw	%r31, (savearea+CPUSAVE_BOOKE_ESR)(%r1); 		\
+	mfspr	%r30, isrr0;						\
+	mfspr	%r31, isrr1;	 	/* MSR at interrupt time */	\
+	stw	%r30, (savearea+CPUSAVE_SRR0)(%r1);			\
+	stw	%r31, (savearea+CPUSAVE_SRR1)(%r1);			\
+	isync;			 					\
+	mfspr	%r1, sprg_sp;	 	/* Restore SP */		\
+	mfcr	%r30;		 	/* Save CR */			\
+	/* switch to per-thread kstack if intr taken in user mode */	\
+	mtcr	%r31;			/* MSR at interrupt time  */	\
+	bf	17, 1f;							\
+	GET_CPUINFO(%r1);		/* Per-cpu structure */		\
+	lwz	%r1, PC_CURPCB(%r1); 	/* Per-thread kernel stack */	\
+1:
+
+#define	STANDARD_CRIT_PROLOG(sprg_sp, savearea, isrr0, isrr1)		\
+	mtspr	sprg_sp, %r1;		/* Save SP */			\
+	GET_CPUINFO(%r1);		/* Per-cpu structure */		\
+	stw	%r30, (savearea+CPUSAVE_R30)(%r1);			\
+	stw	%r31, (savearea+CPUSAVE_R31)(%r1);			\
+	mfdear	%r30;							\
+	mfesr	%r31;							\
+	stw	%r30, (savearea+CPUSAVE_BOOKE_DEAR)(%r1);		\
+	stw	%r31, (savearea+CPUSAVE_BOOKE_ESR)(%r1);		\
+	mfspr	%r30, isrr0;						\
+	mfspr	%r31, isrr1;		/* MSR at interrupt time */	\
+	stw	%r30, (savearea+CPUSAVE_SRR0)(%r1);			\
+	stw	%r31, (savearea+CPUSAVE_SRR1)(%r1);			\
+	mfspr	%r30, SPR_SRR0;						\
+	mfspr	%r31, SPR_SRR1;		/* MSR at interrupt time */	\
+	stw	%r30, (savearea+CPUSAVE_SRR0+8)(%r1);			\
+	stw	%r31, (savearea+CPUSAVE_SRR1+8)(%r1);			\
+	isync;								\
+	mfspr	%r1, sprg_sp;		/* Restore SP */		\
+	mfcr	%r30;			/* Save CR */			\
+	/* switch to per-thread kstack if intr taken in user mode */	\
+	mtcr	%r31;			/* MSR at interrupt time  */	\
+	bf	17, 1f;							\
+	GET_CPUINFO(%r1);		/* Per-cpu structure */		\
+	lwz	%r1, PC_CURPCB(%r1);	/* Per-thread kernel stack */	\
+1:
+
+/*
+ * FRAME_SETUP assumes:
+ *	SPRG{1-3}	SP at the time interrupt occured
+ *	savearea	r30-r31, DEAR, ESR, xSRR0-1
+ *	r30		CR
+ *	r31		scratch
+ *	r1		kernel stack
+ *
+ * sprg_sp - SPRG reg containing SP at the time interrupt occured
+ * savearea - temp save
+ * exc - exception number (EXC_xxx)
+ *
+ * 1. sets a new frame
+ * 2. saves in the frame:
+ *   - R0, R1 (SP at the time of interrupt), R2, LR, CR
+ *   - R3-31 (R30-31 first restored from savearea)
+ *   - XER, CTR, DEAR, ESR (from savearea), xSRR0-1
+ *
+ * Notes:
+ * - potential TLB miss: YES, since we make dereferences to kstack, which
+ *   can happen not covered (we can have up to two DTLB misses if fortunate
+ *   enough i.e. when kstack crosses page boundary and both pages are
+ *   untranslated)
+ */
+#define	FRAME_SETUP(sprg_sp, savearea, exc)				\
+	mfspr	%r31, sprg_sp;		/* get saved SP */		\
+	/* establish a new stack frame and put everything on it */	\
+	stwu	%r31, -FRAMELEN(%r1);					\
+	stw	%r0, FRAME_0+8(%r1);	/* save r0 in the trapframe */	\
+	stw	%r31, FRAME_1+8(%r1);	/* save SP   "      "       */	\
+	stw	%r2, FRAME_2+8(%r1);	/* save r2   "      "       */	\
+	mflr	%r31;		 					\
+	stw	%r31, FRAME_LR+8(%r1);	/* save LR   "      "       */	\
+	stw	%r30, FRAME_CR+8(%r1);	/* save CR   "      "       */	\
+	GET_CPUINFO(%r2);						\
+	lwz	%r30, (savearea+CPUSAVE_R30)(%r2); /* get saved r30 */	\
+	lwz	%r31, (savearea+CPUSAVE_R31)(%r2); /* get saved r31 */	\
+	/* save R3-31 */						\
+	stmw	%r3,  FRAME_3+8(%r1) ;					\
+	/* save DEAR, ESR */						\
+	lwz	%r28, (savearea+CPUSAVE_BOOKE_DEAR)(%r2);		\
+	lwz	%r29, (savearea+CPUSAVE_BOOKE_ESR)(%r2);		\
+	stw	%r28, FRAME_BOOKE_DEAR+8(%r1);				\
+	stw	%r29, FRAME_BOOKE_ESR+8(%r1);				\
+	/* save XER, CTR, exc number */					\
+	mfxer	%r3;							\
+	mfctr	%r4;							\
+	stw	%r3, FRAME_XER+8(%r1);					\
+	stw	%r4, FRAME_CTR+8(%r1);					\
+	li	%r5, exc;						\
+	stw	%r5, FRAME_EXC+8(%r1);					\
+	/* save DBCR0 */						\
+	mfspr	%r3, SPR_DBCR0;						\
+	stw	%r3, FRAME_BOOKE_DBCR0+8(%r1);				\
+	/* save xSSR0-1 */						\
+	lwz	%r30, (savearea+CPUSAVE_SRR0)(%r2);			\
+	lwz	%r31, (savearea+CPUSAVE_SRR1)(%r2);			\
+	stw	%r30, FRAME_SRR0+8(%r1);				\
+	stw	%r31, FRAME_SRR1+8(%r1);				\
+	lwz	%r2,PC_CURTHREAD(%r2)	/* set curthread pointer */
+
+/*
+ *
+ * isrr0-1 - save restore registers to restore CPU state to (may be
+ *           SRR0-1, CSRR0-1, MCSRR0-1
+ *
+ * Notes:
+ *  - potential TLB miss: YES. The deref'd kstack may be not covered
+ */
+#define	FRAME_LEAVE(isrr0, isrr1)					\
+	/* restore CTR, XER, LR, CR */					\
+	lwz	%r4, FRAME_CTR+8(%r1);					\
+	lwz	%r5, FRAME_XER+8(%r1);					\
+	lwz	%r6, FRAME_LR+8(%r1);					\
+	lwz	%r7, FRAME_CR+8(%r1);					\
+	mtctr	%r4;							\
+	mtxer	%r5;							\
+	mtlr	%r6;							\
+	mtcr	%r7;							\
+	/* restore DBCR0 */						\
+	lwz	%r4, FRAME_BOOKE_DBCR0+8(%r1);				\
+	mtspr	SPR_DBCR0, %r4;						\
+	/* restore xSRR0-1 */						\
+	lwz	%r30, FRAME_SRR0+8(%r1);				\
+	lwz	%r31, FRAME_SRR1+8(%r1);				\
+	mtspr	isrr0, %r30;						\
+	mtspr	isrr1, %r31;						\
+	/* restore R2-31, SP */						\
+	lmw	%r2, FRAME_2+8(%r1) ;					\
+	lwz	%r0, FRAME_0+8(%r1);					\
+	lwz	%r1, FRAME_1+8(%r1);					\
+	isync
+
+/*
+ * TLB miss prolog
+ *
+ * saves LR, CR, SRR0-1, R20-31 in the TLBSAVE area
+ *
+ * Notes:
+ *  - potential TLB miss: NO. It is crucial that we do not generate a TLB
+ *    miss within the TLB prolog itself!
+ *  - TLBSAVE is always translated
+ */
+#define TLB_PROLOG							\
+	mtsprg4	%r1;			/* Save SP */			\
+	mtsprg5 %r28;							\
+	mtsprg6 %r29;							\
+	/* calculate TLB nesting level and TLBSAVE instance address */	\
+	GET_CPUINFO(%r1);	 	/* Per-cpu structure */		\
+	lwz	%r28, PC_BOOKE_TLB_LEVEL(%r1);				\
+	rlwinm	%r29, %r28, 6, 23, 25;	/* 4 x TLBSAVE_LEN */		\
+	addi	%r28, %r28, 1;						\
+	stw	%r28, PC_BOOKE_TLB_LEVEL(%r1);				\
+	addi	%r29, %r29, PC_BOOKE_TLBSAVE at l; 			\
+	add	%r1, %r1, %r29;		/* current TLBSAVE ptr */	\
+									\
+	/* save R20-31 */						\
+	mfsprg5 %r28;		 					\
+	mfsprg6 %r29;							\
+	stmw	%r20, (TLBSAVE_BOOKE_R20)(%r1);				\
+	/* save LR, CR */						\
+	mflr	%r30;		 					\
+	mfcr	%r31;							\
+	stw	%r30, (TLBSAVE_BOOKE_LR)(%r1);				\
+	stw	%r31, (TLBSAVE_BOOKE_CR)(%r1);				\
+	/* save SRR0-1 */						\
+	mfsrr0	%r30;		/* execution addr at interrupt time */	\
+	mfsrr1	%r31;		/* MSR at interrupt time*/		\
+	stw	%r30, (TLBSAVE_BOOKE_SRR0)(%r1);	/* save SRR0 */	\
+	stw	%r31, (TLBSAVE_BOOKE_SRR1)(%r1);	/* save SRR1 */	\
+	isync;								\
+	mfsprg4	%r1
+
+/*
+ * restores LR, CR, SRR0-1, R20-31 from the TLBSAVE area
+ *
+ * same notes as for the TLB_PROLOG
+ */
+#define TLB_RESTORE							\
+	mtsprg4	%r1;			/* Save SP */			\
+	GET_CPUINFO(%r1);	 	/* Per-cpu structure */		\
+	/* calculate TLB nesting level and TLBSAVE instance addr */	\
+	lwz	%r28, PC_BOOKE_TLB_LEVEL(%r1);				\
+	subi	%r28, %r28, 1;						\
+	stw	%r28, PC_BOOKE_TLB_LEVEL(%r1);				\
+	rlwinm	%r29, %r28, 6, 23, 25; /* 4 x TLBSAVE_LEN */		\
+	addi	%r29, %r29, PC_BOOKE_TLBSAVE at l;				\
+	add	%r1, %r1, %r29;						\
+									\
+	/* restore LR, CR */						\
+	lwz	%r30, (TLBSAVE_BOOKE_LR)(%r1);				\
+	lwz	%r31, (TLBSAVE_BOOKE_CR)(%r1);				\
+	mtlr	%r30;							\
+	mtcr	%r31;							\
+	/* restore SRR0-1 */						\
+	lwz	%r30, (TLBSAVE_BOOKE_SRR0)(%r1);			\
+	lwz	%r31, (TLBSAVE_BOOKE_SRR1)(%r1);			\
+	mtsrr0	%r30;							\
+	mtsrr1	%r31;							\
+	/* restore R20-31 */						\
+	lmw	%r20, (TLBSAVE_BOOKE_R20)(%r1);				\
+	mfsprg4	%r1
+
+#ifdef SMP
+#define TLB_LOCK							\
+	GET_CPUINFO(%r20);						\
+	lwz	%r21, PC_CURTHREAD(%r20);				\
+	lwz	%r22, PC_BOOKE_TLB_LOCK(%r20);				\
+									\
+1:	lwarx	%r23, 0, %r22;						\
+	cmpwi	%r23, TLB_UNLOCKED;					\
+	beq	2f;							\
+									\
+	/* check if this is recursion */				\
+	cmplw	cr0, %r21, %r23;					\
+	bne-	1b;							\
+									\
+2:	/* try to acquire lock */					\
+	stwcx.	%r21, 0, %r22;						\
+	bne-	1b;							\
+									\
+	/* got it, update recursion counter */				\
+	lwz	%r21, RES_RECURSE(%r22);				\
+	addi	%r21, %r21, 1;						\
+	stw	%r21, RES_RECURSE(%r22);				\
+	isync;								\
+	msync
+
+#define TLB_UNLOCK							\
+	GET_CPUINFO(%r20);						\
+	lwz	%r21, PC_CURTHREAD(%r20);				\
+	lwz	%r22, PC_BOOKE_TLB_LOCK(%r20);				\
+									\
+	/* update recursion counter */					\
+	lwz	%r23, RES_RECURSE(%r22);				\
+	subi	%r23, %r23, 1;						\
+	stw	%r23, RES_RECURSE(%r22);				\
+									\
+	cmpwi	%r23, 0;						\
+	bne	1f;							\
+	isync;								\
+	msync;								\
+									\
+	/* release the lock */						\
+	li	%r23, TLB_UNLOCKED;					\
+	stw	%r23, 0(%r22);						\
+1:	isync;								\
+	msync
+#else
+#define TLB_LOCK
+#define TLB_UNLOCK
+#endif	/* SMP */
+
+#define INTERRUPT(label)						\
+	.globl	label;							\
+	.align	5;							\
+	CNAME(label):
+
+/*
+ * Interrupt handling routines in BookE can be flexibly placed and do not have
+ * to live in pre-defined vectors location. Note they need to be TLB-mapped at
+ * all times in order to be able to handle exceptions. We thus arrange for
+ * them to be part of kernel text which is always TLB-accessible.
+ *
+ * The interrupt handling routines have to be 16 bytes aligned: we align them
+ * to 32 bytes (cache line length) which supposedly performs better.
+ *
+ */
+	.text
+	.globl CNAME(interrupt_vector_base)
+	.align 5
+interrupt_vector_base:
+
+/*****************************************************************************
+ * Critical input interrupt
+ ****************************************************************************/
+INTERRUPT(int_critical_input)
+	STANDARD_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_CSRR0, SPR_CSRR1)
+	FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_CRIT)
+	addi	%r3, %r1, 8
+	bl	CNAME(powerpc_crit_interrupt)
+	FRAME_LEAVE(SPR_CSRR0, SPR_CSRR1)
+	rfci
+
+
+/*****************************************************************************
+ * Machine check interrupt
+ ****************************************************************************/
+INTERRUPT(int_machine_check)
+	STANDARD_PROLOG(SPR_SPRG3, PC_BOOKE_MCHKSAVE, SPR_MCSRR0, SPR_MCSRR1)
+	FRAME_SETUP(SPR_SPRG3, PC_BOOKE_MCHKSAVE, EXC_MCHK)
+	addi	%r3, %r1, 8
+	bl	CNAME(powerpc_mchk_interrupt)
+	FRAME_LEAVE(SPR_MCSRR0, SPR_MCSRR1)
+	rfmci
+
+
+/*****************************************************************************
+ * Data storage interrupt
+ ****************************************************************************/
+INTERRUPT(int_data_storage)
+	STANDARD_PROLOG(SPR_SPRG1, PC_DISISAVE, SPR_SRR0, SPR_SRR1)
+	FRAME_SETUP(SPR_SPRG1, PC_DISISAVE, EXC_DSI)
+	b	trap_common
+
+
+/*****************************************************************************
+ * Instruction storage interrupt
+ ****************************************************************************/
+INTERRUPT(int_instr_storage)
+	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
+	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_ISI)
+	b	trap_common
+
+
+/*****************************************************************************
+ * External input interrupt
+ ****************************************************************************/
+INTERRUPT(int_external_input)
+	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
+	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_EXI)
+	addi	%r3, %r1, 8
+	bl	CNAME(powerpc_extr_interrupt)
+	b	trapexit
+
+
+INTERRUPT(int_alignment)
+	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
+	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_ALI)
+	b	trap_common
+
+
+INTERRUPT(int_program)
+	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
+	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_PGM)
+	b	trap_common
+
+
+/*****************************************************************************
+ * System call
+ ****************************************************************************/
+INTERRUPT(int_syscall)
+	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
+	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SC)
+	b	trap_common
+
+
+/*****************************************************************************
+ * Decrementer interrupt
+ ****************************************************************************/
+INTERRUPT(int_decrementer)
+	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
+	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_DECR)
+	addi	%r3, %r1, 8
+	bl	CNAME(powerpc_decr_interrupt)
+	b	trapexit
+
+
+/*****************************************************************************
+ * Fixed interval timer
+ ****************************************************************************/
+INTERRUPT(int_fixed_interval_timer)
+	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
+	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_FIT)
+	b	trap_common
+
+
+/*****************************************************************************
+ * Watchdog interrupt
+ ****************************************************************************/
+INTERRUPT(int_watchdog)
+	STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
+	FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_WDOG)
+	b	trap_common
+
+
+/*****************************************************************************
+ * Data TLB miss interrupt
+ *
+ * There can be nested TLB misses - while handling a TLB miss we reference
+ * data structures that may be not covered by translations. We support up to
+ * TLB_NESTED_MAX-1 nested misses.
+ * 
+ * Registers use:
+ *	r31 - dear
+ *	r30 - unused
+ *	r29 - saved mas0
+ *	r28 - saved mas1
+ *	r27 - saved mas2
+ *	r26 - pmap address
+ *	r25 - pte address
+ *
+ *	r20:r23 - scratch registers
+ ****************************************************************************/
+INTERRUPT(int_data_tlb_error)
+	TLB_PROLOG
+	TLB_LOCK
+
+	mfdear	%r31
+
+	/*
+	 * Save MAS0-MAS2 registers. There might be another tlb miss during
+	 * pte lookup overwriting current contents (which was hw filled).
+	 */
+	mfspr	%r29, SPR_MAS0
+	mfspr	%r28, SPR_MAS1
+	mfspr	%r27, SPR_MAS2
+
+	/* Check faulting address. */
+	lis	%r21, VM_MAXUSER_ADDRESS at h
+	ori	%r21, %r21, VM_MAXUSER_ADDRESS at l
+	cmplw	cr0, %r31, %r21
+	blt	search_user_pmap
+	
+	/* If it's kernel address, allow only supervisor mode misses. */
+	mfsrr1	%r21
+	mtcr	%r21
+	bt	17, search_failed	/* check MSR[PR] */
+
+search_kernel_pmap:
+	/* Load r26 with kernel_pmap address */
+	lis	%r26, kernel_pmap_store at h
+	ori	%r26, %r26, kernel_pmap_store at l
+
+	/* Force kernel tid, set TID to 0 in MAS1. */
+	li	%r21, 0
+	rlwimi	%r28, %r21, 0, 8, 15	/* clear TID bits */
+
+tlb_miss_handle:
+	/* This may result in nested tlb miss. */
+	bl	pte_lookup		/* returns PTE address in R25 */
+
+	cmpwi	%r25, 0			/* pte found? */
+	beq	search_failed
+
+	/* Finish up, write TLB entry. */
+	bl	tlb_fill_entry
+
+tlb_miss_return:
+	TLB_UNLOCK
+	TLB_RESTORE
+	rfi
+
+search_user_pmap:
+	/* Load r26 with current user space process pmap */
+	GET_CPUINFO(%r26)
+	lwz	%r26, PC_CURPMAP(%r26)
+
+	b	tlb_miss_handle
+
+search_failed:
+	/*
+	 * Whenever we don't find a TLB mapping in PT, set a TLB0 entry with
+	 * the faulting virtual address anyway, but put a fake RPN and no
+	 * access rights. This should cause a following {D,I}SI exception.
+	 */
+	lis	%r23, 0xffff0000 at h	/* revoke all permissions */
+
+	/* Load MAS registers. */
+	mtspr	SPR_MAS0, %r29
+	isync
+	mtspr	SPR_MAS1, %r28
+	isync
+	mtspr	SPR_MAS2, %r27
+	isync
+	mtspr	SPR_MAS3, %r23
+	isync
+
+	tlbwe
+	msync
+	isync
+	b	tlb_miss_return
+
+/*****************************************************************************
+ *
+ * Return pte address that corresponds to given pmap/va.  If there is no valid
+ * entry return 0.
+ *
+ * input: r26 - pmap
+ * input: r31 - dear
+ * output: r25 - pte address
+ *
+ * scratch regs used: r21
+ *
+ ****************************************************************************/
+pte_lookup:
+	cmpwi	%r26, 0
+	beq	1f			/* fail quickly if pmap is invalid */
+
+	srwi	%r21, %r31, PDIR_SHIFT		/* pdir offset */
+	slwi	%r21, %r21, PDIR_ENTRY_SHIFT	/* multiply by pdir entry size */
+
+	addi	%r25, %r26, PM_PDIR	/* pmap pm_dir[] address */
+	add	%r25, %r25, %r21	/* offset within pm_pdir[] table */
+	/*
+	 * Get ptbl address, i.e. pmap->pm_pdir[pdir_idx]
+	 * This load may cause a Data TLB miss for non-kernel pmap!
+	 */
+	lwz	%r25, 0(%r25)
+	cmpwi	%r25, 0
+	beq	2f
+
+	lis	%r21, PTBL_MASK at h
+	ori	%r21, %r21, PTBL_MASK at l
+	and	%r21, %r21, %r31
+
+	/* ptbl offset, multiply by ptbl entry size */
+	srwi	%r21, %r21, (PTBL_SHIFT - PTBL_ENTRY_SHIFT)
+
+	add	%r25, %r25, %r21		/* address of pte entry */
+	/*
+	 * Get pte->flags
+	 * This load may cause a Data TLB miss for non-kernel pmap!
+	 */
+	lwz	%r21, PTE_FLAGS(%r25)
+	andis.	%r21, %r21, PTE_VALID at h
+	bne	2f
+1:
+	li	%r25, 0
+2:
+	blr
+
+/*****************************************************************************
+ *
+ * Load MAS1-MAS3 registers with data, write TLB entry
+ *
+ * input:
+ * r29 - mas0
+ * r28 - mas1
+ * r27 - mas2
+ * r25 - pte
+ *
+ * output: none
+ *
+ * scratch regs: r21-r23
+ *
+ ****************************************************************************/
+tlb_fill_entry:
+	/*
+	 * Update PTE flags: we have to do it atomically, as pmap_protect()
+	 * running on other CPUs could attempt to update the flags at the same
+	 * time.
+	 */
+	li	%r23, PTE_FLAGS
+1:
+	lwarx	%r21, %r23, %r25		/* get pte->flags */
+	oris	%r21, %r21, PTE_REFERENCED at h	/* set referenced bit */
+
+	andi.	%r22, %r21, (PTE_SW | PTE_UW)@l	/* check if writable */
+	beq	2f
+	oris	%r21, %r21, PTE_MODIFIED at h	/* set modified bit */
+2:
+	stwcx.	%r21, %r23, %r25		/* write it back */
+	bne-	1b
+
+	/* Update MAS2. */
+	rlwimi	%r27, %r21, 0, 27, 30		/* insert WIMG bits from pte */
+
+	/* Setup MAS3 value in r23. */
+	lwz	%r23, PTE_RPN(%r25)		/* get pte->rpn */
+
+	rlwimi	%r23, %r21, 24, 26, 31		/* insert protection bits from pte */
+
+	/* Load MAS registers. */
+	mtspr	SPR_MAS0, %r29
+	isync
+	mtspr	SPR_MAS1, %r28
+	isync
+	mtspr	SPR_MAS2, %r27
+	isync
+	mtspr	SPR_MAS3, %r23
+	isync
+
+	tlbwe
+	isync
+	msync
+	blr
+
+/*****************************************************************************
+ * Instruction TLB miss interrupt
+ *
+ * Same notes as for the Data TLB miss
+ ****************************************************************************/
+INTERRUPT(int_inst_tlb_error)
+	TLB_PROLOG
+	TLB_LOCK
+
+	mfsrr0	%r31			/* faulting address */
+
+	/*
+	 * Save MAS0-MAS2 registers. There might be another tlb miss during pte
+	 * lookup overwriting current contents (which was hw filled).
+	 */
+	mfspr	%r29, SPR_MAS0
+	mfspr	%r28, SPR_MAS1
+	mfspr	%r27, SPR_MAS2
+
+	mfsrr1	%r21
+	mtcr	%r21
+
+	/* check MSR[PR] */
+	bt	17, search_user_pmap
+	b	search_kernel_pmap
+
+
+	.globl	interrupt_vector_top
+interrupt_vector_top:
+
+/*****************************************************************************
+ * Debug interrupt
+ ****************************************************************************/
+INTERRUPT(int_debug)
+	STANDARD_CRIT_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_CSRR0, SPR_CSRR1)
+	FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_DEBUG)
+	GET_CPUINFO(%r3)
+	lwz	%r3, (PC_BOOKE_CRITSAVE+CPUSAVE_SRR0)(%r3)
+	lis	%r4, interrupt_vector_base at ha
+	addi	%r4, %r4, interrupt_vector_base at l
+	cmplw	cr0, %r3, %r4
+	blt	1f
+	lis	%r4, interrupt_vector_top at ha
+	addi	%r4, %r4, interrupt_vector_top at l
+	cmplw	cr0, %r3, %r4
+	bge	1f
+	/* Disable single-stepping for the interrupt handlers. */
+	lwz	%r3, FRAME_SRR1+8(%r1);
+	rlwinm	%r3, %r3, 0, 23, 21
+	stw	%r3, FRAME_SRR1+8(%r1);
+	/* Restore srr0 and srr1 as they could have been clobbered. */
+	GET_CPUINFO(%r4)
+	lwz	%r3, (PC_BOOKE_CRITSAVE+CPUSAVE_SRR0+8)(%r4);
+	mtspr	SPR_SRR0, %r3
+	lwz	%r4, (PC_BOOKE_CRITSAVE+CPUSAVE_SRR1+8)(%r4);
+	mtspr	SPR_SRR1, %r4
+	b	9f
+1:
+	addi	%r3, %r1, 8
+	bl	CNAME(trap)
+	/*
+	 * Handle ASTs, needed for proper support of single-stepping.
+	 * We actually need to return to the process with an rfi.
+	 */
+	b	trapexit
+9:
+	FRAME_LEAVE(SPR_CSRR0, SPR_CSRR1)
+	rfci
+
+
+/*****************************************************************************
+ * Common trap code
+ ****************************************************************************/
+trap_common:
+	/* Call C trap dispatcher */
+	addi	%r3, %r1, 8
+	bl	CNAME(trap)
+
+	.globl	CNAME(trapexit)		/* exported for db_backtrace use */
+CNAME(trapexit):
+	/* disable interrupts */
+	wrteei	0
+
+	/* Test AST pending - makes sense for user process only */
+	lwz	%r5, FRAME_SRR1+8(%r1)
+	mtcr	%r5
+	bf	17, 1f
+
+	GET_CPUINFO(%r3)
+	lwz	%r4, PC_CURTHREAD(%r3)
+	lwz	%r4, TD_FLAGS(%r4)
+	lis	%r5, (TDF_ASTPENDING | TDF_NEEDRESCHED)@h
+	ori	%r5, %r5, (TDF_ASTPENDING | TDF_NEEDRESCHED)@l
+	and.	%r4, %r4, %r5
+	beq	1f
+
+	/* re-enable interrupts before calling ast() */
+	wrteei	1
+
+	addi	%r3, %r1, 8
+	bl	CNAME(ast)
+	.globl	CNAME(asttrapexit)	/* db_backtrace code sentinel #2 */
+CNAME(asttrapexit):
+	b	trapexit		/* test ast ret value ? */
+1:
+	FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
+	rfi
+
+
+#if defined(KDB)
+/*
+ * Deliberate entry to dbtrap
+ */
+	.globl	CNAME(breakpoint)
+CNAME(breakpoint):
+	mtsprg1	%r1
+	mfmsr	%r3
+	mtsrr1	%r3
+	andi.	%r3, %r3, ~(PSL_EE | PSL_ME)@l
+	mtmsr	%r3			/* disable interrupts */
+	isync
+	GET_CPUINFO(%r3)
+	stw	%r30, (PC_DBSAVE+CPUSAVE_R30)(%r3)
+	stw	%r31, (PC_DBSAVE+CPUSAVE_R31)(%r3)
+
+	mflr	%r31
+	mtsrr0	%r31
+
+	mfdear	%r30
+	mfesr	%r31
+	stw	%r30, (PC_DBSAVE+CPUSAVE_BOOKE_DEAR)(%r3)
+	stw	%r31, (PC_DBSAVE+CPUSAVE_BOOKE_ESR)(%r3)
+
+	mfsrr0	%r30
+	mfsrr1	%r31
+	stw	%r30, (PC_DBSAVE+CPUSAVE_SRR0)(%r3)
+	stw	%r31, (PC_DBSAVE+CPUSAVE_SRR1)(%r3)
+	isync
+
+	mfcr	%r30
+
+/*
+ * Now the kdb trap catching code.
+ */
+dbtrap:
+	FRAME_SETUP(SPR_SPRG1, PC_DBSAVE, EXC_DEBUG)
+/* Call C trap code: */
+	addi	%r3, %r1, 8
+	bl	CNAME(db_trap_glue)
+	or.	%r3, %r3, %r3
+	bne	dbleave
+/* This wasn't for KDB, so switch to real trap: */
+	b	trap_common
+
+dbleave:
+	FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
+	rfi
+#endif /* KDB */
+
+#ifdef SMP
+ENTRY(tlb_lock)
+	GET_CPUINFO(%r5)
+	lwz	%r5, PC_CURTHREAD(%r5)
+1:	lwarx	%r4, 0, %r3
+	cmpwi	%r4, TLB_UNLOCKED
+	bne	1b
+	stwcx.	%r5, 0, %r3
+	bne-	1b
+	isync
+	msync
+	blr
+
+ENTRY(tlb_unlock)
+	isync
+	msync
+	li	%r4, TLB_UNLOCKED
+	stw	%r4, 0(%r3)
+	isync
+	msync
+	blr
+
+/*
+ * TLB miss spin locks. For each CPU we have a reservation granule (32 bytes);
+ * only a single word from this granule will actually be used as a spin lock
+ * for mutual exclusion between TLB miss handler and pmap layer that
+ * manipulates page table contents.
+ */
+	.data
+	.align	5
+GLOBAL(tlb0_miss_locks)
+	.space	RES_GRANULE * MAXCPU
+#endif


Property changes on: trunk/sys/powerpc/booke/trap_subr.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/conf/DEFAULTS
===================================================================
--- trunk/sys/powerpc/conf/DEFAULTS	                        (rev 0)
+++ trunk/sys/powerpc/conf/DEFAULTS	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,16 @@
+#
+# DEFAULTS -- Default kernel configuration file for FreeBSD/powerpc
+#
+# $MidnightBSD$
+# $FreeBSD: stable/10/sys/powerpc/conf/DEFAULTS 255643 2013-09-17 17:37:04Z nwhitehorn $
+
+# Pseudo devices.
+device		mem		# Memory and kernel memory devices
+
+# UART chips on this platform
+device		uart_ns8250
+
+options 	GEOM_PART_BSD
+options 	GEOM_PART_MBR
+
+options         NEW_PCIB


Property changes on: trunk/sys/powerpc/conf/DEFAULTS
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/conf/GENERIC
===================================================================
--- trunk/sys/powerpc/conf/GENERIC	                        (rev 0)
+++ trunk/sys/powerpc/conf/GENERIC	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,213 @@
+#
+# GENERIC -- Generic kernel configuration file for FreeBSD/powerpc
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+#    http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files. 
+# If you are in doubt as to the purpose or necessity of a line, check first 
+# in NOTES.
+#
+# $MidnightBSD$
+# $FreeBSD: stable/10/sys/powerpc/conf/GENERIC 284665 2015-06-21 06:28:26Z trasz $
+
+cpu		AIM
+ident		GENERIC
+
+machine 	powerpc powerpc
+
+makeoptions	DEBUG=-g		#Build kernel with gdb(1) debug symbols
+makeoptions	WITH_CTF=1
+
+# Platform support
+options 	POWERMAC		#NewWorld Apple PowerMacs
+options 	PSIM			#GDB PSIM ppc simulator
+options 	MAMBO			#IBM Mambo Full System Simulator
+options 	PSERIES			#PAPR-compliant systems
+
+options 	SCHED_ULE		#ULE scheduler
+options 	PREEMPTION		#Enable kernel thread preemption
+options 	INET			#InterNETworking
+options 	INET6			#IPv6 communications protocols
+options 	SCTP			#Stream Control Transmission Protocol
+options 	FFS			#Berkeley Fast Filesystem
+options 	SOFTUPDATES		#Enable FFS soft updates support
+options 	UFS_ACL			#Support for access control lists
+options 	UFS_DIRHASH		#Improve performance on big directories
+options 	UFS_GJOURNAL		#Enable gjournal-based UFS journaling
+options 	QUOTA			#Enable disk quotas for UFS
+options 	MD_ROOT			#MD is a potential root device
+options 	NFSCL			#New Network Filesystem Client
+options 	NFSD			#New Network Filesystem Server
+options 	NFSLOCKD		#Network Lock Manager
+options 	NFS_ROOT		#NFS usable as root device
+options 	MSDOSFS			#MSDOS Filesystem
+options 	CD9660			#ISO 9660 Filesystem
+options 	PROCFS			#Process filesystem (requires PSEUDOFS)
+options 	PSEUDOFS		#Pseudo-filesystem framework
+options 	GEOM_PART_APM		#Apple Partition Maps.
+options 	GEOM_PART_GPT		#GUID Partition Tables.
+options 	GEOM_LABEL		#Provides labelization
+options 	COMPAT_FREEBSD4		#Keep this for a while
+options 	COMPAT_FREEBSD5		#Compatible with FreeBSD5
+options 	COMPAT_FREEBSD6		#Compatible with FreeBSD6
+options 	COMPAT_FREEBSD7		#Compatible with FreeBSD7
+options 	SCSI_DELAY=5000		#Delay (in ms) before probing SCSI 
+options 	KTRACE			#ktrace(1) syscall trace support
+options 	STACK			#stack(9) support
+options 	SYSVSHM			#SYSV-style shared memory
+options 	SYSVMSG			#SYSV-style message queues
+options 	SYSVSEM			#SYSV-style semaphores
+options 	_KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+options 	HWPMC_HOOKS		# Necessary kernel hooks for hwpmc(4)
+options 	AUDIT			# Security event auditing
+options 	CAPABILITY_MODE		# Capsicum capability mode
+options 	CAPABILITIES		# Capsicum capabilities
+options 	PROCDESC		# Support for process descriptors
+options 	MAC			# TrustedBSD MAC Framework
+options 	KDTRACE_HOOKS		# Kernel DTrace hooks
+options 	DDB_CTF			# Kernel ELF linker loads CTF data
+options 	INCLUDE_CONFIG_FILE     # Include this file in kernel
+options 	RACCT			# Resource accounting framework
+options 	RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
+options 	RCTL			# Resource limits
+
+# Debugging support.  Always need this:
+options 	KDB			# Enable kernel debugger support.
+options 	KDB_TRACE		# Print a stack trace for a panic.
+
+# Make an SMP-capable kernel by default
+options 	SMP			# Symmetric MultiProcessor Kernel
+
+# CPU frequency control
+device		cpufreq
+
+# Standard busses
+device		pci
+device		agp
+
+# ATA controllers
+device		ahci		# AHCI-compatible SATA controllers
+device		ata		# Legacy ATA/SATA controllers
+device		mvs		# Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA
+device		siis		# SiliconImage SiI3124/SiI3132/SiI3531 SATA
+
+# SCSI Controllers
+device		ahc		# AHA2940 and onboard AIC7xxx devices
+options 	AHC_ALLOW_MEMIO	# Attempt to use memory mapped I/O
+options 	AHC_REG_PRETTY_PRINT	# Print register bitfields in debug
+					# output.  Adds ~128k to driver.
+device		isp		# Qlogic family
+device		ispfw		# Firmware module for Qlogic host adapters
+device		mpt		# LSI-Logic MPT-Fusion
+device		mps		# LSI-Logic MPT-Fusion 2
+device		sym		# NCR/Symbios/LSI Logic 53C8XX/53C1010/53C1510D
+
+# ATA/SCSI peripherals
+device		scbus		# SCSI bus (required for ATA/SCSI)
+device		da		# Direct Access (disks)
+device		sa		# Sequential Access (tape etc)
+device		cd		# CD
+device		pass		# Passthrough device (direct ATA/SCSI access)
+
+# syscons is the default console driver, resembling an SCO console
+device		sc
+device		kbdmux
+options 	SC_OFWFB	# OFW frame buffer
+options 	SC_DFLT_FONT	# compile font in
+makeoptions	SC_DFLT_FONT=cp437
+
+# Serial (COM) ports
+device		scc
+device		uart
+device		uart_z8530
+
+# FireWire support
+device		firewire	# FireWire bus code
+device		sbp		# SCSI over FireWire (Requires scbus and da)
+device		fwe		# Ethernet over FireWire (non-standard!)
+
+# PCI Ethernet NICs that use the common MII bus controller code.
+device		miibus		# MII bus support
+device		bge		# Broadcom BCM570xx Gigabit Ethernet
+device		bm		# Apple BMAC Ethernet
+device		gem		# Sun GEM/Sun ERI/Apple GMAC
+device		dc		# DEC/Intel 21143 and various workalikes
+device		fxp		# Intel EtherExpress PRO/100B (82557, 82558)
+
+# Pseudo devices.
+device		loop		# Network loopback
+device		random		# Entropy device
+device		ether		# Ethernet support
+device		vlan		# 802.1Q VLAN support
+device		tun		# Packet tunnel.
+device		md		# Memory "disks"
+device		ofwd		# Open Firmware disks
+device		gif		# IPv6 and IPv4 tunneling
+device		faith		# IPv6-to-IPv4 relaying/(translation)
+device		firmware	# firmware assist module
+
+# The `bpf' device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+# Note that 'bpf' is required for DHCP.
+device		bpf		#Berkeley packet filter
+
+# USB support
+options 	USB_DEBUG	# enable debug msgs
+device		uhci		# UHCI PCI->USB interface
+device		ohci		# OHCI PCI->USB interface
+device		ehci		# EHCI PCI->USB interface
+device		usb		# USB Bus (required)
+device		uhid		# "Human Interface Devices"
+device		ukbd		# Keyboard
+options 	KBD_INSTALL_CDEV # install a CDEV entry in /dev
+device		ulpt		# Printer
+device		umass		# Disks/Mass storage - Requires scbus and da0
+device		ums		# Mouse
+device		atp		# Apple USB touchpad
+device		urio		# Diamond Rio 500 MP3 player
+# USB Ethernet
+device		aue		# ADMtek USB Ethernet
+device		axe		# ASIX Electronics USB Ethernet
+device		cdce		# Generic USB over Ethernet
+device		cue		# CATC USB Ethernet
+device		kue		# Kawasaki LSI USB Ethernet
+
+# Wireless NIC cards
+options 	IEEE80211_SUPPORT_MESH
+options 	AH_SUPPORT_AR5416
+
+# Misc
+device		iicbus		# I2C bus code
+device		kiic		# Keywest I2C
+device		ad7417		# PowerMac7,2 temperature sensor
+device		adt746x		# PowerBook5,8 temperature sensor
+device		ds1631		# PowerMac11,2 temperature sensor
+device		ds1775		# PowerMac7,2 temperature sensor
+device		fcu		# Apple Fan Control Unit
+device		max6690		# PowerMac7,2 temperature sensor
+device		powermac_nvram	# Open Firmware configuration NVRAM
+device		smu		# Apple System Management Unit
+device		windtunnel	# Apple G4 MDD fan controller
+device		atibl		# ATI-based backlight driver for PowerBooks/iBooks
+device		nvbl		# nVidia-based backlight driver for PowerBooks/iBooks
+
+# ADB support
+device		adb
+device		cuda
+device		pmu
+
+# Sound support
+device		sound		# Generic sound driver (required)
+device		snd_ai2s	# Apple I2S audio
+device		snd_davbus	# Apple DAVBUS audio
+device		snd_uaudio	# USB Audio
+


Property changes on: trunk/sys/powerpc/conf/GENERIC
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/conf/GENERIC.hints
===================================================================
--- trunk/sys/powerpc/conf/GENERIC.hints	                        (rev 0)
+++ trunk/sys/powerpc/conf/GENERIC.hints	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,2 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/sys/powerpc/conf/GENERIC.hints 132375 2004-07-19 02:08:22Z grehan $


Property changes on: trunk/sys/powerpc/conf/GENERIC.hints
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/conf/GENERIC64
===================================================================
--- trunk/sys/powerpc/conf/GENERIC64	                        (rev 0)
+++ trunk/sys/powerpc/conf/GENERIC64	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,207 @@
+#
+# GENERIC -- Generic kernel configuration file for FreeBSD/powerpc
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+#    http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files. 
+# If you are in doubt as to the purpose or necessity of a line, check first 
+# in NOTES.
+#
+# $FreeBSD: stable/10/sys/powerpc/conf/GENERIC64 271111 2014-09-04 18:15:36Z emaste $
+# $MidnightBSD$
+
+cpu		AIM
+ident		GENERIC
+
+machine 	powerpc	powerpc64
+
+makeoptions	DEBUG=-g		#Build kernel with gdb(1) debug symbols
+makeoptions	WITH_CTF=1
+
+# Platform support
+options 	POWERMAC		#NewWorld Apple PowerMacs
+options 	PS3			#Sony Playstation 3
+options 	MAMBO			#IBM Mambo Full System Simulator
+options 	PSERIES			#PAPR-compliant systems (e.g. IBM p)
+
+options 	SCHED_ULE		#ULE scheduler
+options 	PREEMPTION		#Enable kernel thread preemption
+options 	INET			#InterNETworking
+options 	INET6			#IPv6 communications protocols
+options 	SCTP			#Stream Control Transmission Protocol
+options 	FFS			#Berkeley Fast Filesystem
+options 	SOFTUPDATES		#Enable FFS soft updates support
+options 	UFS_ACL			#Support for access control lists
+options 	UFS_DIRHASH		#Improve performance on big directories
+options 	UFS_GJOURNAL		#Enable gjournal-based UFS journaling
+options 	QUOTA			#Enable disk quotas for UFS
+options 	MD_ROOT			#MD is a potential root device
+options 	NFSCL			#New Network Filesystem Client
+options 	NFSD			#New Network Filesystem Server
+options 	NFSLOCKD		#Network Lock Manager
+options 	NFS_ROOT		#NFS usable as root device
+options 	MSDOSFS			#MSDOS Filesystem
+options 	CD9660			#ISO 9660 Filesystem
+options 	PROCFS			#Process filesystem (requires PSEUDOFS)
+options 	PSEUDOFS		#Pseudo-filesystem framework
+options 	GEOM_PART_APM		#Apple Partition Maps.
+options 	GEOM_PART_GPT		#GUID Partition Tables.
+options 	GEOM_LABEL		#Provides labelization
+options 	COMPAT_FREEBSD32	#Compatible with FreeBSD/powerpc binaries
+options 	COMPAT_FREEBSD5		#Compatible with FreeBSD5
+options 	COMPAT_FREEBSD6		#Compatible with FreeBSD6
+options 	COMPAT_FREEBSD7		#Compatible with FreeBSD7
+options 	SCSI_DELAY=5000		#Delay (in ms) before probing SCSI 
+options 	KTRACE			#ktrace(1) syscall trace support
+options 	STACK			#stack(9) support
+options 	SYSVSHM			#SYSV-style shared memory
+options 	SYSVMSG			#SYSV-style message queues
+options 	SYSVSEM			#SYSV-style semaphores
+options 	_KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+options 	HWPMC_HOOKS		# Necessary kernel hooks for hwpmc(4)
+options 	AUDIT			# Security event auditing
+options 	MAC			# TrustedBSD MAC Framework
+options 	KDTRACE_HOOKS		# Kernel DTrace hooks
+options 	DDB_CTF			# Kernel ELF linker loads CTF data
+options 	INCLUDE_CONFIG_FILE     # Include this file in kernel
+
+# Debugging support.  Always need this:
+options 	KDB			# Enable kernel debugger support.
+options 	KDB_TRACE		# Print a stack trace for a panic.
+
+# Make an SMP-capable kernel by default
+options 	SMP			# Symmetric MultiProcessor Kernel
+
+# CPU frequency control
+device		cpufreq
+
+# Standard busses
+device		pci
+device		agp
+
+# ATA controllers
+device		ahci		# AHCI-compatible SATA controllers
+device		ata		# Legacy ATA/SATA controllers
+device		mvs		# Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA
+device		siis		# SiliconImage SiI3124/SiI3132/SiI3531 SATA
+
+# SCSI Controllers
+device		ahc		# AHA2940 and onboard AIC7xxx devices
+options 	AHC_ALLOW_MEMIO	# Attempt to use memory mapped I/O
+options 	AHC_REG_PRETTY_PRINT	# Print register bitfields in debug
+					# output.  Adds ~128k to driver.
+device		isp		# Qlogic family
+device		ispfw		# Firmware module for Qlogic host adapters
+device		mpt		# LSI-Logic MPT-Fusion
+device		mps		# LSI-Logic MPT-Fusion 2
+device		sym		# NCR/Symbios/LSI Logic 53C8XX/53C1010/53C1510D
+
+# ATA/SCSI peripherals
+device		scbus		# SCSI bus (required for ATA/SCSI)
+device		da		# Direct Access (disks)
+device		sa		# Sequential Access (tape etc)
+device		cd		# CD
+device		pass		# Passthrough device (direct ATA/SCSI access)
+
+# vt is the default console driver, resembling an SCO console
+device		vt		# Core console driver
+device		kbdmux
+
+# Serial (COM) ports
+device		scc
+device		uart
+device		uart_z8530
+
+# Ethernet hardware
+device		em		# Intel PRO/1000 Gigabit Ethernet Family
+device		igb		# Intel PRO/1000 PCIE Server Gigabit Family
+device		ixgbe		# Intel PRO/10GbE PCIE Ethernet Family
+device		glc		# Sony Playstation 3 Ethernet
+device		llan		# IBM pSeries Virtual Ethernet
+
+# PCI Ethernet NICs that use the common MII bus controller code.
+device		miibus		# MII bus support
+device		bge		# Broadcom BCM570xx Gigabit Ethernet
+device		gem		# Sun GEM/Sun ERI/Apple GMAC
+device		dc		# DEC/Intel 21143 and various workalikes
+device		fxp		# Intel EtherExpress PRO/100B (82557, 82558)
+device		re		# RealTek 8139C+/8169/8169S/8110S
+device		rl		# RealTek 8129/8139
+
+# Pseudo devices.
+device		loop		# Network loopback
+device		random		# Entropy device
+device		ether		# Ethernet support
+device		vlan		# 802.1Q VLAN support
+device		tun		# Packet tunnel.
+device		md		# Memory "disks"
+device		ofwd		# Open Firmware disks
+device		gif		# IPv6 and IPv4 tunneling
+device		faith		# IPv6-to-IPv4 relaying/(translation)
+device		firmware	# firmware assist module
+
+# The `bpf' device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+# Note that 'bpf' is required for DHCP.
+device		bpf		#Berkeley packet filter
+
+# USB support
+options 	USB_DEBUG	# enable debug msgs
+device		uhci		# UHCI PCI->USB interface
+device		ohci		# OHCI PCI->USB interface
+device		ehci		# EHCI PCI->USB interface
+device		usb		# USB Bus (required)
+device		uhid		# "Human Interface Devices"
+device		ukbd		# Keyboard
+options 	KBD_INSTALL_CDEV # install a CDEV entry in /dev
+device		ulpt		# Printer
+device		umass		# Disks/Mass storage - Requires scbus and da0
+device		ums		# Mouse
+device		urio		# Diamond Rio 500 MP3 player
+# USB Ethernet
+device		aue		# ADMtek USB Ethernet
+device		axe		# ASIX Electronics USB Ethernet
+device		cdce		# Generic USB over Ethernet
+device		cue		# CATC USB Ethernet
+device		kue		# Kawasaki LSI USB Ethernet
+
+# Wireless NIC cards
+options 	IEEE80211_SUPPORT_MESH
+options 	AH_SUPPORT_AR5416
+
+# FireWire support
+device		firewire	# FireWire bus code
+device		sbp		# SCSI over FireWire (Requires scbus and da)
+device		fwe		# Ethernet over FireWire (non-standard!)
+
+# Misc
+device		iicbus		# I2C bus code
+device		kiic		# Keywest I2C
+device		ad7417		# PowerMac7,2 temperature sensor
+device		ds1631		# PowerMac11,2 temperature sensor
+device		ds1775		# PowerMac7,2 temperature sensor
+device		fcu		# Apple Fan Control Unit
+device		max6690		# PowerMac7,2 temperature sensor
+device		powermac_nvram	# Open Firmware configuration NVRAM
+device		smu		# Apple System Management Unit
+device		atibl		# ATI-based backlight driver for PowerBooks/iBooks
+device		nvbl		# nVidia-based backlight driver for PowerBooks/iBooks
+
+# ADB support
+device		adb
+device		pmu
+
+# Sound support
+device		sound		# Generic sound driver (required)
+device		snd_ai2s	# Apple I2S audio
+device		snd_uaudio	# USB Audio
+


Property changes on: trunk/sys/powerpc/conf/GENERIC64
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/conf/MPC85XX
===================================================================
--- trunk/sys/powerpc/conf/MPC85XX	                        (rev 0)
+++ trunk/sys/powerpc/conf/MPC85XX	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,93 @@
+#
+# Custom kernel for Freescale MPC85XX development boards like the CDS etc.
+#
+# $FreeBSD: stable/10/sys/powerpc/conf/MPC85XX 266331 2014-05-17 17:34:37Z ian $
+# $MidnightBSD$
+
+cpu		BOOKE
+cpu		BOOKE_E500
+ident		MPC85XX
+
+machine		powerpc	powerpc
+
+makeoptions	DEBUG="-Wa,-me500 -g"
+makeoptions	NO_MODULES=yes
+
+options 	FPU_EMU
+
+options 	_KPOSIX_PRIORITY_SCHEDULING
+options 	ALT_BREAK_TO_DEBUGGER
+options 	BREAK_TO_DEBUGGER
+options 	BOOTP
+options 	BOOTP_NFSROOT
+options 	BOOTP_NFSV3
+options 	BOOTP_WIRED_TO=tsec0
+options 	CD9660
+options 	COMPAT_43
+options 	DDB
+#options 	DEADLKRES
+options 	DEVICE_POLLING
+#options 	DIAGNOSTIC
+options 	FDT
+makeoptions	FDT_DTS_FILE=mpc8572ds.dts
+#makeoptions	FDT_DTS_FILE=mpc8555cds.dts
+options 	FFS
+options 	GDB
+options 	GEOM_PART_GPT
+options 	INET
+options 	INET6
+options 	INVARIANTS
+options 	INVARIANT_SUPPORT
+options 	KDB
+options 	KTRACE
+options 	MD_ROOT
+options 	MPC85XX
+options 	MSDOSFS
+options 	NFS_ROOT
+options 	NFSCL
+options 	NFSLOCKD
+options 	PROCFS
+options 	PSEUDOFS
+options 	SCHED_ULE
+options 	CAPABILITIES
+options 	CAPABILITY_MODE
+options 	SMP
+options 	SYSVMSG
+options 	SYSVSEM
+options 	SYSVSHM
+options 	WITNESS
+options 	WITNESS_SKIPSPIN
+
+device		ata
+device		bpf
+device		cfi
+device		crypto
+device		cryptodev
+device		da
+device		ds1553
+device		em
+device		alc
+device		ether
+device		fxp
+device		iic
+device		iicbus
+#device		isa
+device		loop
+device		md
+device		miibus
+device		pass
+device		pci
+device		quicc
+device		random
+#device		rl
+device		scbus
+device		scc
+device		sec
+device		tsec
+device		tun
+device		uart
+options 	USB_DEBUG	# enable debug msgs
+#device		uhci
+device		umass
+device		usb
+device		vlan


Property changes on: trunk/sys/powerpc/conf/MPC85XX
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/conf/Makefile
===================================================================
--- trunk/sys/powerpc/conf/Makefile	                        (rev 0)
+++ trunk/sys/powerpc/conf/Makefile	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,6 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/sys/powerpc/conf/Makefile 249390 2013-04-11 22:18:20Z bz $
+
+TARGET=powerpc
+
+.include "${.CURDIR}/../../conf/makeLINT.mk"


Property changes on: trunk/sys/powerpc/conf/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/conf/NOTES
===================================================================
--- trunk/sys/powerpc/conf/NOTES	                        (rev 0)
+++ trunk/sys/powerpc/conf/NOTES	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,97 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/sys/powerpc/conf/NOTES 309447 2016-12-02 22:53:33Z jhb $
+#
+# This file contains machine dependent kernel configuration notes.  For
+# machine independent notes, look in /sys/conf/NOTES.
+
+
+

+#####################################################################
+# CPU OPTIONS
+
+# You must specify a machine directive to choose powerpc or powerpc64
+#machine		powerpc powerpc[64]
+
+#
+# You must specify at least one CPU (the one you intend to run on).
+cpu		AIM
+#cpu		BOOKE_E500
+#cpu		BOOKE_PPC440
+
+options 	FPU_EMU
+
+#options 	MPC85XX
+options 	POWERMAC		#NewWorld Apple PowerMacs
+#options	PS3			#Sony Playstation 3
+options 	PSIM			#GDB PSIM ppc simulator
+options 	MAMBO			#IBM Mambo Full System Simulator
+#options 	WII			#Nintendo Wii
+
+options 	SC_OFWFB		# OFW frame buffer
+
+# The cpufreq(4) driver provides support for CPU frequency control
+device		cpufreq
+
+# Standard busses
+device		pci
+device		agp
+
+device		bm		# Apple BMAC (Big Mac Ethernet)
+device		glc		# Sony Playstation 3 Ethernet
+device		kiic		# Apple Keywest I2C Controller
+device		ofwd		# Open Firmware disks
+device		adb		# Apple Desktop Bus
+device		cuda		# VIA-CUDA ADB interface
+device          ad7417          # PowerMac7,2 temperature sensor
+device		ds1631		# PowerMac11,2 temperature sensor
+device		ds1775		# PowerMac7,2 temperature sensor
+device		fcu		# Apple Fan Control Unit
+device		max6690		# PowerMac7,2 temperature sensor
+device		pmu		# Apple Power Management Unit
+device		smu		# Apple System Management Unit
+device		snd_ai2s	# Apple I2S Audio
+device		snd_davbus	# Apple Davbus Audio
+device		windtunnel	# Apple G4 MDD fan controller
+
+

+#####################################################################
+# Devices we don't want to deal with
+
+nodevice	bktr
+nodevice	cxgbe		# XXX: builds on powerpc64 only.
+nodevice	cxgbev
+nodevice	fdc
+nodevice	ppc
+nodevice	splash
+# when splash works enable *_saver
+nodevice	blank_saver
+nodevice	daemon_saver
+nodevice	dragon_saver
+nodevice	fade_saver
+nodevice	fire_saver
+nodevice	green_saver
+nodevice	logo_saver
+nodevice	rain_saver
+nodevice	snake_saver
+nodevice	star_saver
+nodevice	warp_saver
+nodevice	daemon_saver
+nodevice	star_saver
+nodevice	snake_saver
+# isa
+nodevice	pcii
+nodevice	tnt4882
+# sound
+nodevice	snd_cmi
+# wants gdb_cur
+nodevice	dcons
+nodevice	dcons_crom
+
+

+#####################################################################
+# Options we don't want to deal with
+
+nooption	PPC_DEBUG
+nooption	PPC_PROBE_CHIPSET
+nooption 	SC_NO_MODE_CHANGE
+nooption 	UKBD_DFLT_KEYMAP


Property changes on: trunk/sys/powerpc/conf/NOTES
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/conf/WII
===================================================================
--- trunk/sys/powerpc/conf/WII	                        (rev 0)
+++ trunk/sys/powerpc/conf/WII	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,112 @@
+#
+# Custom kernel for the Nintendo Wii.
+#
+# $FreeBSD: stable/10/sys/powerpc/conf/WII 253845 2013-07-31 17:21:18Z obrien $
+# $MidnightBSD$
+
+cpu		AIM
+ident		WII
+machine 	powerpc powerpc
+
+makeoptions	DEBUG=-g		#Build kernel with gdb(1) debug symbols
+
+options 	WII
+
+options 	SCHED_ULE		#ULE scheduler
+options 	PREEMPTION		#Enable kernel thread preemption
+options 	INET			#InterNETworking
+options 	INET6			#IPv6 communications protocols
+options 	SCTP			#Stream Control Transmission Protocol
+options 	FFS			#Berkeley Fast Filesystem
+options 	SOFTUPDATES		#Enable FFS soft updates support
+options 	UFS_ACL			#Support for access control lists
+options 	UFS_DIRHASH		#Improve performance on big directories
+options 	UFS_GJOURNAL		#Enable gjournal-based UFS journaling
+options 	MD_ROOT			#MD is a potential root device
+options 	NFSCL			#New Network Filesystem Client
+options 	NFSD			#New Network Filesystem Server
+options 	NFSLOCKD		#Network Lock Manager
+options 	NFS_ROOT		#NFS usable as root device
+options 	MSDOSFS			#MSDOS Filesystem
+options 	CD9660			#ISO 9660 Filesystem
+options 	PROCFS			#Process filesystem (requires PSEUDOFS)
+options 	PSEUDOFS		#Pseudo-filesystem framework
+options 	GEOM_PART_GPT		#GUID Partition Tables.
+options 	GEOM_LABEL		#Provides labelization
+options 	SCSI_DELAY=5000		#Delay (in ms) before probing SCSI 
+options 	KTRACE			#ktrace(1) syscall trace support
+options 	STACK			#stack(9) support
+options 	SYSVSHM			#SYSV-style shared memory
+options 	SYSVMSG			#SYSV-style message queues
+options 	SYSVSEM			#SYSV-style semaphores
+options 	_KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+#options 	HWPMC_HOOKS		# Necessary kernel hooks for hwpmc(4)
+options 	AUDIT			# Security event auditing
+options 	CAPABILITY_MODE		# Capsicum capability mode
+options 	CAPABILITIES		# Capsicum capabilities
+options 	MAC			# TrustedBSD MAC Framework
+options 	INCLUDE_CONFIG_FILE     # Include this file in kernel
+
+# Debugging support.  Always need this:
+options 	KDB			# Enable kernel debugger support.
+# For minimum debugger support (stable branch) use:
+options 	KDB_TRACE		# Print a stack trace for a panic.
+# For full debugger support use this instead:
+options 	DDB			#Support DDB
+#options 	DEADLKRES		#Enable the deadlock resolver
+options 	INVARIANTS		#Enable calls of extra sanity checking
+options 	INVARIANT_SUPPORT	#Extra sanity checks of internal structures, required by INVARIANTS
+options 	WITNESS			#Enable checks to detect deadlocks and cycles
+options 	WITNESS_SKIPSPIN	#Don't run witness on spinlocks for speed
+options 	MALLOC_DEBUG_MAXZONES=8	# Separate malloc(9) zones
+
+# ATA/SCSI peripherals
+device          scbus           # SCSI bus (required for ATA/SCSI)
+device          da              # Direct Access (disks)
+
+# syscons is the default console driver, resembling an SCO console
+device		sc
+device		kbdmux
+options 	SC_DFLT_FONT	# compile font in
+makeoptions	SC_DFLT_FONT=cp437
+
+# Pseudo devices.
+device		loop		# Network loopback
+device		random		# Entropy device
+device		ether		# Ethernet support
+device		vlan		# 802.1Q VLAN support
+device		tun		# Packet tunnel.
+device		md		# Memory "disks"
+device		gif		# IPv6 and IPv4 tunneling
+device		faith		# IPv6-to-IPv4 relaying/(translation)
+device		firmware	# firmware assist module
+
+
+# The `bpf' device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+# Note that 'bpf' is required for DHCP.
+device		bpf		#Berkeley packet filter
+
+# USB support
+options 	USB_DEBUG	# enable debug msgs
+device		uhci		# UHCI PCI->USB interface
+device		ohci		# OHCI PCI->USB interface
+device		ehci		# EHCI PCI->USB interface
+device		usb		# USB Bus (required)
+device		uhid		# "Human Interface Devices"
+device		ukbd		# Keyboard
+options 	KBD_INSTALL_CDEV # install a CDEV entry in /dev
+device		ulpt		# Printer
+device		umass		# Disks/Mass storage - Requires scbus and da0
+device		ums		# Mouse
+# USB Ethernet
+device          miibus          # MII bus support
+device		aue		# ADMtek USB Ethernet
+device		axe		# ASIX Electronics USB Ethernet
+device		cdce		# Generic USB over Ethernet
+device		cue		# CATC USB Ethernet
+device		kue		# Kawasaki LSI USB Ethernet
+
+# GPIO
+device		gpio
+device		wiigpio


Property changes on: trunk/sys/powerpc/conf/WII
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/cpufreq/dfs.c
===================================================================
--- trunk/sys/powerpc/cpufreq/dfs.c	                        (rev 0)
+++ trunk/sys/powerpc/cpufreq/dfs.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,229 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Nathan Whitehorn
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/cpufreq/dfs.c 217065 2011-01-06 20:19:01Z andreast $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include "cpufreq_if.h"
+
+struct dfs_softc {
+	device_t dev;
+	int	 dfs4;
+};
+
+static void	dfs_identify(driver_t *driver, device_t parent);
+static int	dfs_probe(device_t dev);
+static int	dfs_attach(device_t dev);
+static int	dfs_settings(device_t dev, struct cf_setting *sets, int *count);
+static int	dfs_set(device_t dev, const struct cf_setting *set);
+static int	dfs_get(device_t dev, struct cf_setting *set);
+static int	dfs_type(device_t dev, int *type);
+
+static device_method_t dfs_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_identify,	dfs_identify),
+	DEVMETHOD(device_probe,		dfs_probe),
+	DEVMETHOD(device_attach,	dfs_attach),
+
+	/* cpufreq interface */
+	DEVMETHOD(cpufreq_drv_set,	dfs_set),
+	DEVMETHOD(cpufreq_drv_get,	dfs_get),
+	DEVMETHOD(cpufreq_drv_type,	dfs_type),
+	DEVMETHOD(cpufreq_drv_settings,	dfs_settings),
+
+	{0, 0}
+};
+
+static driver_t dfs_driver = {
+	"dfs",
+	dfs_methods,
+	sizeof(struct dfs_softc)
+};
+
+static devclass_t dfs_devclass;
+DRIVER_MODULE(dfs, cpu, dfs_driver, dfs_devclass, 0, 0);
+
+/*
+ * Bits of the HID1 register to enable DFS. See page 2-24 of "MPC7450
+ * RISC Microprocessor Family Reference Manual", rev. 5.
+ */
+
+#define	HID1_DFS2	(1UL << 22)
+#define	HID1_DFS4	(1UL << 23)
+
+static void
+dfs_identify(driver_t *driver, device_t parent)
+{
+	uint16_t vers;
+	vers = mfpvr() >> 16;
+
+	/* Check for an MPC 7447A or 7448 CPU */
+	switch (vers) {
+		case MPC7447A:
+		case MPC7448:
+			break;
+		default:
+			return;
+	}
+
+	/* Make sure we're not being doubly invoked. */
+	if (device_find_child(parent, "dfs", -1) != NULL)
+		return;
+
+	/*
+	 * We attach a child for every CPU since settings need to
+	 * be performed on every CPU in the SMP case.
+	 */
+	if (BUS_ADD_CHILD(parent, 10, "dfs", -1) == NULL)
+		device_printf(parent, "add dfs child failed\n");
+}
+
+static int
+dfs_probe(device_t dev)
+{
+	if (resource_disabled("dfs", 0))
+		return (ENXIO);
+
+	device_set_desc(dev, "Dynamic Frequency Switching");
+	return (0);
+}
+
+static int
+dfs_attach(device_t dev)
+{
+	struct dfs_softc *sc;
+	uint16_t vers;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+	sc->dfs4 = 0;
+	vers = mfpvr() >> 16;
+
+	/* The 7448 supports divide-by-four as well */
+	if (vers == MPC7448)
+		sc->dfs4 = 1;
+
+	cpufreq_register(dev);
+	return (0);
+}
+
+static int
+dfs_settings(device_t dev, struct cf_setting *sets, int *count)
+{
+	struct dfs_softc *sc;
+	int states;
+
+	sc = device_get_softc(dev);
+	states = sc->dfs4 ? 3 : 2;
+	if (sets == NULL || count == NULL)
+		return (EINVAL);
+	if (*count < states)
+		return (E2BIG);
+
+	/* Return a list of valid settings for this driver. */
+	memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * states);
+
+	sets[0].freq = 10000; sets[0].dev = dev;
+	sets[1].freq = 5000; sets[1].dev = dev;
+	if (sc->dfs4)
+		sets[2].freq = 2500; sets[2].dev = dev;
+	*count = states;
+
+	return (0);
+}
+
+static int
+dfs_set(device_t dev, const struct cf_setting *set)
+{
+	register_t hid1;
+	
+	if (set == NULL)
+		return (EINVAL);
+
+	hid1 = mfspr(SPR_HID1);
+	hid1 &= ~(HID1_DFS2 | HID1_DFS4);
+
+	if (set->freq == 5000)
+		hid1 |= HID1_DFS2;
+	else if (set->freq == 2500)
+		hid1 |= HID1_DFS4;
+	
+	/*
+	 * Now set the HID1 register with new values. Calling sequence
+	 * taken from page 2-26 of the MPC7450 family CPU manual.
+	 */
+
+	powerpc_sync();
+	mtspr(SPR_HID1, hid1);
+	powerpc_sync(); isync();
+
+	return (0);
+}
+
+static int
+dfs_get(device_t dev, struct cf_setting *set)
+{
+	struct dfs_softc *sc;
+	register_t hid1;
+
+	if (set == NULL)
+		return (EINVAL);
+	sc = device_get_softc(dev);
+
+	memset(set, CPUFREQ_VAL_UNKNOWN, sizeof(*set));
+
+	hid1 = mfspr(SPR_HID1);
+
+	set->freq = 10000;
+	if (hid1 & HID1_DFS2)
+		set->freq = 5000;
+	else if (sc->dfs4 && (hid1 & HID1_DFS4))
+		set->freq = 2500;
+
+	set->dev = dev;
+
+	return (0);
+}
+
+static int
+dfs_type(device_t dev, int *type)
+{
+
+	if (type == NULL)
+		return (EINVAL);
+
+	*type = CPUFREQ_TYPE_RELATIVE;
+	return (0);
+}
+


Property changes on: trunk/sys/powerpc/cpufreq/dfs.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/cpufreq/pcr.c
===================================================================
--- trunk/sys/powerpc/cpufreq/pcr.c	                        (rev 0)
+++ trunk/sys/powerpc/cpufreq/pcr.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,342 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Nathan Whitehorn
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/cpufreq/pcr.c 217065 2011-01-06 20:19:01Z andreast $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <dev/ofw/ofw_bus.h>
+
+#include "cpufreq_if.h"
+
+struct pcr_softc {
+	device_t dev;
+	uint32_t pcr_vals[3];
+	int nmodes;
+};
+
+static void	pcr_identify(driver_t *driver, device_t parent);
+static int	pcr_probe(device_t dev);
+static int	pcr_attach(device_t dev);
+static int	pcr_settings(device_t dev, struct cf_setting *sets, int *count);
+static int	pcr_set(device_t dev, const struct cf_setting *set);
+static int	pcr_get(device_t dev, struct cf_setting *set);
+static int	pcr_type(device_t dev, int *type);
+
+static device_method_t pcr_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_identify,	pcr_identify),
+	DEVMETHOD(device_probe,		pcr_probe),
+	DEVMETHOD(device_attach,	pcr_attach),
+
+	/* cpufreq interface */
+	DEVMETHOD(cpufreq_drv_set,	pcr_set),
+	DEVMETHOD(cpufreq_drv_get,	pcr_get),
+	DEVMETHOD(cpufreq_drv_type,	pcr_type),
+	DEVMETHOD(cpufreq_drv_settings,	pcr_settings),
+
+	{0, 0}
+};
+
+static driver_t pcr_driver = {
+	"pcr",
+	pcr_methods,
+	sizeof(struct pcr_softc)
+};
+
+static devclass_t pcr_devclass;
+DRIVER_MODULE(pcr, cpu, pcr_driver, pcr_devclass, 0, 0);
+
+/*
+ * States
+ */
+
+#define PCR_TO_FREQ(a)	((a >> 17) & 3)
+
+#define	PCR_FULL	0
+#define PCR_HALF	1
+#define PCR_QUARTER	2		/* Only on 970MP */
+
+#define PSR_RECEIVED	(1ULL << 61)
+#define PSR_COMPLETED	(1ULL << 61)
+
+/*
+ * SCOM addresses
+ */
+
+#define	SCOM_PCR	0x0aa00100	/* Power Control Register */
+#define SCOM_PCR_BIT	0x80000000	/* Data bit for PCR */
+#define SCOM_PSR	0x40800100	/* Power Status Register */
+
+/*
+ * SCOM Glue
+ */
+
+#define SCOMC_READ	0x00008000
+#define SCOMC_WRITE	0x00000000 
+
+static void
+write_scom(register_t address, uint64_t value)
+{
+	register_t msr;
+	#ifndef __powerpc64__
+	register_t hi, lo, scratch;
+	#endif
+
+	msr = mfmsr();
+	mtmsr(msr & ~PSL_EE); isync();
+
+	#ifdef __powerpc64__
+	mtspr(SPR_SCOMD, value);
+	#else
+	hi = (value >> 32) & 0xffffffff;
+	lo = value & 0xffffffff;
+	mtspr64(SPR_SCOMD, hi, lo, scratch); 
+	#endif
+	isync();
+	mtspr(SPR_SCOMC, address | SCOMC_WRITE);
+	isync();
+
+	mtmsr(msr); isync();
+}
+
+static uint64_t
+read_scom(register_t address)
+{
+	register_t msr;
+	uint64_t ret;
+
+	msr = mfmsr();
+	mtmsr(msr & ~PSL_EE); isync();
+
+	mtspr(SPR_SCOMC, address | SCOMC_READ);
+	isync();
+
+	__asm __volatile ("mfspr %0,%1;"
+            " mr %0+1, %0; srdi %0,%0,32" : "=r" (ret) : "K" (SPR_SCOMD));
+
+	(void)mfspr(SPR_SCOMC); /* Complete transcation */
+
+	mtmsr(msr); isync();
+
+	return (ret);
+}
+
+static void
+pcr_identify(driver_t *driver, device_t parent)
+{
+	uint16_t vers;
+	vers = mfpvr() >> 16;
+
+	/* Check for an IBM 970-class CPU */
+	switch (vers) {
+		case IBM970FX:
+		case IBM970GX:
+		case IBM970MP:
+			break;
+		default:
+			return;
+	}
+
+	/* Make sure we're not being doubly invoked. */
+	if (device_find_child(parent, "pcr", -1) != NULL)
+		return;
+
+	/*
+	 * We attach a child for every CPU since settings need to
+	 * be performed on every CPU in the SMP case.
+	 */
+	if (BUS_ADD_CHILD(parent, 10, "pcr", -1) == NULL)
+		device_printf(parent, "add pcr child failed\n");
+}
+
+static int
+pcr_probe(device_t dev)
+{
+	if (resource_disabled("pcr", 0))
+		return (ENXIO);
+
+	device_set_desc(dev, "PPC 970 Power Control Register");
+	return (0);
+}
+
+static int
+pcr_attach(device_t dev)
+{
+	struct pcr_softc *sc;
+	phandle_t cpu;
+	uint32_t modes[3];
+	int i;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+
+	cpu = ofw_bus_get_node(device_get_parent(dev));
+
+	if (cpu <= 0) {
+		device_printf(dev,"No CPU device tree node!\n");
+		return (ENXIO);
+	}
+
+	if (OF_getproplen(cpu, "power-mode-data") <= 0) {
+		/* Use the first CPU's node */
+		cpu = OF_child(OF_parent(cpu));
+	}
+
+	/*
+	 * Collect the PCR values for each mode from the device tree.
+	 * These include bus timing information, and so cannot be
+	 * directly computed.
+	 */
+	sc->nmodes = OF_getproplen(cpu, "power-mode-data");
+	if (sc->nmodes <= 0 || sc->nmodes > sizeof(sc->pcr_vals)) {
+		device_printf(dev,"No power mode data in device tree!\n");
+		return (ENXIO);
+	}
+	OF_getprop(cpu, "power-mode-data", modes, sc->nmodes);
+	sc->nmodes /= sizeof(modes[0]);
+
+	/* Sort the modes */
+	for (i = 0; i < sc->nmodes; i++)
+		sc->pcr_vals[PCR_TO_FREQ(modes[i])] = modes[i];
+
+	cpufreq_register(dev);
+	return (0);
+}
+
+static int
+pcr_settings(device_t dev, struct cf_setting *sets, int *count)
+{
+	struct pcr_softc *sc;
+
+	sc = device_get_softc(dev);
+	if (sets == NULL || count == NULL)
+		return (EINVAL);
+	if (*count < sc->nmodes)
+		return (E2BIG);
+
+	/* Return a list of valid settings for this driver. */
+	memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * sc->nmodes);
+
+	sets[0].freq = 10000; sets[0].dev = dev;
+	sets[1].freq = 5000; sets[1].dev = dev;
+	if (sc->nmodes > 2)
+		sets[2].freq = 2500; sets[2].dev = dev;
+	*count = sc->nmodes;
+
+	return (0);
+}
+
+static int
+pcr_set(device_t dev, const struct cf_setting *set)
+{
+	struct pcr_softc *sc;
+	register_t pcr, msr;
+	uint64_t psr;
+	
+	if (set == NULL)
+		return (EINVAL);
+	sc = device_get_softc(dev);
+
+	/* Construct the new PCR */
+
+	pcr = SCOM_PCR_BIT;
+
+	if (set->freq == 10000)
+		pcr |= sc->pcr_vals[0];
+	else if (set->freq == 5000)
+		pcr |= sc->pcr_vals[1];
+	else if (set->freq == 2500)
+		pcr |= sc->pcr_vals[2];
+
+	msr = mfmsr(); 
+	mtmsr(msr & ~PSL_EE); isync();
+
+	/* 970MP requires PCR and PCRH to be cleared first */
+
+	write_scom(SCOM_PCR,0);			/* Clear PCRH */
+	write_scom(SCOM_PCR,SCOM_PCR_BIT);	/* Clear PCR */
+
+	/* Set PCR */
+
+	write_scom(SCOM_PCR, pcr);
+
+	/* Wait for completion */
+
+	do {
+		DELAY(100);
+		psr = read_scom(SCOM_PSR);
+	} while ((psr & PSR_RECEIVED) && !(psr & PSR_COMPLETED));
+
+	mtmsr(msr); isync();
+
+	return (0);
+}
+
+static int
+pcr_get(device_t dev, struct cf_setting *set)
+{
+	uint64_t psr;
+
+	if (set == NULL)
+		return (EINVAL);
+
+	memset(set, CPUFREQ_VAL_UNKNOWN, sizeof(*set));
+
+	psr = read_scom(SCOM_PSR);
+
+	/* We want bits 6 and 7 */
+	psr = (psr >> 56) & 3;
+
+	set->freq = 10000;
+	if (psr == PCR_HALF)
+		set->freq = 5000;
+	else if (psr == PCR_QUARTER)
+		set->freq = 2500;
+
+	set->dev = dev;
+
+	return (0);
+}
+
+static int
+pcr_type(device_t dev, int *type)
+{
+
+	if (type == NULL)
+		return (EINVAL);
+
+	*type = CPUFREQ_TYPE_RELATIVE;
+	return (0);
+}
+


Property changes on: trunk/sys/powerpc/cpufreq/pcr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/cpufreq/pmufreq.c
===================================================================
--- trunk/sys/powerpc/cpufreq/pmufreq.c	                        (rev 0)
+++ trunk/sys/powerpc/cpufreq/pmufreq.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,222 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Justin Hibbits
+ * Copyright (c) 2009 Nathan Whitehorn
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/cpufreq/pmufreq.c 260674 2014-01-15 06:17:15Z jhibbits $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/module.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
+
+#include "cpufreq_if.h"
+#include "powerpc/powermac/pmuvar.h"
+
+struct pmufreq_softc {
+	device_t dev;
+	uint32_t minfreq;
+	uint32_t maxfreq;
+	uint32_t curfreq;
+};
+
+static void	pmufreq_identify(driver_t *driver, device_t parent);
+static int	pmufreq_probe(device_t dev);
+static int	pmufreq_attach(device_t dev);
+static int	pmufreq_settings(device_t dev, struct cf_setting *sets, int *count);
+static int	pmufreq_set(device_t dev, const struct cf_setting *set);
+static int	pmufreq_get(device_t dev, struct cf_setting *set);
+static int	pmufreq_type(device_t dev, int *type);
+
+static device_method_t pmufreq_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_identify,	pmufreq_identify),
+	DEVMETHOD(device_probe,		pmufreq_probe),
+	DEVMETHOD(device_attach,	pmufreq_attach),
+
+	/* cpufreq interface */
+	DEVMETHOD(cpufreq_drv_set,	pmufreq_set),
+	DEVMETHOD(cpufreq_drv_get,	pmufreq_get),
+	DEVMETHOD(cpufreq_drv_type,	pmufreq_type),
+	DEVMETHOD(cpufreq_drv_settings,	pmufreq_settings),
+
+	{0, 0}
+};
+
+static driver_t pmufreq_driver = {
+	"pmufreq",
+	pmufreq_methods,
+	sizeof(struct pmufreq_softc)
+};
+
+static devclass_t pmufreq_devclass;
+DRIVER_MODULE(pmufreq, cpu, pmufreq_driver, pmufreq_devclass, 0, 0);
+
+static void
+pmufreq_identify(driver_t *driver, device_t parent)
+{
+	phandle_t node;
+	uint32_t min_freq;
+
+	node = ofw_bus_get_node(parent);
+	if (OF_getprop(node, "min-clock-frequency", &min_freq, sizeof(min_freq)) == -1)
+		return;
+
+	/* Make sure we're not being doubly invoked. */
+	if (device_find_child(parent, "pmufreq", -1) != NULL)
+		return;
+
+	/*
+	 * We attach a child for every CPU since settings need to
+	 * be performed on every CPU in the SMP case.
+	 */
+	if (BUS_ADD_CHILD(parent, 10, "pmufreq", -1) == NULL)
+		device_printf(parent, "add pmufreq child failed\n");
+}
+
+static int
+pmufreq_probe(device_t dev)
+{
+	struct pmufreq_softc *sc;
+	phandle_t node;
+	uint32_t min_freq;
+
+	if (resource_disabled("pmufreq", 0))
+		return (ENXIO);
+
+	sc = device_get_softc(dev);
+	node = ofw_bus_get_node(device_get_parent(dev));
+	/*
+	 * A scalable MPC7455 has min-clock-frequency/max-clock-frequency as OFW
+	 * properties of the 'cpu' node.
+	 */
+	if (OF_getprop(node, "min-clock-frequency", &min_freq, sizeof(min_freq)) == -1)
+		return (ENXIO);
+	device_set_desc(dev, "PMU-based frequency scaling");
+	return (0);
+}
+
+static int
+pmufreq_attach(device_t dev)
+{
+	struct pmufreq_softc *sc;
+	phandle_t node;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+
+	node = ofw_bus_get_node(device_get_parent(dev));
+	OF_getprop(node, "min-clock-frequency", &sc->minfreq, sizeof(sc->minfreq));
+	OF_getprop(node, "max-clock-frequency", &sc->maxfreq, sizeof(sc->maxfreq));
+	OF_getprop(node, "rounded-clock-frequency", &sc->curfreq, sizeof(sc->curfreq));
+	sc->minfreq /= 1000000;
+	sc->maxfreq /= 1000000;
+	sc->curfreq /= 1000000;
+
+	cpufreq_register(dev);
+	return (0);
+}
+
+static int
+pmufreq_settings(device_t dev, struct cf_setting *sets, int *count)
+{
+	struct pmufreq_softc *sc;
+
+	sc = device_get_softc(dev);
+	if (sets == NULL || count == NULL)
+		return (EINVAL);
+	if (*count < 2)
+		return (E2BIG);
+
+	/* Return a list of valid settings for this driver. */
+	memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * 2);
+
+	sets[0].freq = sc->maxfreq; sets[0].dev = dev;
+	sets[1].freq = sc->minfreq; sets[1].dev = dev;
+	/* Set high latency for CPU frequency changes, it's a tedious process. */
+	sets[0].lat = INT_MAX;
+	sets[1].lat = INT_MAX;
+	*count = 2;
+
+	return (0);
+}
+
+static int
+pmufreq_set(device_t dev, const struct cf_setting *set)
+{
+	struct pmufreq_softc *sc;
+	int error, speed_sel;
+
+	if (set == NULL)
+		return (EINVAL);
+
+	sc = device_get_softc(dev);
+
+	if (set->freq == sc->maxfreq)
+		speed_sel = 0;
+	else
+		speed_sel = 1;
+
+	error = pmu_set_speed(speed_sel);
+	if (error == 0)
+		sc->curfreq = set->freq;
+
+	return (error);
+}
+
+static int
+pmufreq_get(device_t dev, struct cf_setting *set)
+{
+	struct pmufreq_softc *sc;
+
+	if (set == NULL)
+		return (EINVAL);
+	sc = device_get_softc(dev);
+
+	set->freq = sc->curfreq;
+	set->dev = dev;
+
+	return (0);
+}
+
+static int
+pmufreq_type(device_t dev, int *type)
+{
+
+	if (type == NULL)
+		return (EINVAL);
+
+	*type = CPUFREQ_TYPE_ABSOLUTE;
+	return (0);
+}
+


Property changes on: trunk/sys/powerpc/cpufreq/pmufreq.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_add.c
===================================================================
--- trunk/sys/powerpc/fpu/fpu_add.c	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_add.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,227 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: fpu_add.c,v 1.4 2005/12/11 12:18:42 christos Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ *	@(#)fpu_add.c	8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Perform an FPU add (return x + y).
+ *
+ * To subtract, negate y and call add.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/fpu/fpu_add.c 178030 2008-04-09 08:50:37Z grehan $");
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/fpu.h>
+#include <machine/ieeefp.h>
+#include <machine/reg.h>
+
+#include <powerpc/fpu/fpu_arith.h>
+#include <powerpc/fpu/fpu_emu.h>
+
+struct fpn *
+fpu_add(struct fpemu *fe)
+{
+	struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2, *r;
+	u_int r0, r1, r2, r3;
+	int rd;
+
+	/*
+	 * Put the `heavier' operand on the right (see fpu_emu.h).
+	 * Then we will have one of the following cases, taken in the
+	 * following order:
+	 *
+	 *  - y = NaN.  Implied: if only one is a signalling NaN, y is.
+	 *	The result is y.
+	 *  - y = Inf.  Implied: x != NaN (is 0, number, or Inf: the NaN
+	 *    case was taken care of earlier).
+	 *	If x = -y, the result is NaN.  Otherwise the result
+	 *	is y (an Inf of whichever sign).
+	 *  - y is 0.  Implied: x = 0.
+	 *	If x and y differ in sign (one positive, one negative),
+	 *	the result is +0 except when rounding to -Inf.  If same:
+	 *	+0 + +0 = +0; -0 + -0 = -0.
+	 *  - x is 0.  Implied: y != 0.
+	 *	Result is y.
+	 *  - other.  Implied: both x and y are numbers.
+	 *	Do addition a la Hennessey & Patterson.
+	 */
+	DPRINTF(FPE_REG, ("fpu_add:\n"));
+	DUMPFPN(FPE_REG, x);
+	DUMPFPN(FPE_REG, y);
+	DPRINTF(FPE_REG, ("=>\n"));
+	ORDER(x, y);
+	if (ISNAN(y)) {
+		fe->fe_cx |= FPSCR_VXSNAN;
+		DUMPFPN(FPE_REG, y);
+		return (y);
+	}
+	if (ISINF(y)) {
+		if (ISINF(x) && x->fp_sign != y->fp_sign) {
+			fe->fe_cx |= FPSCR_VXISI;
+			return (fpu_newnan(fe));
+		}
+		DUMPFPN(FPE_REG, y);
+		return (y);
+	}
+	rd = ((fe->fe_fpscr) & FPSCR_RN);
+	if (ISZERO(y)) {
+		if (rd != FP_RM)	/* only -0 + -0 gives -0 */
+			y->fp_sign &= x->fp_sign;
+		else			/* any -0 operand gives -0 */
+			y->fp_sign |= x->fp_sign;
+		DUMPFPN(FPE_REG, y);
+		return (y);
+	}
+	if (ISZERO(x)) {
+		DUMPFPN(FPE_REG, y);
+		return (y);
+	}
+	/*
+	 * We really have two numbers to add, although their signs may
+	 * differ.  Make the exponents match, by shifting the smaller
+	 * number right (e.g., 1.011 => 0.1011) and increasing its
+	 * exponent (2^3 => 2^4).  Note that we do not alter the exponents
+	 * of x and y here.
+	 */
+	r = &fe->fe_f3;
+	r->fp_class = FPC_NUM;
+	if (x->fp_exp == y->fp_exp) {
+		r->fp_exp = x->fp_exp;
+		r->fp_sticky = 0;
+	} else {
+		if (x->fp_exp < y->fp_exp) {
+			/*
+			 * Try to avoid subtract case iii (see below).
+			 * This also guarantees that x->fp_sticky = 0.
+			 */
+			SWAP(x, y);
+		}
+		/* now x->fp_exp > y->fp_exp */
+		r->fp_exp = x->fp_exp;
+		r->fp_sticky = fpu_shr(y, x->fp_exp - y->fp_exp);
+	}
+	r->fp_sign = x->fp_sign;
+	if (x->fp_sign == y->fp_sign) {
+		FPU_DECL_CARRY
+
+		/*
+		 * The signs match, so we simply add the numbers.  The result
+		 * may be `supernormal' (as big as 1.111...1 + 1.111...1, or
+		 * 11.111...0).  If so, a single bit shift-right will fix it
+		 * (but remember to adjust the exponent).
+		 */
+		/* r->fp_mant = x->fp_mant + y->fp_mant */
+		FPU_ADDS(r->fp_mant[3], x->fp_mant[3], y->fp_mant[3]);
+		FPU_ADDCS(r->fp_mant[2], x->fp_mant[2], y->fp_mant[2]);
+		FPU_ADDCS(r->fp_mant[1], x->fp_mant[1], y->fp_mant[1]);
+		FPU_ADDC(r0, x->fp_mant[0], y->fp_mant[0]);
+		if ((r->fp_mant[0] = r0) >= FP_2) {
+			(void) fpu_shr(r, 1);
+			r->fp_exp++;
+		}
+	} else {
+		FPU_DECL_CARRY
+
+		/*
+		 * The signs differ, so things are rather more difficult.
+		 * H&P would have us negate the negative operand and add;
+		 * this is the same as subtracting the negative operand.
+		 * This is quite a headache.  Instead, we will subtract
+		 * y from x, regardless of whether y itself is the negative
+		 * operand.  When this is done one of three conditions will
+		 * hold, depending on the magnitudes of x and y:
+		 *   case i)   |x| > |y|.  The result is just x - y,
+		 *	with x's sign, but it may need to be normalized.
+		 *   case ii)  |x| = |y|.  The result is 0 (maybe -0)
+		 *	so must be fixed up.
+		 *   case iii) |x| < |y|.  We goofed; the result should
+		 *	be (y - x), with the same sign as y.
+		 * We could compare |x| and |y| here and avoid case iii,
+		 * but that would take just as much work as the subtract.
+		 * We can tell case iii has occurred by an overflow.
+		 *
+		 * N.B.: since x->fp_exp >= y->fp_exp, x->fp_sticky = 0.
+		 */
+		/* r->fp_mant = x->fp_mant - y->fp_mant */
+		FPU_SET_CARRY(y->fp_sticky);
+		FPU_SUBCS(r3, x->fp_mant[3], y->fp_mant[3]);
+		FPU_SUBCS(r2, x->fp_mant[2], y->fp_mant[2]);
+		FPU_SUBCS(r1, x->fp_mant[1], y->fp_mant[1]);
+		FPU_SUBC(r0, x->fp_mant[0], y->fp_mant[0]);
+		if (r0 < FP_2) {
+			/* cases i and ii */
+			if ((r0 | r1 | r2 | r3) == 0) {
+				/* case ii */
+				r->fp_class = FPC_ZERO;
+				r->fp_sign = rd == FP_RM;
+				return (r);
+			}
+		} else {
+			/*
+			 * Oops, case iii.  This can only occur when the
+			 * exponents were equal, in which case neither
+			 * x nor y have sticky bits set.  Flip the sign
+			 * (to y's sign) and negate the result to get y - x.
+			 */
+#ifdef DIAGNOSTIC
+			if (x->fp_exp != y->fp_exp || r->fp_sticky)
+				panic("fpu_add");
+#endif
+			r->fp_sign = y->fp_sign;
+			FPU_SUBS(r3, 0, r3);
+			FPU_SUBCS(r2, 0, r2);
+			FPU_SUBCS(r1, 0, r1);
+			FPU_SUBC(r0, 0, r0);
+		}
+		r->fp_mant[3] = r3;
+		r->fp_mant[2] = r2;
+		r->fp_mant[1] = r1;
+		r->fp_mant[0] = r0;
+		if (r0 < FP_1)
+			fpu_norm(r);
+	}
+	DUMPFPN(FPE_REG, r);
+	return (r);
+}


Property changes on: trunk/sys/powerpc/fpu/fpu_add.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_arith.h
===================================================================
--- trunk/sys/powerpc/fpu/fpu_arith.h	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_arith.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,153 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: fpu_arith.h,v 1.4 2005/12/24 20:07:28 perry Exp $ */
+/* $FreeBSD: stable/10/sys/powerpc/fpu/fpu_arith.h 176491 2008-02-23 20:05:26Z marcel $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ *	@(#)fpu_arith.h	8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Extended-precision arithmetic.
+ *
+ * We hold the notion of a `carry register', which may or may not be a
+ * machine carry bit or register.  On the SPARC, it is just the machine's
+ * carry bit.
+ *
+ * In the worst case, you can compute the carry from x+y as
+ *	(unsigned)(x + y) < (unsigned)x
+ * and from x+y+c as
+ *	((unsigned)(x + y + c) <= (unsigned)x && (y|c) != 0)
+ * for example.
+ */
+
+
+#ifndef FPE_USE_ASM
+
+/* set up for extended-precision arithemtic */
+#define	FPU_DECL_CARRY quad_t fpu_carry, fpu_tmp;
+
+/*
+ * We have three kinds of add:
+ *	add with carry:					  r = x + y + c
+ *	add (ignoring current carry) and set carry:	c'r = x + y + 0
+ *	add with carry and set carry:			c'r = x + y + c
+ * The macros use `C' for `use carry' and `S' for `set carry'.
+ * Note that the state of the carry is undefined after ADDC and SUBC,
+ * so if all you have for these is `add with carry and set carry',
+ * that is OK.
+ *
+ * The same goes for subtract, except that we compute x - y - c.
+ *
+ * Finally, we have a way to get the carry into a `regular' variable,
+ * or set it from a value.  SET_CARRY turns 0 into no-carry, nonzero
+ * into carry; GET_CARRY sets its argument to 0 or 1.
+ */
+#define	FPU_ADDC(r, x, y) \
+	(r) = (x) + (y) + (!!fpu_carry)
+#define	FPU_ADDS(r, x, y) \
+	{ \
+		fpu_tmp = (quad_t)(x) + (quad_t)(y); \
+		(r) = (u_int)fpu_tmp; \
+		fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \
+	}
+#define	FPU_ADDCS(r, x, y) \
+	{ \
+		fpu_tmp = (quad_t)(x) + (quad_t)(y) + (!!fpu_carry); \
+		(r) = (u_int)fpu_tmp; \
+		fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \
+	}
+#define	FPU_SUBC(r, x, y) \
+	(r) = (x) - (y) - (!!fpu_carry)
+#define	FPU_SUBS(r, x, y) \
+	{ \
+		fpu_tmp = (quad_t)(x) - (quad_t)(y); \
+		(r) = (u_int)fpu_tmp; \
+		fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \
+	}
+#define	FPU_SUBCS(r, x, y) \
+	{ \
+		fpu_tmp = (quad_t)(x) - (quad_t)(y) - (!!fpu_carry); \
+		(r) = (u_int)fpu_tmp; \
+		fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \
+	}
+
+#define	FPU_GET_CARRY(r) (r) = (!!fpu_carry)
+#define	FPU_SET_CARRY(v) fpu_carry = ((v) != 0)
+
+#else
+/* set up for extended-precision arithemtic */
+#define	FPU_DECL_CARRY
+
+/*
+ * We have three kinds of add:
+ *	add with carry:					  r = x + y + c
+ *	add (ignoring current carry) and set carry:	c'r = x + y + 0
+ *	add with carry and set carry:			c'r = x + y + c
+ * The macros use `C' for `use carry' and `S' for `set carry'.
+ * Note that the state of the carry is undefined after ADDC and SUBC,
+ * so if all you have for these is `add with carry and set carry',
+ * that is OK.
+ *
+ * The same goes for subtract, except that we compute x - y - c.
+ *
+ * Finally, we have a way to get the carry into a `regular' variable,
+ * or set it from a value.  SET_CARRY turns 0 into no-carry, nonzero
+ * into carry; GET_CARRY sets its argument to 0 or 1.
+ */
+#define	FPU_ADDC(r, x, y) \
+	__asm volatile("adde %0,%1,%2" : "=r"(r) : "r"(x), "r"(y))
+#define	FPU_ADDS(r, x, y) \
+	__asm volatile("addc %0,%1,%2" : "=r"(r) : "r"(x), "r"(y))
+#define	FPU_ADDCS(r, x, y) \
+	__asm volatile("adde %0,%1,%2" : "=r"(r) : "r"(x), "r"(y))
+#define	FPU_SUBC(r, x, y) \
+	__asm volatile("subfe %0,%2,%1" : "=r"(r) : "r"(x), "r"(y))
+#define	FPU_SUBS(r, x, y) \
+	__asm volatile("subfc %0,%2,%1" : "=r"(r) : "r"(x), "r"(y))
+#define	FPU_SUBCS(r, x, y) \
+	__asm volatile("subfe %0,%2,%1" : "=r"(r) : "r"(x), "r"(y))
+
+#define	FPU_GET_CARRY(r) __asm volatile("li %0,0; addie %0,%0,0" : "=r"(r))
+/* This one needs to destroy a temp register. */
+#define	FPU_SET_CARRY(v) do { int __tmp;				\
+		__asm volatile("addic %0,%0,-1" : "r"(__tmp) : "r"(v)); \
+	} while (0)
+
+#define	FPU_SHL1_BY_ADD	/* shift left 1 faster by ADDC than (a<<1)|(b>>31) */
+#endif


Property changes on: trunk/sys/powerpc/fpu/fpu_arith.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_compare.c
===================================================================
--- trunk/sys/powerpc/fpu/fpu_compare.c	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_compare.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,163 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: fpu_compare.c,v 1.4 2005/12/11 12:18:42 christos Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ *	@(#)fpu_compare.c	8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * FCMPU and FCMPO instructions.
+ *
+ * These rely on the fact that our internal wide format is achieved by
+ * adding zero bits to the end of narrower mantissas.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/fpu/fpu_compare.c 178030 2008-04-09 08:50:37Z grehan $");
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/fpu.h>
+#include <machine/reg.h>
+
+#include <powerpc/fpu/fpu_arith.h>
+#include <powerpc/fpu/fpu_emu.h>
+
+/*
+ * Perform a compare instruction (with or without unordered exception).
+ * This updates the fcc field in the fsr.
+ *
+ * If either operand is NaN, the result is unordered.  For ordered, this
+ * causes an NV exception.  Everything else is ordered:
+ *	|Inf| > |numbers| > |0|.
+ * We already arranged for fp_class(Inf) > fp_class(numbers) > fp_class(0),
+ * so we get this directly.  Note, however, that two zeros compare equal
+ * regardless of sign, while everything else depends on sign.
+ *
+ * Incidentally, two Infs of the same sign compare equal (per the 80387
+ * manual---it would be nice if the SPARC documentation were more
+ * complete).
+ */
+void
+fpu_compare(struct fpemu *fe, int ordered)
+{
+	struct fpn *a, *b, *r;
+	int cc;
+
+	a = &fe->fe_f1;
+	b = &fe->fe_f2;
+	r = &fe->fe_f3;
+
+	if (ISNAN(a) || ISNAN(b)) {
+		/*
+		 * In any case, we already got an exception for signalling
+		 * NaNs; here we may replace that one with an identical
+		 * exception, but so what?.
+		 */
+		cc = FPSCR_FU;
+		if (ISSNAN(a) || ISSNAN(b))
+			cc |= FPSCR_VXSNAN;
+		if (ordered) {
+			if (fe->fe_fpscr & FPSCR_VE || ISQNAN(a) || ISQNAN(b))
+				cc |= FPSCR_VXVC;
+		}
+		goto done;
+	}
+
+	/*
+	 * Must handle both-zero early to avoid sign goofs.  Otherwise,
+	 * at most one is 0, and if the signs differ we are done.
+	 */
+	if (ISZERO(a) && ISZERO(b)) {
+		cc = FPSCR_FE;
+		goto done;
+	}
+	if (a->fp_sign) {		/* a < 0 (or -0) */
+		if (!b->fp_sign) {	/* b >= 0 (or if a = -0, b > 0) */
+			cc = FPSCR_FL;
+			goto done;
+		}
+	} else {			/* a > 0 (or +0) */
+		if (b->fp_sign) {	/* b <= -0 (or if a = +0, b < 0) */
+			cc = FPSCR_FG;
+			goto done;
+		}
+	}
+
+	/*
+	 * Now the signs are the same (but may both be negative).  All
+	 * we have left are these cases:
+	 *
+	 *	|a| < |b|		[classes or values differ]
+	 *	|a| > |b|		[classes or values differ]
+	 *	|a| == |b|		[classes and values identical]
+	 *
+	 * We define `diff' here to expand these as:
+	 *
+	 *	|a| < |b|, a,b >= 0: a < b => FSR_CC_LT
+	 *	|a| < |b|, a,b < 0:  a > b => FSR_CC_GT
+	 *	|a| > |b|, a,b >= 0: a > b => FSR_CC_GT
+	 *	|a| > |b|, a,b < 0:  a < b => FSR_CC_LT
+	 */
+#define opposite_cc(cc) ((cc) == FPSCR_FL ? FPSCR_FG : FPSCR_FL)
+#define	diff(magnitude) (a->fp_sign ? opposite_cc(magnitude) :  (magnitude))
+	if (a->fp_class < b->fp_class) {	/* |a| < |b| */
+		cc = diff(FPSCR_FL);
+		goto done;
+	}
+	if (a->fp_class > b->fp_class) {	/* |a| > |b| */
+		cc = diff(FPSCR_FG);
+		goto done;
+	}
+	/* now none can be 0: only Inf and numbers remain */
+	if (ISINF(a)) {				/* |Inf| = |Inf| */
+		cc = FPSCR_FE;
+		goto done;
+	}
+	fpu_sub(fe);
+	if (ISZERO(r))
+		cc = FPSCR_FE;
+	else if (r->fp_sign)
+		cc = FPSCR_FL;
+	else
+		cc = FPSCR_FG;
+done:
+	fe->fe_cx = cc;
+}


Property changes on: trunk/sys/powerpc/fpu/fpu_compare.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_div.c
===================================================================
--- trunk/sys/powerpc/fpu/fpu_div.c	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_div.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,293 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: fpu_div.c,v 1.4 2005/12/11 12:18:42 christos Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ *	@(#)fpu_div.c	8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Perform an FPU divide (return x / y).
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/fpu/fpu_div.c 178030 2008-04-09 08:50:37Z grehan $");
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/fpu.h>
+#include <machine/reg.h>
+
+#include <powerpc/fpu/fpu_arith.h>
+#include <powerpc/fpu/fpu_emu.h>
+
+/*
+ * Division of normal numbers is done as follows:
+ *
+ * x and y are floating point numbers, i.e., in the form 1.bbbb * 2^e.
+ * If X and Y are the mantissas (1.bbbb's), the quotient is then:
+ *
+ *	q = (X / Y) * 2^((x exponent) - (y exponent))
+ *
+ * Since X and Y are both in [1.0,2.0), the quotient's mantissa (X / Y)
+ * will be in [0.5,2.0).  Moreover, it will be less than 1.0 if and only
+ * if X < Y.  In that case, it will have to be shifted left one bit to
+ * become a normal number, and the exponent decremented.  Thus, the
+ * desired exponent is:
+ *
+ *	left_shift = x->fp_mant < y->fp_mant;
+ *	result_exp = x->fp_exp - y->fp_exp - left_shift;
+ *
+ * The quotient mantissa X/Y can then be computed one bit at a time
+ * using the following algorithm:
+ *
+ *	Q = 0;			-- Initial quotient.
+ *	R = X;			-- Initial remainder,
+ *	if (left_shift)		--   but fixed up in advance.
+ *		R *= 2;
+ *	for (bit = FP_NMANT; --bit >= 0; R *= 2) {
+ *		if (R >= Y) {
+ *			Q |= 1 << bit;
+ *			R -= Y;
+ *		}
+ *	}
+ *
+ * The subtraction R -= Y always removes the uppermost bit from R (and
+ * can sometimes remove additional lower-order 1 bits); this proof is
+ * left to the reader.
+ *
+ * This loop correctly calculates the guard and round bits since they are
+ * included in the expanded internal representation.  The sticky bit
+ * is to be set if and only if any other bits beyond guard and round
+ * would be set.  From the above it is obvious that this is true if and
+ * only if the remainder R is nonzero when the loop terminates.
+ *
+ * Examining the loop above, we can see that the quotient Q is built
+ * one bit at a time ``from the top down''.  This means that we can
+ * dispense with the multi-word arithmetic and just build it one word
+ * at a time, writing each result word when it is done.
+ *
+ * Furthermore, since X and Y are both in [1.0,2.0), we know that,
+ * initially, R >= Y.  (Recall that, if X < Y, R is set to X * 2 and
+ * is therefore at in [2.0,4.0).)  Thus Q is sure to have bit FP_NMANT-1
+ * set, and R can be set initially to either X - Y (when X >= Y) or
+ * 2X - Y (when X < Y).  In addition, comparing R and Y is difficult,
+ * so we will simply calculate R - Y and see if that underflows.
+ * This leads to the following revised version of the algorithm:
+ *
+ *	R = X;
+ *	bit = FP_1;
+ *	D = R - Y;
+ *	if (D >= 0) {
+ *		result_exp = x->fp_exp - y->fp_exp;
+ *		R = D;
+ *		q = bit;
+ *		bit >>= 1;
+ *	} else {
+ *		result_exp = x->fp_exp - y->fp_exp - 1;
+ *		q = 0;
+ *	}
+ *	R <<= 1;
+ *	do  {
+ *		D = R - Y;
+ *		if (D >= 0) {
+ *			q |= bit;
+ *			R = D;
+ *		}
+ *		R <<= 1;
+ *	} while ((bit >>= 1) != 0);
+ *	Q[0] = q;
+ *	for (i = 1; i < 4; i++) {
+ *		q = 0, bit = 1 << 31;
+ *		do {
+ *			D = R - Y;
+ *			if (D >= 0) {
+ *				q |= bit;
+ *				R = D;
+ *			}
+ *			R <<= 1;
+ *		} while ((bit >>= 1) != 0);
+ *		Q[i] = q;
+ *	}
+ *
+ * This can be refined just a bit further by moving the `R <<= 1'
+ * calculations to the front of the do-loops and eliding the first one.
+ * The process can be terminated immediately whenever R becomes 0, but
+ * this is relatively rare, and we do not bother.
+ */
+
+struct fpn *
+fpu_div(struct fpemu *fe)
+{
+	struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2;
+	u_int q, bit;
+	u_int r0, r1, r2, r3, d0, d1, d2, d3, y0, y1, y2, y3;
+	FPU_DECL_CARRY
+
+	/*
+	 * Since divide is not commutative, we cannot just use ORDER.
+	 * Check either operand for NaN first; if there is at least one,
+	 * order the signalling one (if only one) onto the right, then
+	 * return it.  Otherwise we have the following cases:
+	 *
+	 *	Inf / Inf = NaN, plus NV exception
+	 *	Inf / num = Inf [i.e., return x]
+	 *	Inf / 0   = Inf [i.e., return x]
+	 *	0 / Inf = 0 [i.e., return x]
+	 *	0 / num = 0 [i.e., return x]
+	 *	0 / 0   = NaN, plus NV exception
+	 *	num / Inf = 0
+	 *	num / num = num (do the divide)
+	 *	num / 0   = Inf, plus DZ exception
+	 */
+	DPRINTF(FPE_REG, ("fpu_div:\n"));
+	DUMPFPN(FPE_REG, x);
+	DUMPFPN(FPE_REG, y);
+	DPRINTF(FPE_REG, ("=>\n"));
+	if (ISNAN(x) || ISNAN(y)) {
+		ORDER(x, y);
+		fe->fe_cx |= FPSCR_VXSNAN;
+		DUMPFPN(FPE_REG, y);
+		return (y);
+	}
+	/*
+	 * Need to split the following out cause they generate different
+	 * exceptions. 
+	 */
+	if (ISINF(x)) {
+		if (x->fp_class == y->fp_class) {
+			fe->fe_cx |= FPSCR_VXIDI;
+			return (fpu_newnan(fe));
+		}
+		DUMPFPN(FPE_REG, x);
+		return (x);
+	}
+	if (ISZERO(x)) {
+		fe->fe_cx |= FPSCR_ZX;
+		if (x->fp_class == y->fp_class) {
+			fe->fe_cx |= FPSCR_VXZDZ;
+			return (fpu_newnan(fe));
+		}
+		DUMPFPN(FPE_REG, x);
+		return (x);
+	}
+
+	/* all results at this point use XOR of operand signs */
+	x->fp_sign ^= y->fp_sign;
+	if (ISINF(y)) {
+		x->fp_class = FPC_ZERO;
+		DUMPFPN(FPE_REG, x);
+		return (x);
+	}
+	if (ISZERO(y)) {
+		fe->fe_cx = FPSCR_ZX;
+		x->fp_class = FPC_INF;
+		DUMPFPN(FPE_REG, x);
+		return (x);
+	}
+
+	/*
+	 * Macros for the divide.  See comments at top for algorithm.
+	 * Note that we expand R, D, and Y here.
+	 */
+
+#define	SUBTRACT		/* D = R - Y */ \
+	FPU_SUBS(d3, r3, y3); FPU_SUBCS(d2, r2, y2); \
+	FPU_SUBCS(d1, r1, y1); FPU_SUBC(d0, r0, y0)
+
+#define	NONNEGATIVE		/* D >= 0 */ \
+	((int)d0 >= 0)
+
+#ifdef FPU_SHL1_BY_ADD
+#define	SHL1			/* R <<= 1 */ \
+	FPU_ADDS(r3, r3, r3); FPU_ADDCS(r2, r2, r2); \
+	FPU_ADDCS(r1, r1, r1); FPU_ADDC(r0, r0, r0)
+#else
+#define	SHL1 \
+	r0 = (r0 << 1) | (r1 >> 31), r1 = (r1 << 1) | (r2 >> 31), \
+	r2 = (r2 << 1) | (r3 >> 31), r3 <<= 1
+#endif
+
+#define	LOOP			/* do ... while (bit >>= 1) */ \
+	do { \
+		SHL1; \
+		SUBTRACT; \
+		if (NONNEGATIVE) { \
+			q |= bit; \
+			r0 = d0, r1 = d1, r2 = d2, r3 = d3; \
+		} \
+	} while ((bit >>= 1) != 0)
+
+#define	WORD(r, i)			/* calculate r->fp_mant[i] */ \
+	q = 0; \
+	bit = 1 << 31; \
+	LOOP; \
+	(x)->fp_mant[i] = q
+
+	/* Setup.  Note that we put our result in x. */
+	r0 = x->fp_mant[0];
+	r1 = x->fp_mant[1];
+	r2 = x->fp_mant[2];
+	r3 = x->fp_mant[3];
+	y0 = y->fp_mant[0];
+	y1 = y->fp_mant[1];
+	y2 = y->fp_mant[2];
+	y3 = y->fp_mant[3];
+
+	bit = FP_1;
+	SUBTRACT;
+	if (NONNEGATIVE) {
+		x->fp_exp -= y->fp_exp;
+		r0 = d0, r1 = d1, r2 = d2, r3 = d3;
+		q = bit;
+		bit >>= 1;
+	} else {
+		x->fp_exp -= y->fp_exp + 1;
+		q = 0;
+	}
+	LOOP;
+	x->fp_mant[0] = q;
+	WORD(x, 1);
+	WORD(x, 2);
+	WORD(x, 3);
+	x->fp_sticky = r0 | r1 | r2 | r3;
+
+	DUMPFPN(FPE_REG, x);
+	return (x);
+}


Property changes on: trunk/sys/powerpc/fpu/fpu_div.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_emu.c
===================================================================
--- trunk/sys/powerpc/fpu/fpu_emu.c	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_emu.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,800 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: fpu_emu.c,v 1.14 2005/12/11 12:18:42 christos Exp $ */
+
+/*
+ * Copyright 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc.
+ *
+ * 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 for the NetBSD Project by
+ *      Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ *	@(#)fpu.c	8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/fpu/fpu_emu.c 266005 2014-05-14 04:57:55Z ian $");
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/signal.h>
+#include <sys/syslog.h>
+#include <sys/signalvar.h>
+
+#include <machine/fpu.h>
+#include <machine/reg.h>
+
+#include <powerpc/fpu/fpu_emu.h>
+#include <powerpc/fpu/fpu_extern.h>
+#include <powerpc/fpu/fpu_instr.h>
+
+static SYSCTL_NODE(_hw, OID_AUTO, fpu_emu, CTLFLAG_RW, 0, "FPU emulator");
+
+#define	FPU_EMU_EVCNT_DECL(name)					\
+static u_int fpu_emu_evcnt_##name;					\
+SYSCTL_INT(_hw_fpu_emu, OID_AUTO, evcnt_##name, CTLFLAG_RD,		\
+    &fpu_emu_evcnt_##name, 0, "")
+
+#define	FPU_EMU_EVCNT_INCR(name)	fpu_emu_evcnt_##name++
+
+FPU_EMU_EVCNT_DECL(stfiwx);
+FPU_EMU_EVCNT_DECL(fpstore);
+FPU_EMU_EVCNT_DECL(fpload);
+FPU_EMU_EVCNT_DECL(fcmpu);
+FPU_EMU_EVCNT_DECL(frsp);
+FPU_EMU_EVCNT_DECL(fctiw);
+FPU_EMU_EVCNT_DECL(fcmpo);
+FPU_EMU_EVCNT_DECL(mtfsb1);
+FPU_EMU_EVCNT_DECL(fnegabs);
+FPU_EMU_EVCNT_DECL(mcrfs);
+FPU_EMU_EVCNT_DECL(mtfsb0);
+FPU_EMU_EVCNT_DECL(fmr);
+FPU_EMU_EVCNT_DECL(mtfsfi);
+FPU_EMU_EVCNT_DECL(fnabs);
+FPU_EMU_EVCNT_DECL(fabs);
+FPU_EMU_EVCNT_DECL(mffs);
+FPU_EMU_EVCNT_DECL(mtfsf);
+FPU_EMU_EVCNT_DECL(fctid);
+FPU_EMU_EVCNT_DECL(fcfid);
+FPU_EMU_EVCNT_DECL(fdiv);
+FPU_EMU_EVCNT_DECL(fsub);
+FPU_EMU_EVCNT_DECL(fadd);
+FPU_EMU_EVCNT_DECL(fsqrt);
+FPU_EMU_EVCNT_DECL(fsel);
+FPU_EMU_EVCNT_DECL(fpres);
+FPU_EMU_EVCNT_DECL(fmul);
+FPU_EMU_EVCNT_DECL(frsqrte);
+FPU_EMU_EVCNT_DECL(fmulsub);
+FPU_EMU_EVCNT_DECL(fmuladd);
+FPU_EMU_EVCNT_DECL(fnmsub);
+FPU_EMU_EVCNT_DECL(fnmadd);
+
+/* FPSR exception masks */
+#define FPSR_EX_MSK	(FPSCR_VX|FPSCR_OX|FPSCR_UX|FPSCR_ZX|		\
+			FPSCR_XX|FPSCR_VXSNAN|FPSCR_VXISI|FPSCR_VXIDI|	\
+			FPSCR_VXZDZ|FPSCR_VXIMZ|FPSCR_VXVC|FPSCR_VXSOFT|\
+			FPSCR_VXSQRT|FPSCR_VXCVI)
+#define	FPSR_EX		(FPSCR_VE|FPSCR_OE|FPSCR_UE|FPSCR_ZE|FPSCR_XE)
+#define	FPSR_EXOP	(FPSR_EX_MSK&(~FPSR_EX))
+
+int fpe_debug = 0;
+
+#ifdef DEBUG
+vm_offset_t opc_disasm(vm_offset_t, int);
+
+/*
+ * Dump a `fpn' structure.
+ */
+void
+fpu_dumpfpn(struct fpn *fp)
+{
+	static const char *class[] = {
+		"SNAN", "QNAN", "ZERO", "NUM", "INF"
+	};
+
+	printf("%s %c.%x %x %x %xE%d", class[fp->fp_class + 2],
+		fp->fp_sign ? '-' : ' ',
+		fp->fp_mant[0],	fp->fp_mant[1],
+		fp->fp_mant[2], fp->fp_mant[3], 
+		fp->fp_exp);
+}
+#endif
+
+/*
+ * fpu_execute returns the following error numbers (0 = no error):
+ */
+#define	FPE		1	/* take a floating point exception */
+#define	NOTFPU		2	/* not an FPU instruction */
+#define	FAULT		3
+
+
+/*
+ * Emulate a floating-point instruction.
+ * Return zero for success, else signal number.
+ * (Typically: zero, SIGFPE, SIGILL, SIGSEGV)
+ */
+int
+fpu_emulate(struct trapframe *frame, struct fpreg *fpf)
+{
+	static union instr insn;
+	static struct fpemu fe;
+	static int lastill = 0;
+	int sig;
+
+	/* initialize insn.is_datasize to tell it is *not* initialized */
+	fe.fe_fpstate = fpf;
+	fe.fe_cx = 0;
+
+	/* always set this (to avoid a warning) */
+
+	if (copyin((void *) (frame->srr0), &insn.i_int, sizeof (insn.i_int))) {
+#ifdef DEBUG
+		printf("fpu_emulate: fault reading opcode\n");
+#endif
+		return SIGSEGV;
+	}
+
+	DPRINTF(FPE_EX, ("fpu_emulate: emulating insn %x at %p\n",
+	    insn.i_int, (void *)frame->srr0));
+
+
+	if ((insn.i_any.i_opcd == OPC_TWI) ||
+	    ((insn.i_any.i_opcd == OPC_integer_31) &&
+	    (insn.i_x.i_xo == OPC31_TW))) {
+		/* Check for the two trap insns. */
+		DPRINTF(FPE_EX, ("fpu_emulate: SIGTRAP\n"));
+		return (SIGTRAP);
+	}
+	sig = 0;
+	switch (fpu_execute(frame, &fe, &insn)) {
+	case 0:
+		DPRINTF(FPE_EX, ("fpu_emulate: success\n"));
+		frame->srr0 += 4;
+		break;
+
+	case FPE:
+		DPRINTF(FPE_EX, ("fpu_emulate: SIGFPE\n"));
+		sig = SIGFPE;
+		break;
+
+	case FAULT:
+		DPRINTF(FPE_EX, ("fpu_emulate: SIGSEGV\n"));
+		sig = SIGSEGV;
+		break;
+
+	case NOTFPU:
+	default:
+		DPRINTF(FPE_EX, ("fpu_emulate: SIGILL\n"));
+#ifdef DEBUG
+		if (fpe_debug & FPE_EX) {
+			printf("fpu_emulate:  illegal insn %x at %p:",
+			insn.i_int, (void *) (frame->srr0));
+			opc_disasm(frame->srr0, insn.i_int);
+		}
+#endif
+		/*
+		* XXXX retry an illegal insn once due to cache issues.
+		*/
+		if (lastill == frame->srr0) {
+			sig = SIGILL;
+#ifdef DEBUG
+			if (fpe_debug & FPE_EX)
+				kdb_enter(KDB_WHY_UNSET, "illegal instruction");
+#endif
+		}
+		lastill = frame->srr0;
+		break;
+	}
+
+	return (sig);
+}
+
+/*
+ * Execute an FPU instruction (one that runs entirely in the FPU; not
+ * FBfcc or STF, for instance).  On return, fe->fe_fs->fs_fsr will be
+ * modified to reflect the setting the hardware would have left.
+ *
+ * Note that we do not catch all illegal opcodes, so you can, for instance,
+ * multiply two integers this way.
+ */
+int
+fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
+{
+	struct fpn *fp;
+	union instr instr = *insn;
+	int *a;
+	vm_offset_t addr;
+	int ra, rb, rc, rt, type, mask, fsr, cx, bf, setcr;
+	unsigned int cond;
+	struct fpreg *fs;
+
+	/* Setup work. */
+	fp = NULL;
+	fs = fe->fe_fpstate;
+	fe->fe_fpscr = ((int *)&fs->fpscr)[1];
+
+	/*
+	 * On PowerPC all floating point values are stored in registers
+	 * as doubles, even when used for single precision operations.
+	 */
+	type = FTYPE_DBL;
+	cond = instr.i_any.i_rc;
+	setcr = 0;
+	bf = 0;	/* XXX gcc */
+
+#if defined(DDB) && defined(DEBUG)
+	if (fpe_debug & FPE_EX) {
+		vm_offset_t loc = tf->srr0;
+
+		printf("Trying to emulate: %p ", (void *)loc);
+		opc_disasm(loc, instr.i_int);
+	}
+#endif
+
+	/*
+	 * `Decode' and execute instruction.
+	 */
+
+	if ((instr.i_any.i_opcd >= OPC_LFS && instr.i_any.i_opcd <= OPC_STFDU) ||
+	    instr.i_any.i_opcd == OPC_integer_31) {
+		/*
+		 * Handle load/store insns:
+		 *
+		 * Convert to/from single if needed, calculate addr,
+		 * and update index reg if needed.
+		 */
+		double buf;
+		size_t size = sizeof(float);
+		int store, update;
+
+		cond = 0; /* ld/st never set condition codes */
+
+
+		if (instr.i_any.i_opcd == OPC_integer_31) {
+			if (instr.i_x.i_xo == OPC31_STFIWX) {
+				FPU_EMU_EVCNT_INCR(stfiwx);
+
+				/* Store as integer */
+				ra = instr.i_x.i_ra;
+				rb = instr.i_x.i_rb;
+				DPRINTF(FPE_INSN,
+					("reg %d has %jx reg %d has %jx\n",
+					ra, (uintmax_t)tf->fixreg[ra], rb,
+					(uintmax_t)tf->fixreg[rb]));
+
+				addr = tf->fixreg[rb];
+				if (ra != 0)
+					addr += tf->fixreg[ra];
+				rt = instr.i_x.i_rt;
+				a = (int *)&fs->fpreg[rt];
+				DPRINTF(FPE_INSN,
+					("fpu_execute: Store INT %x at %p\n",
+						a[1], (void *)addr));
+				if (copyout(&a[1], (void *)addr, sizeof(int)))
+					return (FAULT);
+				return (0);
+			}
+
+			if ((instr.i_x.i_xo & OPC31_FPMASK) != OPC31_FPOP)
+				/* Not an indexed FP load/store op */
+				return (NOTFPU);
+
+			store = (instr.i_x.i_xo & 0x80);
+			if (instr.i_x.i_xo & 0x40)
+				size = sizeof(double);
+			else
+				type = FTYPE_SNG;
+			update = (instr.i_x.i_xo & 0x20);
+			
+			/* calculate EA of load/store */
+			ra = instr.i_x.i_ra;
+			rb = instr.i_x.i_rb;
+			DPRINTF(FPE_INSN, ("reg %d has %jx reg %d has %jx\n",
+				ra, (uintmax_t)tf->fixreg[ra], rb,
+				(uintmax_t)tf->fixreg[rb]));
+			addr = tf->fixreg[rb];
+			if (ra != 0)
+				addr += tf->fixreg[ra];
+			rt = instr.i_x.i_rt;
+		} else {
+			store = instr.i_d.i_opcd & 0x4;
+			if (instr.i_d.i_opcd & 0x2)
+				size = sizeof(double);
+			else
+				type = FTYPE_SNG;
+			update = instr.i_d.i_opcd & 0x1;
+
+			/* calculate EA of load/store */
+			ra = instr.i_d.i_ra;
+			addr = instr.i_d.i_d;
+			DPRINTF(FPE_INSN, ("reg %d has %jx displ %jx\n",
+				ra, (uintmax_t)tf->fixreg[ra],
+				(uintmax_t)addr));
+			if (ra != 0)
+				addr += tf->fixreg[ra];
+			rt = instr.i_d.i_rt;
+		}
+
+		if (update && ra == 0)
+			return (NOTFPU);
+
+		if (store) {
+			/* Store */
+			FPU_EMU_EVCNT_INCR(fpstore);
+			if (type != FTYPE_DBL) {
+				DPRINTF(FPE_INSN,
+					("fpu_execute: Store SNG at %p\n",
+						(void *)addr));
+				fpu_explode(fe, fp = &fe->fe_f1, FTYPE_DBL, rt);
+				fpu_implode(fe, fp, type, (void *)&buf);
+				if (copyout(&buf, (void *)addr, size))
+					return (FAULT);
+			} else {
+				DPRINTF(FPE_INSN, 
+					("fpu_execute: Store DBL at %p\n",
+						(void *)addr));
+				if (copyout(&fs->fpreg[rt], (void *)addr, size))
+					return (FAULT);
+			}
+		} else {
+			/* Load */
+			FPU_EMU_EVCNT_INCR(fpload);
+			DPRINTF(FPE_INSN, ("fpu_execute: Load from %p\n",
+				(void *)addr));
+			if (copyin((const void *)addr, &fs->fpreg[rt], size))
+				return (FAULT);
+			if (type != FTYPE_DBL) {
+				fpu_explode(fe, fp = &fe->fe_f1, type, rt);
+				fpu_implode(fe, fp, FTYPE_DBL, 
+					(u_int *)&fs->fpreg[rt]);
+			}
+		}
+		if (update) 
+			tf->fixreg[ra] = addr;
+		/* Complete. */
+		return (0);
+#ifdef notyet
+	} else if (instr.i_any.i_opcd == OPC_load_st_62) {
+		/* These are 64-bit extensions */
+		return (NOTFPU);
+#endif
+	} else if (instr.i_any.i_opcd == OPC_sp_fp_59 ||
+		instr.i_any.i_opcd == OPC_dp_fp_63) {
+
+
+		if (instr.i_any.i_opcd == OPC_dp_fp_63 &&
+		    !(instr.i_a.i_xo & OPC63M_MASK)) {
+			/* Format X */
+			rt = instr.i_x.i_rt;
+			ra = instr.i_x.i_ra;
+			rb = instr.i_x.i_rb;
+
+
+			/* One of the special opcodes.... */
+			switch (instr.i_x.i_xo) {
+			case	OPC63_FCMPU:
+				FPU_EMU_EVCNT_INCR(fcmpu);
+				DPRINTF(FPE_INSN, ("fpu_execute: FCMPU\n"));
+				rt >>= 2;
+				fpu_explode(fe, &fe->fe_f1, type, ra);
+				fpu_explode(fe, &fe->fe_f2, type, rb);
+				fpu_compare(fe, 0);
+				/* Make sure we do the condition regs. */
+				cond = 0;
+				/* N.B.: i_rs is already left shifted by two. */
+				bf = instr.i_x.i_rs & 0xfc;
+				setcr = 1;
+				break;
+
+			case	OPC63_FRSP:
+				/*
+				 * Convert to single: 
+				 *
+				 * PowerPC uses this to round a double
+				 * precision value to single precision,
+				 * but values in registers are always 
+				 * stored in double precision format.
+				 */
+				FPU_EMU_EVCNT_INCR(frsp);
+				DPRINTF(FPE_INSN, ("fpu_execute: FRSP\n"));
+				fpu_explode(fe, fp = &fe->fe_f1, FTYPE_DBL, rb);
+				fpu_implode(fe, fp, FTYPE_SNG, 
+					(u_int *)&fs->fpreg[rt]);
+				fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt);
+				type = FTYPE_DBL;
+				break;
+			case	OPC63_FCTIW:
+			case	OPC63_FCTIWZ:
+				FPU_EMU_EVCNT_INCR(fctiw);
+				DPRINTF(FPE_INSN, ("fpu_execute: FCTIW\n"));
+				fpu_explode(fe, fp = &fe->fe_f1, type, rb);
+				type = FTYPE_INT;
+				break;
+			case	OPC63_FCMPO:
+				FPU_EMU_EVCNT_INCR(fcmpo);
+				DPRINTF(FPE_INSN, ("fpu_execute: FCMPO\n"));
+				rt >>= 2;
+				fpu_explode(fe, &fe->fe_f1, type, ra);
+				fpu_explode(fe, &fe->fe_f2, type, rb);
+				fpu_compare(fe, 1);
+				/* Make sure we do the condition regs. */
+				cond = 0;
+				/* N.B.: i_rs is already left shifted by two. */
+				bf = instr.i_x.i_rs & 0xfc;
+				setcr = 1;
+				break;
+			case	OPC63_MTFSB1:
+				FPU_EMU_EVCNT_INCR(mtfsb1);
+				DPRINTF(FPE_INSN, ("fpu_execute: MTFSB1\n"));
+				fe->fe_fpscr |= 
+					(~(FPSCR_VX|FPSR_EX) & (1<<(31-rt)));
+				break;
+			case	OPC63_FNEG:
+				FPU_EMU_EVCNT_INCR(fnegabs);
+				DPRINTF(FPE_INSN, ("fpu_execute: FNEGABS\n"));
+				memcpy(&fs->fpreg[rt], &fs->fpreg[rb],
+					sizeof(double));
+				a = (int *)&fs->fpreg[rt];
+				*a ^= (1U << 31);
+				break;
+			case	OPC63_MCRFS:
+				FPU_EMU_EVCNT_INCR(mcrfs);
+				DPRINTF(FPE_INSN, ("fpu_execute: MCRFS\n"));
+				cond = 0;
+				rt &= 0x1c;
+				ra &= 0x1c;
+				/* Extract the bits we want */
+				mask = (fe->fe_fpscr >> (28 - ra)) & 0xf;
+				/* Clear the bits we copied. */
+				fe->fe_cx =
+					(FPSR_EX_MSK | (0xf << (28 - ra)));
+				fe->fe_fpscr &= fe->fe_cx;
+				/* Now shove them in the right part of cr */
+				tf->cr &= ~(0xf << (28 - rt));
+				tf->cr |= (mask << (28 - rt));
+				break;
+			case	OPC63_MTFSB0:
+				FPU_EMU_EVCNT_INCR(mtfsb0);
+				DPRINTF(FPE_INSN, ("fpu_execute: MTFSB0\n"));
+				fe->fe_fpscr &=
+					((FPSCR_VX|FPSR_EX) & ~(1<<(31-rt)));
+				break;
+			case	OPC63_FMR:
+				FPU_EMU_EVCNT_INCR(fmr);
+				DPRINTF(FPE_INSN, ("fpu_execute: FMR\n"));
+				memcpy(&fs->fpreg[rt], &fs->fpreg[rb],
+					sizeof(double));
+				break;
+			case	OPC63_MTFSFI:
+				FPU_EMU_EVCNT_INCR(mtfsfi);
+				DPRINTF(FPE_INSN, ("fpu_execute: MTFSFI\n"));
+				rb >>= 1;
+				rt &= 0x1c; /* Already left-shifted 4 */
+				fe->fe_cx = rb << (28 - rt);
+				mask = 0xf<<(28 - rt);
+				fe->fe_fpscr = (fe->fe_fpscr & ~mask) | 
+					fe->fe_cx;
+/* XXX weird stuff about OX, FX, FEX, and VX should be handled */
+				break;
+			case	OPC63_FNABS:
+				FPU_EMU_EVCNT_INCR(fnabs);
+				DPRINTF(FPE_INSN, ("fpu_execute: FABS\n"));
+				memcpy(&fs->fpreg[rt], &fs->fpreg[rb],
+					sizeof(double));
+				a = (int *)&fs->fpreg[rt];
+				*a |= (1U << 31);
+				break;
+			case	OPC63_FABS:
+				FPU_EMU_EVCNT_INCR(fabs);
+				DPRINTF(FPE_INSN, ("fpu_execute: FABS\n"));
+				memcpy(&fs->fpreg[rt], &fs->fpreg[rb],
+					sizeof(double));
+				a = (int *)&fs->fpreg[rt];
+				*a &= ~(1U << 31);
+				break;
+			case	OPC63_MFFS:
+				FPU_EMU_EVCNT_INCR(mffs);
+				DPRINTF(FPE_INSN, ("fpu_execute: MFFS\n"));
+				memcpy(&fs->fpreg[rt], &fs->fpscr,
+					sizeof(fs->fpscr));
+				break;
+			case	OPC63_MTFSF:
+				FPU_EMU_EVCNT_INCR(mtfsf);
+				DPRINTF(FPE_INSN, ("fpu_execute: MTFSF\n"));
+				if ((rt = instr.i_xfl.i_flm) == -1)
+					mask = -1;
+				else {
+					mask = 0;
+					/* Convert 1 bit -> 4 bits */
+					for (ra = 0; ra < 8; ra ++)
+						if (rt & (1<<ra))
+							mask |= (0xf<<(4*ra));
+				}
+				a = (int *)&fs->fpreg[rt];
+				fe->fe_cx = mask & a[1];
+				fe->fe_fpscr = (fe->fe_fpscr&~mask) | 
+					(fe->fe_cx);
+/* XXX weird stuff about OX, FX, FEX, and VX should be handled */
+				break;
+			case	OPC63_FCTID:
+			case	OPC63_FCTIDZ:
+				FPU_EMU_EVCNT_INCR(fctid);
+				DPRINTF(FPE_INSN, ("fpu_execute: FCTID\n"));
+				fpu_explode(fe, fp = &fe->fe_f1, type, rb);
+				type = FTYPE_LNG;
+				break;
+			case	OPC63_FCFID:
+				FPU_EMU_EVCNT_INCR(fcfid);
+				DPRINTF(FPE_INSN, ("fpu_execute: FCFID\n"));
+				type = FTYPE_LNG;
+				fpu_explode(fe, fp = &fe->fe_f1, type, rb);
+				type = FTYPE_DBL;
+				break;
+			default:
+				return (NOTFPU);
+				break;
+			}
+		} else {
+			/* Format A */
+			rt = instr.i_a.i_frt;
+			ra = instr.i_a.i_fra;
+			rb = instr.i_a.i_frb;
+			rc = instr.i_a.i_frc;
+
+			/*
+			 * All arithmetic operations work on registers, which
+			 * are stored as doubles.
+			 */
+			type = FTYPE_DBL;
+			switch ((unsigned int)instr.i_a.i_xo) {
+			case	OPC59_FDIVS:
+				FPU_EMU_EVCNT_INCR(fdiv);
+				DPRINTF(FPE_INSN, ("fpu_execute: FDIV\n"));
+				fpu_explode(fe, &fe->fe_f1, type, ra);
+				fpu_explode(fe, &fe->fe_f2, type, rb);
+				fp = fpu_div(fe);
+				break;
+			case	OPC59_FSUBS:
+				FPU_EMU_EVCNT_INCR(fsub);
+				DPRINTF(FPE_INSN, ("fpu_execute: FSUB\n"));
+				fpu_explode(fe, &fe->fe_f1, type, ra);
+				fpu_explode(fe, &fe->fe_f2, type, rb);
+				fp = fpu_sub(fe);
+				break;
+			case	OPC59_FADDS:
+				FPU_EMU_EVCNT_INCR(fadd);
+				DPRINTF(FPE_INSN, ("fpu_execute: FADD\n"));
+				fpu_explode(fe, &fe->fe_f1, type, ra);
+				fpu_explode(fe, &fe->fe_f2, type, rb);
+				fp = fpu_add(fe);
+				break;
+			case	OPC59_FSQRTS:
+				FPU_EMU_EVCNT_INCR(fsqrt);
+				DPRINTF(FPE_INSN, ("fpu_execute: FSQRT\n"));
+				fpu_explode(fe, &fe->fe_f1, type, rb);
+				fp = fpu_sqrt(fe);
+				break;
+			case	OPC63M_FSEL:
+				FPU_EMU_EVCNT_INCR(fsel);
+				DPRINTF(FPE_INSN, ("fpu_execute: FSEL\n"));
+				a = (int *)&fe->fe_fpstate->fpreg[ra];
+				if ((*a & 0x80000000) && (*a & 0x7fffffff)) 
+					/* fra < 0 */
+					rc = rb;
+				DPRINTF(FPE_INSN, ("f%d => f%d\n", rc, rt));
+				memcpy(&fs->fpreg[rt], &fs->fpreg[rc],
+					sizeof(double));
+				break;
+			case	OPC59_FRES:
+				FPU_EMU_EVCNT_INCR(fpres);
+				DPRINTF(FPE_INSN, ("fpu_execute: FPRES\n"));
+				fpu_explode(fe, &fe->fe_f1, type, rb);
+				fp = fpu_sqrt(fe);
+				/* now we've gotta overwrite the dest reg */
+				*((int *)&fe->fe_fpstate->fpreg[rt]) = 1;
+				fpu_explode(fe, &fe->fe_f1, FTYPE_INT, rt);
+				fpu_div(fe);
+				break;
+			case	OPC59_FMULS:
+				FPU_EMU_EVCNT_INCR(fmul);
+				DPRINTF(FPE_INSN, ("fpu_execute: FMUL\n"));
+				fpu_explode(fe, &fe->fe_f1, type, ra);
+				fpu_explode(fe, &fe->fe_f2, type, rc);
+				fp = fpu_mul(fe);
+				break;
+			case	OPC63M_FRSQRTE:
+				/* Reciprocal sqrt() estimate */
+				FPU_EMU_EVCNT_INCR(frsqrte);
+				DPRINTF(FPE_INSN, ("fpu_execute: FRSQRTE\n"));
+				fpu_explode(fe, &fe->fe_f1, type, rb);
+				fp = fpu_sqrt(fe);
+				fe->fe_f2 = *fp;
+				/* now we've gotta overwrite the dest reg */
+				*((int *)&fe->fe_fpstate->fpreg[rt]) = 1;
+				fpu_explode(fe, &fe->fe_f1, FTYPE_INT, rt);
+				fpu_div(fe);
+				break;
+			case	OPC59_FMSUBS:
+				FPU_EMU_EVCNT_INCR(fmulsub);
+				DPRINTF(FPE_INSN, ("fpu_execute: FMULSUB\n"));
+				fpu_explode(fe, &fe->fe_f1, type, ra);
+				fpu_explode(fe, &fe->fe_f2, type, rc);
+				fp = fpu_mul(fe);
+				fe->fe_f1 = *fp;
+				fpu_explode(fe, &fe->fe_f2, type, rb);
+				fp = fpu_sub(fe);
+				break;
+			case	OPC59_FMADDS:
+				FPU_EMU_EVCNT_INCR(fmuladd);
+				DPRINTF(FPE_INSN, ("fpu_execute: FMULADD\n"));
+				fpu_explode(fe, &fe->fe_f1, type, ra);
+				fpu_explode(fe, &fe->fe_f2, type, rc);
+				fp = fpu_mul(fe);
+				fe->fe_f1 = *fp;
+				fpu_explode(fe, &fe->fe_f2, type, rb);
+				fp = fpu_add(fe);
+				break;
+			case	OPC59_FNMSUBS:
+				FPU_EMU_EVCNT_INCR(fnmsub);
+				DPRINTF(FPE_INSN, ("fpu_execute: FNMSUB\n"));
+				fpu_explode(fe, &fe->fe_f1, type, ra);
+				fpu_explode(fe, &fe->fe_f2, type, rc);
+				fp = fpu_mul(fe);
+				fe->fe_f1 = *fp;
+				fpu_explode(fe, &fe->fe_f2, type, rb);
+				fp = fpu_sub(fe);
+				/* Negate */
+				fp->fp_sign ^= 1;
+				break;
+			case	OPC59_FNMADDS:
+				FPU_EMU_EVCNT_INCR(fnmadd);
+				DPRINTF(FPE_INSN, ("fpu_execute: FNMADD\n"));
+				fpu_explode(fe, &fe->fe_f1, type, ra);
+				fpu_explode(fe, &fe->fe_f2, type, rc);
+				fp = fpu_mul(fe);
+				fe->fe_f1 = *fp;
+				fpu_explode(fe, &fe->fe_f2, type, rb);
+				fp = fpu_add(fe);
+				/* Negate */
+				fp->fp_sign ^= 1;
+				break;
+			default:
+				return (NOTFPU);
+				break;
+			}
+
+			/* If the instruction was single precision, round */
+			if (!(instr.i_any.i_opcd & 0x4)) {
+				fpu_implode(fe, fp, FTYPE_SNG, 
+					(u_int *)&fs->fpreg[rt]);
+				fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt);
+			}
+		}
+	} else {
+		return (NOTFPU);
+	}
+
+	/*
+	 * ALU operation is complete.  Collapse the result and then check
+	 * for exceptions.  If we got any, and they are enabled, do not
+	 * alter the destination register, just stop with an exception.
+	 * Otherwise set new current exceptions and accrue.
+	 */
+	if (fp)
+		fpu_implode(fe, fp, type, (u_int *)&fs->fpreg[rt]);
+	cx = fe->fe_cx;
+	fsr = fe->fe_fpscr;
+	if (cx != 0) {
+		fsr &= ~FPSCR_FX;
+		if ((cx^fsr)&FPSR_EX_MSK)
+			fsr |= FPSCR_FX;
+		mask = fsr & FPSR_EX;
+		mask <<= (25-3);
+		if (cx & mask) 
+			fsr |= FPSCR_FEX;
+		if (cx & FPSCR_FPRF) {
+			/* Need to replace CC */
+			fsr &= ~FPSCR_FPRF;
+		}
+		if (cx & (FPSR_EXOP))
+			fsr |= FPSCR_VX;
+		fsr |= cx;
+		DPRINTF(FPE_INSN, ("fpu_execute: cx %x, fsr %x\n", cx, fsr));
+	}
+
+	if (cond) {
+		cond = fsr & 0xf0000000;
+		/* Isolate condition codes */
+		cond >>= 28;
+		/* Move fpu condition codes to cr[1] */
+		tf->cr &= (0x0f000000);
+		tf->cr |= (cond<<24);
+		DPRINTF(FPE_INSN, ("fpu_execute: cr[1] <= %x\n", cond));
+	}
+
+	if (setcr) {
+		cond = fsr & FPSCR_FPCC;
+		/* Isolate condition codes */
+		cond <<= 16;
+		/* Move fpu condition codes to cr[1] */
+		tf->cr &= ~(0xf0000000>>bf);
+		tf->cr |= (cond>>bf);
+		DPRINTF(FPE_INSN, ("fpu_execute: cr[%d] (cr=%jx) <= %x\n",
+			bf/4, (uintmax_t)tf->cr, cond));
+	}
+
+	((int *)&fs->fpscr)[1] = fsr;
+	if (fsr & FPSCR_FEX)
+		return(FPE);
+	return (0);	/* success */
+}


Property changes on: trunk/sys/powerpc/fpu/fpu_emu.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_emu.h
===================================================================
--- trunk/sys/powerpc/fpu/fpu_emu.h	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_emu.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,195 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: fpu_emu.h,v 1.3 2005/12/11 12:18:42 christos Exp $ */
+/* $FreeBSD: stable/10/sys/powerpc/fpu/fpu_emu.h 176501 2008-02-24 03:01:26Z marcel $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ *	@(#)fpu_emu.h	8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Floating point emulator (tailored for SPARC, but structurally
+ * machine-independent).
+ *
+ * Floating point numbers are carried around internally in an `expanded'
+ * or `unpacked' form consisting of:
+ *	- sign
+ *	- unbiased exponent
+ *	- mantissa (`1.' + 112-bit fraction + guard + round)
+ *	- sticky bit
+ * Any implied `1' bit is inserted, giving a 113-bit mantissa that is
+ * always nonzero.  Additional low-order `guard' and `round' bits are
+ * scrunched in, making the entire mantissa 115 bits long.  This is divided
+ * into four 32-bit words, with `spare' bits left over in the upper part
+ * of the top word (the high bits of fp_mant[0]).  An internal `exploded'
+ * number is thus kept within the half-open interval [1.0,2.0) (but see
+ * the `number classes' below).  This holds even for denormalized numbers:
+ * when we explode an external denorm, we normalize it, introducing low-order
+ * zero bits, so that the rest of the code always sees normalized values.
+ *
+ * Note that a number of our algorithms use the `spare' bits at the top.
+ * The most demanding algorithm---the one for sqrt---depends on two such
+ * bits, so that it can represent values up to (but not including) 8.0,
+ * and then it needs a carry on top of that, so that we need three `spares'.
+ *
+ * The sticky-word is 32 bits so that we can use `OR' operators to goosh
+ * whole words from the mantissa into it.
+ *
+ * All operations are done in this internal extended precision.  According
+ * to Hennesey & Patterson, Appendix A, rounding can be repeated---that is,
+ * it is OK to do a+b in extended precision and then round the result to
+ * single precision---provided single, double, and extended precisions are
+ * `far enough apart' (they always are), but we will try to avoid any such
+ * extra work where possible.
+ */
+struct fpn {
+	int	fp_class;		/* see below */
+	int	fp_sign;		/* 0 => positive, 1 => negative */
+	int	fp_exp;			/* exponent (unbiased) */
+	int	fp_sticky;		/* nonzero bits lost at right end */
+	u_int	fp_mant[4];		/* 115-bit mantissa */
+};
+
+#define	FP_NMANT	115		/* total bits in mantissa (incl g,r) */
+#define	FP_NG		2		/* number of low-order guard bits */
+#define	FP_LG		((FP_NMANT - 1) & 31)	/* log2(1.0) for fp_mant[0] */
+#define	FP_LG2		((FP_NMANT - 1) & 63)	/* log2(1.0) for fp_mant[0] and fp_mant[1] */
+#define	FP_QUIETBIT	(1 << (FP_LG - 1))	/* Quiet bit in NaNs (0.5) */
+#define	FP_1		(1 << FP_LG)		/* 1.0 in fp_mant[0] */
+#define	FP_2		(1 << (FP_LG + 1))	/* 2.0 in fp_mant[0] */
+
+/*
+ * Number classes.  Since zero, Inf, and NaN cannot be represented using
+ * the above layout, we distinguish these from other numbers via a class.
+ * In addition, to make computation easier and to follow Appendix N of
+ * the SPARC Version 8 standard, we give each kind of NaN a separate class.
+ */
+#define	FPC_SNAN	-2		/* signalling NaN (sign irrelevant) */
+#define	FPC_QNAN	-1		/* quiet NaN (sign irrelevant) */
+#define	FPC_ZERO	0		/* zero (sign matters) */
+#define	FPC_NUM		1		/* number (sign matters) */
+#define	FPC_INF		2		/* infinity (sign matters) */
+
+#define	ISSNAN(fp)	((fp)->fp_class == FPC_SNAN)
+#define	ISQNAN(fp)	((fp)->fp_class == FPC_QNAN)
+#define	ISNAN(fp)	((fp)->fp_class < 0)
+#define	ISZERO(fp)	((fp)->fp_class == 0)
+#define	ISINF(fp)	((fp)->fp_class == FPC_INF)
+
+/*
+ * ORDER(x,y) `sorts' a pair of `fpn *'s so that the right operand (y) points
+ * to the `more significant' operand for our purposes.  Appendix N says that
+ * the result of a computation involving two numbers are:
+ *
+ *	If both are SNaN: operand 2, converted to Quiet
+ *	If only one is SNaN: the SNaN operand, converted to Quiet
+ *	If both are QNaN: operand 2
+ *	If only one is QNaN: the QNaN operand
+ *
+ * In addition, in operations with an Inf operand, the result is usually
+ * Inf.  The class numbers are carefully arranged so that if
+ *	(unsigned)class(op1) > (unsigned)class(op2)
+ * then op1 is the one we want; otherwise op2 is the one we want.
+ */
+#define	ORDER(x, y) { \
+	if ((u_int)(x)->fp_class > (u_int)(y)->fp_class) \
+		SWAP(x, y); \
+}
+#define	SWAP(x, y) { \
+	struct fpn *swap; \
+	swap = (x), (x) = (y), (y) = swap; \
+}
+
+/*
+ * Emulator state.
+ */
+struct fpemu {
+	struct	fpreg *fe_fpstate;	/* registers, etc */
+	int	fe_fpscr;		/* fpscr copy (modified during op) */
+	int	fe_cx;			/* keep track of exceptions */
+	struct	fpn fe_f1;		/* operand 1 */
+	struct	fpn fe_f2;		/* operand 2, if required */
+	struct	fpn fe_f3;		/* available storage for result */
+};
+
+/*
+ * Arithmetic functions.
+ * Each of these may modify its inputs (f1,f2) and/or the temporary.
+ * Each returns a pointer to the result and/or sets exceptions.
+ */
+struct	fpn *fpu_add(struct fpemu *);
+#define	fpu_sub(fe) ((fe)->fe_f2.fp_sign ^= 1, fpu_add(fe))
+struct	fpn *fpu_mul(struct fpemu *);
+struct	fpn *fpu_div(struct fpemu *);
+struct	fpn *fpu_sqrt(struct fpemu *);
+
+/*
+ * Other functions.
+ */
+
+/* Perform a compare instruction (with or without unordered exception). */
+void	fpu_compare(struct fpemu *, int);
+
+/* Build a new Quiet NaN (sign=0, frac=all 1's). */
+struct	fpn *fpu_newnan(struct fpemu *);
+
+void	fpu_norm(struct fpn *);
+
+/*
+ * Shift a number right some number of bits, taking care of round/sticky.
+ * Note that the result is probably not a well-formed number (it will lack
+ * the normal 1-bit mant[0]&FP_1).
+ */
+int	fpu_shr(struct fpn *, int);
+
+void	fpu_explode(struct fpemu *, struct fpn *, int, int);
+void	fpu_implode(struct fpemu *, struct fpn *, int, u_int *);
+
+#ifdef DEBUG
+#define	FPE_EX		0x1
+#define	FPE_INSN	0x2
+#define	FPE_OP		0x4
+#define	FPE_REG		0x8
+extern int fpe_debug;
+void	fpu_dumpfpn(struct fpn *);
+#define	DPRINTF(x, y)	if (fpe_debug & (x)) printf y
+#define DUMPFPN(x, f)	if (fpe_debug & (x)) fpu_dumpfpn((f))
+#else
+#define	DPRINTF(x, y)
+#define DUMPFPN(x, f)
+#endif


Property changes on: trunk/sys/powerpc/fpu/fpu_emu.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_explode.c
===================================================================
--- trunk/sys/powerpc/fpu/fpu_explode.c	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_explode.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,264 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: fpu_explode.c,v 1.6 2005/12/11 12:18:42 christos Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ *	@(#)fpu_explode.c	8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * FPU subroutines: `explode' the machine's `packed binary' format numbers
+ * into our internal format.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/fpu/fpu_explode.c 266004 2014-05-14 04:42:38Z ian $");
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/fpu.h>
+#include <machine/ieee.h>
+#include <machine/reg.h>
+
+#include <powerpc/fpu/fpu_arith.h>
+#include <powerpc/fpu/fpu_emu.h>
+#include <powerpc/fpu/fpu_extern.h>
+#include <powerpc/fpu/fpu_instr.h>
+
+/*
+ * N.B.: in all of the following, we assume the FP format is
+ *
+ *	---------------------------
+ *	| s | exponent | fraction |
+ *	---------------------------
+ *
+ * (which represents -1**s * 1.fraction * 2**exponent), so that the
+ * sign bit is way at the top (bit 31), the exponent is next, and
+ * then the remaining bits mark the fraction.  A zero exponent means
+ * zero or denormalized (0.fraction rather than 1.fraction), and the
+ * maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN.
+ *
+ * Since the sign bit is always the topmost bit---this holds even for
+ * integers---we set that outside all the *tof functions.  Each function
+ * returns the class code for the new number (but note that we use
+ * FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate).
+ */
+
+/*
+ * int -> fpn.
+ */
+int
+fpu_itof(struct fpn *fp, u_int i)
+{
+
+	if (i == 0)
+		return (FPC_ZERO);
+	/*
+	 * The value FP_1 represents 2^FP_LG, so set the exponent
+	 * there and let normalization fix it up.  Convert negative
+	 * numbers to sign-and-magnitude.  Note that this relies on
+	 * fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
+	 */
+	fp->fp_exp = FP_LG;
+	fp->fp_mant[0] = (int)i < 0 ? -i : i;
+	fp->fp_mant[1] = 0;
+	fp->fp_mant[2] = 0;
+	fp->fp_mant[3] = 0;
+	fpu_norm(fp);
+	return (FPC_NUM);
+}
+
+/*
+ * 64-bit int -> fpn.
+ */
+int
+fpu_xtof(struct fpn *fp, u_int64_t i)
+{
+
+	if (i == 0)
+		return (FPC_ZERO);
+	/*
+	 * The value FP_1 represents 2^FP_LG, so set the exponent
+	 * there and let normalization fix it up.  Convert negative
+	 * numbers to sign-and-magnitude.  Note that this relies on
+	 * fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
+	 */
+	fp->fp_exp = FP_LG2;
+	*((int64_t*)fp->fp_mant) = (int64_t)i < 0 ? -i : i;
+	fp->fp_mant[2] = 0;
+	fp->fp_mant[3] = 0;
+	fpu_norm(fp);
+	return (FPC_NUM);
+}
+
+#define	mask(nbits) ((1L << (nbits)) - 1)
+
+/*
+ * All external floating formats convert to internal in the same manner,
+ * as defined here.  Note that only normals get an implied 1.0 inserted.
+ */
+#define	FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \
+	if (exp == 0) { \
+		if (allfrac == 0) \
+			return (FPC_ZERO); \
+		fp->fp_exp = 1 - expbias; \
+		fp->fp_mant[0] = f0; \
+		fp->fp_mant[1] = f1; \
+		fp->fp_mant[2] = f2; \
+		fp->fp_mant[3] = f3; \
+		fpu_norm(fp); \
+		return (FPC_NUM); \
+	} \
+	if (exp == (2 * expbias + 1)) { \
+		if (allfrac == 0) \
+			return (FPC_INF); \
+		fp->fp_mant[0] = f0; \
+		fp->fp_mant[1] = f1; \
+		fp->fp_mant[2] = f2; \
+		fp->fp_mant[3] = f3; \
+		return (FPC_QNAN); \
+	} \
+	fp->fp_exp = exp - expbias; \
+	fp->fp_mant[0] = FP_1 | f0; \
+	fp->fp_mant[1] = f1; \
+	fp->fp_mant[2] = f2; \
+	fp->fp_mant[3] = f3; \
+	return (FPC_NUM)
+
+/*
+ * 32-bit single precision -> fpn.
+ * We assume a single occupies at most (64-FP_LG) bits in the internal
+ * format: i.e., needs at most fp_mant[0] and fp_mant[1].
+ */
+int
+fpu_stof(struct fpn *fp, u_int i)
+{
+	int exp;
+	u_int frac, f0, f1;
+#define SNG_SHIFT (SNG_FRACBITS - FP_LG)
+
+	exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS);
+	frac = i & mask(SNG_FRACBITS);
+	f0 = frac >> SNG_SHIFT;
+	f1 = frac << (32 - SNG_SHIFT);
+	FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0);
+}
+
+/*
+ * 64-bit double -> fpn.
+ * We assume this uses at most (96-FP_LG) bits.
+ */
+int
+fpu_dtof(struct fpn *fp, u_int i, u_int j)
+{
+	int exp;
+	u_int frac, f0, f1, f2;
+#define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG)
+
+	exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS);
+	frac = i & mask(DBL_FRACBITS - 32);
+	f0 = frac >> DBL_SHIFT;
+	f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT);
+	f2 = j << (32 - DBL_SHIFT);
+	frac |= j;
+	FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0);
+}
+
+/*
+ * Explode the contents of a register / regpair / regquad.
+ * If the input is a signalling NaN, an NV (invalid) exception
+ * will be set.  (Note that nothing but NV can occur until ALU
+ * operations are performed.)
+ */
+void
+fpu_explode(struct fpemu *fe, struct fpn *fp, int type, int reg)
+{
+	u_int s, *space;
+	u_int64_t l, *xspace;
+
+	xspace = (u_int64_t *)&fe->fe_fpstate->fpreg[reg];
+	l = xspace[0];
+	space = (u_int *)&fe->fe_fpstate->fpreg[reg];
+	s = space[0];
+	fp->fp_sign = s >> 31;
+	fp->fp_sticky = 0;
+	switch (type) {
+
+	case FTYPE_LNG:
+		s = fpu_xtof(fp, l);
+		break;
+
+	case FTYPE_INT:
+		s = fpu_itof(fp, space[1]);
+		break;
+
+	case FTYPE_SNG:
+		s = fpu_stof(fp, s);
+		break;
+
+	case FTYPE_DBL:
+		s = fpu_dtof(fp, s, space[1]);
+		break;
+
+	default:
+		panic("fpu_explode");
+		panic("fpu_explode: invalid type %d", type);
+	}
+
+	if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {
+		/*
+		 * Input is a signalling NaN.  All operations that return
+		 * an input NaN operand put it through a ``NaN conversion'',
+		 * which basically just means ``turn on the quiet bit''.
+		 * We do this here so that all NaNs internally look quiet
+		 * (we can tell signalling ones by their class).
+		 */
+		fp->fp_mant[0] |= FP_QUIETBIT;
+		fe->fe_cx = FPSCR_VXSNAN;	/* assert invalid operand */
+		s = FPC_SNAN;
+	}
+	fp->fp_class = s;
+	DPRINTF(FPE_REG, ("fpu_explode: %%%c%d => ", (type == FTYPE_LNG) ? 'x' :
+		((type == FTYPE_INT) ? 'i' : 
+			((type == FTYPE_SNG) ? 's' :
+				((type == FTYPE_DBL) ? 'd' : '?'))),
+		reg));
+	DUMPFPN(FPE_REG, fp);
+	DPRINTF(FPE_REG, ("\n"));
+}


Property changes on: trunk/sys/powerpc/fpu/fpu_explode.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_extern.h
===================================================================
--- trunk/sys/powerpc/fpu/fpu_extern.h	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_extern.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,56 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: fpu_extern.h,v 1.3 2005/12/11 12:18:42 christos Exp $	*/
+/* $FreeBSD: stable/10/sys/powerpc/fpu/fpu_extern.h 204640 2010-03-03 17:07:02Z joel $ */
+
+/*-
+ * Copyright (c) 1995 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+struct proc;
+struct fpreg;
+struct trapframe;
+union instr;
+struct fpemu;
+struct fpn;
+
+/* fpu.c */
+int fpu_emulate(struct trapframe *, struct fpreg *);
+int fpu_execute(struct trapframe *, struct fpemu *, union instr *);
+
+/* fpu_explode.c */
+int fpu_itof(struct fpn *, u_int);
+int fpu_xtof(struct fpn *, u_int64_t);
+int fpu_stof(struct fpn *, u_int);
+int fpu_dtof(struct fpn *, u_int, u_int);
+
+/* fpu_implode.c */
+u_int fpu_ftoi(struct fpemu *, struct fpn *);
+u_int fpu_ftox(struct fpemu *, struct fpn *, u_int *);
+u_int fpu_ftos(struct fpemu *, struct fpn *);
+u_int fpu_ftod(struct fpemu *, struct fpn *, u_int *);
+


Property changes on: trunk/sys/powerpc/fpu/fpu_extern.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_implode.c
===================================================================
--- trunk/sys/powerpc/fpu/fpu_implode.c	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_implode.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,463 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: fpu_implode.c,v 1.6 2005/12/11 12:18:42 christos Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ *	@(#)fpu_implode.c	8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * FPU subroutines: `implode' internal format numbers into the machine's
+ * `packed binary' format.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/fpu/fpu_implode.c 178030 2008-04-09 08:50:37Z grehan $");
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/fpu.h>
+#include <machine/ieee.h>
+#include <machine/ieeefp.h>
+#include <machine/reg.h>
+
+#include <powerpc/fpu/fpu_arith.h>
+#include <powerpc/fpu/fpu_emu.h>
+#include <powerpc/fpu/fpu_extern.h>
+#include <powerpc/fpu/fpu_instr.h>
+
+static int round(struct fpemu *, struct fpn *);
+static int toinf(struct fpemu *, int);
+
+/*
+ * Round a number (algorithm from Motorola MC68882 manual, modified for
+ * our internal format).  Set inexact exception if rounding is required.
+ * Return true iff we rounded up.
+ *
+ * After rounding, we discard the guard and round bits by shifting right
+ * 2 bits (a la fpu_shr(), but we do not bother with fp->fp_sticky).
+ * This saves effort later.
+ *
+ * Note that we may leave the value 2.0 in fp->fp_mant; it is the caller's
+ * responsibility to fix this if necessary.
+ */
+static int
+round(struct fpemu *fe, struct fpn *fp)
+{
+	u_int m0, m1, m2, m3;
+	int gr, s;
+	FPU_DECL_CARRY;
+
+	m0 = fp->fp_mant[0];
+	m1 = fp->fp_mant[1];
+	m2 = fp->fp_mant[2];
+	m3 = fp->fp_mant[3];
+	gr = m3 & 3;
+	s = fp->fp_sticky;
+
+	/* mant >>= FP_NG */
+	m3 = (m3 >> FP_NG) | (m2 << (32 - FP_NG));
+	m2 = (m2 >> FP_NG) | (m1 << (32 - FP_NG));
+	m1 = (m1 >> FP_NG) | (m0 << (32 - FP_NG));
+	m0 >>= FP_NG;
+
+	if ((gr | s) == 0)	/* result is exact: no rounding needed */
+		goto rounddown;
+
+	fe->fe_cx |= FPSCR_XX|FPSCR_FI;	/* inexact */
+
+	/* Go to rounddown to round down; break to round up. */
+	switch ((fe->fe_fpscr) & FPSCR_RN) {
+
+	case FP_RN:
+	default:
+		/*
+		 * Round only if guard is set (gr & 2).  If guard is set,
+		 * but round & sticky both clear, then we want to round
+		 * but have a tie, so round to even, i.e., add 1 iff odd.
+		 */
+		if ((gr & 2) == 0)
+			goto rounddown;
+		if ((gr & 1) || fp->fp_sticky || (m3 & 1))
+			break;
+		goto rounddown;
+
+	case FP_RZ:
+		/* Round towards zero, i.e., down. */
+		goto rounddown;
+
+	case FP_RM:
+		/* Round towards -Inf: up if negative, down if positive. */
+		if (fp->fp_sign)
+			break;
+		goto rounddown;
+
+	case FP_RP:
+		/* Round towards +Inf: up if positive, down otherwise. */
+		if (!fp->fp_sign)
+			break;
+		goto rounddown;
+	}
+
+	/* Bump low bit of mantissa, with carry. */
+	fe->fe_cx |= FPSCR_FR;
+
+	FPU_ADDS(m3, m3, 1);
+	FPU_ADDCS(m2, m2, 0);
+	FPU_ADDCS(m1, m1, 0);
+	FPU_ADDC(m0, m0, 0);
+	fp->fp_mant[0] = m0;
+	fp->fp_mant[1] = m1;
+	fp->fp_mant[2] = m2;
+	fp->fp_mant[3] = m3;
+	return (1);
+
+rounddown:
+	fp->fp_mant[0] = m0;
+	fp->fp_mant[1] = m1;
+	fp->fp_mant[2] = m2;
+	fp->fp_mant[3] = m3;
+	return (0);
+}
+
+/*
+ * For overflow: return true if overflow is to go to +/-Inf, according
+ * to the sign of the overflowing result.  If false, overflow is to go
+ * to the largest magnitude value instead.
+ */
+static int
+toinf(struct fpemu *fe, int sign)
+{
+	int inf;
+
+	/* look at rounding direction */
+	switch ((fe->fe_fpscr) & FPSCR_RN) {
+
+	default:
+	case FP_RN:		/* the nearest value is always Inf */
+		inf = 1;
+		break;
+
+	case FP_RZ:		/* toward 0 => never towards Inf */
+		inf = 0;
+		break;
+
+	case FP_RP:		/* toward +Inf iff positive */
+		inf = sign == 0;
+		break;
+
+	case FP_RM:		/* toward -Inf iff negative */
+		inf = sign;
+		break;
+	}
+	if (inf)
+		fe->fe_cx |= FPSCR_OX;
+	return (inf);
+}
+
+/*
+ * fpn -> int (int value returned as return value).
+ *
+ * N.B.: this conversion always rounds towards zero (this is a peculiarity
+ * of the SPARC instruction set).
+ */
+u_int
+fpu_ftoi(struct fpemu *fe, struct fpn *fp)
+{
+	u_int i;
+	int sign, exp;
+
+	sign = fp->fp_sign;
+	switch (fp->fp_class) {
+
+	case FPC_ZERO:
+		return (0);
+
+	case FPC_NUM:
+		/*
+		 * If exp >= 2^32, overflow.  Otherwise shift value right
+		 * into last mantissa word (this will not exceed 0xffffffff),
+		 * shifting any guard and round bits out into the sticky
+		 * bit.  Then ``round'' towards zero, i.e., just set an
+		 * inexact exception if sticky is set (see round()).
+		 * If the result is > 0x80000000, or is positive and equals
+		 * 0x80000000, overflow; otherwise the last fraction word
+		 * is the result.
+		 */
+		if ((exp = fp->fp_exp) >= 32)
+			break;
+		/* NB: the following includes exp < 0 cases */
+		if (fpu_shr(fp, FP_NMANT - 1 - exp) != 0)
+			fe->fe_cx |= FPSCR_UX;
+		i = fp->fp_mant[3];
+		if (i >= ((u_int)0x80000000 + sign))
+			break;
+		return (sign ? -i : i);
+
+	default:		/* Inf, qNaN, sNaN */
+		break;
+	}
+	/* overflow: replace any inexact exception with invalid */
+	fe->fe_cx |= FPSCR_VXCVI;
+	return (0x7fffffff + sign);
+}
+
+/*
+ * fpn -> extended int (high bits of int value returned as return value).
+ *
+ * N.B.: this conversion always rounds towards zero (this is a peculiarity
+ * of the SPARC instruction set).
+ */
+u_int
+fpu_ftox(struct fpemu *fe, struct fpn *fp, u_int *res)
+{
+	u_int64_t i;
+	int sign, exp;
+
+	sign = fp->fp_sign;
+	switch (fp->fp_class) {
+
+	case FPC_ZERO:
+		res[1] = 0;
+		return (0);
+
+	case FPC_NUM:
+		/*
+		 * If exp >= 2^64, overflow.  Otherwise shift value right
+		 * into last mantissa word (this will not exceed 0xffffffffffffffff),
+		 * shifting any guard and round bits out into the sticky
+		 * bit.  Then ``round'' towards zero, i.e., just set an
+		 * inexact exception if sticky is set (see round()).
+		 * If the result is > 0x8000000000000000, or is positive and equals
+		 * 0x8000000000000000, overflow; otherwise the last fraction word
+		 * is the result.
+		 */
+		if ((exp = fp->fp_exp) >= 64)
+			break;
+		/* NB: the following includes exp < 0 cases */
+		if (fpu_shr(fp, FP_NMANT - 1 - exp) != 0)
+			fe->fe_cx |= FPSCR_UX;
+		i = ((u_int64_t)fp->fp_mant[2]<<32)|fp->fp_mant[3];
+		if (i >= ((u_int64_t)0x8000000000000000LL + sign))
+			break;
+		return (sign ? -i : i);
+
+	default:		/* Inf, qNaN, sNaN */
+		break;
+	}
+	/* overflow: replace any inexact exception with invalid */
+	fe->fe_cx |= FPSCR_VXCVI;
+	return (0x7fffffffffffffffLL + sign);
+}
+
+/*
+ * fpn -> single (32 bit single returned as return value).
+ * We assume <= 29 bits in a single-precision fraction (1.f part).
+ */
+u_int
+fpu_ftos(struct fpemu *fe, struct fpn *fp)
+{
+	u_int sign = fp->fp_sign << 31;
+	int exp;
+
+#define	SNG_EXP(e)	((e) << SNG_FRACBITS)	/* makes e an exponent */
+#define	SNG_MASK	(SNG_EXP(1) - 1)	/* mask for fraction */
+
+	/* Take care of non-numbers first. */
+	if (ISNAN(fp)) {
+		/*
+		 * Preserve upper bits of NaN, per SPARC V8 appendix N.
+		 * Note that fp->fp_mant[0] has the quiet bit set,
+		 * even if it is classified as a signalling NaN.
+		 */
+		(void) fpu_shr(fp, FP_NMANT - 1 - SNG_FRACBITS);
+		exp = SNG_EXP_INFNAN;
+		goto done;
+	}
+	if (ISINF(fp))
+		return (sign | SNG_EXP(SNG_EXP_INFNAN));
+	if (ISZERO(fp))
+		return (sign);
+
+	/*
+	 * Normals (including subnormals).  Drop all the fraction bits
+	 * (including the explicit ``implied'' 1 bit) down into the
+	 * single-precision range.  If the number is subnormal, move
+	 * the ``implied'' 1 into the explicit range as well, and shift
+	 * right to introduce leading zeroes.  Rounding then acts
+	 * differently for normals and subnormals: the largest subnormal
+	 * may round to the smallest normal (1.0 x 2^minexp), or may
+	 * remain subnormal.  In the latter case, signal an underflow
+	 * if the result was inexact or if underflow traps are enabled.
+	 *
+	 * Rounding a normal, on the other hand, always produces another
+	 * normal (although either way the result might be too big for
+	 * single precision, and cause an overflow).  If rounding a
+	 * normal produces 2.0 in the fraction, we need not adjust that
+	 * fraction at all, since both 1.0 and 2.0 are zero under the
+	 * fraction mask.
+	 *
+	 * Note that the guard and round bits vanish from the number after
+	 * rounding.
+	 */
+	if ((exp = fp->fp_exp + SNG_EXP_BIAS) <= 0) {	/* subnormal */
+		/* -NG for g,r; -SNG_FRACBITS-exp for fraction */
+		(void) fpu_shr(fp, FP_NMANT - FP_NG - SNG_FRACBITS - exp);
+		if (round(fe, fp) && fp->fp_mant[3] == SNG_EXP(1))
+			return (sign | SNG_EXP(1) | 0);
+		if ((fe->fe_cx & FPSCR_FI) ||
+		    (fe->fe_fpscr & FPSCR_UX))
+			fe->fe_cx |= FPSCR_UX;
+		return (sign | SNG_EXP(0) | fp->fp_mant[3]);
+	}
+	/* -FP_NG for g,r; -1 for implied 1; -SNG_FRACBITS for fraction */
+	(void) fpu_shr(fp, FP_NMANT - FP_NG - 1 - SNG_FRACBITS);
+#ifdef DIAGNOSTIC
+	if ((fp->fp_mant[3] & SNG_EXP(1 << FP_NG)) == 0)
+		panic("fpu_ftos");
+#endif
+	if (round(fe, fp) && fp->fp_mant[3] == SNG_EXP(2))
+		exp++;
+	if (exp >= SNG_EXP_INFNAN) {
+		/* overflow to inf or to max single */
+		if (toinf(fe, sign))
+			return (sign | SNG_EXP(SNG_EXP_INFNAN));
+		return (sign | SNG_EXP(SNG_EXP_INFNAN - 1) | SNG_MASK);
+	}
+done:
+	/* phew, made it */
+	return (sign | SNG_EXP(exp) | (fp->fp_mant[3] & SNG_MASK));
+}
+
+/*
+ * fpn -> double (32 bit high-order result returned; 32-bit low order result
+ * left in res[1]).  Assumes <= 61 bits in double precision fraction.
+ *
+ * This code mimics fpu_ftos; see it for comments.
+ */
+u_int
+fpu_ftod(struct fpemu *fe, struct fpn *fp, u_int *res)
+{
+	u_int sign = fp->fp_sign << 31;
+	int exp;
+
+#define	DBL_EXP(e)	((e) << (DBL_FRACBITS & 31))
+#define	DBL_MASK	(DBL_EXP(1) - 1)
+
+	if (ISNAN(fp)) {
+		(void) fpu_shr(fp, FP_NMANT - 1 - DBL_FRACBITS);
+		exp = DBL_EXP_INFNAN;
+		goto done;
+	}
+	if (ISINF(fp)) {
+		sign |= DBL_EXP(DBL_EXP_INFNAN);
+		goto zero;
+	}
+	if (ISZERO(fp)) {
+zero:		res[1] = 0;
+		return (sign);
+	}
+
+	if ((exp = fp->fp_exp + DBL_EXP_BIAS) <= 0) {
+		(void) fpu_shr(fp, FP_NMANT - FP_NG - DBL_FRACBITS - exp);
+		if (round(fe, fp) && fp->fp_mant[2] == DBL_EXP(1)) {
+			res[1] = 0;
+			return (sign | DBL_EXP(1) | 0);
+		}
+		if ((fe->fe_cx & FPSCR_FI) ||
+		    (fe->fe_fpscr & FPSCR_UX))
+			fe->fe_cx |= FPSCR_UX;
+		exp = 0;
+		goto done;
+	}
+	(void) fpu_shr(fp, FP_NMANT - FP_NG - 1 - DBL_FRACBITS);
+	if (round(fe, fp) && fp->fp_mant[2] == DBL_EXP(2))
+		exp++;
+	if (exp >= DBL_EXP_INFNAN) {
+		fe->fe_cx |= FPSCR_OX | FPSCR_UX;
+		if (toinf(fe, sign)) {
+			res[1] = 0;
+			return (sign | DBL_EXP(DBL_EXP_INFNAN) | 0);
+		}
+		res[1] = ~0;
+		return (sign | DBL_EXP(DBL_EXP_INFNAN) | DBL_MASK);
+	}
+done:
+	res[1] = fp->fp_mant[3];
+	return (sign | DBL_EXP(exp) | (fp->fp_mant[2] & DBL_MASK));
+}
+
+/*
+ * Implode an fpn, writing the result into the given space.
+ */
+void
+fpu_implode(struct fpemu *fe, struct fpn *fp, int type, u_int *space)
+{
+
+	switch (type) {
+
+	case FTYPE_LNG:
+		space[0] = fpu_ftox(fe, fp, space);
+		DPRINTF(FPE_REG, ("fpu_implode: long %x %x\n",
+			space[0], space[1]));
+		break;
+
+	case FTYPE_INT:
+		space[0] = 0;
+		space[1] = fpu_ftoi(fe, fp);
+		DPRINTF(FPE_REG, ("fpu_implode: int %x\n",
+			space[1]));
+		break;
+
+	case FTYPE_SNG:
+		space[0] = fpu_ftos(fe, fp);
+		DPRINTF(FPE_REG, ("fpu_implode: single %x\n",
+			space[0]));
+		break;
+
+	case FTYPE_DBL:
+		space[0] = fpu_ftod(fe, fp, space);
+		DPRINTF(FPE_REG, ("fpu_implode: double %x %x\n",
+			space[0], space[1]));
+		break;		break;
+
+	default:
+		panic("fpu_implode: invalid type %d", type);
+	}
+}


Property changes on: trunk/sys/powerpc/fpu/fpu_implode.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_instr.h
===================================================================
--- trunk/sys/powerpc/fpu/fpu_instr.h	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_instr.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,387 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: instr.h,v 1.4 2005/12/11 12:18:43 christos Exp $ */
+/* $FreeBSD: stable/10/sys/powerpc/fpu/fpu_instr.h 176491 2008-02-23 20:05:26Z marcel $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ *	@(#)instr.h	8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * An instruction.
+ */
+union instr {
+	int	i_int;			/* as a whole */
+ 
+	/*
+	 * Any instruction type.
+	 */
+	struct {
+		u_int	i_opcd:6;	/* first-level decode */
+		u_int	:25;
+		u_int	i_rc:1;
+	} i_any;
+
+	/*
+	 * Format A
+	 */
+	struct {
+		u_int	i_opcd:6;
+		u_int	i_frt:5;
+		u_int	i_fra:5;
+		u_int	i_frb:5;
+		u_int	i_frc:5;
+		u_int	i_xo:5;
+		u_int	i_rc:1;
+	} i_a;
+
+	/*
+	 * Format B
+	 */
+	struct {
+		u_int	i_opcd:6;
+		int	i_bo:5;
+		int	i_bi:5;
+		int	i_bd:14;
+		int	i_aa:1;
+		int	i_lk:1;
+	} i_b;
+
+	/*
+	 * Format D
+	 */
+	struct {
+		u_int	i_opcd:6;
+		u_int	i_rs:5;
+		u_int	i_ra:5;
+		int	i_d:16;
+	} i_d;
+
+	/*
+	 * Format DE
+	 */
+	struct {
+		u_int	i_opcd:6;
+		u_int	i_rs:5;
+		u_int	i_ra:5;
+		int	i_d:12;
+		u_int	i_xo:4;
+	} i_de;
+
+	/*
+	 * Format I
+	 */
+	struct {
+		u_int	i_opcd:6;
+		int	i_li:24;
+		int	i_aa:1;
+		int	i_lk:1;
+	} i_i;
+
+	/*
+	 * Format M
+	 */
+	struct {
+		u_int	i_opcd:6;
+		u_int	i_rs:5;
+		u_int	i_ra:5;
+		u_int	i_rb:5;
+		int	i_mb:5;
+		int	i_me:5;
+		u_int	i_rc:1;
+	} i_m;
+
+	/*
+	 * Format MD
+	 */
+	struct {
+		u_int	i_opcd:6;
+		u_int	i_rs:5;
+		u_int	i_ra:5;
+		u_int	i_rb:5;
+		int	i_sh1_5:5;
+		int	i_mb:6;
+		u_int	i_xo:3;
+		int	i_sh0:2;
+		u_int	i_rc:1;
+	} i_md;
+
+	/*
+	 * Format MDS
+	 */
+	struct {
+		u_int	i_opcd:6;
+		u_int	i_rs:5;
+		u_int	i_ra:5;
+		u_int	i_rb:5;
+		int	i_sh:5;
+		int	i_mb:6;
+		u_int	i_xo:4;
+		u_int	i_rc:1;
+	} i_mds;
+
+
+	/*
+	 * Format S
+	 */
+	struct {
+		u_int	i_opcd:6;
+		int	:24;
+		int	i_i:1;
+		int	:1;
+	} i_s;
+
+	/*
+	 * Format X
+	 */
+	struct {
+		u_int	i_opcd:6;
+		u_int	i_rs:5;
+		u_int	i_ra:5;
+		u_int	i_rb:5;
+		u_int	i_xo:10;
+		u_int	i_rc:1;
+	} i_x;
+
+	/*
+	 * Format XFL
+	 */
+	struct {
+		u_int	i_opcd:6;
+		int	:1;
+		int	i_flm:8;
+		int	:1;
+		int	i_frb:5;
+		u_int	i_xo:10;
+		int	:1;
+	} i_xfl;
+
+	/*
+	 * Format XFX
+	 */
+	struct {
+		u_int	i_opcd:6;
+		int	i_dcrn:10;
+		u_int	i_xo:10;
+		int	:1;
+	} i_xfx;
+
+	/*
+	 * Format XL
+	 */
+	struct {
+		u_int	i_opcd:6;
+		int	i_bt:5;
+		int	i_ba:5;
+		int	i_bb:5;
+		u_int	i_xo:10;
+		int	i_lk:1;
+	} i_xl;
+
+	/*
+	 * Format XS
+	 */
+	struct {
+		u_int	i_opcd:6;
+		u_int	i_rs:5;
+		u_int	i_ra:5;
+		int	i_sh0_4:5;
+		u_int	i_xo:9;
+		int	i_sh5:1;
+		u_int	i_rc:1;
+	} i_xs;
+
+};
+
+#define	i_rt	i_rs
+
+/*
+ * Primary opcode numbers:
+ */
+
+#define	OPC_TDI		0x02
+#define	OPC_TWI		0x03
+#define	OPC_MULLI	0x07
+#define	OPC_SUBFIC	0x08
+#define	OPC_BCE		0x09
+#define	OPC_CMPLI	0x0a
+#define	OPC_CMPI	0x0b
+#define	OPC_ADDIC	0x0c
+#define	OPC_ADDIC_DOT	0x0d
+#define	OPC_ADDI	0x0e
+#define	OPC_ADDIS	0x0f
+#define	OPC_BC		0x10
+#define	OPC_SC		0x11
+#define	OPC_B		0x12
+#define	OPC_branch_19	0x13
+#define	OPC_RLWIMI	0x14
+#define	OPC_RLWINM	0x15
+#define	OPC_BE		0x16
+#define	OPC_RLWNM	0x17
+#define	OPC_ORI		0x18
+#define	OPC_ORIS	0x19
+#define	OPC_XORI	0x1a
+#define	OPC_XORIS	0x1b
+#define	OPC_ANDI	0x1c
+#define	OPC_ANDIS	0x1d
+#define	OPC_dwe_rot_30	0x1e
+#define	OPC_integer_31	0x1f
+#define	OPC_LWZ		0x20
+#define	OPC_LWZU	0x21
+#define	OPC_LBZ		0x22
+#define	OPC_LBZU	0x23
+#define	OPC_STW		0x24
+#define	OPC_STWU	0x25
+#define	OPC_STB		0x26
+#define	OPC_STBU	0x27
+#define	OPC_LHZ		0x28
+#define	OPC_LHZU	0x29
+#define	OPC_LHA		0x2a
+#define	OPC_LHAU	0x2b
+#define	OPC_STH		0x2c
+#define	OPC_STHU	0x2d
+#define	OPC_LMW		0x2e
+#define	OPC_STMW	0x2f
+#define	OPC_LFS		0x30
+#define	OPC_LFSU	0x31
+#define	OPC_LFD		0x32
+#define	OPC_LFDU	0x33
+#define	OPC_STFS	0x34
+#define	OPC_STFSU	0x35
+#define	OPC_STFD	0x36
+#define	OPC_STFDU	0x37
+#define	OPC_load_st_58	0x3a
+#define	OPC_sp_fp_59	0x3b
+#define	OPC_load_st_62	0x3e
+#define	OPC_dp_fp_63	0x3f
+
+/*
+ * Opcode 31 sub-types (FP only)
+ */
+#define	OPC31_TW	0x004
+#define	OPC31_LFSX	0x217
+#define	OPC31_LFSUX	0x237
+#define	OPC31_LFDX	0x257
+#define	OPC31_LFDUX	0x277
+#define	OPC31_STFSX	0x297
+#define	OPC31_STFSUX	0x2b7
+#define	OPC31_STFDX	0x2d7
+#define	OPC31_STFDUX	0x2f7
+#define	OPC31_STFIWX	0x3d7
+
+/* Mask for all valid indexed FP load/store ops (except stfiwx) */
+#define	OPC31_FPMASK	0x31f
+#define	OPC31_FPOP	0x217
+
+/*
+ * Opcode 59 sub-types:
+ */
+
+#define	OPC59_FDIVS	0x12
+#define	OPC59_FSUBS	0x14
+#define	OPC59_FADDS	0x15
+#define	OPC59_FSQRTS	0x16
+#define	OPC59_FRES	0x18
+#define	OPC59_FMULS	0x19
+#define	OPC59_FMSUBS	0x1c
+#define	OPC59_FMADDS	0x1d
+#define	OPC59_FNMSUBS	0x1e
+#define	OPC59_FNMADDS	0x1f
+
+/*
+ * Opcode 62 sub-types:
+ */
+#define	OPC62_LDE	0x0
+#define	OPC62_LDEU	0x1
+#define	OPC62_LFSE	0x4
+#define	OPC62_LFSEU	0x5
+#define	OPC62_LFDE	0x6
+#define	OPC62_LFDEU	0x7
+#define	OPC62_STDE	0x8
+#define	OPC62_STDEU	0x9
+#define	OPC62_STFSE	0xc
+#define	OPC62_STFSEU	0xd
+#define	OPC62_STFDE	0xe
+#define	OPC62_STFDEU	0xf
+
+/*
+ * Opcode 63 sub-types:
+ *
+ * (The first group are masks....)
+ */
+
+#define	OPC63M_MASK	0x10
+#define	OPC63M_FDIV	0x12
+#define	OPC63M_FSUB	0x14
+#define	OPC63M_FADD	0x15
+#define	OPC63M_FSQRT	0x16
+#define	OPC63M_FSEL	0x17
+#define	OPC63M_FMUL	0x19
+#define	OPC63M_FRSQRTE	0x1a
+#define	OPC63M_FMSUB	0x1c
+#define	OPC63M_FMADD	0x1d
+#define	OPC63M_FNMSUB	0x1e
+#define	OPC63M_FNMADD	0x1f
+
+#define	OPC63_FCMPU	0x00
+#define	OPC63_FRSP	0x0c
+#define	OPC63_FCTIW	0x0e
+#define	OPC63_FCTIWZ	0x0f
+#define	OPC63_FCMPO	0x20
+#define	OPC63_MTFSB1	0x26
+#define	OPC63_FNEG	0x28
+#define	OPC63_MCRFS	0x40
+#define	OPC63_MTFSB0	0x46
+#define	OPC63_FMR	0x48
+#define	OPC63_MTFSFI	0x86
+#define	OPC63_FNABS	0x88
+#define	OPC63_FABS	0x108
+#define	OPC63_MFFS	0x247
+#define	OPC63_MTFSF	0x2c7
+#define	OPC63_FCTID	0x32e
+#define	OPC63_FCTIDZ	0x32f
+#define	OPC63_FCFID	0x34e
+
+/*
+ * FPU data types.
+ */
+#define FTYPE_LNG	-1	/* data = 64-bit signed long integer */		
+#define	FTYPE_INT	0	/* data = 32-bit signed integer */
+#define	FTYPE_SNG	1	/* data = 32-bit float */
+#define	FTYPE_DBL	2	/* data = 64-bit double */
+


Property changes on: trunk/sys/powerpc/fpu/fpu_instr.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_mul.c
===================================================================
--- trunk/sys/powerpc/fpu/fpu_mul.c	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_mul.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,240 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: fpu_mul.c,v 1.4 2005/12/11 12:18:42 christos Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ *	@(#)fpu_mul.c	8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Perform an FPU multiply (return x * y).
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/fpu/fpu_mul.c 178030 2008-04-09 08:50:37Z grehan $");
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/fpu.h>
+#include <machine/reg.h>
+
+#include <powerpc/fpu/fpu_arith.h>
+#include <powerpc/fpu/fpu_emu.h>
+
+/*
+ * The multiplication algorithm for normal numbers is as follows:
+ *
+ * The fraction of the product is built in the usual stepwise fashion.
+ * Each step consists of shifting the accumulator right one bit
+ * (maintaining any guard bits) and, if the next bit in y is set,
+ * adding the multiplicand (x) to the accumulator.  Then, in any case,
+ * we advance one bit leftward in y.  Algorithmically:
+ *
+ *	A = 0;
+ *	for (bit = 0; bit < FP_NMANT; bit++) {
+ *		sticky |= A & 1, A >>= 1;
+ *		if (Y & (1 << bit))
+ *			A += X;
+ *	}
+ *
+ * (X and Y here represent the mantissas of x and y respectively.)
+ * The resultant accumulator (A) is the product's mantissa.  It may
+ * be as large as 11.11111... in binary and hence may need to be
+ * shifted right, but at most one bit.
+ *
+ * Since we do not have efficient multiword arithmetic, we code the
+ * accumulator as four separate words, just like any other mantissa.
+ * We use local variables in the hope that this is faster than memory.
+ * We keep x->fp_mant in locals for the same reason.
+ *
+ * In the algorithm above, the bits in y are inspected one at a time.
+ * We will pick them up 32 at a time and then deal with those 32, one
+ * at a time.  Note, however, that we know several things about y:
+ *
+ *    - the guard and round bits at the bottom are sure to be zero;
+ *
+ *    - often many low bits are zero (y is often from a single or double
+ *	precision source);
+ *
+ *    - bit FP_NMANT-1 is set, and FP_1*2 fits in a word.
+ *
+ * We can also test for 32-zero-bits swiftly.  In this case, the center
+ * part of the loop---setting sticky, shifting A, and not adding---will
+ * run 32 times without adding X to A.  We can do a 32-bit shift faster
+ * by simply moving words.  Since zeros are common, we optimize this case.
+ * Furthermore, since A is initially zero, we can omit the shift as well
+ * until we reach a nonzero word.
+ */
+struct fpn *
+fpu_mul(struct fpemu *fe)
+{
+	struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2;
+	u_int a3, a2, a1, a0, x3, x2, x1, x0, bit, m;
+	int sticky;
+	FPU_DECL_CARRY;
+
+	/*
+	 * Put the `heavier' operand on the right (see fpu_emu.h).
+	 * Then we will have one of the following cases, taken in the
+	 * following order:
+	 *
+	 *  - y = NaN.  Implied: if only one is a signalling NaN, y is.
+	 *	The result is y.
+	 *  - y = Inf.  Implied: x != NaN (is 0, number, or Inf: the NaN
+	 *    case was taken care of earlier).
+	 *	If x = 0, the result is NaN.  Otherwise the result
+	 *	is y, with its sign reversed if x is negative.
+	 *  - x = 0.  Implied: y is 0 or number.
+	 *	The result is 0 (with XORed sign as usual).
+	 *  - other.  Implied: both x and y are numbers.
+	 *	The result is x * y (XOR sign, multiply bits, add exponents).
+	 */
+	DPRINTF(FPE_REG, ("fpu_mul:\n"));
+	DUMPFPN(FPE_REG, x);
+	DUMPFPN(FPE_REG, y);
+	DPRINTF(FPE_REG, ("=>\n"));
+
+	ORDER(x, y);
+	if (ISNAN(y)) {
+		y->fp_sign ^= x->fp_sign;
+		fe->fe_cx |= FPSCR_VXSNAN;
+		DUMPFPN(FPE_REG, y);
+		return (y);
+	}
+	if (ISINF(y)) {
+		if (ISZERO(x)) {
+			fe->fe_cx |= FPSCR_VXIMZ;
+			return (fpu_newnan(fe));
+		}
+		y->fp_sign ^= x->fp_sign;
+			DUMPFPN(FPE_REG, y);
+		return (y);
+	}
+	if (ISZERO(x)) {
+		x->fp_sign ^= y->fp_sign;
+		DUMPFPN(FPE_REG, x);
+		return (x);
+	}
+
+	/*
+	 * Setup.  In the code below, the mask `m' will hold the current
+	 * mantissa byte from y.  The variable `bit' denotes the bit
+	 * within m.  We also define some macros to deal with everything.
+	 */
+	x3 = x->fp_mant[3];
+	x2 = x->fp_mant[2];
+	x1 = x->fp_mant[1];
+	x0 = x->fp_mant[0];
+	sticky = a3 = a2 = a1 = a0 = 0;
+
+#define	ADD	/* A += X */ \
+	FPU_ADDS(a3, a3, x3); \
+	FPU_ADDCS(a2, a2, x2); \
+	FPU_ADDCS(a1, a1, x1); \
+	FPU_ADDC(a0, a0, x0)
+
+#define	SHR1	/* A >>= 1, with sticky */ \
+	sticky |= a3 & 1, a3 = (a3 >> 1) | (a2 << 31), \
+	a2 = (a2 >> 1) | (a1 << 31), a1 = (a1 >> 1) | (a0 << 31), a0 >>= 1
+
+#define	SHR32	/* A >>= 32, with sticky */ \
+	sticky |= a3, a3 = a2, a2 = a1, a1 = a0, a0 = 0
+
+#define	STEP	/* each 1-bit step of the multiplication */ \
+	SHR1; if (bit & m) { ADD; }; bit <<= 1
+
+	/*
+	 * We are ready to begin.  The multiply loop runs once for each
+	 * of the four 32-bit words.  Some words, however, are special.
+	 * As noted above, the low order bits of Y are often zero.  Even
+	 * if not, the first loop can certainly skip the guard bits.
+	 * The last word of y has its highest 1-bit in position FP_NMANT-1,
+	 * so we stop the loop when we move past that bit.
+	 */
+	if ((m = y->fp_mant[3]) == 0) {
+		/* SHR32; */			/* unneeded since A==0 */
+	} else {
+		bit = 1 << FP_NG;
+		do {
+			STEP;
+		} while (bit != 0);
+	}
+	if ((m = y->fp_mant[2]) == 0) {
+		SHR32;
+	} else {
+		bit = 1;
+		do {
+			STEP;
+		} while (bit != 0);
+	}
+	if ((m = y->fp_mant[1]) == 0) {
+		SHR32;
+	} else {
+		bit = 1;
+		do {
+			STEP;
+		} while (bit != 0);
+	}
+	m = y->fp_mant[0];		/* definitely != 0 */
+	bit = 1;
+	do {
+		STEP;
+	} while (bit <= m);
+
+	/*
+	 * Done with mantissa calculation.  Get exponent and handle
+	 * 11.111...1 case, then put result in place.  We reuse x since
+	 * it already has the right class (FP_NUM).
+	 */
+	m = x->fp_exp + y->fp_exp;
+	if (a0 >= FP_2) {
+		SHR1;
+		m++;
+	}
+	x->fp_sign ^= y->fp_sign;
+	x->fp_exp = m;
+	x->fp_sticky = sticky;
+	x->fp_mant[3] = a3;
+	x->fp_mant[2] = a2;
+	x->fp_mant[1] = a1;
+	x->fp_mant[0] = a0;
+
+	DUMPFPN(FPE_REG, x);
+	return (x);
+}


Property changes on: trunk/sys/powerpc/fpu/fpu_mul.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_sqrt.c
===================================================================
--- trunk/sys/powerpc/fpu/fpu_sqrt.c	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_sqrt.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,416 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: fpu_sqrt.c,v 1.4 2005/12/11 12:18:42 christos Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ *	@(#)fpu_sqrt.c	8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Perform an FPU square root (return sqrt(x)).
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/fpu/fpu_sqrt.c 261455 2014-02-04 03:36:42Z eadler $");
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/fpu.h>
+#include <machine/reg.h>
+
+#include <powerpc/fpu/fpu_arith.h>
+#include <powerpc/fpu/fpu_emu.h>
+
+/*
+ * Our task is to calculate the square root of a floating point number x0.
+ * This number x normally has the form:
+ *
+ *		    exp
+ *	x = mant * 2		(where 1 <= mant < 2 and exp is an integer)
+ *
+ * This can be left as it stands, or the mantissa can be doubled and the
+ * exponent decremented:
+ *
+ *			  exp-1
+ *	x = (2 * mant) * 2	(where 2 <= 2 * mant < 4)
+ *
+ * If the exponent `exp' is even, the square root of the number is best
+ * handled using the first form, and is by definition equal to:
+ *
+ *				exp/2
+ *	sqrt(x) = sqrt(mant) * 2
+ *
+ * If exp is odd, on the other hand, it is convenient to use the second
+ * form, giving:
+ *
+ *				    (exp-1)/2
+ *	sqrt(x) = sqrt(2 * mant) * 2
+ *
+ * In the first case, we have
+ *
+ *	1 <= mant < 2
+ *
+ * and therefore
+ *
+ *	sqrt(1) <= sqrt(mant) < sqrt(2)
+ *
+ * while in the second case we have
+ *
+ *	2 <= 2*mant < 4
+ *
+ * and therefore
+ *
+ *	sqrt(2) <= sqrt(2*mant) < sqrt(4)
+ *
+ * so that in any case, we are sure that
+ *
+ *	sqrt(1) <= sqrt(n * mant) < sqrt(4),	n = 1 or 2
+ *
+ * or
+ *
+ *	1 <= sqrt(n * mant) < 2,		n = 1 or 2.
+ *
+ * This root is therefore a properly formed mantissa for a floating
+ * point number.  The exponent of sqrt(x) is either exp/2 or (exp-1)/2
+ * as above.  This leaves us with the problem of finding the square root
+ * of a fixed-point number in the range [1..4).
+ *
+ * Though it may not be instantly obvious, the following square root
+ * algorithm works for any integer x of an even number of bits, provided
+ * that no overflows occur:
+ *
+ *	let q = 0
+ *	for k = NBITS-1 to 0 step -1 do -- for each digit in the answer...
+ *		x *= 2			-- multiply by radix, for next digit
+ *		if x >= 2q + 2^k then	-- if adding 2^k does not
+ *			x -= 2q + 2^k	-- exceed the correct root,
+ *			q += 2^k	-- add 2^k and adjust x
+ *		fi
+ *	done
+ *	sqrt = q / 2^(NBITS/2)		-- (and any remainder is in x)
+ *
+ * If NBITS is odd (so that k is initially even), we can just add another
+ * zero bit at the top of x.  Doing so means that q is not going to acquire
+ * a 1 bit in the first trip around the loop (since x0 < 2^NBITS).  If the
+ * final value in x is not needed, or can be off by a factor of 2, this is
+ * equivalant to moving the `x *= 2' step to the bottom of the loop:
+ *
+ *	for k = NBITS-1 to 0 step -1 do if ... fi; x *= 2; done
+ *
+ * and the result q will then be sqrt(x0) * 2^floor(NBITS / 2).
+ * (Since the algorithm is destructive on x, we will call x's initial
+ * value, for which q is some power of two times its square root, x0.)
+ *
+ * If we insert a loop invariant y = 2q, we can then rewrite this using
+ * C notation as:
+ *
+ *	q = y = 0; x = x0;
+ *	for (k = NBITS; --k >= 0;) {
+ * #if (NBITS is even)
+ *		x *= 2;
+ * #endif
+ *		t = y + (1 << k);
+ *		if (x >= t) {
+ *			x -= t;
+ *			q += 1 << k;
+ *			y += 1 << (k + 1);
+ *		}
+ * #if (NBITS is odd)
+ *		x *= 2;
+ * #endif
+ *	}
+ *
+ * If x0 is fixed point, rather than an integer, we can simply alter the
+ * scale factor between q and sqrt(x0).  As it happens, we can easily arrange
+ * for the scale factor to be 2**0 or 1, so that sqrt(x0) == q.
+ *
+ * In our case, however, x0 (and therefore x, y, q, and t) are multiword
+ * integers, which adds some complication.  But note that q is built one
+ * bit at a time, from the top down, and is not used itself in the loop
+ * (we use 2q as held in y instead).  This means we can build our answer
+ * in an integer, one word at a time, which saves a bit of work.  Also,
+ * since 1 << k is always a `new' bit in q, 1 << k and 1 << (k+1) are
+ * `new' bits in y and we can set them with an `or' operation rather than
+ * a full-blown multiword add.
+ *
+ * We are almost done, except for one snag.  We must prove that none of our
+ * intermediate calculations can overflow.  We know that x0 is in [1..4)
+ * and therefore the square root in q will be in [1..2), but what about x,
+ * y, and t?
+ *
+ * We know that y = 2q at the beginning of each loop.  (The relation only
+ * fails temporarily while y and q are being updated.)  Since q < 2, y < 4.
+ * The sum in t can, in our case, be as much as y+(1<<1) = y+2 < 6, and.
+ * Furthermore, we can prove with a bit of work that x never exceeds y by
+ * more than 2, so that even after doubling, 0 <= x < 8.  (This is left as
+ * an exercise to the reader, mostly because I have become tired of working
+ * on this comment.)
+ *
+ * If our floating point mantissas (which are of the form 1.frac) occupy
+ * B+1 bits, our largest intermediary needs at most B+3 bits, or two extra.
+ * In fact, we want even one more bit (for a carry, to avoid compares), or
+ * three extra.  There is a comment in fpu_emu.h reminding maintainers of
+ * this, so we have some justification in assuming it.
+ */
+struct fpn *
+fpu_sqrt(struct fpemu *fe)
+{
+	struct fpn *x = &fe->fe_f1;
+	u_int bit, q, tt;
+	u_int x0, x1, x2, x3;
+	u_int y0, y1, y2, y3;
+	u_int d0, d1, d2, d3;
+	int e;
+	FPU_DECL_CARRY;
+
+	/*
+	 * Take care of special cases first.  In order:
+	 *
+	 *	sqrt(NaN) = NaN
+	 *	sqrt(+0) = +0
+	 *	sqrt(-0) = -0
+	 *	sqrt(x < 0) = NaN	(including sqrt(-Inf))
+	 *	sqrt(+Inf) = +Inf
+	 *
+	 * Then all that remains are numbers with mantissas in [1..2).
+	 */
+	DPRINTF(FPE_REG, ("fpu_sqer:\n"));
+	DUMPFPN(FPE_REG, x);
+	DPRINTF(FPE_REG, ("=>\n"));
+	if (ISNAN(x)) {
+		fe->fe_cx |= FPSCR_VXSNAN;
+		DUMPFPN(FPE_REG, x);
+		return (x);
+	}
+	if (ISZERO(x)) {
+		fe->fe_cx |= FPSCR_ZX;
+		x->fp_class = FPC_INF;
+		DUMPFPN(FPE_REG, x);
+		return (x);
+	}
+	if (x->fp_sign) {
+		return (fpu_newnan(fe));
+	}
+	if (ISINF(x)) {
+		fe->fe_cx |= FPSCR_VXSQRT;
+		DUMPFPN(FPE_REG, 0);
+		return (0);
+	}
+
+	/*
+	 * Calculate result exponent.  As noted above, this may involve
+	 * doubling the mantissa.  We will also need to double x each
+	 * time around the loop, so we define a macro for this here, and
+	 * we break out the multiword mantissa.
+	 */
+#ifdef FPU_SHL1_BY_ADD
+#define	DOUBLE_X { \
+	FPU_ADDS(x3, x3, x3); FPU_ADDCS(x2, x2, x2); \
+	FPU_ADDCS(x1, x1, x1); FPU_ADDC(x0, x0, x0); \
+}
+#else
+#define	DOUBLE_X { \
+	x0 = (x0 << 1) | (x1 >> 31); x1 = (x1 << 1) | (x2 >> 31); \
+	x2 = (x2 << 1) | (x3 >> 31); x3 <<= 1; \
+}
+#endif
+#if (FP_NMANT & 1) != 0
+# define ODD_DOUBLE	DOUBLE_X
+# define EVEN_DOUBLE	/* nothing */
+#else
+# define ODD_DOUBLE	/* nothing */
+# define EVEN_DOUBLE	DOUBLE_X
+#endif
+	x0 = x->fp_mant[0];
+	x1 = x->fp_mant[1];
+	x2 = x->fp_mant[2];
+	x3 = x->fp_mant[3];
+	e = x->fp_exp;
+	if (e & 1)		/* exponent is odd; use sqrt(2mant) */
+		DOUBLE_X;
+	/* THE FOLLOWING ASSUMES THAT RIGHT SHIFT DOES SIGN EXTENSION */
+	x->fp_exp = e >> 1;	/* calculates (e&1 ? (e-1)/2 : e/2 */
+
+	/*
+	 * Now calculate the mantissa root.  Since x is now in [1..4),
+	 * we know that the first trip around the loop will definitely
+	 * set the top bit in q, so we can do that manually and start
+	 * the loop at the next bit down instead.  We must be sure to
+	 * double x correctly while doing the `known q=1.0'.
+	 *
+	 * We do this one mantissa-word at a time, as noted above, to
+	 * save work.  To avoid `(1U << 31) << 1', we also do the top bit
+	 * outside of each per-word loop.
+	 *
+	 * The calculation `t = y + bit' breaks down into `t0 = y0, ...,
+	 * t3 = y3, t? |= bit' for the appropriate word.  Since the bit
+	 * is always a `new' one, this means that three of the `t?'s are
+	 * just the corresponding `y?'; we use `#define's here for this.
+	 * The variable `tt' holds the actual `t?' variable.
+	 */
+
+	/* calculate q0 */
+#define	t0 tt
+	bit = FP_1;
+	EVEN_DOUBLE;
+	/* if (x >= (t0 = y0 | bit)) { */	/* always true */
+		q = bit;
+		x0 -= bit;
+		y0 = bit << 1;
+	/* } */
+	ODD_DOUBLE;
+	while ((bit >>= 1) != 0) {	/* for remaining bits in q0 */
+		EVEN_DOUBLE;
+		t0 = y0 | bit;		/* t = y + bit */
+		if (x0 >= t0) {		/* if x >= t then */
+			x0 -= t0;	/*	x -= t */
+			q |= bit;	/*	q += bit */
+			y0 |= bit << 1;	/*	y += bit << 1 */
+		}
+		ODD_DOUBLE;
+	}
+	x->fp_mant[0] = q;
+#undef t0
+
+	/* calculate q1.  note (y0&1)==0. */
+#define t0 y0
+#define t1 tt
+	q = 0;
+	y1 = 0;
+	bit = 1 << 31;
+	EVEN_DOUBLE;
+	t1 = bit;
+	FPU_SUBS(d1, x1, t1);
+	FPU_SUBC(d0, x0, t0);		/* d = x - t */
+	if ((int)d0 >= 0) {		/* if d >= 0 (i.e., x >= t) then */
+		x0 = d0, x1 = d1;	/*	x -= t */
+		q = bit;		/*	q += bit */
+		y0 |= 1;		/*	y += bit << 1 */
+	}
+	ODD_DOUBLE;
+	while ((bit >>= 1) != 0) {	/* for remaining bits in q1 */
+		EVEN_DOUBLE;		/* as before */
+		t1 = y1 | bit;
+		FPU_SUBS(d1, x1, t1);
+		FPU_SUBC(d0, x0, t0);
+		if ((int)d0 >= 0) {
+			x0 = d0, x1 = d1;
+			q |= bit;
+			y1 |= bit << 1;
+		}
+		ODD_DOUBLE;
+	}
+	x->fp_mant[1] = q;
+#undef t1
+
+	/* calculate q2.  note (y1&1)==0; y0 (aka t0) is fixed. */
+#define t1 y1
+#define t2 tt
+	q = 0;
+	y2 = 0;
+	bit = 1 << 31;
+	EVEN_DOUBLE;
+	t2 = bit;
+	FPU_SUBS(d2, x2, t2);
+	FPU_SUBCS(d1, x1, t1);
+	FPU_SUBC(d0, x0, t0);
+	if ((int)d0 >= 0) {
+		x0 = d0, x1 = d1, x2 = d2;
+		q |= bit;
+		y1 |= 1;		/* now t1, y1 are set in concrete */
+	}
+	ODD_DOUBLE;
+	while ((bit >>= 1) != 0) {
+		EVEN_DOUBLE;
+		t2 = y2 | bit;
+		FPU_SUBS(d2, x2, t2);
+		FPU_SUBCS(d1, x1, t1);
+		FPU_SUBC(d0, x0, t0);
+		if ((int)d0 >= 0) {
+			x0 = d0, x1 = d1, x2 = d2;
+			q |= bit;
+			y2 |= bit << 1;
+		}
+		ODD_DOUBLE;
+	}
+	x->fp_mant[2] = q;
+#undef t2
+
+	/* calculate q3.  y0, t0, y1, t1 all fixed; y2, t2, almost done. */
+#define t2 y2
+#define t3 tt
+	q = 0;
+	y3 = 0;
+	bit = 1 << 31;
+	EVEN_DOUBLE;
+	t3 = bit;
+	FPU_SUBS(d3, x3, t3);
+	FPU_SUBCS(d2, x2, t2);
+	FPU_SUBCS(d1, x1, t1);
+	FPU_SUBC(d0, x0, t0);
+	ODD_DOUBLE;
+	if ((int)d0 >= 0) {
+		x0 = d0, x1 = d1, x2 = d2;
+		q |= bit;
+		y2 |= 1;
+	}
+	while ((bit >>= 1) != 0) {
+		EVEN_DOUBLE;
+		t3 = y3 | bit;
+		FPU_SUBS(d3, x3, t3);
+		FPU_SUBCS(d2, x2, t2);
+		FPU_SUBCS(d1, x1, t1);
+		FPU_SUBC(d0, x0, t0);
+		if ((int)d0 >= 0) {
+			x0 = d0, x1 = d1, x2 = d2;
+			q |= bit;
+			y3 |= bit << 1;
+		}
+		ODD_DOUBLE;
+	}
+	x->fp_mant[3] = q;
+
+	/*
+	 * The result, which includes guard and round bits, is exact iff
+	 * x is now zero; any nonzero bits in x represent sticky bits.
+	 */
+	x->fp_sticky = x0 | x1 | x2 | x3;
+	DUMPFPN(FPE_REG, x);
+	return (x);
+}


Property changes on: trunk/sys/powerpc/fpu/fpu_sqrt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/fpu/fpu_subr.c
===================================================================
--- trunk/sys/powerpc/fpu/fpu_subr.c	                        (rev 0)
+++ trunk/sys/powerpc/fpu/fpu_subr.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,221 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: fpu_subr.c,v 1.4 2005/12/11 12:18:42 christos Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ *
+ *	@(#)fpu_subr.c	8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * FPU subroutines.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/fpu/fpu_subr.c 178030 2008-04-09 08:50:37Z grehan $");
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/fpu.h>
+#include <machine/reg.h>
+
+#include <powerpc/fpu/fpu_arith.h>
+#include <powerpc/fpu/fpu_emu.h>
+
+/*
+ * Shift the given number right rsh bits.  Any bits that `fall off' will get
+ * shoved into the sticky field; we return the resulting sticky.  Note that
+ * shifting NaNs is legal (this will never shift all bits out); a NaN's
+ * sticky field is ignored anyway.
+ */
+int
+fpu_shr(struct fpn *fp, int rsh)
+{
+	u_int m0, m1, m2, m3, s;
+	int lsh;
+
+#ifdef DIAGNOSTIC
+	if (rsh <= 0 || (fp->fp_class != FPC_NUM && !ISNAN(fp)))
+		panic("fpu_rightshift 1");
+#endif
+
+	m0 = fp->fp_mant[0];
+	m1 = fp->fp_mant[1];
+	m2 = fp->fp_mant[2];
+	m3 = fp->fp_mant[3];
+
+	/* If shifting all the bits out, take a shortcut. */
+	if (rsh >= FP_NMANT) {
+#ifdef DIAGNOSTIC
+		if ((m0 | m1 | m2 | m3) == 0)
+			panic("fpu_rightshift 2");
+#endif
+		fp->fp_mant[0] = 0;
+		fp->fp_mant[1] = 0;
+		fp->fp_mant[2] = 0;
+		fp->fp_mant[3] = 0;
+#ifdef notdef
+		if ((m0 | m1 | m2 | m3) == 0)
+			fp->fp_class = FPC_ZERO;
+		else
+#endif
+			fp->fp_sticky = 1;
+		return (1);
+	}
+
+	/* Squish out full words. */
+	s = fp->fp_sticky;
+	if (rsh >= 32 * 3) {
+		s |= m3 | m2 | m1;
+		m3 = m0, m2 = 0, m1 = 0, m0 = 0;
+	} else if (rsh >= 32 * 2) {
+		s |= m3 | m2;
+		m3 = m1, m2 = m0, m1 = 0, m0 = 0;
+	} else if (rsh >= 32) {
+		s |= m3;
+		m3 = m2, m2 = m1, m1 = m0, m0 = 0;
+	}
+
+	/* Handle any remaining partial word. */
+	if ((rsh &= 31) != 0) {
+		lsh = 32 - rsh;
+		s |= m3 << lsh;
+		m3 = (m3 >> rsh) | (m2 << lsh);
+		m2 = (m2 >> rsh) | (m1 << lsh);
+		m1 = (m1 >> rsh) | (m0 << lsh);
+		m0 >>= rsh;
+	}
+	fp->fp_mant[0] = m0;
+	fp->fp_mant[1] = m1;
+	fp->fp_mant[2] = m2;
+	fp->fp_mant[3] = m3;
+	fp->fp_sticky = s;
+	return (s);
+}
+
+/*
+ * Force a number to be normal, i.e., make its fraction have all zero
+ * bits before FP_1, then FP_1, then all 1 bits.  This is used for denorms
+ * and (sometimes) for intermediate results.
+ *
+ * Internally, this may use a `supernormal' -- a number whose fp_mant
+ * is greater than or equal to 2.0 -- so as a side effect you can hand it
+ * a supernormal and it will fix it (provided fp->fp_mant[3] == 0).
+ */
+void
+fpu_norm(struct fpn *fp)
+{
+	u_int m0, m1, m2, m3, top, sup, nrm;
+	int lsh, rsh, exp;
+
+	exp = fp->fp_exp;
+	m0 = fp->fp_mant[0];
+	m1 = fp->fp_mant[1];
+	m2 = fp->fp_mant[2];
+	m3 = fp->fp_mant[3];
+
+	/* Handle severe subnormals with 32-bit moves. */
+	if (m0 == 0) {
+		if (m1)
+			m0 = m1, m1 = m2, m2 = m3, m3 = 0, exp -= 32;
+		else if (m2)
+			m0 = m2, m1 = m3, m2 = 0, m3 = 0, exp -= 2 * 32;
+		else if (m3)
+			m0 = m3, m1 = 0, m2 = 0, m3 = 0, exp -= 3 * 32;
+		else {
+			fp->fp_class = FPC_ZERO;
+			return;
+		}
+	}
+
+	/* Now fix any supernormal or remaining subnormal. */
+	nrm = FP_1;
+	sup = nrm << 1;
+	if (m0 >= sup) {
+		/*
+		 * We have a supernormal number.  We need to shift it right.
+		 * We may assume m3==0.
+		 */
+		for (rsh = 1, top = m0 >> 1; top >= sup; rsh++)	/* XXX slow */
+			top >>= 1;
+		exp += rsh;
+		lsh = 32 - rsh;
+		m3 = m2 << lsh;
+		m2 = (m2 >> rsh) | (m1 << lsh);
+		m1 = (m1 >> rsh) | (m0 << lsh);
+		m0 = top;
+	} else if (m0 < nrm) {
+		/*
+		 * We have a regular denorm (a subnormal number), and need
+		 * to shift it left.
+		 */
+		for (lsh = 1, top = m0 << 1; top < nrm; lsh++)	/* XXX slow */
+			top <<= 1;
+		exp -= lsh;
+		rsh = 32 - lsh;
+		m0 = top | (m1 >> rsh);
+		m1 = (m1 << lsh) | (m2 >> rsh);
+		m2 = (m2 << lsh) | (m3 >> rsh);
+		m3 <<= lsh;
+	}
+
+	fp->fp_exp = exp;
+	fp->fp_mant[0] = m0;
+	fp->fp_mant[1] = m1;
+	fp->fp_mant[2] = m2;
+	fp->fp_mant[3] = m3;
+}
+
+/*
+ * Concoct a `fresh' Quiet NaN per Appendix N.
+ * As a side effect, we set NV (invalid) for the current exceptions.
+ */
+struct fpn *
+fpu_newnan(struct fpemu *fe)
+{
+	struct fpn *fp;
+
+	fe->fe_cx |= FPSCR_VXSNAN;
+	fp = &fe->fe_f3;
+	fp->fp_class = FPC_QNAN;
+	fp->fp_sign = 0;
+	fp->fp_mant[0] = FP_1 - 1;
+	fp->fp_mant[1] = fp->fp_mant[2] = fp->fp_mant[3] = ~0;
+	DUMPFPN(FPE_REG, fp);
+	return (fp);
+}


Property changes on: trunk/sys/powerpc/fpu/fpu_subr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/_align.h
===================================================================
--- trunk/sys/powerpc/include/_align.h	                        (rev 0)
+++ trunk/sys/powerpc/include/_align.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,53 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 David E. O'Brien
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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 University of
+ *	California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ *	from: @(#)param.h	5.8 (Berkeley) 6/28/91
+ * $FreeBSD: stable/10/sys/powerpc/include/_align.h 209975 2010-07-13 05:32:19Z nwhitehorn $
+ */
+
+#ifndef _POWERPC_INCLUDE__ALIGN_H_
+#define	_POWERPC_INCLUDE__ALIGN_H_
+
+/*
+ * Round p (pointer or byte index) up to a correctly-aligned value
+ * for all data types (int, long, ...).   The result is unsigned int
+ * and must be cast to any desired pointer type.
+ */
+#define	_ALIGNBYTES	(sizeof(register_t) - 1)
+#define	_ALIGN(p)	(((uintptr_t)(p) + _ALIGNBYTES) & ~_ALIGNBYTES)
+
+#endif /* !_POWERPC_INCLUDE__ALIGN_H_ */


Property changes on: trunk/sys/powerpc/include/_align.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/_bus.h
===================================================================
--- trunk/sys/powerpc/include/_bus.h	                        (rev 0)
+++ trunk/sys/powerpc/include/_bus.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,49 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 M. Warner Losh.
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/_bus.h 209975 2010-07-13 05:32:19Z nwhitehorn $
+ */
+
+#ifndef POWERPC_INCLUDE__BUS_H
+#define POWERPC_INCLUDE__BUS_H
+
+#include <vm/vm_param.h>
+
+/*
+ * Bus address and size types
+ */
+typedef vm_paddr_t bus_addr_t;
+typedef vm_size_t bus_size_t;
+
+/*
+ * Access methods for bus resources and address space.
+ */
+typedef struct bus_space *bus_space_tag_t;
+typedef vm_offset_t bus_space_handle_t;
+
+#endif /* POWERPC_INCLUDE__BUS_H */


Property changes on: trunk/sys/powerpc/include/_bus.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/_inttypes.h
===================================================================
--- trunk/sys/powerpc/include/_inttypes.h	                        (rev 0)
+++ trunk/sys/powerpc/include/_inttypes.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,222 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *	From: $NetBSD: int_fmtio.h,v 1.2 2001/04/26 16:25:21 kleink Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/_inttypes.h 217156 2011-01-08 18:02:46Z tijl $
+ */
+
+#ifndef _MACHINE_INTTYPES_H_
+#define	_MACHINE_INTTYPES_H_
+
+/*
+ * Macros for format specifiers.
+ */
+
+#ifdef __LP64__
+#define	__PRI64		"l"
+#define	__PRIptr	"l"
+#else
+#define	__PRI64		"ll"
+#define	__PRIptr
+#endif
+
+/* fprintf(3) macros for signed integers. */
+
+#define	PRId8		"d"		/* int8_t */
+#define	PRId16		"d"		/* int16_t */
+#define	PRId32		"d"		/* int32_t */
+#define	PRId64		__PRI64"d"	/* int64_t */
+#define	PRIdLEAST8	"d"		/* int_least8_t */
+#define	PRIdLEAST16	"d"		/* int_least16_t */
+#define	PRIdLEAST32	"d"		/* int_least32_t */
+#define	PRIdLEAST64	__PRI64"d"	/* int_least64_t */
+#define	PRIdFAST8	"d"		/* int_fast8_t */
+#define	PRIdFAST16	"d"		/* int_fast16_t */
+#define	PRIdFAST32	"d"		/* int_fast32_t */
+#define	PRIdFAST64	__PRI64"d"	/* int_fast64_t */
+#define	PRIdMAX		"jd"		/* intmax_t */
+#define	PRIdPTR		__PRIptr"d"	/* intptr_t */
+
+#define	PRIi8		"i"		/* int8_t */
+#define	PRIi16		"i"		/* int16_t */
+#define	PRIi32		"i"		/* int32_t */
+#define	PRIi64		__PRI64"i"	/* int64_t */
+#define	PRIiLEAST8	"i"		/* int_least8_t  */
+#define	PRIiLEAST16	"i"		/* int_least16_t */
+#define	PRIiLEAST32	"i"		/* int_least32_t */
+#define	PRIiLEAST64	__PRI64"i"	/* int_least64_t */
+#define	PRIiFAST8	"i"		/* int_fast8_t */
+#define	PRIiFAST16	"i"		/* int_fast16_t */
+#define	PRIiFAST32	"i"		/* int_fast32_t */
+#define	PRIiFAST64	__PRI64"i"	/* int_fast64_t */
+#define	PRIiMAX		"ji"		/* intmax_t */
+#define	PRIiPTR		__PRIptr"i"	/* intptr_t */
+
+/* fprintf(3) macros for unsigned integers. */
+
+#define	PRIo8		"o"		/* uint8_t */
+#define	PRIo16		"o"		/* uint16_t */
+#define	PRIo32		"o"		/* uint32_t */
+#define	PRIo64		__PRI64"o"	/* uint64_t */
+#define	PRIoLEAST8	"o"		/* uint_least8_t */
+#define	PRIoLEAST16	"o"		/* uint_least16_t */
+#define	PRIoLEAST32	"o"		/* uint_least32_t */
+#define	PRIoLEAST64	__PRI64"o"	/* uint_least64_t */
+#define	PRIoFAST8	"o"		/* uint_fast8_t */
+#define	PRIoFAST16	"o"		/* uint_fast16_t */
+#define	PRIoFAST32	"o"		/* uint_fast32_t */
+#define	PRIoFAST64	__PRI64"o"	/* uint_fast64_t */
+#define	PRIoMAX		"jo"		/* uintmax_t */
+#define	PRIoPTR		__PRIptr"o"	/* uintptr_t */
+
+#define	PRIu8		"u"		/* uint8_t */
+#define	PRIu16		"u"		/* uint16_t */
+#define	PRIu32		"u"		/* uint32_t */
+#define	PRIu64		__PRI64"u"	/* uint64_t */
+#define	PRIuLEAST8	"u"		/* uint_least8_t */
+#define	PRIuLEAST16	"u"		/* uint_least16_t */
+#define	PRIuLEAST32	"u"		/* uint_least32_t */
+#define	PRIuLEAST64	__PRI64"u"	/* uint_least64_t */
+#define	PRIuFAST8	"u"		/* uint_fast8_t */
+#define	PRIuFAST16	"u"		/* uint_fast16_t */
+#define	PRIuFAST32	"u"		/* uint_fast32_t */
+#define	PRIuFAST64	__PRI64"u"	/* uint_fast64_t */
+#define	PRIuMAX		"ju"		/* uintmax_t */
+#define	PRIuPTR		__PRIptr"u"	/* uintptr_t */
+
+#define	PRIx8		"x"		/* uint8_t */
+#define	PRIx16		"x"		/* uint16_t */
+#define	PRIx32		"x"		/* uint32_t */
+#define	PRIx64		__PRI64"x"	/* uint64_t */
+#define	PRIxLEAST8	"x"		/* uint_least8_t */
+#define	PRIxLEAST16	"x"		/* uint_least16_t */
+#define	PRIxLEAST32	"x"		/* uint_least32_t */
+#define	PRIxLEAST64	__PRI64"x"	/* uint_least64_t */
+#define	PRIxFAST8	"x"		/* uint_fast8_t */
+#define	PRIxFAST16	"x"		/* uint_fast16_t */
+#define	PRIxFAST32	"x"		/* uint_fast32_t */
+#define	PRIxFAST64	__PRI64"x"	/* uint_fast64_t */
+#define	PRIxMAX		"jx"		/* uintmax_t */
+#define	PRIxPTR		__PRIptr"x"	/* uintptr_t */
+
+#define	PRIX8		"X"		/* uint8_t */
+#define	PRIX16		"X"		/* uint16_t */
+#define	PRIX32		"X"		/* uint32_t */
+#define	PRIX64		__PRI64"X"	/* uint64_t */
+#define	PRIXLEAST8	"X"		/* uint_least8_t */
+#define	PRIXLEAST16	"X"		/* uint_least16_t */
+#define	PRIXLEAST32	"X"		/* uint_least32_t */
+#define	PRIXLEAST64	__PRI64"X"	/* uint_least64_t */
+#define	PRIXFAST8	"X"		/* uint_fast8_t */
+#define	PRIXFAST16	"X"		/* uint_fast16_t */
+#define	PRIXFAST32	"X"		/* uint_fast32_t */
+#define	PRIXFAST64	__PRI64"X"	/* uint_fast64_t */
+#define	PRIXMAX		"jX"		/* uintmax_t */
+#define	PRIXPTR		__PRIptr"X"	/* uintptr_t */
+
+/* fscanf(3) macros for signed integers. */
+
+#define	SCNd8		"hhd"		/* int8_t */
+#define	SCNd16		"hd"		/* int16_t */
+#define	SCNd32		"d"		/* int32_t */
+#define	SCNd64		__PRI64"d"	/* int64_t */
+#define	SCNdLEAST8	"hhd"		/* int_least8_t */
+#define	SCNdLEAST16	"hd"		/* int_least16_t */
+#define	SCNdLEAST32	"d"		/* int_least32_t */
+#define	SCNdLEAST64	__PRI64"d"	/* int_least64_t */
+#define	SCNdFAST8	"d"		/* int_fast8_t */
+#define	SCNdFAST16	"d"		/* int_fast16_t */
+#define	SCNdFAST32	"d"		/* int_fast32_t */
+#define	SCNdFAST64	__PRI64"d"	/* int_fast64_t */
+#define	SCNdMAX		"jd"		/* intmax_t */
+#define	SCNdPTR		__PRIptr"d"	/* intptr_t */
+
+#define	SCNi8		"hhi"		/* int8_t */
+#define	SCNi16		"hi"		/* int16_t */
+#define	SCNi32		"i"		/* int32_t */
+#define	SCNi64		__PRI64"i"	/* int64_t */
+#define	SCNiLEAST8	"hhi"		/* int_least8_t */
+#define	SCNiLEAST16	"hi"		/* int_least16_t */
+#define	SCNiLEAST32	"i"		/* int_least32_t */
+#define	SCNiLEAST64	__PRI64"i"	/* int_least64_t */
+#define	SCNiFAST8	"i"		/* int_fast8_t */
+#define	SCNiFAST16	"i"		/* int_fast16_t */
+#define	SCNiFAST32	"i"		/* int_fast32_t */
+#define	SCNiFAST64	__PRI64"i"	/* int_fast64_t */
+#define	SCNiMAX		"ji"		/* intmax_t */
+#define	SCNiPTR		__PRIptr"i"	/* intptr_t */
+
+/* fscanf(3) macros for unsigned integers. */
+
+#define	SCNo8		"hho"		/* uint8_t */
+#define	SCNo16		"ho"		/* uint16_t */
+#define	SCNo32		"o"		/* uint32_t */
+#define	SCNo64		__PRI64"o"	/* uint64_t */
+#define	SCNoLEAST8	"hho"		/* uint_least8_t */
+#define	SCNoLEAST16	"ho"		/* uint_least16_t */
+#define	SCNoLEAST32	"o"		/* uint_least32_t */
+#define	SCNoLEAST64	__PRI64"o"	/* uint_least64_t */
+#define	SCNoFAST8	"o"		/* uint_fast8_t */
+#define	SCNoFAST16	"o"		/* uint_fast16_t */
+#define	SCNoFAST32	"o"		/* uint_fast32_t */
+#define	SCNoFAST64	__PRI64"o"	/* uint_fast64_t */
+#define	SCNoMAX		"jo"		/* uintmax_t */
+#define	SCNoPTR		__PRIptr"o"	/* uintptr_t */
+
+#define	SCNu8		"hhu"		/* uint8_t */
+#define	SCNu16		"hu"		/* uint16_t */
+#define	SCNu32		"u"		/* uint32_t */
+#define	SCNu64		__PRI64"u"	/* uint64_t */
+#define	SCNuLEAST8	"hhu"		/* uint_least8_t */
+#define	SCNuLEAST16	"hu"		/* uint_least16_t */
+#define	SCNuLEAST32	"u"		/* uint_least32_t */
+#define	SCNuLEAST64	__PRI64"u"	/* uint_least64_t */
+#define	SCNuFAST8	"u"		/* uint_fast8_t */
+#define	SCNuFAST16	"u"		/* uint_fast16_t */
+#define	SCNuFAST32	"u"		/* uint_fast32_t */
+#define	SCNuFAST64	__PRI64"u"	/* uint_fast64_t */
+#define	SCNuMAX		"ju"		/* uintmax_t */
+#define	SCNuPTR		__PRIptr"u"	/* uintptr_t */
+
+#define	SCNx8		"hhx"		/* uint8_t */
+#define	SCNx16		"hx"		/* uint16_t */
+#define	SCNx32		"x"		/* uint32_t */
+#define	SCNx64		__PRI64"x"	/* uint64_t */
+#define	SCNxLEAST8	"hhx"		/* uint_least8_t */
+#define	SCNxLEAST16	"hx"		/* uint_least16_t */
+#define	SCNxLEAST32	"x"		/* uint_least32_t */
+#define	SCNxLEAST64	__PRI64"x"	/* uint_least64_t */
+#define	SCNxFAST8	"x"		/* uint_fast8_t */
+#define	SCNxFAST16	"x"		/* uint_fast16_t */
+#define	SCNxFAST32	"x"		/* uint_fast32_t */
+#define	SCNxFAST64	__PRI64"x"	/* uint_fast64_t */
+#define	SCNxMAX		"jx"		/* uintmax_t */
+#define	SCNxPTR		__PRIptr"x"	/* uintptr_t */
+
+#endif /* !_MACHINE_INTTYPES_H_ */


Property changes on: trunk/sys/powerpc/include/_inttypes.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/_limits.h
===================================================================
--- trunk/sys/powerpc/include/_limits.h	                        (rev 0)
+++ trunk/sys/powerpc/include/_limits.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,98 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1988, 1993
+ *	The 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.
+ * 4. 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.
+ *
+ *	@(#)limits.h	8.3 (Berkeley) 1/4/94
+ * $FreeBSD: stable/10/sys/powerpc/include/_limits.h 217147 2011-01-08 12:43:05Z tijl $
+ */
+
+#ifndef _MACHINE__LIMITS_H_
+#define	_MACHINE__LIMITS_H_
+
+/*
+ * According to ANSI (section 2.2.4.2), the values below must be usable by
+ * #if preprocessing directives.  Additionally, the expression must have the
+ * same type as would an expression that is an object of the corresponding
+ * type converted according to the integral promotions.  The subtraction for
+ * INT_MIN, etc., is so the value is not unsigned; e.g., 0x80000000 is an
+ * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2).
+ */
+
+#define	__CHAR_BIT	8		/* number of bits in a char */
+
+#define	__SCHAR_MAX	0x7f		/* max value for a signed char */
+#define	__SCHAR_MIN	(-0x7f - 1)	/* min value for a signed char */
+
+#define	__UCHAR_MAX	0xff		/* max value for an unsigned char */
+
+#define	__USHRT_MAX	0xffff		/* max value for an unsigned short */
+#define	__SHRT_MAX	0x7fff		/* max value for a short */
+#define	__SHRT_MIN	(-0x7fff - 1)	/* min value for a short */
+
+#define	__UINT_MAX	0xffffffff	/* max value for an unsigned int */
+#define	__INT_MAX	0x7fffffff	/* max value for an int */
+#define	__INT_MIN	(-0x7fffffff - 1)	/* min value for an int */
+
+#ifdef __LP64__
+#define	__ULONG_MAX	0xffffffffffffffff
+#define	__LONG_MAX	0x7fffffffffffffff
+#define	__LONG_MIN	(-0x7fffffffffffffff - 1)
+#define	__LONG_BIT	64
+#else
+#define	__ULONG_MAX	0xffffffffUL	/* max value for an unsigned long */
+#define	__LONG_MAX	0x7fffffffL	/* max value for a long */
+#define	__LONG_MIN	(-0x7fffffffL - 1)	/* min value for a long */
+#define	__LONG_BIT	32
+#endif
+
+#define	__ULLONG_MAX	0xffffffffffffffffULL
+#define	__LLONG_MAX	0x7fffffffffffffffLL	/* max value for a long long */
+#define	__LLONG_MIN	(-0x7fffffffffffffffLL - 1)  /* min for a long long */
+
+#ifdef __LP64__
+#define	__SSIZE_MAX	__LONG_MAX	/* max value for a ssize_t */
+#define	__SIZE_T_MAX	__ULONG_MAX	/* max value for a size_t */
+#else
+#define	__SSIZE_MAX	__INT_MAX	/* max value for a ssize_t */
+#define	__SIZE_T_MAX	__UINT_MAX	/* max value for a size_t */
+#endif
+
+#define	__OFF_MAX	__LLONG_MAX	/* max value for an off_t */
+#define	__OFF_MIN	__LLONG_MIN	/* min value for an off_t */
+
+/* Quads and long longs are the same size.  Ensure they stay in sync. */
+#define	__UQUAD_MAX	__ULLONG_MAX	/* max value for a uquad_t */
+#define	__QUAD_MAX	__LLONG_MAX	/* max value for a quad_t */
+#define	__QUAD_MIN	__LLONG_MIN	/* min value for a quad_t */
+
+#define	__WORD_BIT	32
+
+/* Minimum signal stack size. */
+#define	__MINSIGSTKSZ	(512 * 4)
+
+#endif /* !_MACHINE__LIMITS_H_ */


Property changes on: trunk/sys/powerpc/include/_limits.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/_stdint.h
===================================================================
--- trunk/sys/powerpc/include/_stdint.h	                        (rev 0)
+++ trunk/sys/powerpc/include/_stdint.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,201 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001, 2002 Mike Barcroft <mike at FreeBSD.org>
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/_stdint.h 255194 2013-09-03 22:04:55Z imp $
+ */
+
+#ifndef _MACHINE__STDINT_H_
+#define	_MACHINE__STDINT_H_
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS)
+
+#define	INT8_C(c)		(c)
+#define	INT16_C(c)		(c)
+#define	INT32_C(c)		(c)
+
+#define	UINT8_C(c)		(c)
+#define	UINT16_C(c)		(c)
+#define	UINT32_C(c)		(c ## U)
+
+#ifdef __LP64__
+#define	INT64_C(c)		(c ## L)
+#define	UINT64_C(c)		(c ## UL)
+#else
+#define	INT64_C(c)		(c ## LL)
+#define	UINT64_C(c)		(c ## ULL)
+#endif
+
+#define	INTMAX_C(c)		INT64_C(c)
+#define	UINTMAX_C(c)		UINT64_C(c)
+
+#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
+
+#ifndef __INT64_C
+#ifdef __LP64__
+#define	__INT64_C(c)		(c ## L)
+#define	__UINT64_C(c)		(c ## UL)
+#else
+#define	__INT64_C(c)		(c ## LL)
+#define	__UINT64_C(c)		(c ## ULL)
+#endif
+#endif
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.1 Limits of exact-width integer types
+ */
+/* Minimum values of exact-width signed integer types. */
+#define	INT8_MIN	(-0x7f-1)
+#define	INT16_MIN	(-0x7fff-1)
+#define	INT32_MIN	(-0x7fffffff-1)
+#define	INT64_MIN	(-__INT64_C(0x7fffffffffffffff)-1)
+
+/* Maximum values of exact-width signed integer types. */
+#define	INT8_MAX	0x7f
+#define	INT16_MAX	0x7fff
+#define	INT32_MAX	0x7fffffff
+#define	INT64_MAX	__INT64_C(0x7fffffffffffffff)
+
+/* Maximum values of exact-width unsigned integer types. */
+#define	UINT8_MAX	0xff
+#define	UINT16_MAX	0xffff
+#define	UINT32_MAX	0xffffffff
+#define	UINT64_MAX	__UINT64_C(0xffffffffffffffff)
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.2  Limits of minimum-width integer types
+ */
+/* Minimum values of minimum-width signed integer types. */
+#define	INT_LEAST8_MIN	INT8_MIN
+#define	INT_LEAST16_MIN	INT16_MIN
+#define	INT_LEAST32_MIN	INT32_MIN
+#define	INT_LEAST64_MIN	INT64_MIN
+
+/* Maximum values of minimum-width signed integer types. */
+#define	INT_LEAST8_MAX	INT8_MAX
+#define	INT_LEAST16_MAX	INT16_MAX
+#define	INT_LEAST32_MAX	INT32_MAX
+#define	INT_LEAST64_MAX	INT64_MAX
+
+/* Maximum values of minimum-width unsigned integer types. */
+#define	UINT_LEAST8_MAX	 UINT8_MAX
+#define	UINT_LEAST16_MAX UINT16_MAX
+#define	UINT_LEAST32_MAX UINT32_MAX
+#define	UINT_LEAST64_MAX UINT64_MAX
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.3  Limits of fastest minimum-width integer types
+ */
+/* Minimum values of fastest minimum-width signed integer types. */
+#define	INT_FAST8_MIN	INT32_MIN
+#define	INT_FAST16_MIN	INT32_MIN
+#define	INT_FAST32_MIN	INT32_MIN
+#define	INT_FAST64_MIN	INT64_MIN
+
+/* Maximum values of fastest minimum-width signed integer types. */
+#define	INT_FAST8_MAX	INT32_MAX
+#define	INT_FAST16_MAX	INT32_MAX
+#define	INT_FAST32_MAX	INT32_MAX
+#define	INT_FAST64_MAX	INT64_MAX
+
+/* Maximum values of fastest minimum-width unsigned integer types. */
+#define	UINT_FAST8_MAX	UINT32_MAX
+#define	UINT_FAST16_MAX	UINT32_MAX
+#define	UINT_FAST32_MAX	UINT32_MAX
+#define	UINT_FAST64_MAX	UINT64_MAX
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.4  Limits of integer types capable of holding object pointers
+ */
+#ifdef __LP64__
+#define	INTPTR_MIN	INT64_MIN
+#define	INTPTR_MAX	INT64_MAX
+#define	UINTPTR_MAX	UINT64_MAX
+#else
+#define	INTPTR_MIN	INT32_MIN
+#define	INTPTR_MAX	INT32_MAX
+#define	UINTPTR_MAX	UINT32_MAX
+#endif
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.2.5  Limits of greatest-width integer types
+ */
+#define	INTMAX_MIN	INT64_MIN
+#define	INTMAX_MAX	INT64_MAX
+#define	UINTMAX_MAX	UINT64_MAX
+
+/*
+ * ISO/IEC 9899:1999
+ * 7.18.3  Limits of other integer types
+ */
+#ifdef __LP64__
+/* Limits of ptrdiff_t. */
+#define	PTRDIFF_MIN	INT64_MIN	
+#define	PTRDIFF_MAX	INT64_MAX
+
+/* Limits of sig_atomic_t. */
+#define	SIG_ATOMIC_MIN	INT64_MIN
+#define	SIG_ATOMIC_MAX	INT64_MAX
+
+/* Limit of size_t. */
+#define	SIZE_MAX	UINT64_MAX
+#else
+/* Limits of ptrdiff_t. */
+#define	PTRDIFF_MIN	INT32_MIN	
+#define	PTRDIFF_MAX	INT32_MAX
+
+/* Limits of sig_atomic_t. */
+#define	SIG_ATOMIC_MIN	INT32_MIN
+#define	SIG_ATOMIC_MAX	INT32_MAX
+
+/* Limit of size_t. */
+#define	SIZE_MAX	UINT32_MAX
+#endif
+
+/* Limits of wint_t. */
+#define	WINT_MIN	INT32_MIN
+#define	WINT_MAX	INT32_MAX
+
+#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */
+
+#endif /* !_MACHINE__STDINT_H_ */


Property changes on: trunk/sys/powerpc/include/_stdint.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/_types.h
===================================================================
--- trunk/sys/powerpc/include/_types.h	                        (rev 0)
+++ trunk/sys/powerpc/include/_types.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,162 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2002 Mike Barcroft <mike at FreeBSD.org>
+ * Copyright (c) 1990, 1993
+ *	The 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ *	From: @(#)ansi.h	8.2 (Berkeley) 1/4/94
+ *	From: @(#)types.h	8.3 (Berkeley) 1/5/94
+ * $FreeBSD: stable/10/sys/powerpc/include/_types.h 264496 2014-04-15 09:41:52Z tijl $
+ */
+
+#ifndef _MACHINE__TYPES_H_
+#define	_MACHINE__TYPES_H_
+
+#ifndef _SYS_CDEFS_H_
+#error this file needs sys/cdefs.h as a prerequisite
+#endif
+
+/*
+ * Basic types upon which most other types are built.
+ */
+typedef	signed char		__int8_t;
+typedef	unsigned char		__uint8_t;
+typedef	short			__int16_t;
+typedef	unsigned short		__uint16_t;
+typedef	int			__int32_t;
+typedef	unsigned int		__uint32_t;
+#ifdef __LP64__
+typedef	long			__int64_t;
+typedef	unsigned long		__uint64_t;
+#else
+#ifndef lint
+__extension__
+#endif
+/* LONGLONG */
+typedef	long long		__int64_t;
+#ifndef lint
+__extension__
+#endif
+/* LONGLONG */
+typedef	unsigned long long	__uint64_t;
+#endif
+
+/*
+ * Standard type definitions.
+ */
+typedef	__uint32_t	__clock_t;		/* clock()... */
+typedef	double		__double_t;
+typedef	float		__float_t;
+#ifdef __LP64__
+typedef	__int64_t	__critical_t;
+typedef	__int64_t	__intfptr_t;
+typedef	__int64_t	__intptr_t;
+#else
+typedef	__int32_t	__critical_t;
+typedef	__int32_t	__intfptr_t;
+typedef	__int32_t	__intptr_t;
+#endif
+typedef	__int64_t	__intmax_t;
+typedef	__int32_t	__int_fast8_t;
+typedef	__int32_t	__int_fast16_t;
+typedef	__int32_t	__int_fast32_t;
+typedef	__int64_t	__int_fast64_t;
+typedef	__int8_t	__int_least8_t;
+typedef	__int16_t	__int_least16_t;
+typedef	__int32_t	__int_least32_t;
+typedef	__int64_t	__int_least64_t;
+#ifdef __LP64__
+typedef	__int64_t	__ptrdiff_t;		/* ptr1 - ptr2 */
+typedef	__int64_t	__register_t;
+typedef	__int64_t	__segsz_t;		/* segment size (in pages) */
+typedef	__uint64_t	__size_t;		/* sizeof() */
+typedef	__int64_t	__ssize_t;		/* byte count or error */
+typedef	__int64_t	__time_t;		/* time()... */
+typedef	__uint64_t	__uintfptr_t;
+typedef	__uint64_t	__uintptr_t;
+#else
+typedef	__int32_t	__ptrdiff_t;		/* ptr1 - ptr2 */
+typedef	__int32_t	__register_t;
+typedef	__int32_t	__segsz_t;		/* segment size (in pages) */
+typedef	__uint32_t	__size_t;		/* sizeof() */
+typedef	__int32_t	__ssize_t;		/* byte count or error */
+typedef	__int32_t	__time_t;		/* time()... */
+typedef	__uint32_t	__uintfptr_t;
+typedef	__uint32_t	__uintptr_t;
+#endif
+typedef	__uint64_t	__uintmax_t;
+typedef	__uint32_t	__uint_fast8_t;
+typedef	__uint32_t	__uint_fast16_t;
+typedef	__uint32_t	__uint_fast32_t;
+typedef	__uint64_t	__uint_fast64_t;
+typedef	__uint8_t	__uint_least8_t;
+typedef	__uint16_t	__uint_least16_t;
+typedef	__uint32_t	__uint_least32_t;
+typedef	__uint64_t	__uint_least64_t;
+#ifdef __LP64__
+typedef	__uint64_t	__u_register_t;
+typedef	__uint64_t	__vm_offset_t;
+typedef	__uint64_t	__vm_paddr_t;
+typedef	__uint64_t	__vm_size_t;
+#else
+typedef	__uint32_t	__u_register_t;
+typedef	__uint32_t	__vm_offset_t;
+typedef	__uint32_t	__vm_paddr_t;
+typedef	__uint32_t	__vm_size_t;
+#endif
+typedef	__int64_t	__vm_ooffset_t;
+typedef	__uint64_t	__vm_pindex_t;
+typedef	int		___wchar_t;
+
+#define	__WCHAR_MIN	__INT_MIN	/* min value for a wchar_t */
+#define	__WCHAR_MAX	__INT_MAX	/* max value for a wchar_t */
+
+/*
+ * Unusual type definitions.
+ */
+#if defined(__GNUCLIKE_BUILTIN_VARARGS)
+typedef __builtin_va_list	__va_list;	/* internally known to gcc */
+#else
+typedef	struct {
+	char	__gpr;
+	char	__fpr;
+	char	__pad[2];
+	char	*__stack;
+	char	*__base;
+} __va_list;
+#endif /* post GCC 2.95 */
+#if defined(__GNUC_VA_LIST_COMPATIBILITY) && !defined(__GNUC_VA_LIST) \
+    && !defined(__NO_GNUC_VA_LIST)
+#define __GNUC_VA_LIST
+typedef __va_list		__gnuc_va_list;	/* compatibility w/GNU headers*/
+#endif
+
+#endif /* !_MACHINE__TYPES_H_ */


Property changes on: trunk/sys/powerpc/include/_types.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/altivec.h
===================================================================
--- trunk/sys/powerpc/include/altivec.h	                        (rev 0)
+++ trunk/sys/powerpc/include/altivec.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,40 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/altivec.h 213456 2010-10-05 18:08:07Z nwhitehorn $
+ */
+
+#ifndef	_MACHINE_ALTIVEC_H_
+#define	_MACHINE_ALTIVEC_H_
+
+#define ALTIVEC_VSCR_NJ		0x00010000	/* Enable non-Java mode */
+#define ALTIVEC_VSCR_SAT	0x00000001	/* Saturation status bit */
+
+void    enable_vec(struct thread *);
+void    save_vec(struct thread *);
+
+#endif	/* _MACHINE_ALTIVEC_H_ */
+


Property changes on: trunk/sys/powerpc/include/altivec.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/asm.h
===================================================================
--- trunk/sys/powerpc/include/asm.h	                        (rev 0)
+++ trunk/sys/powerpc/include/asm.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,165 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: asm.h,v 1.6.18.1 2000/07/25 08:37:14 kleink Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/asm.h 232488 2012-03-04 11:55:28Z andreast $
+ */
+
+#ifndef _MACHINE_ASM_H_
+#define	_MACHINE_ASM_H_
+
+#include <sys/cdefs.h>
+
+#if defined(PIC) && !defined(__powerpc64__)
+#define	PIC_PROLOGUE	XXX
+#define	PIC_EPILOGUE	XXX
+#define	PIC_PLT(x)	x at plt
+#ifdef	__STDC__
+#define	PIC_GOT(x)	XXX
+#else	/* not __STDC__ */
+#define	PIC_GOT(x)	XXX
+#endif	/* __STDC__ */
+#else
+#define	PIC_PROLOGUE
+#define	PIC_EPILOGUE
+#define	PIC_PLT(x)	x
+#define PIC_GOT(x)	x
+#endif
+
+#define	CNAME(csym)		csym
+#define	ASMNAME(asmsym)		asmsym
+#ifdef __powerpc64__
+#define	HIDENAME(asmsym)	__CONCAT(_,asmsym)
+#else
+#define	HIDENAME(asmsym)	__CONCAT(.,asmsym)
+#endif
+
+#ifdef _KERNEL
+#define	DOT_LABEL(name)		__CONCAT(.,name)
+#define	TYPE_ENTRY(name)	.size	name,24; \
+				.type	DOT_LABEL(name), at function; \
+				.globl	DOT_LABEL(name);
+#define	END_SIZE(name)		.size	DOT_LABEL(name),.-DOT_LABEL(name);
+#else /* !_KERNEL */
+#define	DOT_LABEL(name)		__CONCAT(.L.,name)
+#define	TYPE_ENTRY(name)	.type	name, at function;
+#define	END_SIZE(name)		.size	name,.-DOT_LABEL(name);
+#endif /* _KERNEL */
+
+#define	_GLOBAL(name) \
+	.data; \
+	.p2align 2; \
+	.globl	name; \
+	name:
+
+#ifdef __powerpc64__
+#define	_ENTRY(name) \
+	.section ".text"; \
+	.p2align 2; \
+	.globl	name; \
+	.section ".opd","aw"; \
+	.p2align 3; \
+	name: \
+	.quad	DOT_LABEL(name),.TOC. at tocbase,0; \
+	.previous; \
+	.p2align 4; \
+	TYPE_ENTRY(name) \
+DOT_LABEL(name):
+
+#define	_END(name) \
+	.long	0; \
+	.byte	0,0,0,0,0,0,0,0; \
+	END_SIZE(name)
+#else /* !__powerpc64__ */
+#define	_ENTRY(name) \
+	.text; \
+	.p2align 4; \
+	.globl	name; \
+	.type	name, at function; \
+	name:
+#define	_END(name)
+#endif /* __powerpc64__ */
+
+#if defined(PROF) || (defined(_KERNEL) && defined(GPROF))
+# ifdef __powerpc64__
+#   define	_PROF_PROLOGUE	mflr 0;					\
+				std 3,48(1);				\
+				std 4,56(1);				\
+				std 5,64(1);				\
+				std 0,16(1);				\
+				stdu 1,-112(1);				\
+				bl _mcount;				\
+				nop;					\
+				ld 0,112+16(1);				\
+				ld 3,112+48(1);				\
+				ld 4,112+56(1);				\
+				ld 5,112+64(1);				\
+				mtlr 0;					\
+				addi 1,1,112
+# else
+#   define	_PROF_PROLOGUE	mflr 0; stw 0,4(1); bl _mcount
+# endif
+#else
+# define	_PROF_PROLOGUE
+#endif
+
+#define	ASENTRY(y)	_ENTRY(ASMNAME(y)); _PROF_PROLOGUE
+#define	END(y)		_END(CNAME(y))
+#define	ENTRY(y)	_ENTRY(CNAME(y)); _PROF_PROLOGUE
+#define	GLOBAL(y)	_GLOBAL(CNAME(y))
+
+#define	ASENTRY_NOPROF(y)	_ENTRY(ASMNAME(y))
+#define	ENTRY_NOPROF(y)		_ENTRY(CNAME(y))
+
+#define	ASMSTR		.asciz
+
+#define	RCSID(x)	.text; .asciz x
+
+#undef __FBSDID
+#if !defined(lint) && !defined(STRIP_FBSDID)
+#define __FBSDID(s)	.ident s
+#else
+#define __FBSDID(s)	/* nothing */
+#endif /* not lint and not STRIP_FBSDID */
+
+#define	WEAK_REFERENCE(sym, alias)				\
+	.weak alias;						\
+	.equ alias,sym
+
+#ifdef __STDC__
+#define	WARN_REFERENCES(_sym,_msg)				\
+	.section .gnu.warning. ## _sym ; .ascii _msg ; .text
+#else
+#define	WARN_REFERENCES(_sym,_msg)				\
+	.section .gnu.warning./**/_sym ; .ascii _msg ; .text
+#endif /* __STDC__ */
+
+#endif /* !_MACHINE_ASM_H_ */


Property changes on: trunk/sys/powerpc/include/asm.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/atomic.h
===================================================================
--- trunk/sys/powerpc/include/atomic.h	                        (rev 0)
+++ trunk/sys/powerpc/include/atomic.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,734 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Marcel Moolenaar
+ * Copyright (c) 2001 Benno Rice
+ * Copyright (c) 2001 David E. O'Brien
+ * Copyright (c) 1998 Doug Rabson
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/atomic.h 264375 2014-04-12 19:57:15Z andreast $
+ */
+
+#ifndef _MACHINE_ATOMIC_H_
+#define	_MACHINE_ATOMIC_H_
+
+#ifndef _SYS_CDEFS_H_
+#error this file needs sys/cdefs.h as a prerequisite
+#endif
+
+/*
+ * The __ATOMIC_REL/ACQ() macros provide memory barriers only in conjunction
+ * with the atomic lXarx/stXcx. sequences below. They are not exposed outside
+ * of this file. See also Appendix B.2 of Book II of the architecture manual.
+ *
+ * Note that not all Book-E processors accept the light-weight sync variant.
+ * In particular, early models of E500 cores are known to wedge. Bank on all
+ * 64-bit capable CPUs to accept lwsync properly and pressimize 32-bit CPUs
+ * to use the heavier-weight sync.
+ */
+
+#ifdef __powerpc64__
+#define mb()		__asm __volatile("lwsync" : : : "memory")
+#define rmb()		__asm __volatile("lwsync" : : : "memory")
+#define wmb()		__asm __volatile("lwsync" : : : "memory")
+#define __ATOMIC_REL()	__asm __volatile("lwsync" : : : "memory")
+#define __ATOMIC_ACQ()	__asm __volatile("isync" : : : "memory")
+#else
+#define mb()		__asm __volatile("sync" : : : "memory")
+#define rmb()		__asm __volatile("sync" : : : "memory")
+#define wmb()		__asm __volatile("sync" : : : "memory")
+#define __ATOMIC_REL()	__asm __volatile("sync" : : : "memory")
+#define __ATOMIC_ACQ()	__asm __volatile("isync" : : : "memory")
+#endif
+
+/*
+ * atomic_add(p, v)
+ * { *p += v; }
+ */
+
+#define __atomic_add_int(p, v, t)				\
+    __asm __volatile(						\
+	"1:	lwarx	%0, 0, %2\n"				\
+	"	add	%0, %3, %0\n"				\
+	"	stwcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cc", "memory")					\
+    /* __atomic_add_int */
+
+#ifdef __powerpc64__
+#define __atomic_add_long(p, v, t)				\
+    __asm __volatile(						\
+	"1:	ldarx	%0, 0, %2\n"				\
+	"	add	%0, %3, %0\n"				\
+	"	stdcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cc", "memory")					\
+    /* __atomic_add_long */
+#else
+#define	__atomic_add_long(p, v, t)				\
+    __asm __volatile(						\
+	"1:	lwarx	%0, 0, %2\n"				\
+	"	add	%0, %3, %0\n"				\
+	"	stwcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cc", "memory")					\
+    /* __atomic_add_long */
+#endif
+
+#define	_ATOMIC_ADD(type)					\
+    static __inline void					\
+    atomic_add_##type(volatile u_##type *p, u_##type v) {	\
+	u_##type t;						\
+	__atomic_add_##type(p, v, t);				\
+    }								\
+								\
+    static __inline void					\
+    atomic_add_acq_##type(volatile u_##type *p, u_##type v) {	\
+	u_##type t;						\
+	__atomic_add_##type(p, v, t);				\
+	__ATOMIC_ACQ();						\
+    }								\
+								\
+    static __inline void					\
+    atomic_add_rel_##type(volatile u_##type *p, u_##type v) {	\
+	u_##type t;						\
+	__ATOMIC_REL();						\
+	__atomic_add_##type(p, v, t);				\
+    }								\
+    /* _ATOMIC_ADD */
+
+_ATOMIC_ADD(int)
+_ATOMIC_ADD(long)
+
+#define	atomic_add_32		atomic_add_int
+#define	atomic_add_acq_32	atomic_add_acq_int
+#define	atomic_add_rel_32	atomic_add_rel_int
+
+#ifdef __powerpc64__
+#define	atomic_add_64		atomic_add_long
+#define	atomic_add_acq_64	atomic_add_acq_long
+#define	atomic_add_rel_64	atomic_add_rel_long
+
+#define	atomic_add_ptr		atomic_add_long
+#define	atomic_add_acq_ptr	atomic_add_acq_long
+#define	atomic_add_rel_ptr	atomic_add_rel_long
+#else
+#define	atomic_add_ptr		atomic_add_int
+#define	atomic_add_acq_ptr	atomic_add_acq_int
+#define	atomic_add_rel_ptr	atomic_add_rel_int
+#endif
+#undef _ATOMIC_ADD
+#undef __atomic_add_long
+#undef __atomic_add_int
+
+/*
+ * atomic_clear(p, v)
+ * { *p &= ~v; }
+ */
+
+#define __atomic_clear_int(p, v, t)				\
+    __asm __volatile(						\
+	"1:	lwarx	%0, 0, %2\n"				\
+	"	andc	%0, %0, %3\n"				\
+	"	stwcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cc", "memory")					\
+    /* __atomic_clear_int */
+
+#ifdef __powerpc64__
+#define __atomic_clear_long(p, v, t)				\
+    __asm __volatile(						\
+	"1:	ldarx	%0, 0, %2\n"				\
+	"	andc	%0, %0, %3\n"				\
+	"	stdcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cc", "memory")					\
+    /* __atomic_clear_long */
+#else
+#define	__atomic_clear_long(p, v, t)				\
+    __asm __volatile(						\
+	"1:	lwarx	%0, 0, %2\n"				\
+	"	andc	%0, %0, %3\n"				\
+	"	stwcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cc", "memory")					\
+    /* __atomic_clear_long */
+#endif
+
+#define	_ATOMIC_CLEAR(type)					\
+    static __inline void					\
+    atomic_clear_##type(volatile u_##type *p, u_##type v) {	\
+	u_##type t;						\
+	__atomic_clear_##type(p, v, t);				\
+    }								\
+								\
+    static __inline void					\
+    atomic_clear_acq_##type(volatile u_##type *p, u_##type v) {	\
+	u_##type t;						\
+	__atomic_clear_##type(p, v, t);				\
+	__ATOMIC_ACQ();						\
+    }								\
+								\
+    static __inline void					\
+    atomic_clear_rel_##type(volatile u_##type *p, u_##type v) {	\
+	u_##type t;						\
+	__ATOMIC_REL();						\
+	__atomic_clear_##type(p, v, t);				\
+    }								\
+    /* _ATOMIC_CLEAR */
+
+
+_ATOMIC_CLEAR(int)
+_ATOMIC_CLEAR(long)
+
+#define	atomic_clear_32		atomic_clear_int
+#define	atomic_clear_acq_32	atomic_clear_acq_int
+#define	atomic_clear_rel_32	atomic_clear_rel_int
+
+#ifdef __powerpc64__
+#define	atomic_clear_64		atomic_clear_long
+#define	atomic_clear_acq_64	atomic_clear_acq_long
+#define	atomic_clear_rel_64	atomic_clear_rel_long
+
+#define	atomic_clear_ptr	atomic_clear_long
+#define	atomic_clear_acq_ptr	atomic_clear_acq_long
+#define	atomic_clear_rel_ptr	atomic_clear_rel_long
+#else
+#define	atomic_clear_ptr	atomic_clear_int
+#define	atomic_clear_acq_ptr	atomic_clear_acq_int
+#define	atomic_clear_rel_ptr	atomic_clear_rel_int
+#endif
+#undef _ATOMIC_CLEAR
+#undef __atomic_clear_long
+#undef __atomic_clear_int
+
+/*
+ * atomic_cmpset(p, o, n)
+ */
+/* TODO -- see below */
+
+/*
+ * atomic_load_acq(p)
+ */
+/* TODO -- see below */
+
+/*
+ * atomic_readandclear(p)
+ */
+/* TODO -- see below */
+
+/*
+ * atomic_set(p, v)
+ * { *p |= v; }
+ */
+
+#define __atomic_set_int(p, v, t)				\
+    __asm __volatile(						\
+	"1:	lwarx	%0, 0, %2\n"				\
+	"	or	%0, %3, %0\n"				\
+	"	stwcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cc", "memory")					\
+    /* __atomic_set_int */
+
+#ifdef __powerpc64__
+#define __atomic_set_long(p, v, t)				\
+    __asm __volatile(						\
+	"1:	ldarx	%0, 0, %2\n"				\
+	"	or	%0, %3, %0\n"				\
+	"	stdcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cc", "memory")					\
+    /* __atomic_set_long */
+#else
+#define	__atomic_set_long(p, v, t)				\
+    __asm __volatile(						\
+	"1:	lwarx	%0, 0, %2\n"				\
+	"	or	%0, %3, %0\n"				\
+	"	stwcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cc", "memory")					\
+    /* __atomic_set_long */
+#endif
+
+#define	_ATOMIC_SET(type)					\
+    static __inline void					\
+    atomic_set_##type(volatile u_##type *p, u_##type v) {	\
+	u_##type t;						\
+	__atomic_set_##type(p, v, t);				\
+    }								\
+								\
+    static __inline void					\
+    atomic_set_acq_##type(volatile u_##type *p, u_##type v) {	\
+	u_##type t;						\
+	__atomic_set_##type(p, v, t);				\
+	__ATOMIC_ACQ();						\
+    }								\
+								\
+    static __inline void					\
+    atomic_set_rel_##type(volatile u_##type *p, u_##type v) {	\
+	u_##type t;						\
+	__ATOMIC_REL();						\
+	__atomic_set_##type(p, v, t);				\
+    }								\
+    /* _ATOMIC_SET */
+
+_ATOMIC_SET(int)
+_ATOMIC_SET(long)
+
+#define	atomic_set_32		atomic_set_int
+#define	atomic_set_acq_32	atomic_set_acq_int
+#define	atomic_set_rel_32	atomic_set_rel_int
+
+#ifdef __powerpc64__
+#define	atomic_set_64		atomic_set_long
+#define	atomic_set_acq_64	atomic_set_acq_long
+#define	atomic_set_rel_64	atomic_set_rel_long
+
+#define	atomic_set_ptr		atomic_set_long
+#define	atomic_set_acq_ptr	atomic_set_acq_long
+#define	atomic_set_rel_ptr	atomic_set_rel_long
+#else
+#define	atomic_set_ptr		atomic_set_int
+#define	atomic_set_acq_ptr	atomic_set_acq_int
+#define	atomic_set_rel_ptr	atomic_set_rel_int
+#endif
+#undef _ATOMIC_SET
+#undef __atomic_set_long
+#undef __atomic_set_int
+
+/*
+ * atomic_subtract(p, v)
+ * { *p -= v; }
+ */
+
+#define __atomic_subtract_int(p, v, t)				\
+    __asm __volatile(						\
+	"1:	lwarx	%0, 0, %2\n"				\
+	"	subf	%0, %3, %0\n"				\
+	"	stwcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cc", "memory")					\
+    /* __atomic_subtract_int */
+
+#ifdef __powerpc64__
+#define __atomic_subtract_long(p, v, t)				\
+    __asm __volatile(						\
+	"1:	ldarx	%0, 0, %2\n"				\
+	"	subf	%0, %3, %0\n"				\
+	"	stdcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cc", "memory")					\
+    /* __atomic_subtract_long */
+#else
+#define	__atomic_subtract_long(p, v, t)				\
+    __asm __volatile(						\
+	"1:	lwarx	%0, 0, %2\n"				\
+	"	subf	%0, %3, %0\n"				\
+	"	stwcx.	%0, 0, %2\n"				\
+	"	bne-	1b\n"					\
+	: "=&r" (t), "=m" (*p)					\
+	: "r" (p), "r" (v), "m" (*p)				\
+	: "cc", "memory")					\
+    /* __atomic_subtract_long */
+#endif
+
+#define	_ATOMIC_SUBTRACT(type)						\
+    static __inline void						\
+    atomic_subtract_##type(volatile u_##type *p, u_##type v) {		\
+	u_##type t;							\
+	__atomic_subtract_##type(p, v, t);				\
+    }									\
+									\
+    static __inline void						\
+    atomic_subtract_acq_##type(volatile u_##type *p, u_##type v) {	\
+	u_##type t;							\
+	__atomic_subtract_##type(p, v, t);				\
+	__ATOMIC_ACQ();							\
+    }									\
+									\
+    static __inline void						\
+    atomic_subtract_rel_##type(volatile u_##type *p, u_##type v) {	\
+	u_##type t;							\
+	__ATOMIC_REL();							\
+	__atomic_subtract_##type(p, v, t);				\
+    }									\
+    /* _ATOMIC_SUBTRACT */
+
+_ATOMIC_SUBTRACT(int)
+_ATOMIC_SUBTRACT(long)
+
+#define	atomic_subtract_32	atomic_subtract_int
+#define	atomic_subtract_acq_32	atomic_subtract_acq_int
+#define	atomic_subtract_rel_32	atomic_subtract_rel_int
+
+#ifdef __powerpc64__
+#define	atomic_subtract_64	atomic_subtract_long
+#define	atomic_subtract_acq_64	atomic_subract_acq_long
+#define	atomic_subtract_rel_64	atomic_subtract_rel_long
+
+#define	atomic_subtract_ptr	atomic_subtract_long
+#define	atomic_subtract_acq_ptr	atomic_subtract_acq_long
+#define	atomic_subtract_rel_ptr	atomic_subtract_rel_long
+#else
+#define	atomic_subtract_ptr	atomic_subtract_int
+#define	atomic_subtract_acq_ptr	atomic_subtract_acq_int
+#define	atomic_subtract_rel_ptr	atomic_subtract_rel_int
+#endif
+#undef _ATOMIC_SUBTRACT
+#undef __atomic_subtract_long
+#undef __atomic_subtract_int
+
+/*
+ * atomic_store_rel(p, v)
+ */
+/* TODO -- see below */
+
+/*
+ * Old/original implementations that still need revisiting.
+ */
+
+static __inline u_int
+atomic_readandclear_int(volatile u_int *addr)
+{
+	u_int result,temp;
+
+#ifdef __GNUCLIKE_ASM
+	__asm __volatile (
+		"\tsync\n"			/* drain writes */
+		"1:\tlwarx %0, 0, %3\n\t"	/* load old value */
+		"li %1, 0\n\t"			/* load new value */
+		"stwcx. %1, 0, %3\n\t"      	/* attempt to store */
+		"bne- 1b\n\t"			/* spin if failed */
+		: "=&r"(result), "=&r"(temp), "=m" (*addr)
+		: "r" (addr), "m" (*addr)
+		: "cc", "memory");
+#endif
+
+	return (result);
+}
+
+#ifdef __powerpc64__
+static __inline u_long
+atomic_readandclear_long(volatile u_long *addr)
+{
+	u_long result,temp;
+
+#ifdef __GNUCLIKE_ASM
+	__asm __volatile (
+		"\tsync\n"			/* drain writes */
+		"1:\tldarx %0, 0, %3\n\t"	/* load old value */
+		"li %1, 0\n\t"			/* load new value */
+		"stdcx. %1, 0, %3\n\t"      	/* attempt to store */
+		"bne- 1b\n\t"			/* spin if failed */
+		: "=&r"(result), "=&r"(temp), "=m" (*addr)
+		: "r" (addr), "m" (*addr)
+		: "cc", "memory");
+#endif
+
+	return (result);
+}
+#endif
+
+#define	atomic_readandclear_32		atomic_readandclear_int
+
+#ifdef __powerpc64__
+#define	atomic_readandclear_64		atomic_readandclear_long
+
+#define	atomic_readandclear_ptr		atomic_readandclear_long
+#else
+static __inline u_long
+atomic_readandclear_long(volatile u_long *addr)
+{
+
+	return ((u_long)atomic_readandclear_int((volatile u_int *)addr));
+}
+
+#define	atomic_readandclear_ptr		atomic_readandclear_int
+#endif
+
+/*
+ * We assume that a = b will do atomic loads and stores.
+ */
+#define	ATOMIC_STORE_LOAD(TYPE)					\
+static __inline u_##TYPE					\
+atomic_load_acq_##TYPE(volatile u_##TYPE *p)			\
+{								\
+	u_##TYPE v;						\
+								\
+	v = *p;							\
+	mb();							\
+	return (v);						\
+}								\
+								\
+static __inline void						\
+atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)	\
+{								\
+	mb();							\
+	*p = v;							\
+}
+
+ATOMIC_STORE_LOAD(int)
+
+#define	atomic_load_acq_32	atomic_load_acq_int
+#define	atomic_store_rel_32	atomic_store_rel_int
+
+#ifdef __powerpc64__
+ATOMIC_STORE_LOAD(long)
+
+#define	atomic_load_acq_64	atomic_load_acq_long
+#define	atomic_store_rel_64	atomic_store_rel_long
+
+#define	atomic_load_acq_ptr	atomic_load_acq_long
+#define	atomic_store_rel_ptr	atomic_store_rel_long
+#else
+static __inline u_long
+atomic_load_acq_long(volatile u_long *addr)
+{
+
+	return ((u_long)atomic_load_acq_int((volatile u_int *)addr));
+}
+
+static __inline void
+atomic_store_rel_long(volatile u_long *addr, u_long val)
+{
+
+	atomic_store_rel_int((volatile u_int *)addr, (u_int)val);
+}
+
+#define	atomic_load_acq_ptr	atomic_load_acq_int
+#define	atomic_store_rel_ptr	atomic_store_rel_int
+#endif
+#undef ATOMIC_STORE_LOAD
+
+/*
+ * Atomically compare the value stored at *p with cmpval and if the
+ * two values are equal, update the value of *p with newval. Returns
+ * zero if the compare failed, nonzero otherwise.
+ */
+static __inline int
+atomic_cmpset_int(volatile u_int* p, u_int cmpval, u_int newval)
+{
+	int	ret;
+
+#ifdef __GNUCLIKE_ASM
+	__asm __volatile (
+		"1:\tlwarx %0, 0, %2\n\t"	/* load old value */
+		"cmplw %3, %0\n\t"		/* compare */
+		"bne 2f\n\t"			/* exit if not equal */
+		"stwcx. %4, 0, %2\n\t"      	/* attempt to store */
+		"bne- 1b\n\t"			/* spin if failed */
+		"li %0, 1\n\t"			/* success - retval = 1 */
+		"b 3f\n\t"			/* we've succeeded */
+		"2:\n\t"
+		"stwcx. %0, 0, %2\n\t"       	/* clear reservation (74xx) */
+		"li %0, 0\n\t"			/* failure - retval = 0 */
+		"3:\n\t"
+		: "=&r" (ret), "=m" (*p)
+		: "r" (p), "r" (cmpval), "r" (newval), "m" (*p)
+		: "cc", "memory");
+#endif
+
+	return (ret);
+}
+static __inline int
+atomic_cmpset_long(volatile u_long* p, u_long cmpval, u_long newval)
+{
+	int ret;
+
+#ifdef __GNUCLIKE_ASM
+	__asm __volatile (
+	    #ifdef __powerpc64__
+		"1:\tldarx %0, 0, %2\n\t"	/* load old value */
+		"cmpld %3, %0\n\t"		/* compare */
+		"bne 2f\n\t"			/* exit if not equal */
+		"stdcx. %4, 0, %2\n\t"		/* attempt to store */
+	    #else
+		"1:\tlwarx %0, 0, %2\n\t"	/* load old value */
+		"cmplw %3, %0\n\t"		/* compare */
+		"bne 2f\n\t"			/* exit if not equal */
+		"stwcx. %4, 0, %2\n\t"		/* attempt to store */
+	    #endif
+		"bne- 1b\n\t"			/* spin if failed */
+		"li %0, 1\n\t"			/* success - retval = 1 */
+		"b 3f\n\t"			/* we've succeeded */
+		"2:\n\t"
+	    #ifdef __powerpc64__
+		"stdcx. %0, 0, %2\n\t"		/* clear reservation (74xx) */
+	    #else
+		"stwcx. %0, 0, %2\n\t"		/* clear reservation (74xx) */
+	    #endif
+		"li %0, 0\n\t"			/* failure - retval = 0 */
+		"3:\n\t"
+		: "=&r" (ret), "=m" (*p)
+		: "r" (p), "r" (cmpval), "r" (newval), "m" (*p)
+		: "cc", "memory");
+#endif
+
+	return (ret);
+}
+
+static __inline int
+atomic_cmpset_acq_int(volatile u_int *p, u_int cmpval, u_int newval)
+{
+	int retval;
+
+	retval = atomic_cmpset_int(p, cmpval, newval);
+	__ATOMIC_ACQ();
+	return (retval);
+}
+
+static __inline int
+atomic_cmpset_rel_int(volatile u_int *p, u_int cmpval, u_int newval)
+{
+	__ATOMIC_REL();
+	return (atomic_cmpset_int(p, cmpval, newval));
+}
+
+static __inline int
+atomic_cmpset_acq_long(volatile u_long *p, u_long cmpval, u_long newval)
+{
+	u_long retval;
+
+	retval = atomic_cmpset_long(p, cmpval, newval);
+	__ATOMIC_ACQ();
+	return (retval);
+}
+
+static __inline int
+atomic_cmpset_rel_long(volatile u_long *p, u_long cmpval, u_long newval)
+{
+	__ATOMIC_REL();
+	return (atomic_cmpset_long(p, cmpval, newval));
+}
+
+#define	atomic_cmpset_32	atomic_cmpset_int
+#define	atomic_cmpset_acq_32	atomic_cmpset_acq_int
+#define	atomic_cmpset_rel_32	atomic_cmpset_rel_int
+
+#ifdef __powerpc64__
+#define	atomic_cmpset_64	atomic_cmpset_long
+#define	atomic_cmpset_acq_64	atomic_cmpset_acq_long
+#define	atomic_cmpset_rel_64	atomic_cmpset_rel_long
+
+#define	atomic_cmpset_ptr	atomic_cmpset_long
+#define	atomic_cmpset_acq_ptr	atomic_cmpset_acq_long
+#define	atomic_cmpset_rel_ptr	atomic_cmpset_rel_long
+#else
+#define	atomic_cmpset_ptr	atomic_cmpset_int
+#define	atomic_cmpset_acq_ptr	atomic_cmpset_acq_int
+#define	atomic_cmpset_rel_ptr	atomic_cmpset_rel_int
+#endif
+
+static __inline u_int
+atomic_fetchadd_int(volatile u_int *p, u_int v)
+{
+	u_int value;
+
+	do {
+		value = *p;
+	} while (!atomic_cmpset_int(p, value, value + v));
+	return (value);
+}
+
+static __inline u_long
+atomic_fetchadd_long(volatile u_long *p, u_long v)
+{
+	u_long value;
+
+	do {
+		value = *p;
+	} while (!atomic_cmpset_long(p, value, value + v));
+	return (value);
+}
+
+static __inline u_int
+atomic_swap_32(volatile u_int *p, u_int v)
+{
+	u_int prev;
+
+	__asm __volatile(
+	"1:	lwarx	%0,0,%2\n"
+	"	stwcx.	%3,0,%2\n"
+	"	bne-	1b\n"
+	: "=&r" (prev), "+m" (*(volatile u_int *)p)
+	: "r" (p), "r" (v)
+	: "cc", "memory");
+
+	return (prev);
+}
+
+#ifdef __powerpc64__
+static __inline u_long
+atomic_swap_64(volatile u_long *p, u_long v)
+{
+	u_long prev;
+
+	__asm __volatile(
+	"1:	ldarx	%0,0,%2\n"
+	"	stdcx.	%3,0,%2\n"
+	"	bne-	1b\n"
+	: "=&r" (prev), "+m" (*(volatile u_long *)p)
+	: "r" (p), "r" (v)
+	: "cc", "memory");
+
+	return (prev);
+}
+#endif
+
+#define	atomic_fetchadd_32	atomic_fetchadd_int
+#define	atomic_swap_int		atomic_swap_32
+
+#ifdef __powerpc64__
+#define	atomic_fetchadd_64	atomic_fetchadd_long
+#define	atomic_swap_long	atomic_swap_64
+#define	atomic_swap_ptr		atomic_swap_64
+#endif
+
+#undef __ATOMIC_REL
+#undef __ATOMIC_ACQ
+
+#endif /* ! _MACHINE_ATOMIC_H_ */


Property changes on: trunk/sys/powerpc/include/atomic.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/bat.h
===================================================================
--- trunk/sys/powerpc/include/bat.h	                        (rev 0)
+++ trunk/sys/powerpc/include/bat.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,168 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+/*-
+ * 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.
+ *
+ *	$NetBSD: bat.h,v 1.2 1999/12/18 01:36:06 thorpej Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/bat.h 263687 2014-03-24 13:48:04Z emaste $
+ */
+
+#ifndef	_MACHINE_BAT_H_
+#define	_MACHINE_BAT_H_
+
+#ifndef LOCORE
+struct bat {
+	u_int32_t batu;
+	u_int32_t batl;
+};
+#endif
+
+/* Lower BAT bits (all but PowerPC 601): */
+#define	BAT_PBS		0xfffe0000	/* physical block start */
+#define	BAT_W		0x00000040	/* 1 = write-through, 0 = write-back */
+#define	BAT_I		0x00000020	/* cache inhibit */
+#define	BAT_M		0x00000010	/* memory coherency enable */
+#define	BAT_G		0x00000008	/* guarded region */
+
+#define	BAT_PP_NONE	0x00000000	/* no access permission */
+#define	BAT_PP_RO_S	0x00000001	/* read-only (soft) */
+#define	BAT_PP_RW	0x00000002	/* read/write */
+#define	BAT_PP_RO	0x00000003	/* read-only */
+
+/* Upper BAT bits (all but PowerPC 601): */
+#define	BAT_EBS		0xfffe0000	/* effective block start */
+#define	BAT_BL		0x00001ffc	/* block length */
+#define	BAT_Vs		0x00000002	/* valid in supervisor mode */
+#define	BAT_Vu		0x00000001	/* valid in user mode */
+
+#define	BAT_V		(BAT_Vs|BAT_Vu)
+
+/* Block Length encoding (all but PowerPC 601): */
+#define	BAT_BL_128K	0x00000000
+#define	BAT_BL_256K	0x00000004
+#define	BAT_BL_512K	0x0000000c
+#define	BAT_BL_1M	0x0000001c
+#define	BAT_BL_2M	0x0000003c
+#define	BAT_BL_4M	0x0000007c
+#define	BAT_BL_8M	0x000000fc
+#define	BAT_BL_16M	0x000001fc
+#define	BAT_BL_32M	0x000003fc
+#define	BAT_BL_64M	0x000007fc
+#define	BAT_BL_128M	0x00000ffc
+#define	BAT_BL_256M	0x00001ffc
+
+#define	BATU(va, len, v)						\
+	(((va) & BAT_EBS) | ((len) & BAT_BL) | ((v) & BAT_V))
+
+#define	BATL(pa, wimg, pp)						\
+	(((pa) & BAT_PBS) | (wimg) | (pp))
+
+
+/* Lower BAT bits (PowerPC 601): */
+#define	BAT601_PBN	0xfffe0000	/* physical block number */
+#define	BAT601_V	0x00000040	/* valid */
+#define	BAT601_BSM	0x0000003f	/* block size mask */
+
+/* Upper BAT bits (PowerPC 601): */
+#define	BAT601_BLPI	0xfffe0000	/* block logical page index */
+#define	BAT601_W	0x00000040	/* 1 = write-through, 0 = write-back */
+#define	BAT601_I	0x00000020	/* cache inhibit */
+#define	BAT601_M	0x00000010	/* memory coherency enable */
+#define	BAT601_Ks	0x00000008	/* key-supervisor */
+#define	BAT601_Ku	0x00000004	/* key-user */
+
+/*
+ * Permission bits on the PowerPC 601 are modified by the appropriate
+ * Key bit:
+ *
+ *	Key	PP	Access
+ *	0	NONE	read/write
+ *	0	RO_S	read/write
+ *	0	RW	read/write
+ *	0	RO	read-only
+ *
+ *	1	NONE	none
+ *	1	RO_S	read-only
+ *	1	RW	read/write
+ *	1	RO	read-only
+ */
+#define	BAT601_PP_NONE	0x00000000	/* no access permission */
+#define	BAT601_PP_RO_S	0x00000001	/* read-only (soft) */
+#define	BAT601_PP_RW	0x00000002	/* read/write */
+#define	BAT601_PP_RO	0x00000003	/* read-only */
+
+/* Block Size Mask encoding (PowerPC 601): */
+#define	BAT601_BSM_128K	0x00000000
+#define	BAT601_BSM_256K	0x00000001
+#define	BAT601_BSM_512K	0x00000003
+#define	BAT601_BSM_1M	0x00000007
+#define	BAT601_BSM_2M	0x0000000f
+#define	BAT601_BSM_4M	0x0000001f
+#define	BAT601_BSM_8M	0x0000003f
+
+#define	BATU601(va, wim, key, pp)					\
+	(((va) & BAT601_BLPI) | (wim) | (key) | (pp))
+
+#define	BATL601(pa, size, v)						\
+	(((pa) & BAT601_PBN) | (v) | (size))
+
+#if defined(_KERNEL) && !defined(LOCORE)
+extern struct bat battable[16];
+#endif
+
+#endif	/* _MACHINE_BAT_H_ */


Property changes on: trunk/sys/powerpc/include/bat.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/bus.h
===================================================================
--- trunk/sys/powerpc/include/bus.h	                        (rev 0)
+++ trunk/sys/powerpc/include/bus.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,461 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: bus.h,v 1.11 2003/07/28 17:35:54 thorpej Exp $	*/
+
+/*-
+ * Copyright (c) 1996, 1997, 1998, 2001 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.
+ *
+ * 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.
+ */
+
+/*-
+ * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
+ * Copyright (c) 1996 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
+ *	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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/bus.h 263687 2014-03-24 13:48:04Z emaste $
+ */
+
+#ifndef _MACHINE_BUS_H_
+#define _MACHINE_BUS_H_
+
+#include <machine/_bus.h>
+
+#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
+
+#define BUS_SPACE_MAXADDR_24BIT	0xFFFFFFUL
+#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFFUL
+#define BUS_SPACE_MAXSIZE_24BIT	0xFFFFFFUL
+#define BUS_SPACE_MAXSIZE_32BIT	0xFFFFFFFFUL
+
+#ifdef __powerpc64__
+#define BUS_SPACE_MAXADDR 	0xFFFFFFFFFFFFFFFFUL
+#define BUS_SPACE_MAXSIZE 	0xFFFFFFFFFFFFFFFFUL
+#else
+#define BUS_SPACE_MAXADDR 	0xFFFFFFFFUL
+#define BUS_SPACE_MAXSIZE 	0xFFFFFFFFUL
+#endif
+
+#define	BUS_SPACE_MAP_CACHEABLE		0x01
+#define	BUS_SPACE_MAP_LINEAR		0x02
+#define	BUS_SPACE_MAP_PREFETCHABLE     	0x04
+
+#define	BUS_SPACE_UNRESTRICTED	(~0)
+
+#define	BUS_SPACE_BARRIER_READ	0x01
+#define	BUS_SPACE_BARRIER_WRITE	0x02
+
+struct bus_space_access;
+
+struct bus_space {
+	/* mapping/unmapping */
+	int	(*bs_map)(bus_addr_t, bus_size_t, int,
+	    bus_space_handle_t *);
+	void	(*bs_unmap)(bus_size_t);
+	int	(*bs_subregion)(bus_space_handle_t, bus_size_t,
+	    bus_size_t, bus_space_handle_t *);
+
+	/* allocation/deallocation */
+	int	(*bs_alloc)(bus_addr_t, bus_addr_t, bus_size_t,
+	    bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *);
+	void	(*bs_free)(bus_space_handle_t, bus_size_t);
+
+	void	(*bs_barrier)(bus_space_handle_t, bus_size_t,
+	    bus_size_t, int);
+
+	/* Read single. */
+	uint8_t (*bs_r_1)(bus_space_handle_t, bus_size_t);
+	uint16_t (*bs_r_2)(bus_space_handle_t, bus_size_t);
+	uint32_t (*bs_r_4)(bus_space_handle_t, bus_size_t);
+	uint64_t (*bs_r_8)(bus_space_handle_t, bus_size_t);
+
+	uint16_t (*bs_r_s_2)(bus_space_handle_t, bus_size_t);
+	uint32_t (*bs_r_s_4)(bus_space_handle_t, bus_size_t);
+	uint64_t (*bs_r_s_8)(bus_space_handle_t, bus_size_t);
+
+	/* read multiple */
+	void	(*bs_rm_1)(bus_space_handle_t, bus_size_t, uint8_t *,
+	    bus_size_t);
+	void	(*bs_rm_2)(bus_space_handle_t, bus_size_t, uint16_t *,
+	    bus_size_t);
+	void	(*bs_rm_4)(bus_space_handle_t, bus_size_t, uint32_t *,
+	    bus_size_t);
+	void	(*bs_rm_8)(bus_space_handle_t, bus_size_t, uint64_t *,
+	    bus_size_t);
+
+	void	(*bs_rm_s_2)(bus_space_handle_t, bus_size_t, uint16_t *,
+	    bus_size_t);
+	void	(*bs_rm_s_4)(bus_space_handle_t, bus_size_t, uint32_t *,
+	    bus_size_t);
+	void	(*bs_rm_s_8)(bus_space_handle_t, bus_size_t, uint64_t *,
+	    bus_size_t);
+
+	/* read region */
+	void	(*bs_rr_1)(bus_space_handle_t, bus_size_t, uint8_t *,
+	    bus_size_t);
+	void	(*bs_rr_2)(bus_space_handle_t, bus_size_t, uint16_t *,
+	    bus_size_t);
+	void	(*bs_rr_4)(bus_space_handle_t, bus_size_t, uint32_t *,
+	    bus_size_t);
+	void	(*bs_rr_8)(bus_space_handle_t, bus_size_t, uint64_t *,
+	    bus_size_t);
+
+	void	(*bs_rr_s_2)(bus_space_handle_t, bus_size_t, uint16_t *,
+	    bus_size_t);
+	void	(*bs_rr_s_4)(bus_space_handle_t, bus_size_t, uint32_t *,
+	    bus_size_t);
+	void	(*bs_rr_s_8)(bus_space_handle_t, bus_size_t, uint64_t *,
+	    bus_size_t);
+
+	/* write */
+	void	(*bs_w_1)(bus_space_handle_t, bus_size_t, uint8_t);
+	void	(*bs_w_2)(bus_space_handle_t, bus_size_t, uint16_t);
+	void	(*bs_w_4)(bus_space_handle_t, bus_size_t, uint32_t);
+	void	(*bs_w_8)(bus_space_handle_t, bus_size_t, uint64_t);
+
+	void	(*bs_w_s_2)(bus_space_handle_t, bus_size_t, uint16_t);
+	void	(*bs_w_s_4)(bus_space_handle_t, bus_size_t, uint32_t);
+	void	(*bs_w_s_8)(bus_space_handle_t, bus_size_t, uint64_t);
+
+	/* write multiple */
+	void	(*bs_wm_1)(bus_space_handle_t, bus_size_t,
+	    const uint8_t *, bus_size_t);
+	void	(*bs_wm_2)(bus_space_handle_t, bus_size_t,
+	    const uint16_t *, bus_size_t);
+	void	(*bs_wm_4)(bus_space_handle_t, bus_size_t,
+	    const uint32_t *, bus_size_t);
+	void	(*bs_wm_8)(bus_space_handle_t, bus_size_t,
+	    const uint64_t *, bus_size_t);
+
+	void	(*bs_wm_s_2)(bus_space_handle_t, bus_size_t,
+	    const uint16_t *, bus_size_t);
+	void	(*bs_wm_s_4)(bus_space_handle_t, bus_size_t,
+	    const uint32_t *, bus_size_t);
+	void	(*bs_wm_s_8)(bus_space_handle_t, bus_size_t,
+	    const uint64_t *, bus_size_t);
+
+	/* write region */
+	void	(*bs_wr_1)(bus_space_handle_t, bus_size_t,
+	    const uint8_t *, bus_size_t);
+	void	(*bs_wr_2)(bus_space_handle_t, bus_size_t,
+	    const uint16_t *, bus_size_t);
+	void	(*bs_wr_4)(bus_space_handle_t, bus_size_t,
+	    const uint32_t *, bus_size_t);
+	void	(*bs_wr_8)(bus_space_handle_t, bus_size_t,
+	    const uint64_t *, bus_size_t);
+
+	void	(*bs_wr_s_2)(bus_space_handle_t, bus_size_t,
+	    const uint16_t *, bus_size_t);
+	void	(*bs_wr_s_4)(bus_space_handle_t, bus_size_t,
+	    const uint32_t *, bus_size_t);
+	void	(*bs_wr_s_8)(bus_space_handle_t, bus_size_t,
+	    const uint64_t *, bus_size_t);
+
+	/* set multiple */
+	void	(*bs_sm_1)(bus_space_handle_t, bus_size_t, uint8_t,
+	    bus_size_t);
+	void	(*bs_sm_2)(bus_space_handle_t, bus_size_t, uint16_t,
+	    bus_size_t);
+	void	(*bs_sm_4)(bus_space_handle_t, bus_size_t, uint32_t,
+	    bus_size_t);
+	void	(*bs_sm_8)(bus_space_handle_t, bus_size_t, uint64_t,
+	    bus_size_t);
+
+	void	(*bs_sm_s_2)(bus_space_handle_t, bus_size_t, uint16_t,
+	    bus_size_t);
+	void	(*bs_sm_s_4)(bus_space_handle_t, bus_size_t, uint32_t,
+	    bus_size_t);
+	void	(*bs_sm_s_8)(bus_space_handle_t, bus_size_t, uint64_t,
+	    bus_size_t);
+
+	/* set region */
+	void	(*bs_sr_1)(bus_space_handle_t, bus_size_t, uint8_t,
+	    bus_size_t);
+	void	(*bs_sr_2)(bus_space_handle_t, bus_size_t, uint16_t,
+	    bus_size_t);
+	void	(*bs_sr_4)(bus_space_handle_t, bus_size_t, uint32_t,
+	    bus_size_t);
+	void	(*bs_sr_8)(bus_space_handle_t, bus_size_t, uint64_t,
+	    bus_size_t);
+
+	void	(*bs_sr_s_2)(bus_space_handle_t, bus_size_t, uint16_t,
+	    bus_size_t);
+	void	(*bs_sr_s_4)(bus_space_handle_t, bus_size_t, uint32_t,
+	    bus_size_t);
+	void	(*bs_sr_s_8)(bus_space_handle_t, bus_size_t, uint64_t,
+	    bus_size_t);
+
+	/* copy region */
+	void	(*bs_cr_1)(bus_space_handle_t, bus_size_t,
+	    bus_space_handle_t, bus_size_t, bus_size_t);
+	void	(*bs_cr_2)(bus_space_handle_t, bus_size_t,
+	    bus_space_handle_t, bus_size_t, bus_size_t);
+	void	(*bs_cr_4)(bus_space_handle_t, bus_size_t,
+	    bus_space_handle_t, bus_size_t, bus_size_t);
+	void	(*bs_cr_8)(bus_space_handle_t, bus_size_t,
+	    bus_space_handle_t, bus_size_t, bus_size_t);
+
+	void	(*bs_cr_s_2)(bus_space_handle_t, bus_size_t,
+	    bus_space_handle_t, bus_size_t, bus_size_t);
+	void	(*bs_cr_s_4)(bus_space_handle_t, bus_size_t,
+	    bus_space_handle_t, bus_size_t, bus_size_t);
+	void	(*bs_cr_s_8)(bus_space_handle_t, bus_size_t,
+	    bus_space_handle_t, bus_size_t, bus_size_t);
+};
+
+extern struct bus_space bs_be_tag;
+extern struct bus_space bs_le_tag;
+
+#define	__bs_c(a,b)		__CONCAT(a,b)
+#define	__bs_opname(op,size)	__bs_c(__bs_c(__bs_c(bs_,op),_),size)
+
+#define	__bs_rs(sz, t, h, o)						\
+	(*(t)->__bs_opname(r,sz))(h, o)
+#define	__bs_ws(sz, t, h, o, v)				\
+	(*(t)->__bs_opname(w,sz))(h, o, v)
+#define	__bs_nonsingle(type, sz, t, h, o, a, c)				\
+	(*(t)->__bs_opname(type,sz))(h, o, a, c)
+#define	__bs_set(type, sz, t, h, o, v, c)				\
+	(*(t)->__bs_opname(type,sz))(h, o, v, c)
+#define	__bs_copy(sz, t, h1, o1, h2, o2, cnt)				\
+	(*(t)->__bs_opname(c,sz))(h1, o1, h2, o2, cnt)
+
+/*
+ * Mapping and unmapping operations.
+ */
+#define bus_space_map(t, a, s, c, hp) (*(t)->bs_map)(a, s, c, hp)
+#define bus_space_unmap(t, h, s)	(*(t)->bs_unmap)(h, s)
+#define	bus_space_subregion(t, h, o, s, hp)	(*(t)->bs_subregion)(h, o, s, hp)
+
+/*
+ * Allocation and deallocation operations.
+ */
+#define	bus_space_alloc(t, rs, re, s, a, b, c, ap, hp)	\
+	(*(t)->bs_alloc)(rs, re, s, a, b, c, ap, hp)
+#define	bus_space_free(t, h, s)				\
+	(*(t)->bs_free)(h, s)
+
+/*
+ * Bus barrier operations.
+ */
+#define	bus_space_barrier(t, h, o, l, f)	(*(t)->bs_barrier)(h, o, l, f)
+
+/*
+ * Bus read (single) operations.
+ */
+#define	bus_space_read_1(t, h, o)	__bs_rs(1,t,h,o)
+#define	bus_space_read_2(t, h, o)	__bs_rs(2,t,h,o)
+#define	bus_space_read_4(t, h, o)	__bs_rs(4,t,h,o)
+#define	bus_space_read_8(t, h, o)	__bs_rs(8,t,h,o)
+
+#define bus_space_read_stream_1 bus_space_read_1
+#define	bus_space_read_stream_2(t, h, o)	__bs_rs(s_2,t,h,o)
+#define	bus_space_read_stream_4(t, h, o)	__bs_rs(s_4,t,h,o)
+#define	bus_space_read_stream_8(t, h, o)	__bs_rs(s_8,t,h,o)
+
+/*
+ * Bus read multiple operations.
+ */
+#define	bus_space_read_multi_1(t, h, o, a, c)				\
+	__bs_nonsingle(rm,1,(t),(h),(o),(a),(c))
+#define	bus_space_read_multi_2(t, h, o, a, c)				\
+	__bs_nonsingle(rm,2,(t),(h),(o),(a),(c))
+#define	bus_space_read_multi_4(t, h, o, a, c)				\
+	__bs_nonsingle(rm,4,(t),(h),(o),(a),(c))
+#define	bus_space_read_multi_8(t, h, o, a, c)				\
+	__bs_nonsingle(rm,8,(t),(h),(o),(a),(c))
+
+#define bus_space_read_multi_stream_1 bus_space_read_multi_1
+#define	bus_space_read_multi_stream_2(t, h, o, a, c)			\
+	__bs_nonsingle(rm,s_2,(t),(h),(o),(a),(c))
+#define	bus_space_read_multi_stream_4(t, h, o, a, c)			\
+	__bs_nonsingle(rm,s_4,(t),(h),(o),(a),(c))
+#define	bus_space_read_multi_stream_8(t, h, o, a, c)			\
+	__bs_nonsingle(rm,s_8,(t),(h),(o),(a),(c))
+
+/*
+ * Bus read region operations.
+ */
+#define	bus_space_read_region_1(t, h, o, a, c)				\
+	__bs_nonsingle(rr,1,(t),(h),(o),(a),(c))
+#define	bus_space_read_region_2(t, h, o, a, c)				\
+	__bs_nonsingle(rr,2,(t),(h),(o),(a),(c))
+#define	bus_space_read_region_4(t, h, o, a, c)				\
+	__bs_nonsingle(rr,4,(t),(h),(o),(a),(c))
+#define	bus_space_read_region_8(t, h, o, a, c)				\
+	__bs_nonsingle(rr,8,(t),(h),(o),(a),(c))
+
+#define bus_space_read_region_stream_1 bus_space_read_region_1
+#define	bus_space_read_region_stream_2(t, h, o, a, c)			\
+	__bs_nonsingle(rr,s_2,(t),(h),(o),(a),(c))
+#define	bus_space_read_region_stream_4(t, h, o, a, c)			\
+	__bs_nonsingle(rr,s_4,(t),(h),(o),(a),(c))
+#define	bus_space_read_region_stream_8(t, h, o, a, c)			\
+	__bs_nonsingle(rr,s_8,(t),(h),(o),(a),(c))
+
+/*
+ * Bus write (single) operations.
+ */
+#define	bus_space_write_1(t, h, o, v)	__bs_ws(1,(t),(h),(o),(v))
+#define	bus_space_write_2(t, h, o, v)	__bs_ws(2,(t),(h),(o),(v))
+#define	bus_space_write_4(t, h, o, v)	__bs_ws(4,(t),(h),(o),(v))
+#define	bus_space_write_8(t, h, o, v)	__bs_ws(8,(t),(h),(o),(v))
+
+#define bus_space_write_stream_1 bus_space_write_1
+#define	bus_space_write_stream_2(t, h, o, v)	__bs_ws(s_2,(t),(h),(o),(v))
+#define	bus_space_write_stream_4(t, h, o, v)	__bs_ws(s_4,(t),(h),(o),(v))
+#define	bus_space_write_stream_8(t, h, o, v)	__bs_ws(s_8,(t),(h),(o),(v))
+
+/*
+ * Bus write multiple operations.
+ */
+#define	bus_space_write_multi_1(t, h, o, a, c)				\
+	__bs_nonsingle(wm,1,(t),(h),(o),(a),(c))
+#define	bus_space_write_multi_2(t, h, o, a, c)				\
+	__bs_nonsingle(wm,2,(t),(h),(o),(a),(c))
+#define	bus_space_write_multi_4(t, h, o, a, c)				\
+	__bs_nonsingle(wm,4,(t),(h),(o),(a),(c))
+#define	bus_space_write_multi_8(t, h, o, a, c)				\
+	__bs_nonsingle(wm,8,(t),(h),(o),(a),(c))
+
+#define bus_space_write_multi_stream_1 bus_space_write_multi_1
+#define	bus_space_write_multi_stream_2(t, h, o, a, c)			\
+	__bs_nonsingle(wm,s_2,(t),(h),(o),(a),(c))
+#define	bus_space_write_multi_stream_4(t, h, o, a, c)			\
+	__bs_nonsingle(wm,s_4,(t),(h),(o),(a),(c))
+#define	bus_space_write_multi_stream_8(t, h, o, a, c)			\
+	__bs_nonsingle(wm,s_8,(t),(h),(o),(a),(c))
+
+/*
+ * Bus write region operations.
+ */
+#define	bus_space_write_region_1(t, h, o, a, c)				\
+	__bs_nonsingle(wr,1,(t),(h),(o),(a),(c))
+#define	bus_space_write_region_2(t, h, o, a, c)				\
+	__bs_nonsingle(wr,2,(t),(h),(o),(a),(c))
+#define	bus_space_write_region_4(t, h, o, a, c)				\
+	__bs_nonsingle(wr,4,(t),(h),(o),(a),(c))
+#define	bus_space_write_region_8(t, h, o, a, c)				\
+	__bs_nonsingle(wr,8,(t),(h),(o),(a),(c))
+
+#define bus_space_write_region_stream_1 bus_space_write_region_1
+#define	bus_space_write_region_stream_2(t, h, o, a, c)			\
+	__bs_nonsingle(wr,s_2,(t),(h),(o),(a),(c))
+#define	bus_space_write_region_stream_4(t, h, o, a, c)			\
+	__bs_nonsingle(wr,s_4,(t),(h),(o),(a),(c))
+#define	bus_space_write_region_stream_8(t, h, o, a, c)			\
+	__bs_nonsingle(wr,s_8,(t),(h),(o),(a),(c))
+
+/*
+ * Set multiple operations.
+ */
+#define	bus_space_set_multi_1(t, h, o, v, c)				\
+	__bs_set(sm,1,(t),(h),(o),(v),(c))
+#define	bus_space_set_multi_2(t, h, o, v, c)				\
+	__bs_set(sm,2,(t),(h),(o),(v),(c))
+#define	bus_space_set_multi_4(t, h, o, v, c)				\
+	__bs_set(sm,4,(t),(h),(o),(v),(c))
+#define	bus_space_set_multi_8(t, h, o, v, c)				\
+	__bs_set(sm,8,(t),(h),(o),(v),(c))
+
+#define bus_space_set_multi_stream_1 bus_space_set_multi_1
+#define	bus_space_set_multi_stream_2(t, h, o, v, c)			\
+	__bs_set(sm,s_2,(t),(h),(o),(v),(c))
+#define	bus_space_set_multi_stream_4(t, h, o, v, c)			\
+	__bs_set(sm,s_4,(t),(h),(o),(v),(c))
+#define	bus_space_set_multi_stream_8(t, h, o, v, c)			\
+	__bs_set(sm,s_8,(t),(h),(o),(v),(c))
+
+/*
+ * Set region operations.
+ */
+#define	bus_space_set_region_1(t, h, o, v, c)				\
+	__bs_set(sr,1,(t),(h),(o),(v),(c))
+#define	bus_space_set_region_2(t, h, o, v, c)				\
+	__bs_set(sr,2,(t),(h),(o),(v),(c))
+#define	bus_space_set_region_4(t, h, o, v, c)				\
+	__bs_set(sr,4,(t),(h),(o),(v),(c))
+#define	bus_space_set_region_8(t, h, o, v, c)				\
+	__bs_set(sr,8,(t),(h),(o),(v),(c))
+
+#define bus_space_set_region_stream_1 bus_space_set_region_1
+#define	bus_space_set_region_stream_2(t, h, o, v, c)			\
+	__bs_set(sr,s_2,(t),(h),(o),(v),(c))
+#define	bus_space_set_region_stream_4(t, h, o, v, c)			\
+	__bs_set(sr,s_4,(t),(h),(o),(v),(c))
+#define	bus_space_set_region_stream_8(t, h, o, v, c)			\
+	__bs_set(sr,s_8,(t),(h),(o),(v),(c))
+
+#if 0
+/*
+ * Copy operations.
+ */
+#define	bus_space_copy_region_1(t, h1, o1, h2, o2, c)				\
+	__bs_copy(1, t, h1, o1, h2, o2, c)
+#define	bus_space_copy_region_2(t, h1, o1, h2, o2, c)				\
+	__bs_copy(2, t, h1, o1, h2, o2, c)
+#define	bus_space_copy_region_4(t, h1, o1, h2, o2, c)				\
+	__bs_copy(4, t, h1, o1, h2, o2, c)
+#define	bus_space_copy_region_8(t, h1, o1, h2, o2, c)				\
+	__bs_copy(8, t, h1, o1, h2, o2, c)
+
+#define bus_space_copy_region_stream_1 bus_space_copy_region_1
+#define	bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c)			\
+	__bs_copy(s_2, t, h1, o1, h2, o2, c)
+#define	bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c)			\
+	__bs_copy(s_4, t, h1, o1, h2, o2, c)
+#define	bus_space_copy_region_stream_8(t, h1, o1, h2, o2, c)			\
+	__bs_copy(s_8, t, h1, o1, h2, o2, c)
+#endif
+
+#include <machine/bus_dma.h>
+
+#endif /* _MACHINE_BUS_H_ */


Property changes on: trunk/sys/powerpc/include/bus.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/bus_dma.h
===================================================================
--- trunk/sys/powerpc/include/bus_dma.h	                        (rev 0)
+++ trunk/sys/powerpc/include/bus_dma.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,38 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Scott Long
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+/* $FreeBSD: stable/10/sys/powerpc/include/bus_dma.h 216154 2010-12-03 16:37:37Z nwhitehorn $ */
+
+#ifndef _POWERPC_BUS_DMA_H_
+#define _POWERPC_BUS_DMA_H_
+
+#include <sys/bus_dma.h>
+
+struct device;
+
+int bus_dma_tag_set_iommu(bus_dma_tag_t, struct device *iommu, void *cookie);
+
+#endif /* _POWERPC_BUS_DMA_H_ */


Property changes on: trunk/sys/powerpc/include/bus_dma.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/clock.h
===================================================================
--- trunk/sys/powerpc/include/clock.h	                        (rev 0)
+++ trunk/sys/powerpc/include/clock.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,21 @@
+/* $MidnightBSD$ */
+/*-
+ * Kernel interface to machine-dependent clock driver.
+ * Garrett Wollman, September 1994.
+ * This file is in the public domain.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/clock.h 177642 2008-03-26 20:09:21Z phk $
+ */
+
+#ifndef _MACHINE_CLOCK_H_
+#define	_MACHINE_CLOCK_H_
+
+#ifdef _KERNEL
+
+struct trapframe;
+
+void	decr_intr(struct trapframe *);
+
+#endif
+
+#endif /* !_MACHINE_CLOCK_H_ */


Property changes on: trunk/sys/powerpc/include/clock.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/counter.h
===================================================================
--- trunk/sys/powerpc/include/counter.h	                        (rev 0)
+++ trunk/sys/powerpc/include/counter.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,163 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012, 2013 Konstantin Belousov <kib at FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/counter.h 266004 2014-05-14 04:42:38Z ian $
+ */
+
+#ifndef __MACHINE_COUNTER_H__
+#define __MACHINE_COUNTER_H__
+
+#include <sys/pcpu.h>
+#ifdef INVARIANTS
+#include <sys/proc.h>
+#endif
+
+#ifdef __powerpc64__
+
+#define	counter_enter()	do {} while (0)
+#define	counter_exit()	do {} while (0)
+
+#ifdef IN_SUBR_COUNTER_C
+static inline uint64_t
+counter_u64_read_one(uint64_t *p, int cpu)
+{
+
+	return (*(uint64_t *)((char *)p + sizeof(struct pcpu) * cpu));
+}
+
+static inline uint64_t
+counter_u64_fetch_inline(uint64_t *p)
+{
+	uint64_t r;
+	int i;
+
+	r = 0;
+	for (i = 0; i < mp_ncpus; i++)
+		r += counter_u64_read_one((uint64_t *)p, i);
+
+	return (r);
+}
+
+static void
+counter_u64_zero_one_cpu(void *arg)
+{
+
+	*((uint64_t *)((char *)arg + sizeof(struct pcpu) *
+	    PCPU_GET(cpuid))) = 0;
+}
+
+static inline void
+counter_u64_zero_inline(counter_u64_t c)
+{
+
+	smp_rendezvous(smp_no_rendevous_barrier, counter_u64_zero_one_cpu,
+	    smp_no_rendevous_barrier, c);
+}
+#endif
+
+#define	counter_u64_add_protected(c, i)	counter_u64_add(c, i)
+
+extern struct pcpu __pcpu[MAXCPU];
+
+static inline void
+counter_u64_add(counter_u64_t c, int64_t inc)
+{
+	uint64_t ccpu, old;
+
+	__asm __volatile("\n"
+      "1:\n\t"
+	    "mfsprg	%0, 0\n\t"
+	    "ldarx	%1, %0, %2\n\t"
+	    "add	%1, %1, %3\n\t"
+	    "stdcx.	%1, %0, %2\n\t"
+	    "bne-	1b"
+	    : "=&b" (ccpu), "=&r" (old)
+	    : "r" ((char *)c - (char *)&__pcpu[0]), "r" (inc)
+	    : "cc", "memory");
+}
+
+#else	/* !64bit */
+
+#define	counter_enter()	critical_enter()
+#define	counter_exit()	critical_exit()
+
+#ifdef IN_SUBR_COUNTER_C
+/* XXXKIB non-atomic 64bit read */
+static inline uint64_t
+counter_u64_read_one(uint64_t *p, int cpu)
+{
+
+	return (*(uint64_t *)((char *)p + sizeof(struct pcpu) * cpu));
+}
+
+static inline uint64_t
+counter_u64_fetch_inline(uint64_t *p)
+{
+	uint64_t r;
+	int i;
+
+	r = 0;
+	for (i = 0; i < mp_ncpus; i++)
+		r += counter_u64_read_one((uint64_t *)p, i);
+
+	return (r);
+}
+
+/* XXXKIB non-atomic 64bit store, might interrupt increment */
+static void
+counter_u64_zero_one_cpu(void *arg)
+{
+
+	*((uint64_t *)((char *)arg + sizeof(struct pcpu) *
+	    PCPU_GET(cpuid))) = 0;
+}
+
+static inline void
+counter_u64_zero_inline(counter_u64_t c)
+{
+
+	smp_rendezvous(smp_no_rendevous_barrier, counter_u64_zero_one_cpu,
+	    smp_no_rendevous_barrier, c);
+}
+#endif
+
+#define	counter_u64_add_protected(c, inc)	do {	\
+	CRITICAL_ASSERT(curthread);			\
+	*(uint64_t *)zpcpu_get(c) += (inc);		\
+} while (0)
+
+static inline void
+counter_u64_add(counter_u64_t c, int64_t inc)
+{
+
+	counter_enter();
+	counter_u64_add_protected(c, inc);
+	counter_exit();
+}
+
+#endif	/* 64bit */
+
+#endif	/* ! __MACHINE_COUNTER_H__ */


Property changes on: trunk/sys/powerpc/include/counter.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/cpu.h
===================================================================
--- trunk/sys/powerpc/include/cpu.h	                        (rev 0)
+++ trunk/sys/powerpc/include/cpu.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,104 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 1995-1997 Wolfgang Solfrank.
+ * Copyright (C) 1995-1997 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.
+ *
+ *	$NetBSD: cpu.h,v 1.11 2000/05/26 21:19:53 thorpej Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/cpu.h 262675 2014-03-02 02:35:46Z jhibbits $
+ */
+
+#ifndef _MACHINE_CPU_H_
+#define	_MACHINE_CPU_H_
+
+#include <machine/frame.h>
+#include <machine/pcb.h>
+#include <machine/psl.h>
+
+/*
+ * CPU Feature Attributes
+ *
+ * These are defined in the PowerPC ELF ABI for the AT_HWCAP vector,
+ * and are exported to userland via the machdep.cpu_features
+ * sysctl.
+ */
+
+extern int cpu_features;
+
+#define	PPC_FEATURE_32		0x80000000	/* Always true */
+#define	PPC_FEATURE_64		0x40000000	/* Defined on a 64-bit CPU */
+#define	PPC_FEATURE_HAS_ALTIVEC	0x10000000	
+#define	PPC_FEATURE_HAS_FPU	0x08000000
+#define	PPC_FEATURE_HAS_MMU	0x04000000
+#define PPC_FEATURE_UNIFIED_CACHE 0x01000000
+
+#define	PPC_FEATURE_BITMASK						\
+	"\20"								\
+	"\040PPC32\037PPC64\035ALTIVEC\034FPU\033MMU\031UNIFIEDCACHE"
+
+#define	TRAPF_USERMODE(frame)	(((frame)->srr1 & PSL_PR) != 0)
+#define	TRAPF_PC(frame)		((frame)->srr0)
+
+#define	cpu_swapout(p)
+#define	cpu_number()		0
+
+/*
+ * CTL_MACHDEP definitions.
+ */
+#define	CPU_CACHELINE	1
+
+static __inline u_int64_t
+get_cyclecount(void)
+{
+	u_int32_t _upper, _lower;
+	u_int64_t _time;
+
+	__asm __volatile(
+		"mftb %0\n"
+		"mftbu %1"
+		: "=r" (_lower), "=r" (_upper));
+
+	_time = (u_int64_t)_upper;
+	_time = (_time << 32) + _lower;
+	return (_time);
+}
+
+#define	cpu_getstack(td)	((td)->td_frame->fixreg[1])
+#define	cpu_spinwait()		/* nothing */
+
+extern char btext[];
+extern char etext[];
+
+void	cpu_halt(void);
+void	cpu_reset(void);
+void	cpu_sleep(void);
+void	flush_disable_caches(void);
+void	fork_trampoline(void);
+void	swi_vm(void *);
+
+#endif	/* _MACHINE_CPU_H_ */


Property changes on: trunk/sys/powerpc/include/cpu.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/cpufunc.h
===================================================================
--- trunk/sys/powerpc/include/cpufunc.h	                        (rev 0)
+++ trunk/sys/powerpc/include/cpufunc.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,216 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1998 Doug Rabson
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/cpufunc.h 234589 2012-04-22 21:55:19Z nwhitehorn $
+ */
+
+#ifndef _MACHINE_CPUFUNC_H_
+#define	_MACHINE_CPUFUNC_H_
+
+#ifdef _KERNEL
+
+#include <sys/types.h>
+
+#include <machine/psl.h>
+#include <machine/spr.h>
+
+struct thread;
+
+#ifdef KDB
+void breakpoint(void);
+#else
+static __inline void
+breakpoint(void)
+{
+
+	return;
+}
+#endif
+
+/* CPU register mangling inlines */
+
+static __inline void
+mtmsr(register_t value)
+{
+
+	__asm __volatile ("mtmsr %0; isync" :: "r"(value));
+}
+
+#ifdef __powerpc64__
+static __inline void
+mtmsrd(register_t value)
+{
+
+	__asm __volatile ("mtmsrd %0; isync" :: "r"(value));
+}
+#endif
+
+static __inline register_t
+mfmsr(void)
+{
+	register_t value;
+
+	__asm __volatile ("mfmsr %0" : "=r"(value));
+
+	return (value);
+}
+
+#ifndef __powerpc64__
+static __inline void
+mtsrin(vm_offset_t va, register_t value)
+{
+
+	__asm __volatile ("mtsrin %0,%1" :: "r"(value), "r"(va));
+}
+
+static __inline register_t
+mfsrin(vm_offset_t va)
+{
+	register_t value;
+
+	__asm __volatile ("mfsrin %0,%1" : "=r"(value) : "r"(va));
+
+	return (value);
+}
+#endif
+
+static __inline register_t
+mfctrl(void)
+{
+	register_t value;
+
+	__asm __volatile ("mfspr %0,136" : "=r"(value));
+
+	return (value);
+}
+
+
+static __inline void
+mtdec(register_t value)
+{
+
+	__asm __volatile ("mtdec %0" :: "r"(value));
+}
+
+static __inline register_t
+mfdec(void)
+{
+	register_t value;
+
+	__asm __volatile ("mfdec %0" : "=r"(value));
+
+	return (value);
+}
+
+static __inline register_t
+mfpvr(void)
+{
+	register_t value;
+
+	__asm __volatile ("mfpvr %0" : "=r"(value));
+
+	return (value);
+}
+
+static __inline u_quad_t
+mftb(void)
+{
+	u_quad_t tb;
+      #ifdef __powerpc64__
+	__asm __volatile ("mftb %0" : "=r"(tb));
+      #else
+	uint32_t *tbup = (uint32_t *)&tb;
+	uint32_t *tblp = tbup + 1;
+
+	do {
+		*tbup = mfspr(TBR_TBU);
+		*tblp = mfspr(TBR_TBL);
+	} while (*tbup != mfspr(TBR_TBU));
+      #endif
+
+	return (tb);
+}
+
+static __inline void
+mttb(u_quad_t time)
+{
+
+	mtspr(TBR_TBWL, 0);
+	mtspr(TBR_TBWU, (uint32_t)(time >> 32));
+	mtspr(TBR_TBWL, (uint32_t)(time & 0xffffffff));
+}
+
+static __inline void
+eieio(void)
+{
+
+	__asm __volatile ("eieio" : : : "memory");
+}
+
+static __inline void
+isync(void)
+{
+
+	__asm __volatile ("isync" : : : "memory");
+}
+
+static __inline void
+powerpc_sync(void)
+{
+
+	__asm __volatile ("sync" : : : "memory");
+}
+
+static __inline register_t
+intr_disable(void)
+{
+	register_t msr;
+
+	msr = mfmsr();
+	mtmsr(msr & ~PSL_EE);
+	return (msr);
+}
+
+static __inline void
+intr_restore(register_t msr)
+{
+
+	mtmsr(msr);
+}
+
+static __inline struct pcpu *
+powerpc_get_pcpup(void)
+{
+	struct pcpu *ret;
+
+	__asm __volatile("mfsprg %0, 0" : "=r"(ret));
+
+	return (ret);
+}
+
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_CPUFUNC_H_ */


Property changes on: trunk/sys/powerpc/include/cpufunc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/db_machdep.h
===================================================================
--- trunk/sys/powerpc/include/db_machdep.h	                        (rev 0)
+++ trunk/sys/powerpc/include/db_machdep.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,94 @@
+/* $MidnightBSD$ */
+/*-
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution at CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ *
+ *	$OpenBSD: db_machdep.h,v 1.2 1997/03/21 00:48:48 niklas Exp $
+ *	$NetBSD: db_machdep.h,v 1.4.22.1 2000/08/05 11:10:43 wiz Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/db_machdep.h 209975 2010-07-13 05:32:19Z nwhitehorn $
+ */
+
+/*
+ * Machine-dependent defines for new kernel debugger.
+ */
+#ifndef _POWERPC_DB_MACHDEP_H_
+#define	_POWERPC_DB_MACHDEP_H_
+
+#include <vm/vm_param.h>
+#include <machine/elf.h>
+
+#define	DB_ELF_SYMBOLS
+#define	DB_ELFSIZE	__ELF_WORD_SIZE
+
+#define BYTE_MSF        (1)
+
+typedef	vm_offset_t	db_addr_t;	/* address - unsigned */
+typedef	intptr_t	db_expr_t;	/* expression - signed */
+
+#define	PC_REGS(regs)	((db_addr_t)kdb_thrctx->pcb_lr)
+
+#define	BKPT_INST	0x7C810808	/* breakpoint instruction */
+
+#define	BKPT_SIZE	(4)		/* size of breakpoint inst */
+#define	BKPT_SET(inst)	(BKPT_INST)
+
+#define db_clear_single_step	kdb_cpu_clear_singlestep
+#define db_set_single_step	kdb_cpu_set_singlestep
+
+#if 0
+#define	SR_SINGLESTEP	0x400
+#define	db_clear_single_step(regs)	((regs)->msr &= ~SR_SINGLESTEP)
+#define	db_set_single_step(regs)	((regs)->msr |=  SR_SINGLESTEP)
+#endif
+
+#define	T_BREAKPOINT	0xffff
+#define	IS_BREAKPOINT_TRAP(type, code)	((type) == T_BREAKPOINT)
+
+#define T_WATCHPOINT	0xeeee
+#ifdef T_WATCHPOINT
+#define	IS_WATCHPOINT_TRAP(type, code)	((type) == T_WATCHPOINT)
+#else
+#define	IS_WATCHPOINT_TRAP(type, code)	0
+#endif
+
+#define	M_RTS		0xfc0007fe
+#define	I_RTS		0x4c000020
+#define	M_BC		0xfc000000
+#define	I_BC		0x40000000
+#define	M_B		0xfc000000
+#define	I_B		0x50000000
+#define	M_RFI		0xfc0007fe
+#define	I_RFI		0x4c000064
+
+#define	inst_trap_return(ins)	(((ins)&M_RFI) == I_RFI)
+#define	inst_return(ins)	(((ins)&M_RTS) == I_RTS)
+#define	inst_call(ins)		(((ins)&M_BC ) == I_BC  || \
+				 ((ins)&M_B  ) == I_B )
+#define	inst_load(ins)		0
+#define	inst_store(ins)		0
+
+#define	DB_SMALL_VALUE_MAX	(0x7fffffff)
+#define	DB_SMALL_VALUE_MIN	(-0x40001)
+
+#endif	/* _POWERPC_DB_MACHDEP_H_ */


Property changes on: trunk/sys/powerpc/include/db_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/dbdma.h
===================================================================
--- trunk/sys/powerpc/include/dbdma.h	                        (rev 0)
+++ trunk/sys/powerpc/include/dbdma.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,154 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/dbdma.h 260674 2014-01-15 06:17:15Z jhibbits $
+ */
+
+#ifndef _MACHINE_DBDMA_H_
+#define _MACHINE_DBDMA_H_
+
+#include <sys/param.h>
+#include <machine/bus.h>
+
+/* 
+ * Apple's DBDMA (Descriptor-based DMA) interface is a common DMA engine
+ * used by a variety of custom Apple ASICs. It is described in the CHRP
+ * specification and in the book Macintosh Technology in the Common
+ * Hardware Reference Platform, copyright 1995 Apple Computer.
+ */
+
+/* DBDMA Command Values */
+
+enum {
+	DBDMA_OUTPUT_MORE	= 0,
+	DBDMA_OUTPUT_LAST	= 1,
+	DBDMA_INPUT_MORE	= 2,
+	DBDMA_INPUT_LAST	= 3,
+
+	DBDMA_STORE_QUAD	= 4,
+	DBDMA_LOAD_QUAD		= 5,
+	DBDMA_NOP		= 6,
+	DBDMA_STOP		= 7
+};
+
+/* These codes are for the interrupt, branch, and wait flags */
+
+enum {
+	DBDMA_NEVER		= 0,
+	DBDMA_COND_TRUE		= 1,
+	DBDMA_COND_FALSE	= 2,
+	DBDMA_ALWAYS		= 3
+};
+
+/* Channel status bits */
+#define DBDMA_STATUS_RUN    (0x01 << 15)
+#define DBDMA_STATUS_PAUSE  (0x01 << 14)
+#define DBDMA_STATUS_FLUSH  (0x01 << 13)
+#define DBDMA_STATUS_WAKE   (0x01 << 12)
+#define DBDMA_STATUS_DEAD   (0x01 << 11)
+#define DBDMA_STATUS_ACTIVE (0x01 << 10)
+
+/* Set by hardware if a branch was taken */
+#define DBDMA_STATUS_BRANCH 8
+
+struct dbdma_command;
+typedef struct dbdma_command dbdma_command_t;
+struct dbdma_channel;
+typedef struct dbdma_channel dbdma_channel_t;
+
+int dbdma_allocate_channel(struct resource *dbdma_regs, u_int offset,
+    bus_dma_tag_t parent_dma, int slots, dbdma_channel_t **chan);
+
+int dbdma_resize_channel(dbdma_channel_t *chan, int newslots);
+int dbdma_free_channel(dbdma_channel_t *chan);
+
+void dbdma_run(dbdma_channel_t *chan);
+void dbdma_stop(dbdma_channel_t *chan);
+void dbdma_reset(dbdma_channel_t *chan);
+void dbdma_set_current_cmd(dbdma_channel_t *chan, int slot);
+
+void dbdma_pause(dbdma_channel_t *chan);
+void dbdma_wake(dbdma_channel_t *chan);
+
+/*
+ * DBDMA uses a 16 bit channel control register to describe the current
+ * state of DMA on the channel. The high-order bits (8-15) contain information
+ * on the run state and are listed in the DBDMA_STATUS_* constants above. These
+ * are manipulated with the dbdma_run/stop/reset() routines above.
+ *
+ * The low order bits (0-7) are device dependent status bits. These can be set
+ * and read by both hardware and software. The mask is the set of bits to 
+ * modify; if mask is 0x03 and value is 0, the lowest order 2 bits will be
+ * zeroed.
+ */
+
+uint16_t dbdma_get_chan_status(dbdma_channel_t *chan);
+
+uint8_t dbdma_get_device_status(dbdma_channel_t *chan);
+void dbdma_set_device_status(dbdma_channel_t *chan, uint8_t mask,
+    uint8_t value);
+
+/*
+ * Each DBDMA command word has the current channel status register and the
+ * number of residual bytes (requested - actually transferred) written to it
+ * at time of command completion.
+ */
+
+uint16_t dbdma_get_cmd_status(dbdma_channel_t *chan, int slot);
+uint16_t dbdma_get_residuals(dbdma_channel_t *chan, int slot);
+
+void dbdma_clear_cmd_status(dbdma_channel_t *chan, int slot);
+
+/*
+ * The interrupt/branch/wait selector let you specify a set of values
+ * of the device dependent status bits that will cause intterupt/branch/wait
+ * conditions to be taken if the flags for these are set to one of the 
+ * DBDMA_COND_* values.
+ * 
+ * The condition is considered true if (status & mask) == value.
+ */
+
+void dbdma_set_interrupt_selector(dbdma_channel_t *chan, uint8_t mask,
+    uint8_t value);
+void dbdma_set_branch_selector(dbdma_channel_t *chan, uint8_t mask,
+    uint8_t value);
+void dbdma_set_wait_selector(dbdma_channel_t *chan, uint8_t mask,
+    uint8_t value);
+
+void dbdma_insert_command(dbdma_channel_t *chan, int slot, int command,
+    int stream, bus_addr_t data, size_t count, uint8_t interrupt,
+    uint8_t branch, uint8_t wait, uint32_t branch_slot); 
+
+void dbdma_insert_stop(dbdma_channel_t *chan, int slot);
+void dbdma_insert_nop(dbdma_channel_t *chan, int slot);
+void dbdma_insert_branch(dbdma_channel_t *chan, int slot, int to_slot);
+
+void dbdma_sync_commands(dbdma_channel_t *chan, bus_dmasync_op_t op);
+
+void dbdma_save_state(dbdma_channel_t *chan);
+void dbdma_restore_state(dbdma_channel_t *chan);
+
+#endif /* _MACHINE_DBDMA_H_ */


Property changes on: trunk/sys/powerpc/include/dbdma.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/elf.h
===================================================================
--- trunk/sys/powerpc/include/elf.h	                        (rev 0)
+++ trunk/sys/powerpc/include/elf.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,138 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 David E. O'Brien
+ * Copyright (c) 1996-1997 John D. Polstra.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/elf.h 237430 2012-06-22 06:38:31Z kib $
+ */
+
+#ifndef _MACHINE_ELF_H_
+#define	_MACHINE_ELF_H_ 1
+
+/*
+ * EABI ELF definitions for the PowerPC architecture.
+ * See "PowerPC Embedded Application Binary Interface, 32-Bit Impliementation"
+ * [ppc-eabi-1995-01.pdf] for details.
+ */
+
+#ifndef __ELF_WORD_SIZE
+#ifdef __powerpc64__
+#define	__ELF_WORD_SIZE	64	/* Used by <sys/elf_generic.h> */
+#else
+#define	__ELF_WORD_SIZE	32	/* Used by <sys/elf_generic.h> */
+#endif
+#endif
+
+#include <sys/elf32.h>	/* Definitions common to all 32 bit architectures. */
+#include <sys/elf64.h>	/* Definitions common to all 64 bit architectures. */
+#include <sys/elf_generic.h>
+
+#if __ELF_WORD_SIZE == 64
+#define	ELF_ARCH	EM_PPC64
+#define	ELF_MACHINE_OK(x) ((x) == EM_PPC64)
+#else
+#define	ELF_ARCH	EM_PPC
+#define	ELF_ARCH32	EM_PPC
+#define	ELF_MACHINE_OK(x) ((x) == EM_PPC)
+#endif
+
+/*
+ * Auxiliary vector entries for passing information to the interpreter.
+ *
+ * The PowerPC supplement to the SVR4 ABI specification names this "auxv_t",
+ * but POSIX lays claim to all symbols ending with "_t".
+ */
+
+typedef struct {	/* Auxiliary vector entry on initial stack */
+	int	a_type;			/* Entry type. */
+	union {
+		long	a_val;		/* Integer value. */
+		void	*a_ptr;		/* Address. */
+		void	(*a_fcn)(void);	/* Function pointer (not used). */
+	} a_un;
+} Elf32_Auxinfo;
+
+typedef struct {	/* Auxiliary vector entry on initial stack */
+	long	a_type;			/* Entry type. */
+	union {
+		long	a_val;		/* Integer value. */
+		void	*a_ptr;		/* Address. */
+		void	(*a_fcn)(void);	/* Function pointer (not used). */
+	} a_un;
+} Elf64_Auxinfo;
+
+__ElfType(Auxinfo);
+
+/* Values for a_type. */
+#define	AT_NULL		0	/* Terminates the vector. */
+#define	AT_IGNORE	1	/* Ignored entry. */
+#define	AT_EXECFD	2	/* File descriptor of program to load. */
+#define	AT_PHDR		3	/* Program header of program already loaded. */
+#define	AT_PHENT	4	/* Size of each program header entry. */
+#define	AT_PHNUM	5	/* Number of program header entries. */
+#define	AT_PAGESZ	6	/* Page size in bytes. */
+#define	AT_BASE		7	/* Interpreter's base address. */
+#define	AT_FLAGS	8	/* Flags (unused for PowerPC). */
+#define	AT_ENTRY	9	/* Where interpreter should transfer control. */
+#define	AT_DCACHEBSIZE	10	/* Data cache block size for the processor. */
+#define	AT_ICACHEBSIZE	11	/* Instruction cache block size for the uP. */
+#define	AT_UCACHEBSIZE	12	/* Cache block size, or `0' if cache not unified. */
+#define	AT_EXECPATH	13	/* Path to the executable. */
+#define	AT_CANARY	14	/* Canary for SSP */
+#define	AT_CANARYLEN	15	/* Length of the canary. */
+#define	AT_OSRELDATE	16	/* OSRELDATE. */
+#define	AT_NCPUS	17	/* Number of CPUs. */
+#define	AT_PAGESIZES	18	/* Pagesizes. */
+#define	AT_PAGESIZESLEN	19	/* Number of pagesizes. */
+#define	AT_STACKPROT	21	/* Initial stack protection. */
+#define	AT_TIMEKEEP	22	/* Pointer to timehands. */
+
+#define	AT_COUNT	23	/* Count of defined aux entry types. */
+
+/*
+ * Relocation types.
+ */
+
+#define	R_PPC_COUNT		37	/* Count of defined relocation types. */
+
+					/* Count of defined relocation types. */
+#define	R_PPC_EMB_COUNT		(R_PPC_EMB_RELSDA - R_PPC_EMB_NADDR32 + 1)
+
+/* Define "machine" characteristics */
+#if __ELF_WORD_SIZE == 64
+#define	ELF_TARG_CLASS	ELFCLASS64
+#define	ELF_TARG_DATA	ELFDATA2MSB
+#define	ELF_TARG_MACH	EM_PPC64
+#define	ELF_TARG_VER	1
+#else
+#define	ELF_TARG_CLASS	ELFCLASS32
+#define	ELF_TARG_DATA	ELFDATA2MSB
+#define	ELF_TARG_MACH	EM_PPC
+#define	ELF_TARG_VER	1
+#endif
+
+#define	ET_DYN_LOAD_ADDR 0x01010000
+
+#endif /* !_MACHINE_ELF_H_ */


Property changes on: trunk/sys/powerpc/include/elf.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/endian.h
===================================================================
--- trunk/sys/powerpc/include/endian.h	                        (rev 0)
+++ trunk/sys/powerpc/include/endian.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,140 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1987, 1991, 1993
+ *	The 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.
+ * 4. 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.
+ *
+ *	@(#)endian.h	8.1 (Berkeley) 6/10/93
+ * $FreeBSD: stable/10/sys/powerpc/include/endian.h 232745 2012-03-09 20:34:31Z dim $
+ */
+
+#ifndef _MACHINE_ENDIAN_H_
+#define	_MACHINE_ENDIAN_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+/*
+ * Define the order of 32-bit words in 64-bit words.
+ */
+#define	_QUAD_HIGHWORD 0
+#define	_QUAD_LOWWORD 1
+
+/*
+ * GCC defines _BIG_ENDIAN and _LITTLE_ENDIAN equal to __BIG_ENDIAN__
+ * and __LITTLE_ENDIAN__ (resp).
+ */
+#ifdef _BIG_ENDIAN
+#undef _BIG_ENDIAN
+#endif
+#ifdef _LITTLE_ENDIAN
+#undef _LITTLE_ENDIAN
+#endif
+
+/*
+ * Definitions for byte order, according to byte significance from low
+ * address to high.
+ */
+#define	_LITTLE_ENDIAN	1234	/* LSB first: i386, vax */
+#define	_BIG_ENDIAN	4321	/* MSB first: 68000, ibm, net */
+#define	_PDP_ENDIAN	3412	/* LSB first in word, MSW first in long */
+
+#ifdef __LITTLE_ENDIAN__
+#define	_BYTE_ORDER	_LITTLE_ENDIAN
+#else
+#define	_BYTE_ORDER	_BIG_ENDIAN
+#endif
+
+/*
+ * Deprecated variants that don't have enough underscores to be useful in more
+ * strict namespaces.
+ */
+#if __BSD_VISIBLE
+#define	LITTLE_ENDIAN	_LITTLE_ENDIAN
+#define	BIG_ENDIAN	_BIG_ENDIAN
+#define	PDP_ENDIAN	_PDP_ENDIAN
+#define	BYTE_ORDER	_BYTE_ORDER
+#endif
+
+#if defined(__GNUCLIKE_BUILTIN_CONSTANT_P)
+#define	__is_constant(x)	__builtin_constant_p(x)
+#else
+#define	__is_constant(x)	0
+#endif
+
+#define	__bswap16_const(x)	((((__uint16_t)(x) >> 8) & 0xff) |	\
+	(((__uint16_t)(x) << 8) & 0xff00))
+#define	__bswap32_const(x)	((((__uint32_t)(x) >> 24) & 0xff) |	\
+	(((__uint32_t)(x) >> 8) & 0xff00) |				\
+	(((__uint32_t)(x)<< 8) & 0xff0000) |				\
+	(((__uint32_t)(x) << 24) & 0xff000000))
+#define	__bswap64_const(x)	((((__uint64_t)(x) >> 56) & 0xff) |	\
+	(((__uint64_t)(x) >> 40) & 0xff00) |				\
+	(((__uint64_t)(x) >> 24) & 0xff0000) |				\
+	(((__uint64_t)(x) >> 8) & 0xff000000) |				\
+	(((__uint64_t)(x) << 8) & ((__uint64_t)0xff << 32)) |		\
+	(((__uint64_t)(x) << 24) & ((__uint64_t)0xff << 40)) |		\
+	(((__uint64_t)(x) << 40) & ((__uint64_t)0xff << 48)) |		\
+	(((__uint64_t)(x) << 56) & ((__uint64_t)0xff << 56)))
+
+static __inline __uint16_t
+__bswap16_var(__uint16_t _x)
+{
+
+	return ((_x >> 8) | ((_x << 8) & 0xff00));
+}
+
+static __inline __uint32_t
+__bswap32_var(__uint32_t _x)
+{
+
+	return ((_x >> 24) | ((_x >> 8) & 0xff00) | ((_x << 8) & 0xff0000) |
+	    ((_x << 24) & 0xff000000));
+}
+
+static __inline __uint64_t
+__bswap64_var(__uint64_t _x)
+{
+
+	return ((_x >> 56) | ((_x >> 40) & 0xff00) | ((_x >> 24) & 0xff0000) |
+	    ((_x >> 8) & 0xff000000) | ((_x << 8) & ((__uint64_t)0xff << 32)) |
+	    ((_x << 24) & ((__uint64_t)0xff << 40)) |
+	    ((_x << 40) & ((__uint64_t)0xff << 48)) | ((_x << 56)));
+}
+
+#define	__bswap16(x)	((__uint16_t)(__is_constant(x) ? __bswap16_const(x) : \
+	__bswap16_var(x)))
+#define	__bswap32(x)	(__is_constant(x) ? __bswap32_const(x) : \
+	__bswap32_var(x))
+#define	__bswap64(x)	(__is_constant(x) ? __bswap64_const(x) : \
+	__bswap64_var(x))
+
+#define	__htonl(x)	((__uint32_t)(x))
+#define	__htons(x)	((__uint16_t)(x))
+#define	__ntohl(x)	((__uint32_t)(x))
+#define	__ntohs(x)	((__uint16_t)(x))
+
+#endif /* !_MACHINE_ENDIAN_H_ */


Property changes on: trunk/sys/powerpc/include/endian.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/exec.h
===================================================================
--- trunk/sys/powerpc/include/exec.h	                        (rev 0)
+++ trunk/sys/powerpc/include/exec.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,38 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 David E. O'Brien
+ * 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 author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/exec.h 142107 2005-02-19 21:16:48Z ru $
+ */
+
+#ifndef	_MACHINE_EXEC_H_
+#define	_MACHINE_EXEC_H_
+
+#define	__LDPGSZ	4096
+
+#endif /* !_MACHINE_EXEC_H_ */


Property changes on: trunk/sys/powerpc/include/exec.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/float.h
===================================================================
--- trunk/sys/powerpc/include/float.h	                        (rev 0)
+++ trunk/sys/powerpc/include/float.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,100 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1989 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.
+ * 4. 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.
+ *
+ *	from: @(#)float.h	7.1 (Berkeley) 5/8/90
+ *	from: FreeBSD: src/sys/i386/include/float.h,v 1.8 1999/08/28 00:44:11
+ * $FreeBSD: stable/10/sys/powerpc/include/float.h 230475 2012-01-23 06:36:41Z das $
+ */
+
+#ifndef _MACHINE_FLOAT_H_
+#define _MACHINE_FLOAT_H_ 1
+
+#include <sys/cdefs.h>
+
+#ifndef _SOFT_FLOAT
+__BEGIN_DECLS
+extern int __flt_rounds(void);
+__END_DECLS
+#define FLT_ROUNDS	__flt_rounds()
+#else
+#define FLT_ROUNDS	(-1)
+#endif
+
+#define FLT_RADIX	2		/* b */
+#if __ISO_C_VISIBLE >= 1999
+#define	FLT_EVAL_METHOD	0
+#define	DECIMAL_DIG	17		/* max precision in decimal digits */
+#endif
+
+#define FLT_MANT_DIG	24		/* p */
+#define FLT_EPSILON	1.19209290E-07F	/* b**(1-p) */
+#define FLT_DIG		6		/* floor((p-1)*log10(b))+(b == 10) */
+#define FLT_MIN_EXP	(-125)		/* emin */
+#define FLT_MIN		1.17549435E-38F	/* b**(emin-1) */
+#define FLT_MIN_10_EXP	(-37)		/* ceil(log10(b**(emin-1))) */
+#define FLT_MAX_EXP	128		/* emax */
+#define FLT_MAX		3.40282347E+38F	/* (1-b**(-p))*b**emax */
+#define FLT_MAX_10_EXP	38		/* floor(log10((1-b**(-p))*b**emax)) */
+#if __ISO_C_VISIBLE >= 2011
+#define	FLT_TRUE_MIN	1.40129846E-45F	/* b**(emin-p) */
+#define	FLT_DECIMAL_DIG	9		/* ceil(1+p*log10(b)) */
+#define	FLT_HAS_SUBNORM	1
+#endif /* __ISO_C_VISIBLE >= 2011 */
+
+#define DBL_MANT_DIG	53
+#define DBL_EPSILON	2.2204460492503131E-16
+#define DBL_DIG		15
+#define DBL_MIN_EXP	(-1021)
+#define DBL_MIN		2.2250738585072014E-308
+#define DBL_MIN_10_EXP	(-307)
+#define DBL_MAX_EXP	1024
+#define DBL_MAX		1.7976931348623157E+308
+#define DBL_MAX_10_EXP	308
+#if __ISO_C_VISIBLE >= 2011
+#define	DBL_TRUE_MIN	4.9406564584124654E-324
+#define	DBL_DECIMAL_DIG	17
+#define	DBL_HAS_SUBNORM	1
+#endif /* __ISO_C_VISIBLE >= 2011 */
+
+#define LDBL_MANT_DIG	DBL_MANT_DIG
+#define LDBL_EPSILON	((long double)DBL_EPSILON)
+#define LDBL_DIG	DBL_DIG
+#define LDBL_MIN_EXP	DBL_MIN_EXP
+#define LDBL_MIN	((long double)DBL_MIN)
+#define LDBL_MIN_10_EXP	DBL_MIN_10_EXP
+#define LDBL_MAX_EXP	DBL_MAX_EXP
+#define LDBL_MAX	((long double)DBL_MAX)
+#define LDBL_MAX_10_EXP	DBL_MAX_10_EXP
+#if __ISO_C_VISIBLE >= 2011
+#define	LDBL_TRUE_MIN	((long double)DBL_TRUE_MIN)
+#define	LDBL_DECIMAL_DIG DBL_DECIMAL_DIG
+#define	LDBL_HAS_SUBNORM DBL_HAS_SUBNORM
+#endif /* __ISO_C_VISIBLE >= 2011 */
+
+#endif /* _MACHINE_FLOAT_H_ */


Property changes on: trunk/sys/powerpc/include/float.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/floatingpoint.h
===================================================================
--- trunk/sys/powerpc/include/floatingpoint.h	                        (rev 0)
+++ trunk/sys/powerpc/include/floatingpoint.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,38 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2004 Suleiman Souhlal <refugee at segfaulted.com>
+ * 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 author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DAVID O'BRIEN 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/floatingpoint.h 139825 2005-01-07 02:29:27Z imp $
+ */
+
+#ifndef _FLOATINGPOINT_H_
+#define _FLOATINGPOINT_H_
+
+#include <machine/ieeefp.h>
+
+#endif /* !_FLOATINGPOINT_H_ */


Property changes on: trunk/sys/powerpc/include/floatingpoint.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/fpu.h
===================================================================
--- trunk/sys/powerpc/include/fpu.h	                        (rev 0)
+++ trunk/sys/powerpc/include/fpu.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,79 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: fpu.h,v 1.2 1999/12/07 15:14:56 danw Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/fpu.h 174632 2007-12-16 00:45:56Z marcel $
+ */
+
+#ifndef	_MACHINE_FPU_H_
+#define	_MACHINE_FPU_H_
+
+#define	FPSCR_FX	0x80000000
+#define	FPSCR_FEX	0x40000000
+#define	FPSCR_VX	0x20000000
+#define	FPSCR_OX	0x10000000
+#define	FPSCR_UX	0x08000000
+#define	FPSCR_ZX	0x04000000
+#define	FPSCR_XX	0x02000000
+#define	FPSCR_VXSNAN	0x01000000
+#define	FPSCR_VXISI	0x00800000
+#define	FPSCR_VXIDI	0x00400000
+#define	FPSCR_VXZDZ	0x00200000
+#define	FPSCR_VXIMZ	0x00100000
+#define	FPSCR_VXVC	0x00080000
+#define	FPSCR_FR	0x00040000
+#define	FPSCR_FI	0x00020000
+#define	FPSCR_FPRF	0x0001f000
+#define	FPSCR_C		0x00010000
+#define	FPSCR_FPCC	0x0000f000
+#define	FPSCR_FL	0x00008000
+#define	FPSCR_FG	0x00004000
+#define	FPSCR_FE	0x00002000
+#define	FPSCR_FU	0x00001000
+#define	FPSCR_VXSOFT	0x00000400
+#define	FPSCR_VXSQRT	0x00000200
+#define	FPSCR_VXCVI	0x00000100
+#define	FPSCR_VE	0x00000080
+#define	FPSCR_OE	0x00000040
+#define	FPSCR_UE	0x00000020
+#define	FPSCR_ZE	0x00000010
+#define	FPSCR_XE	0x00000008
+#define	FPSCR_NI	0x00000004
+#define	FPSCR_RN	0x00000003
+
+#ifdef _KERNEL
+
+void    enable_fpu(struct thread *);
+void    save_fpu(struct thread *);
+
+#endif /* _KERNEL */
+
+#endif	/* _MACHINE_FPU_H_ */


Property changes on: trunk/sys/powerpc/include/fpu.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/frame.h
===================================================================
--- trunk/sys/powerpc/include/frame.h	                        (rev 0)
+++ trunk/sys/powerpc/include/frame.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,117 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: frame.h,v 1.2 1999/01/10 10:13:15 tsubai Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/frame.h 255282 2013-09-05 23:28:50Z nwhitehorn $
+ */
+
+#ifndef	_MACHINE_FRAME_H_
+#define	_MACHINE_FRAME_H_
+
+#include <sys/types.h>
+
+/*
+ * We have to save all registers on every trap, because
+ *	1. user could attach this process every time
+ *	2. we must be able to restore all user registers in case of fork
+ * Actually, we do not save the fp registers on trap, since
+ * these are not used by the kernel. They are saved only when switching
+ * between processes using the FPU.
+ *
+ * Change ordering to cluster together these register_t's.		XXX
+ */
+struct trapframe {
+	register_t fixreg[32];
+	register_t lr;
+	register_t cr;
+	register_t xer;
+	register_t ctr;
+	register_t srr0;
+	register_t srr1;
+	register_t exc;
+	union {
+		struct {
+			/* dar & dsisr are only filled on a DSI trap */
+			register_t dar;
+			register_t dsisr;
+		} aim;
+		struct {
+			register_t dear;
+			register_t esr;
+			register_t dbcr0;
+		} booke;
+	} cpu;
+};
+
+/*
+ * FRAMELEN is the size of the stack region used by the low-level trap
+ * handler. It is the size of its data (trapframe) plus the callframe
+ * header (sizeof(struct callframe) - 3 register widths). It must also
+ * be 16-byte aligned.
+ */
+#define	FRAMELEN	roundup(sizeof(struct trapframe) + \
+			    sizeof(struct callframe) - 3*sizeof(register_t), 16)
+#define	trapframe(td)	((td)->td_frame)
+
+/*
+ * Call frame for PowerPC used during fork.
+ */
+#ifdef __powerpc64__
+struct callframe {
+	register_t	cf_dummy_fp;	/* dummy frame pointer */
+	register_t	cf_cr;
+	register_t	cf_lr;
+	register_t	cf_compiler;
+	register_t	cf_linkeditor;
+	register_t	cf_toc;
+	register_t	cf_func;
+	register_t	cf_arg0;
+	register_t	cf_arg1;
+	register_t	_padding;	/* Maintain 16-byte alignment */
+};
+#else
+struct callframe {
+	register_t	cf_dummy_fp;	/* dummy frame pointer */
+	register_t	cf_lr;		/* space for link register save */
+	register_t	cf_func;
+	register_t	cf_arg0;
+	register_t	cf_arg1;
+	register_t	_padding;	/* Maintain 16-byte alignment */
+};
+#endif
+
+/* Definitions for syscalls */
+#define	FIRSTARG	3				/* first arg in reg 3 */
+#define	NARGREG		8				/* 8 args in regs */
+#define	MOREARGS(sp)	((caddr_t)((uintptr_t)(sp) + \
+    sizeof(struct callframe) - 3*sizeof(register_t))) /* more args go here */
+
+#endif	/* _MACHINE_FRAME_H_ */


Property changes on: trunk/sys/powerpc/include/frame.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/gdb_machdep.h
===================================================================
--- trunk/sys/powerpc/include/gdb_machdep.h	                        (rev 0)
+++ trunk/sys/powerpc/include/gdb_machdep.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,82 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Marcel Moolenaar
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/gdb_machdep.h 250864 2013-05-21 18:00:47Z marcel $
+ */
+
+#ifndef _MACHINE_GDB_MACHDEP_H_
+#define	_MACHINE_GDB_MACHDEP_H_
+
+#ifdef BOOKE
+#define	PPC_GDB_NREGS0	1
+#define	PPC_GDB_NREGS4	(70 + 1)
+#define	PPC_GDB_NREGS8	(1 + 32)
+#define	PPC_GDB_NREGS16	0
+#else
+#define	PPC_GDB_NREGS0	0
+#define	PPC_GDB_NREGS4	(32 + 7 + 2)
+#define	PPC_GDB_NREGS8	32
+#define	PPC_GDB_NREGS16	32
+#endif
+
+#define GDB_NREGS	(PPC_GDB_NREGS0 + PPC_GDB_NREGS4 + \
+			 PPC_GDB_NREGS8 + PPC_GDB_NREGS16)
+#define	GDB_REG_PC	64
+
+#define	GDB_BUFSZ	(PPC_GDB_NREGS4 * 8 +	\
+			 PPC_GDB_NREGS8 * 16 +	\
+			 PPC_GDB_NREGS16 * 32)
+
+static __inline size_t
+gdb_cpu_regsz(int regnum)
+{
+
+#ifdef BOOKE
+	if (regnum == 70)
+		return (0);
+	if (regnum == 71 || regnum >= 73)
+		return (8);
+#else
+	if (regnum >= 32 && regnum <= 63)
+		return (8);
+	if (regnum >= 71 && regnum <= 102)
+		return (16);
+#endif
+	return (4);
+}
+
+static __inline int
+gdb_cpu_query(void)
+{
+
+	return (0);
+}
+
+void *gdb_cpu_getreg(int, size_t *);
+void gdb_cpu_setreg(int, void *);
+int gdb_cpu_signal(int, int);
+
+#endif /* !_MACHINE_GDB_MACHDEP_H_ */


Property changes on: trunk/sys/powerpc/include/gdb_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/hid.h
===================================================================
--- trunk/sys/powerpc/include/hid.h	                        (rev 0)
+++ trunk/sys/powerpc/include/hid.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,221 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2000 Tsubai Masanari.  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. 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.
+ *
+ * $NetBSD: hid.h,v 1.2 2001/08/22 21:05:25 matt Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/hid.h 236025 2012-05-25 21:12:24Z raj $
+ */
+
+#ifndef _POWERPC_HID_H_
+#define _POWERPC_HID_H_
+
+/* Hardware Implementation Dependent registers for the PowerPC */
+
+#define HID0_EMCP	0x80000000  /* Enable machine check pin */
+#define HID0_DBP	0x40000000  /* Disable 60x bus parity generation */
+#define HID0_EBA	0x20000000  /* Enable 60x bus address parity checking */
+#define HID0_EBD	0x10000000  /* Enable 60x bus data parity checking */
+#define HID0_BCLK	0x08000000  /* CLK_OUT clock type selection */
+#define HID0_EICE	0x04000000  /* Enable ICE output */
+#define HID0_ECLK	0x02000000  /* CLK_OUT clock type selection */
+#define HID0_PAR	0x01000000  /* Disable precharge of ARTRY */
+#define HID0_STEN	0x01000000  /* Software table search enable (7450) */
+#define HID0_DEEPNAP	0x01000000  /* Enable deep nap mode (970) */
+#define HID0_HBATEN	0x00800000  /* High BAT enable (74[45][578])  */
+#define HID0_DOZE	0x00800000  /* Enable doze mode */
+#define HID0_NAP	0x00400000  /* Enable nap mode */
+#define HID0_SLEEP	0x00200000  /* Enable sleep mode */
+#define HID0_DPM	0x00100000  /* Enable Dynamic power management */
+#define HID0_RISEG	0x00080000  /* Read I-SEG */
+#define HID0_TG		0x00040000  /* Timebase Granularity (OEA64) */
+#define HID0_BHTCLR	0x00040000  /* Clear branch history table (7450) */
+#define HID0_EIEC	0x00040000  /* Enable internal error checking */
+#define HID0_XAEN	0x00020000  /* Enable eXtended Addressing (7450) */
+#define HID0_NHR	0x00010000  /* Not hard reset */
+#define HID0_ICE	0x00008000  /* Enable i-cache */
+#define HID0_DCE	0x00004000  /* Enable d-cache */
+#define HID0_ILOCK	0x00002000  /* i-cache lock */
+#define HID0_DLOCK	0x00001000  /* d-cache lock */
+#define HID0_ICFI	0x00000800  /* i-cache flush invalidate */
+#define HID0_DCFI	0x00000400  /* d-cache flush invalidate */
+#define HID0_SPD	0x00000200  /* Disable speculative cache access */
+#define HID0_XBSEN	0x00000100  /* Extended BAT block-size enable (7457) */
+#define HID0_IFEM	0x00000100  /* Enable M-bit for I-fetch */
+#define HID0_XBSEN	0x00000100  /* Extended BAT block size enable (7455+)*/
+#define HID0_SGE	0x00000080  /* Enable store gathering */
+#define HID0_DCFA	0x00000040  /* Data cache flush assist */
+#define HID0_BTIC	0x00000020  /* Enable BTIC */
+#define HID0_LRSTK	0x00000010  /* Link register stack enable (7450) */
+#define HID0_ABE	0x00000008  /* Enable address broadcast */
+#define HID0_FOLD	0x00000008  /* Branch folding enable (7450) */
+#define HID0_BHT	0x00000004  /* Enable branch history table */
+#define HID0_NOPTI	0x00000001  /* No-op the dcbt(st) */
+
+#define HID0_AIM_TBEN	0x04000000  /* Time base enable (7450) */
+
+#define HID0_E500_TBEN		0x00004000 /* Time Base and decr. enable */
+#define HID0_E500_SEL_TBCLK	0x00002000 /* Select Time Base clock */
+#define HID0_E500_MAS7UPDEN	0x00000080 /* Enable MAS7 update (e500v2) */
+
+#define HID0_E500MC_L2MMU_MHD	0x40000000 /* L2MMU Multiple Hit Detection */
+
+#define HID0_BITMASK							\
+    "\20"								\
+    "\040EMCP\037DBP\036EBA\035EBD\034BCLK\033EICE\032ECLK\031PAR"	\
+    "\030DOZE\027NAP\026SLEEP\025DPM\024RISEG\023EIEC\022res\021NHR"	\
+    "\020ICE\017DCE\016ILOCK\015DLOCK\014ICFI\013DCFI\012SPD\011IFEM"	\
+    "\010SGE\007DCFA\006BTIC\005FBIOB\004ABE\003BHT\002NOPDST\001NOPTI"
+
+#define HID0_7450_BITMASK						\
+    "\20"								\
+    "\040EMCP\037b1\036b2\035b3\034b4\033TBEN\032b6\031STEN"		\
+    "\030HBATEN\027NAP\026SLEEP\025DPM\024b12\023BHTCLR\022XAEN\021NHR"	\
+    "\020ICE\017DCE\016ILOCK\015DLOCK\014ICFI\013DCFI\012SPD\011XBSEN"	\
+    "\010SGE\007b25\006BTIC\005LRSTK\004FOLD\003BHT\002NOPDST\001NOPTI"
+
+#define HID0_E500_BITMASK						\
+    "\20"								\
+    "\040EMCP\037b1\036b2\035b3\034b4\033b5\032b6\031b7"		\
+    "\030DOZE\027NAP\026SLEEP\025b11\024b12\023b13\022b14\021b15"	\
+    "\020b16\017TBEN\016SEL_TBCLK\015b19\014b20\013b21\012b22\011b23"	\
+    "\010EN_MAS7_UPDATE\007DCFA\006b26\005b27\004b28\003b29\002b30\001NOPTI"
+
+#define HID0_970_BITMASK						\
+    "\20"								\
+    "\040ONEPPC\037SINGLE\036ISYNCSC\035SERGP\031DEEPNAP\030DOZE"	\
+    "\027NAP\025DPM\023TG\022HANGDETECT\021NHR\020INORDER"		\
+    "\016TBCTRL\015TBEN\012CIABREN\011HDICEEN\001ENATTN"		
+
+#define HID0_E500MC_BITMASK						\
+    "\20"								\
+    "\040EMCP\037EN_L2MMU_MHD\036b2\035b3\034b4\033b5\032b6\031b7"	\
+    "\030b8\027b9\026b10\025b11\024b12\023b13\022b14\021b15"		\
+    "\020b16\017b17\016b18\015b19\014b20\013b21\012b22\011b23"		\
+    "\010EN_MAS7_UPDATE\007DCFA\006b26\005CIGLSO\004b28\003b29\002b30\001NOPTI"
+
+#define HID0_E5500_BITMASK						\
+    "\20"								\
+    "\040EMCP\037EN_L2MMU_MHD\036b2\035b3\034b4\033b5\032b6\031b7"	\
+    "\030b8\027b9\026b10\025b11\024b12\023b13\022b14\021b15"		\
+    "\020b16\017b17\016b18\015b19\014b20\013b21\012b22\011b23"		\
+    "\010b24\007DCFA\006b26\005CIGLSO\004b28\003b29\002b30\001NOPTI"
+
+/*
+ *  HID0 bit definitions per cpu model
+ *
+ * bit	603	604	750	7400	7410	7450	7457	e500
+ *   0	EMCP	EMCP	EMCP	EMCP	EMCP	-	-	EMCP
+ *   1	-	ECP	DBP	-	-	-	-	-
+ *   2	EBA	EBA	EBA	EBA	EDA	-	-	-
+ *   3	EBD	EBD	EBD	EBD	EBD	-	-	-
+ *   4	SBCLK	-	BCLK	BCKL	BCLK	-	-	-
+ *   5	EICE	-	-	-	-	TBEN	TBEN	-
+ *   6	ECLK	-	ECLK	ECLK	ECLK	-	-	-
+ *   7	PAR	PAR	PAR	PAR	PAR	STEN	STEN	-
+ *   8	DOZE	-	DOZE	DOZE	DOZE	-	HBATEN	DOZE
+ *   9	NAP	-	NAP	NAP	NAP	NAP	NAP	NAP
+ *  10	SLEEP	-	SLEEP	SLEEP	SLEEP	SLEEP	SLEEP	SLEEP
+ *  11	DPM	-	DPM	DPM	DPM	DPM	DPM	-
+ *  12	RISEG	-	-	RISEG	-	-	-	-
+ *  13	-	-	-	EIEC	EIEC	BHTCLR	BHTCLR	-
+ *  14	-	-	-	-	-	XAEN	XAEN	-
+ *  15	-	NHR	NHR	NHR	NHR	NHR	NHR	-
+ *  16	ICE	ICE	ICE	ICE	ICE	ICE	ICE	-
+ *  17	DCE	DCE	DCE	DCE	DCE	DCE	DCE	TBEN
+ *  18	ILOCK	ILOCK	ILOCK	ILOCK	ILOCK	ILOCK	ILOCK	SEL_TBCLK
+ *  19	DLOCK	DLOCK	DLOCK	DLOCK	DLOCK	DLOCK	DLOCK	-
+ *  20	ICFI	ICFI	ICFI	ICFI	ICFI	ICFI	ICFI	-
+ *  21	DCFI	DCFI	DCFI	DCFI	DCFI	DCFI	DCFI	-
+ *  22	-	-	SPD	SPD	SPG	SPD	SPD	-
+ *  23	-	-	IFEM	IFTT	IFTT	-	XBSEN	-
+ *  24	-	SIE	SGE	SGE	SGE	SGE	SGE	EN_MAS7_UPDATE
+ *  25	-	-	DCFA	DCFA	DCFA	-	-	DCFA
+ *  26	-	-	BTIC	BTIC	BTIC	BTIC	BTIC	-
+ *  27	FBIOB	-	-	-	-	LRSTK	LRSTK	-
+ *  28	-	-	ABE	-	-	FOLD	FOLD	-
+ *  29	-	BHT	BHT	BHT	BHT	BHT	BHT	-
+ *  30	-	-	-	NOPDST	NOPDST	NOPDST	NOPDST	-
+ *  31	NOOPTI	-	NOOPTI	NOPTI	NOPTI	NOPTI	NOPTI	NOPTI
+ *
+ * bit	e500mc		e5500
+ *   0	EMCP		EMCP
+ *   1	EN_L2MMU_MHD	EN_L2MMU_MHD
+ *   2	-		-
+ *   3	-		-
+ *   4	-		-
+ *   5	-		-
+ *   6	-		-
+ *   7	-		-
+ *   8	-		-
+ *   9	-		-
+ *  10	-		-
+ *  11	-		-
+ *  12	-		-
+ *  13	-		-
+ *  14	-		-
+ *  15	-		-
+ *  16	-		-
+ *  17	-		-
+ *  18	-		-
+ *  19	-		-
+ *  20	-		-
+ *  21	-		-
+ *  22	-		-
+ *  23	-		-
+ *  24	EN_MAS7_UPDATE	-
+ *  25	DCFA		DCFA
+ *  26	-		-
+ *  27	CIGLSO		CIGLSO
+ *  28	-		-
+ *  29	-		-
+ *  30	-		-
+ *  31	NOPTI		NOPTI
+ *
+ *  604: ECP = Enable cache parity checking
+ *  604: SIE = Serial instruction execution disable
+ * 7450: TBEN = Time Base Enable
+ * 7450: STEN = Software table lookup enable
+ * 7450: BHTCLR = Branch history clear
+ * 7450: XAEN = Extended Addressing Enabled
+ * 7450: LRSTK = Link Register Stack Enable
+ * 7450: FOLD = Branch folding enable
+ * 7457: HBATEN = High BAT Enable
+ * 7457: XBSEN = Extended BAT Block Size Enable
+ */
+
+#define HID1_E500_ABE	0x00001000  /* Address broadcast enable */
+#define HID1_E500_ASTME	0x00002000  /* Address bus streaming mode enable */
+#define HID1_E500_RFXE	0x00020000  /* Read fault exception enable */
+
+#define HID0_E500_DEFAULT_SET	(HID0_EMCP | HID0_E500_TBEN)
+#define HID1_E500_DEFAULT_SET	(HID1_E500_ABE | HID1_E500_ASTME)
+#define HID0_E500MC_DEFAULT_SET	(HID0_EMCP | HID0_E500MC_L2MMU_MHD | \
+				 HID0_E500_MAS7UPDEN)
+#define HID0_E5500_DEFAULT_SET	(HID0_EMCP | HID0_E500MC_L2MMU_MHD)
+
+#define HID5_970_DCBZ_SIZE_HI	0x00000080UL	/* dcbz does a 32-byte store */
+#define HID4_970_DISABLE_LG_PG	0x00000004ULL	/* disables large pages */
+
+#endif /* _POWERPC_HID_H_ */


Property changes on: trunk/sys/powerpc/include/hid.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/ieee.h
===================================================================
--- trunk/sys/powerpc/include/ieee.h	                        (rev 0)
+++ trunk/sys/powerpc/include/ieee.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,143 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ * 4. 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.
+ *
+ *	@(#)ieee.h	8.1 (Berkeley) 6/11/93
+ *	from: NetBSD: ieee.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp
+ * $FreeBSD: stable/10/sys/powerpc/include/ieee.h 139825 2005-01-07 02:29:27Z imp $
+ */
+
+#ifndef _MACHINE_IEEE_H_
+#define	_MACHINE_IEEE_H_
+
+/*
+ * ieee.h defines the machine-dependent layout of the machine's IEEE
+ * floating point.  It does *not* define (yet?) any of the rounding
+ * mode bits, exceptions, and so forth.
+ */
+
+/*
+ * Define the number of bits in each fraction and exponent.
+ *
+ *		     k	         k+1
+ * Note that  1.0 x 2  == 0.1 x 2      and that denorms are represented
+ *
+ *					  (-exp_bias+1)
+ * as fractions that look like 0.fffff x 2             .  This means that
+ *
+ *			 -126
+ * the number 0.10000 x 2    , for instance, is the same as the normalized
+ *
+ *		-127			   -128
+ * float 1.0 x 2    .  Thus, to represent 2    , we need one leading zero
+ *
+ *				  -129
+ * in the fraction; to represent 2    , we need two, and so on.  This
+ *
+ *						     (-exp_bias-fracbits+1)
+ * implies that the smallest denormalized number is 2
+ *
+ * for whichever format we are talking about: for single precision, for
+ *
+ *						-126		-149
+ * instance, we get .00000000000000000000001 x 2    , or 1.0 x 2    , and
+ *
+ * -149 == -127 - 23 + 1.
+ */
+#define	SNG_EXPBITS	8
+#define	SNG_FRACBITS	23
+
+#define	DBL_EXPBITS	11
+#define	DBL_FRACBITS	52
+
+#ifdef notyet
+#define	E80_EXPBITS	15
+#define	E80_FRACBITS	64
+#endif
+
+#define	EXT_EXPBITS	15
+#define	EXT_FRACBITS	112
+
+struct ieee_single {
+	u_int	sng_sign:1;
+	u_int	sng_exp:8;
+	u_int	sng_frac:23;
+};
+
+struct ieee_double {
+	u_int	dbl_sign:1;
+	u_int	dbl_exp:11;
+	u_int	dbl_frach:20;
+	u_int	dbl_fracl;
+};
+
+struct ieee_ext {
+	u_int	ext_sign:1;
+	u_int	ext_exp:15;
+	u_int	ext_frach:16;
+	u_int	ext_frachm;
+	u_int	ext_fraclm;
+	u_int	ext_fracl;
+};
+
+/*
+ * Floats whose exponent is in [1..INFNAN) (of whatever type) are
+ * `normal'.  Floats whose exponent is INFNAN are either Inf or NaN.
+ * Floats whose exponent is zero are either zero (iff all fraction
+ * bits are zero) or subnormal values.
+ *
+ * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its
+ * high fraction; if the bit is set, it is a `quiet NaN'.
+ */
+#define	SNG_EXP_INFNAN	255
+#define	DBL_EXP_INFNAN	2047
+#define	EXT_EXP_INFNAN	32767
+
+#if 0
+#define	SNG_QUIETNAN	(1 << 22)
+#define	DBL_QUIETNAN	(1 << 19)
+#define	EXT_QUIETNAN	(1 << 15)
+#endif
+
+/*
+ * Exponent biases.
+ */
+#define	SNG_EXP_BIAS	127
+#define	DBL_EXP_BIAS	1023
+#define	EXT_EXP_BIAS	16383
+
+#endif


Property changes on: trunk/sys/powerpc/include/ieee.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/ieeefp.h
===================================================================
--- trunk/sys/powerpc/include/ieeefp.h	                        (rev 0)
+++ trunk/sys/powerpc/include/ieeefp.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,36 @@
+/* $MidnightBSD$ */
+/* -
+ * Written by J.T. Conklin, Apr 6, 1995
+ * Public domain.
+ * $NetBSD: ieeefp.h,v 1.2 1999/07/07 01:52:26 danw Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/ieeefp.h 226607 2011-10-21 06:41:46Z das $
+ */
+
+#ifndef _MACHINE_IEEEFP_H_
+#define _MACHINE_IEEEFP_H_
+
+/* Deprecated historical FPU control interface */
+
+typedef int fp_except_t;
+#define FP_X_IMP	0x01	/* imprecise (loss of precision) */
+#define FP_X_DZ		0x02	/* divide-by-zero exception */
+#define FP_X_UFL	0x04	/* underflow exception */
+#define FP_X_OFL	0x08	/* overflow exception */
+#define FP_X_INV	0x10	/* invalid operation exception */
+
+typedef enum {
+    FP_RN=0,			/* round to nearest representable number */
+    FP_RZ=1,			/* round to zero (truncate) */
+    FP_RP=2,			/* round toward positive infinity */
+    FP_RM=3			/* round toward negative infinity */
+} fp_rnd_t;
+
+__BEGIN_DECLS
+extern fp_rnd_t    fpgetround(void);
+extern fp_rnd_t    fpsetround(fp_rnd_t);
+extern fp_except_t fpgetmask(void);
+extern fp_except_t fpsetmask(fp_except_t);
+extern fp_except_t fpgetsticky(void);
+__END_DECLS
+
+#endif /* _MACHINE_IEEEFP_H_ */


Property changes on: trunk/sys/powerpc/include/ieeefp.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/in_cksum.h
===================================================================
--- trunk/sys/powerpc/include/in_cksum.h	                        (rev 0)
+++ trunk/sys/powerpc/include/in_cksum.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,81 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1990 The 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.
+ * 4. 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.
+ *
+ *	from tahoe:	in_cksum.c	1.2	86/01/05
+ *	from:		@(#)in_cksum.c	1.3 (Berkeley) 1/19/91
+ *	from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp
+ * $FreeBSD: stable/10/sys/powerpc/include/in_cksum.h 235941 2012-05-24 22:00:48Z bz $
+ */
+
+#ifndef _MACHINE_IN_CKSUM_H_
+#define	_MACHINE_IN_CKSUM_H_	1
+
+#include <sys/cdefs.h>
+
+#define in_cksum(m, len)	in_cksum_skip(m, len, 0)
+
+#if defined(IPVERSION) && (IPVERSION == 4)
+/*
+ * It it useful to have an Internet checksum routine which is inlineable
+ * and optimized specifically for the task of computing IP header checksums
+ * in the normal case (where there are no options and the header length is
+ * therefore always exactly five 32-bit words.
+ */
+#ifdef __CC_SUPPORTS___INLINE
+
+static __inline void
+in_cksum_update(struct ip *ip)
+{
+	int __tmpsum;
+	__tmpsum = (int)ntohs(ip->ip_sum) + 256;
+	ip->ip_sum = htons(__tmpsum + (__tmpsum >> 16));
+}
+
+#else
+
+#define	in_cksum_update(ip) \
+	do { \
+		int __tmpsum; \
+		__tmpsum = (int)ntohs(ip->ip_sum) + 256; \
+		ip->ip_sum = htons(__tmpsum + (__tmpsum >> 16)); \
+	} while(0)
+
+#endif
+#endif
+
+#ifdef _KERNEL
+#if defined(IPVERSION) && (IPVERSION == 4)
+u_int in_cksum_hdr(const struct ip *ip);
+#endif
+u_short	in_addword(u_short sum, u_short b);
+u_short	in_pseudo(u_int sum, u_int b, u_int c);
+u_short	in_cksum_skip(struct mbuf *m, int len, int skip);
+#endif
+
+#endif /* _MACHINE_IN_CKSUM_H_ */


Property changes on: trunk/sys/powerpc/include/in_cksum.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/intr_machdep.h
===================================================================
--- trunk/sys/powerpc/include/intr_machdep.h	                        (rev 0)
+++ trunk/sys/powerpc/include/intr_machdep.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,62 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2002 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/intr_machdep.h 265969 2014-05-13 18:06:26Z ian $
+ */
+
+#ifndef	_MACHINE_INTR_MACHDEP_H_
+#define	_MACHINE_INTR_MACHDEP_H_
+
+#define	INTR_VECTORS	256
+
+#define	MAX_PICS		5
+#define	MAP_IRQ(node, pin)	powerpc_get_irq(node, pin)
+
+/*
+ * Default base address for MSI messages on PowerPC
+ */
+#define	MSI_INTEL_ADDR_BASE		0xfee00000
+
+extern device_t root_pic;
+
+struct trapframe;
+
+driver_filter_t powerpc_ipi_handler;
+
+void	intrcnt_add(const char *name, u_long **countp);
+
+void	powerpc_register_pic(device_t, uint32_t, u_int, u_int, u_int);
+u_int	powerpc_get_irq(uint32_t, u_int);
+
+void	powerpc_dispatch_intr(u_int, struct trapframe *);
+int	powerpc_enable_intr(void);
+int	powerpc_setup_intr(const char *, u_int, driver_filter_t, driver_intr_t,
+	    void *, enum intr_type, void **);
+int	powerpc_teardown_intr(void *);
+int	powerpc_bind_intr(u_int irq, u_char cpu);
+int	powerpc_config_intr(int, enum intr_trigger, enum intr_polarity);
+int	powerpc_fw_config_intr(int irq, int sense_code);
+
+#endif /* _MACHINE_INTR_MACHDEP_H_ */


Property changes on: trunk/sys/powerpc/include/intr_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/kdb.h
===================================================================
--- trunk/sys/powerpc/include/kdb.h	                        (rev 0)
+++ trunk/sys/powerpc/include/kdb.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,54 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2004 Marcel Moolenaar
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/kdb.h 176742 2008-03-02 17:05:57Z raj $
+ */
+
+#ifndef _MACHINE_KDB_H_
+#define _MACHINE_KDB_H_
+
+#include <machine/cpufunc.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/psl.h>
+#include <machine/spr.h>
+
+void kdb_cpu_clear_singlestep(void);
+void kdb_cpu_set_singlestep(void);
+
+static __inline void
+kdb_cpu_sync_icache(unsigned char *addr, size_t size)
+{
+
+	__syncicache(addr, size);
+}
+
+static __inline void
+kdb_cpu_trap(int vector, int _)
+{
+}
+
+#endif /* _MACHINE_KDB_H_ */


Property changes on: trunk/sys/powerpc/include/kdb.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/limits.h
===================================================================
--- trunk/sys/powerpc/include/limits.h	                        (rev 0)
+++ trunk/sys/powerpc/include/limits.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,45 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1988, 1993
+ *	The 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.
+ * 4. 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.
+ *
+ *	@(#)limits.h	8.3 (Berkeley) 1/4/94
+ * $FreeBSD: stable/10/sys/powerpc/include/limits.h 143063 2005-03-02 21:33:29Z joerg $
+ */
+
+#ifndef _MACHINE_LIMITS_H_
+#define	_MACHINE_LIMITS_H_
+
+#include <sys/cdefs.h>
+
+#ifdef __CC_SUPPORTS_WARNING
+#warning "machine/limits.h is deprecated.  Include sys/limits.h instead."
+#endif
+
+#include <sys/limits.h>
+
+#endif /* !_MACHINE_LIMITS_H_ */


Property changes on: trunk/sys/powerpc/include/limits.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/machdep.h
===================================================================
--- trunk/sys/powerpc/include/machdep.h	                        (rev 0)
+++ trunk/sys/powerpc/include/machdep.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,40 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011-2012 Semihalf
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/machdep.h 236324 2012-05-30 17:34:40Z raj $
+ */
+
+#ifndef _POWERPC_MACHDEP_H_
+#define _POWERPC_MACHDEP_H_
+
+void booke_disable_l2_cache(void);
+void booke_enable_l1_cache(void);
+void booke_enable_l2_cache(void);
+void booke_enable_l3_cache(void);
+void booke_enable_bpred(void);
+void booke_init_tlb(vm_paddr_t);
+
+#endif /* _POWERPC_MACHDEP_H_ */


Property changes on: trunk/sys/powerpc/include/machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/md_var.h
===================================================================
--- trunk/sys/powerpc/include/md_var.h	                        (rev 0)
+++ trunk/sys/powerpc/include/md_var.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,70 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1998 Doug Rabson
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/md_var.h 212453 2010-09-11 04:45:51Z mav $
+ */
+
+#ifndef _MACHINE_MD_VAR_H_
+#define	_MACHINE_MD_VAR_H_
+
+/*
+ * Miscellaneous machine-dependent declarations.
+ */
+
+extern	char	sigcode32[];
+extern	int	szsigcode32;
+
+#ifdef __powerpc64__
+extern	char	sigcode64[];
+extern	int	szsigcode64;
+#endif
+
+extern	long	Maxmem;
+extern	int	busdma_swi_pending;
+
+extern	vm_offset_t	kstack0;
+extern	vm_offset_t	kstack0_phys;
+
+extern	int powerpc_pow_enabled;
+extern	int cacheline_size;
+extern  int hw_direct_map;
+
+void	__syncicache(void *, int);
+
+void	busdma_swi(void);
+int	is_physical_memory(vm_offset_t addr);
+int	mem_valid(vm_offset_t addr, int len);
+
+void	decr_init(void);
+void	decr_ap_init(void);
+void	decr_tc_init(void);
+
+void	cpu_setup(u_int);
+
+struct	trapframe;
+void	powerpc_interrupt(struct trapframe *);
+
+#endif /* !_MACHINE_MD_VAR_H_ */


Property changes on: trunk/sys/powerpc/include/md_var.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/memdev.h
===================================================================
--- trunk/sys/powerpc/include/memdev.h	                        (rev 0)
+++ trunk/sys/powerpc/include/memdev.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,41 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2004 Mark R V Murray
+ * 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
+ *    in this position and unchanged.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/memdev.h 217515 2011-01-17 22:58:28Z jkim $
+ */
+
+#ifndef _MACHINE_MEMDEV_H_
+#define	_MACHINE_MEMDEV_H_
+
+#define	CDEV_MINOR_MEM	0
+#define	CDEV_MINOR_KMEM	1
+
+d_open_t	memopen;
+d_read_t	memrw;
+d_ioctl_t	memioctl;
+d_mmap_t	memmmap;
+
+#endif /* _MACHINE_MEMDEV_H_ */


Property changes on: trunk/sys/powerpc/include/memdev.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/metadata.h
===================================================================
--- trunk/sys/powerpc/include/metadata.h	                        (rev 0)
+++ trunk/sys/powerpc/include/metadata.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,39 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 Jake Burkholder.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/metadata.h 217459 2011-01-15 20:18:08Z marcel $
+ */
+
+#ifndef _MACHINE_METADATA_H_
+#define	_MACHINE_METADATA_H_
+
+#define	MODINFOMD_ENVP		0x1001
+#define	MODINFOMD_HOWTO		0x1002
+#define	MODINFOMD_KERNEND	0x1003
+#define	MODINFOMD_BOOTINFO	0x1004
+#define	MODINFOMD_DTBP		0x1005
+
+#endif /* !_MACHINE_METADATA_H_ */


Property changes on: trunk/sys/powerpc/include/metadata.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/mmuvar.h
===================================================================
--- trunk/sys/powerpc/include/mmuvar.h	                        (rev 0)
+++ trunk/sys/powerpc/include/mmuvar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,120 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Peter Grehan
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/mmuvar.h 212627 2010-09-15 00:17:52Z grehan $
+ */
+
+#ifndef _MACHINE_MMUVAR_H_
+#define _MACHINE_MMUVAR_H_
+
+/*
+ * A PowerPC MMU implementation is declared with a kernel object and
+ * an associated method table. The MMU_DEF macro is used to declare
+ * the class, and also links it to the global MMU class list.
+ *
+ * e.g.
+ *
+ * static mmu_method_t ppc8xx_methods[] = {
+ *	MMUMETHOD(mmu_change_wiring,		ppc8xx_mmu_change_wiring),
+ *	MMUMETHOD(mmu_clear_modify,		ppc8xx_mmu_clear_modify),
+ *	MMUMETHOD(mmu_clear_reference,		ppc8xx_mmu_clear_reference),
+ *  ...
+ *	MMUMETHOD(mmu_dev_direct_mapped,	ppc8xx_mmu_dev_direct_mapped),
+ *	{ 0, 0 }
+ * };
+ *
+ * MMU_DEF(ppc8xx, MMU_TYPE_8xx, ppc8xx_methods, sizeof(ppc8xx_mmu_softc));
+ *
+ * A single level of inheritance is supported in a similar fashion to
+ * kobj inheritance e.g.
+ *
+ * MMU_DEF_1(ppc860c, MMU_TYPE_860c, ppc860c_methods, 0, ppc8xx);
+ */
+
+#include <sys/kobj.h>
+
+struct mmu_kobj {
+	/*
+	 * An MMU instance is a kernel object
+	 */
+	KOBJ_FIELDS;
+
+	/*
+	 * Utility elements that an instance may use
+	 */
+	struct mtx	mmu_mtx;	/* available for instance use */
+	void		*mmu_iptr;	/* instance data pointer */
+
+	/*
+	 * Opaque data that can be overlaid with an instance-private
+	 * structure. MMU code can test that this is large enough at
+	 * compile time with a sizeof() test againt it's softc. There
+	 * is also a run-time test when the MMU kernel object is
+	 * registered.
+	 */
+#define MMU_OPAQUESZ	64
+	u_int		mmu_opaque[MMU_OPAQUESZ];
+};
+
+typedef struct mmu_kobj		*mmu_t;
+typedef struct kobj_class	mmu_def_t;
+#define mmu_method_t		kobj_method_t
+
+#define MMUMETHOD	KOBJMETHOD
+
+#define MMU_DEF(name, ident, methods, size)	\
+						\
+mmu_def_t name = {				\
+	ident, methods, size, NULL		\
+};						\
+DATA_SET(mmu_set, name)
+
+#define MMU_DEF_INHERIT(name, ident, methods, size, base1)	\
+						\
+static kobj_class_t name ## _baseclasses[] =	\
+       	{ &base1, NULL };			\
+mmu_def_t name = {                              \
+	ident, methods, size, name ## _baseclasses	\
+};                                              \
+DATA_SET(mmu_set, name)
+
+
+#if 0
+mmu_def_t name = {				\
+	ident, methods, size, name ## _baseclasses	\
+};						
+DATA_SET(mmu_set, name)
+#endif
+
+/*
+ * Known MMU names
+ */
+#define MMU_TYPE_BOOKE	"mmu_booke"	/* Book-E MMU specification */
+#define MMU_TYPE_OEA	"mmu_oea"	/* 32-bit OEA */
+#define MMU_TYPE_G5	"mmu_g5"	/* 64-bit bridge (ibm 970) */
+#define MMU_TYPE_8xx	"mmu_8xx"	/* 8xx quicc TLB */
+
+#endif /* _MACHINE_MMUVAR_H_ */


Property changes on: trunk/sys/powerpc/include/mmuvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/ofw_machdep.h
===================================================================
--- trunk/sys/powerpc/include/ofw_machdep.h	                        (rev 0)
+++ trunk/sys/powerpc/include/ofw_machdep.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,53 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 by Thomas Moestl <tmm at FreeBSD.org>.
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/ofw_machdep.h 266020 2014-05-14 14:17:51Z ian $
+ */
+
+#ifndef _MACHINE_OFW_MACHDEP_H_
+#define _MACHINE_OFW_MACHDEP_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/rman.h>
+#include <sys/bus.h>
+#include <dev/ofw/openfirm.h>
+#include <machine/platform.h>
+
+typedef	uint32_t	cell_t;
+
+int  OF_decode_addr(phandle_t, int, bus_space_tag_t *, bus_space_handle_t *);
+void OF_getetheraddr(device_t dev, u_char *addr);
+
+void OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *));
+boolean_t OF_bootstrap(void);
+
+void OF_reboot(void);
+
+void ofw_mem_regions(struct mem_region *, int *, struct mem_region *, int *);
+void ofw_quiesce(void); /* Must be called before VM is up! */
+void ofw_save_trap_vec(char *);
+
+#endif /* _MACHINE_OFW_MACHDEP_H_ */


Property changes on: trunk/sys/powerpc/include/ofw_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/openpicreg.h
===================================================================
--- trunk/sys/powerpc/include/openpicreg.h	                        (rev 0)
+++ trunk/sys/powerpc/include/openpicreg.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,141 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2000 Tsubai Masanari.  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. 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.
+ *
+ * from NetBSD: openpicreg.h,v 1.3 2001/08/30 03:08:52 briggs Exp
+ * $FreeBSD: stable/10/sys/powerpc/include/openpicreg.h 176208 2008-02-12 18:14:46Z marcel $
+ */
+
+/*
+ * Size of OpenPIC register space
+ */
+#define	OPENPIC_SIZE			0x40000
+
+/*
+ * Per Processor Registers [private access] (0x00000 - 0x00fff)
+ */
+
+/* IPI dispatch command reg */
+#define	OPENPIC_IPI_DISPATCH(ipi)	(0x40 + (ipi) * 0x10)
+
+/* current task priority reg */
+#define	OPENPIC_TPR			0x80
+#define  OPENPIC_TPR_MASK			0x0000000f
+
+#define	OPENPIC_WHOAMI			0x90
+
+/* interrupt acknowledge reg */
+#define	OPENPIC_IACK			0xa0
+
+/* end of interrupt reg */
+#define	OPENPIC_EOI			0xb0
+
+/*
+ * Global registers (0x01000-0x0ffff)
+ */
+
+/* feature reporting reg 0 */
+#define OPENPIC_FEATURE			0x1000
+#define	 OPENPIC_FEATURE_VERSION_MASK		0x000000ff
+#define	 OPENPIC_FEATURE_LAST_CPU_MASK		0x00001f00
+#define	 OPENPIC_FEATURE_LAST_CPU_SHIFT		8
+#define	 OPENPIC_FEATURE_LAST_IRQ_MASK		0x07ff0000
+#define	 OPENPIC_FEATURE_LAST_IRQ_SHIFT		16
+
+/* global config reg 0 */
+#define OPENPIC_CONFIG			0x1020
+#define  OPENPIC_CONFIG_RESET			0x80000000
+#define  OPENPIC_CONFIG_8259_PASSTHRU_DISABLE	0x20000000
+
+/* interrupt configuration mode (direct or serial) */
+#define OPENPIC_ICR			0x1030
+#define  OPENPIC_ICR_SERIAL_MODE		(1 << 27)
+#define  OPENPIC_ICR_SERIAL_RATIO_MASK		(0x7 << 28)
+#define  OPENPIC_ICR_SERIAL_RATIO_SHIFT		28
+
+/* vendor ID */
+#define OPENPIC_VENDOR_ID		0x1080
+
+/* processor initialization reg */
+#define OPENPIC_PROC_INIT		0x1090
+
+/* IPI vector/priority reg */
+#define OPENPIC_IPI_VECTOR(ipi)		(0x10a0 + (ipi) * 0x10)
+
+/* spurious intr. vector */
+#define OPENPIC_SPURIOUS_VECTOR		0x10e0
+
+/* Timer registers */
+#define	OPENPIC_TIMERS			4
+#define	OPENPIC_TFREQ			0x10f0
+#define	OPENPIC_TCNT(t)			(0x1100 + (t) * 0x40)
+#define	OPENPIC_TBASE(t)		(0x1110 + (t) * 0x40)
+#define	OPENPIC_TVEC(t)			(0x1120 + (t) * 0x40)
+#define	OPENPIC_TDST(t)			(0x1130 + (t) * 0x40)
+
+/*
+ * Interrupt Source Configuration Registers (0x10000 - 0x1ffff)
+ */
+
+/* interrupt vector/priority reg */
+#ifndef OPENPIC_SRC_VECTOR
+#define OPENPIC_SRC_VECTOR(irq)		(0x10000 + (irq) * 0x20)
+#endif
+#define  OPENPIC_SENSE_LEVEL			0x00400000
+#define  OPENPIC_SENSE_EDGE			0x00000000
+#define  OPENPIC_POLARITY_POSITIVE		0x00800000
+#define  OPENPIC_POLARITY_NEGATIVE		0x00000000
+#define  OPENPIC_IMASK				0x80000000
+#define  OPENPIC_ACTIVITY			0x40000000
+#define  OPENPIC_PRIORITY_MASK			0x000f0000
+#define  OPENPIC_PRIORITY_SHIFT			16
+#define  OPENPIC_VECTOR_MASK			0x000000ff
+
+/* interrupt destination cpu */
+#ifndef OPENPIC_IDEST
+#define OPENPIC_IDEST(irq)		(0x10010 + (irq) * 0x20)
+#endif
+
+/*
+ * Per Processor Registers [global access] (0x20000 - 0x3ffff)
+ */
+
+#define	OPENPIC_PCPU_BASE(cpu)		(0x20000 + (cpu) * 0x1000)
+
+#define	OPENPIC_PCPU_IPI_DISPATCH(cpu, ipi)	\
+	(OPENPIC_PCPU_BASE(cpu) + OPENPIC_IPI_DISPATCH(ipi))
+
+#define	OPENPIC_PCPU_TPR(cpu)		\
+	(OPENPIC_PCPU_BASE(cpu) + OPENPIC_TPR)
+
+#define	OPENPIC_PCPU_WHOAMI(cpu)		\
+	(OPENPIC_PCPU_BASE(cpu) + OPENPIC_WHOAMI)
+
+#define OPENPIC_PCPU_IACK(cpu)			\
+	(OPENPIC_PCPU_BASE(cpu) + OPENPIC_IACK)
+
+#define OPENPIC_PCPU_EOI(cpu)			\
+	(OPENPIC_PCPU_BASE(cpu) + OPENPIC_EOI)
+


Property changes on: trunk/sys/powerpc/include/openpicreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/openpicvar.h
===================================================================
--- trunk/sys/powerpc/include/openpicvar.h	                        (rev 0)
+++ trunk/sys/powerpc/include/openpicvar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,70 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2002 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/openpicvar.h 222813 2011-06-07 08:46:13Z attilio $
+ */
+
+#ifndef	_POWERPC_OPENPICVAR_H_
+#define	_POWERPC_OPENPICVAR_H_
+
+#define OPENPIC_DEVSTR	"OpenPIC Interrupt Controller"
+
+#define OPENPIC_IRQMAX	256	/* h/w allows more */
+
+struct openpic_softc {
+	device_t	sc_dev;
+	struct resource	*sc_memr;
+	struct resource	*sc_intr;
+	bus_space_tag_t sc_bt;
+	bus_space_handle_t sc_bh;
+	char		*sc_version;
+	int		sc_rid;
+	int		sc_irq;
+	void		*sc_icookie;
+	u_int		sc_ncpu;
+	u_int		sc_nirq;
+	int		sc_psim;
+};
+
+extern devclass_t openpic_devclass;
+
+/*
+ * Bus-independent attach i/f
+ */
+int	openpic_common_attach(device_t, uint32_t);
+
+/*
+ * PIC interface.
+ */
+void	openpic_bind(device_t dev, u_int irq, cpuset_t cpumask);
+void	openpic_config(device_t, u_int, enum intr_trigger, enum intr_polarity);
+void	openpic_dispatch(device_t, struct trapframe *);
+void	openpic_enable(device_t, u_int, u_int);
+void	openpic_eoi(device_t, u_int);
+void	openpic_ipi(device_t, u_int);
+void	openpic_mask(device_t, u_int);
+void	openpic_unmask(device_t, u_int);
+
+#endif /* _POWERPC_OPENPICVAR_H_ */


Property changes on: trunk/sys/powerpc/include/openpicvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/param.h
===================================================================
--- trunk/sys/powerpc/include/param.h	                        (rev 0)
+++ trunk/sys/powerpc/include/param.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,131 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 David E. O'Brien
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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 University of
+ *	California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ *	from: @(#)param.h	5.8 (Berkeley) 6/28/91
+ * $FreeBSD: stable/10/sys/powerpc/include/param.h 271153 2014-09-05 05:07:38Z jhibbits $
+ */
+
+#ifndef _POWERPC_INCLUDE_PARAM_H_
+#define	_POWERPC_INCLUDE_PARAM_H_
+
+/*
+ * Machine dependent constants for PowerPC
+ */
+
+#include <machine/_align.h>
+
+/* Needed to display interrupts on OFW PCI */
+#define __PCI_REROUTE_INTERRUPT
+
+#ifndef MACHINE
+#define	MACHINE		"powerpc"
+#endif
+#ifndef MACHINE_ARCH
+#ifdef __powerpc64__
+#define	MACHINE_ARCH	"powerpc64"
+#else
+#define	MACHINE_ARCH	"powerpc"
+#endif
+#endif
+#define	MID_MACHINE	MID_POWERPC
+#ifdef __powerpc64__
+#ifndef	MACHINE_ARCH32
+#define	MACHINE_ARCH32	"powerpc"
+#endif
+#endif
+
+#if defined(SMP) || defined(KLD_MODULE)
+#ifndef MAXCPU
+#define	MAXCPU		32	
+#endif
+#else
+#define	MAXCPU		1
+#endif /* SMP || KLD_MODULE */
+
+#ifndef MAXMEMDOM
+#define	MAXMEMDOM	1
+#endif
+
+#define	ALIGNBYTES	_ALIGNBYTES
+#define	ALIGN(p)	_ALIGN(p)
+/*
+ * ALIGNED_POINTER is a boolean macro that checks whether an address
+ * is valid to fetch data elements of type t from on this architecture.
+ * This does not reflect the optimal alignment, just the possibility
+ * (within reasonable limits). 
+ */
+#define	ALIGNED_POINTER(p, t)	((((uintptr_t)(p)) & (sizeof (t) - 1)) == 0)
+
+/*
+ * CACHE_LINE_SIZE is the compile-time maximum cache line size for an
+ * architecture.  It should be used with appropriate caution.
+ */
+#define	CACHE_LINE_SHIFT	7
+#define	CACHE_LINE_SIZE		(1 << CACHE_LINE_SHIFT)
+
+#define	PAGE_SHIFT	12
+#define	PAGE_SIZE	(1L << PAGE_SHIFT)	/* Page size */
+#define	PAGE_MASK	(vm_offset_t)(PAGE_SIZE - 1)
+#define	NPTEPG		(PAGE_SIZE/(sizeof (pt_entry_t)))
+
+#define	MAXPAGESIZES	1		/* maximum number of supported page sizes */
+
+#ifndef KSTACK_PAGES
+#ifdef __powerpc64__
+#define	KSTACK_PAGES		8		/* includes pcb */
+#else
+#define	KSTACK_PAGES		4		/* includes pcb */
+#endif
+#endif
+#define	KSTACK_GUARD_PAGES	1	/* pages of kstack guard; 0 disables */
+#define	USPACE		(KSTACK_PAGES * PAGE_SIZE)	/* total size of pcb */
+
+/*
+ * Mach derived conversion macros
+ */
+#define	trunc_page(x)		((unsigned long)(x) & ~(PAGE_MASK))
+#define	round_page(x)		(((x) + PAGE_MASK) & ~PAGE_MASK)
+
+#define	atop(x)			((unsigned long)(x) >> PAGE_SHIFT)
+#define	ptoa(x)			((unsigned long)(x) << PAGE_SHIFT)
+
+#define	powerpc_btop(x)		((unsigned long)(x) >> PAGE_SHIFT)
+#define	powerpc_ptob(x)		((unsigned long)(x) << PAGE_SHIFT)
+
+#define	pgtok(x)		((x) * (PAGE_SIZE / 1024UL))
+
+#endif /* !_POWERPC_INCLUDE_PARAM_H_ */


Property changes on: trunk/sys/powerpc/include/param.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/pcb.h
===================================================================
--- trunk/sys/powerpc/include/pcb.h	                        (rev 0)
+++ trunk/sys/powerpc/include/pcb.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,95 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: pcb.h,v 1.4 2000/06/04 11:57:17 tsubai Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/pcb.h 266004 2014-05-14 04:42:38Z ian $
+ */
+
+#ifndef _MACHINE_PCB_H_
+#define	_MACHINE_PCB_H_
+
+typedef register_t faultbuf[25];
+
+struct pcb {
+	register_t	pcb_context[20];	/* non-volatile r14-r31 */
+	register_t	pcb_cr;			/* Condition register */
+	register_t	pcb_sp;			/* stack pointer */
+	register_t	pcb_toc;		/* toc pointer */
+	register_t	pcb_lr;			/* link register */
+	struct		pmap *pcb_pm;		/* pmap of our vmspace */
+	faultbuf	*pcb_onfault;		/* For use during
+						    copyin/copyout */
+	int		pcb_flags;
+#define	PCB_FPU		1	/* Process uses FPU */
+#define	PCB_FPREGS	2	/* Process had FPU registers initialized */
+#define	PCB_VEC		4	/* Process had Altivec initialized */
+	struct fpu {
+		double	fpr[32];
+		double	fpscr;	/* FPSCR stored as double for easier access */
+	} pcb_fpu;		/* Floating point processor */
+	unsigned int	pcb_fpcpu;		/* which CPU had our FPU
+							stuff. */
+	struct vec {
+		uint32_t vr[32][4];
+		register_t vrsave;
+		register_t spare[2];
+		register_t vscr;	/* aligned at vector element 3 */
+	} pcb_vec __aligned(16);	/* Vector processor */
+	unsigned int	pcb_veccpu;		/* which CPU had our vector
+							stuff. */
+
+	union {
+		struct {
+			vm_offset_t	usr_segm;	/* Base address */
+			register_t	usr_vsid;	/* USER_SR segment */
+		} aim;
+		struct {
+			register_t	dbcr0;
+		} booke;
+	} pcb_cpu;
+};
+
+#ifdef	_KERNEL
+
+struct trapframe;
+
+#ifndef curpcb
+extern struct pcb *curpcb;
+#endif
+
+extern struct pmap *curpm;
+extern struct proc *fpuproc;
+
+void	makectx(struct trapframe *, struct pcb *);
+void	savectx(struct pcb *) __returns_twice;
+
+#endif
+#endif	/* _MACHINE_PCB_H_ */


Property changes on: trunk/sys/powerpc/include/pcb.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/pcpu.h
===================================================================
--- trunk/sys/powerpc/include/pcpu.h	                        (rev 0)
+++ trunk/sys/powerpc/include/pcpu.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,166 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1999 Luoqi Chen <luoqi at freebsd.org>
+ * Copyright (c) Peter Wemm <peter at netplex.com.au>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/pcpu.h 266001 2014-05-14 03:09:37Z ian $
+ */
+
+#ifndef	_MACHINE_PCPU_H_
+#define	_MACHINE_PCPU_H_
+
+#include <machine/cpufunc.h>
+#include <machine/slb.h>
+#include <machine/tlb.h>
+
+struct pmap;
+#define	CPUSAVE_LEN	9
+
+#define	PCPU_MD_COMMON_FIELDS						\
+	int		pc_inside_intr;					\
+	struct pmap	*pc_curpmap;		/* current pmap */	\
+	struct thread	*pc_fputhread;		/* current fpu user */  \
+	struct thread	*pc_vecthread;		/* current vec user */  \
+	uintptr_t	pc_hwref;					\
+	uint32_t	pc_pir;						\
+	int		pc_bsp;						\
+	volatile int	pc_awake;					\
+	uint32_t	pc_ipimask;					\
+	register_t	pc_tempsave[CPUSAVE_LEN];			\
+	register_t	pc_disisave[CPUSAVE_LEN];			\
+	register_t	pc_dbsave[CPUSAVE_LEN];				\
+	void		*pc_restore;
+
+#define PCPU_MD_AIM32_FIELDS						\
+	/* char		__pad[0] */
+
+#define PCPU_MD_AIM64_FIELDS						\
+	struct slb	pc_slb[64];					\
+	struct slb	**pc_userslb;					\
+	register_t	pc_slbsave[18];					\
+	uint8_t		pc_slbstack[1024];				\
+	char		__pad[1137]
+
+#ifdef __powerpc64__
+#define PCPU_MD_AIM_FIELDS	PCPU_MD_AIM64_FIELDS
+#else
+#define PCPU_MD_AIM_FIELDS	PCPU_MD_AIM32_FIELDS
+#endif
+
+#define	BOOKE_CRITSAVE_LEN	(CPUSAVE_LEN + 2)
+#define	BOOKE_TLB_MAXNEST	3
+#define	BOOKE_TLB_SAVELEN	16
+#define	BOOKE_TLBSAVE_LEN	(BOOKE_TLB_SAVELEN * BOOKE_TLB_MAXNEST)
+
+#define PCPU_MD_BOOKE_FIELDS						\
+	register_t	pc_booke_critsave[BOOKE_CRITSAVE_LEN];		\
+	register_t	pc_booke_mchksave[CPUSAVE_LEN];			\
+	register_t	pc_booke_tlbsave[BOOKE_TLBSAVE_LEN];		\
+	register_t	pc_booke_tlb_level;				\
+	uint32_t	*pc_booke_tlb_lock;				\
+	int		pc_tid_next;					\
+	char		__pad[173]
+
+/* Definitions for register offsets within the exception tmp save areas */
+#define	CPUSAVE_R27	0		/* where r27 gets saved */
+#define	CPUSAVE_R28	1		/* where r28 gets saved */
+#define	CPUSAVE_R29	2		/* where r29 gets saved */
+#define	CPUSAVE_R30	3		/* where r30 gets saved */
+#define	CPUSAVE_R31	4		/* where r31 gets saved */
+#define	CPUSAVE_AIM_DAR		5	/* where SPR_DAR gets saved */
+#define	CPUSAVE_AIM_DSISR	6	/* where SPR_DSISR gets saved */
+#define	CPUSAVE_BOOKE_DEAR	5	/* where SPR_DEAR gets saved */
+#define	CPUSAVE_BOOKE_ESR	6	/* where SPR_ESR gets saved */
+#define	CPUSAVE_SRR0	7		/* where SRR0 gets saved */
+#define	CPUSAVE_SRR1	8		/* where SRR1 gets saved */
+
+/* Book-E TLBSAVE is more elaborate */
+#define TLBSAVE_BOOKE_LR	0
+#define TLBSAVE_BOOKE_CR	1
+#define TLBSAVE_BOOKE_SRR0	2
+#define TLBSAVE_BOOKE_SRR1	3
+#define TLBSAVE_BOOKE_R20	4
+#define TLBSAVE_BOOKE_R21	5
+#define TLBSAVE_BOOKE_R22	6
+#define TLBSAVE_BOOKE_R23	7
+#define TLBSAVE_BOOKE_R24	8
+#define TLBSAVE_BOOKE_R25	9
+#define TLBSAVE_BOOKE_R26	10
+#define TLBSAVE_BOOKE_R27	11
+#define TLBSAVE_BOOKE_R28	12
+#define TLBSAVE_BOOKE_R29	13
+#define TLBSAVE_BOOKE_R30	14
+#define TLBSAVE_BOOKE_R31	15
+
+#ifdef AIM
+#define	PCPU_MD_FIELDS		\
+	PCPU_MD_COMMON_FIELDS	\
+	PCPU_MD_AIM_FIELDS
+#endif
+#if defined(BOOKE)
+#define	PCPU_MD_FIELDS		\
+	PCPU_MD_COMMON_FIELDS	\
+	PCPU_MD_BOOKE_FIELDS
+#endif
+
+/*
+ * Catch-all for ports (e.g. lsof, used by gtop)
+ */
+#ifndef PCPU_MD_FIELDS
+#define	PCPU_MD_FIELDS							\
+	int		pc_md_placeholder[32]
+#endif
+
+#ifdef _KERNEL
+
+#define pcpup	((struct pcpu *) powerpc_get_pcpup())
+
+static __inline __pure2 struct thread *
+__curthread(void)
+{
+	struct thread *td;
+#ifdef __powerpc64__
+	__asm __volatile("mr %0,13" : "=r"(td));
+#else
+	__asm __volatile("mr %0,2" : "=r"(td));
+#endif
+	return (td);
+}
+#define curthread (__curthread())
+
+#define	PCPU_GET(member)	(pcpup->pc_ ## member)
+
+/*
+ * XXX The implementation of this operation should be made atomic
+ * with respect to preemption.
+ */
+#define	PCPU_ADD(member, value)	(pcpup->pc_ ## member += (value))
+#define	PCPU_INC(member)	PCPU_ADD(member, 1)
+#define	PCPU_PTR(member)	(&pcpup->pc_ ## member)
+#define	PCPU_SET(member,value)	(pcpup->pc_ ## member = (value))
+
+#endif	/* _KERNEL */
+
+#endif	/* !_MACHINE_PCPU_H_ */


Property changes on: trunk/sys/powerpc/include/pcpu.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/pio.h
===================================================================
--- trunk/sys/powerpc/include/pio.h	                        (rev 0)
+++ trunk/sys/powerpc/include/pio.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,305 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1997 Per Fogelstrom, Opsycon AB and RTMX Inc, USA.
+ * 
+ * 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 by
+ *	Per Fogelstrom Opsycon AB for RTMX Inc, North Carolina, USA.
+ * 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.
+ *
+ *	$NetBSD: pio.h,v 1.1 1998/05/15 10:15:54 tsubai Exp $
+ *	$OpenBSD: pio.h,v 1.1 1997/10/13 10:53:47 pefo Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/pio.h 235013 2012-05-04 16:00:22Z nwhitehorn $
+ */
+
+#ifndef _MACHINE_PIO_H_
+#define	_MACHINE_PIO_H_
+/*
+ * I/O macros.
+ */
+
+/*
+ * Use sync so that bus space operations cannot sneak out the bottom of
+ * mutex-protected sections (mutex release does not guarantee completion of
+ * accesses to caching-inhibited memory on some systems)
+ */
+#define powerpc_iomb() __asm __volatile("sync" : : : "memory")
+
+static __inline void
+__outb(volatile u_int8_t *a, u_int8_t v)
+{
+	*a = v;
+	powerpc_iomb();
+}
+
+static __inline void
+__outw(volatile u_int16_t *a, u_int16_t v)
+{
+	*a = v;
+	powerpc_iomb();
+}
+
+static __inline void
+__outl(volatile u_int32_t *a, u_int32_t v)
+{
+	*a = v;
+	powerpc_iomb();
+}
+
+static __inline void
+__outll(volatile u_int64_t *a, u_int64_t v)
+{
+	*a = v;
+	powerpc_iomb();
+}
+
+static __inline void
+__outwrb(volatile u_int16_t *a, u_int16_t v)
+{
+	__asm__ volatile("sthbrx %0, 0, %1" :: "r"(v), "r"(a));
+	powerpc_iomb();
+}
+
+static __inline void
+__outlrb(volatile u_int32_t *a, u_int32_t v)
+{
+	__asm__ volatile("stwbrx %0, 0, %1" :: "r"(v), "r"(a));
+	powerpc_iomb();
+}
+
+static __inline u_int8_t
+__inb(volatile u_int8_t *a)
+{
+	u_int8_t _v_;
+
+	_v_ = *a;
+	powerpc_iomb();
+	return _v_;
+}
+
+static __inline u_int16_t
+__inw(volatile u_int16_t *a)
+{
+	u_int16_t _v_;
+
+	_v_ = *a;
+	powerpc_iomb();
+	return _v_;
+}
+
+static __inline u_int32_t
+__inl(volatile u_int32_t *a)
+{
+	u_int32_t _v_;
+
+	_v_ = *a;
+	powerpc_iomb();
+	return _v_;
+}
+
+static __inline u_int64_t
+__inll(volatile u_int64_t *a)
+{
+	u_int64_t _v_;
+
+	_v_ = *a;
+	powerpc_iomb();
+	return _v_;
+}
+
+static __inline u_int16_t
+__inwrb(volatile u_int16_t *a)
+{
+	u_int16_t _v_;
+
+	__asm__ volatile("lhbrx %0, 0, %1" : "=r"(_v_) : "r"(a));
+	powerpc_iomb();
+	return _v_;
+}
+
+static __inline u_int32_t
+__inlrb(volatile u_int32_t *a)
+{
+	u_int32_t _v_;
+
+	__asm__ volatile("lwbrx %0, 0, %1" : "=r"(_v_) : "r"(a));
+	powerpc_iomb();
+	return _v_;
+}
+
+#define	outb(a,v)	(__outb((volatile u_int8_t *)(a), v))
+#define	out8(a,v)	outb(a,v)
+#define	outw(a,v)	(__outw((volatile u_int16_t *)(a), v))
+#define	out16(a,v)	outw(a,v)
+#define	outl(a,v)	(__outl((volatile u_int32_t *)(a), v))
+#define	out32(a,v)	outl(a,v)
+#define	outll(a,v)	(__outll((volatile u_int64_t *)(a), v))
+#define	out64(a,v)	outll(a,v)
+#define	inb(a)		(__inb((volatile u_int8_t *)(a)))
+#define	in8(a)		inb(a)
+#define	inw(a)		(__inw((volatile u_int16_t *)(a)))
+#define	in16(a)		inw(a)
+#define	inl(a)		(__inl((volatile u_int32_t *)(a)))
+#define	in32(a)		inl(a)
+#define	inll(a)		(__inll((volatile u_int64_t *)(a)))
+#define	in64(a)		inll(a)
+
+#define	out8rb(a,v)	outb(a,v)
+#define	outwrb(a,v)	(__outwrb((volatile u_int16_t *)(a), v))
+#define	out16rb(a,v)	outwrb(a,v)
+#define	outlrb(a,v)	(__outlrb((volatile u_int32_t *)(a), v))
+#define	out32rb(a,v)	outlrb(a,v)
+#define	in8rb(a)	inb(a)
+#define	inwrb(a)	(__inwrb((volatile u_int16_t *)(a)))
+#define	in16rb(a)	inwrb(a)
+#define	inlrb(a)	(__inlrb((volatile u_int32_t *)(a)))
+#define	in32rb(a)	inlrb(a)
+
+
+static __inline void
+__outsb(volatile u_int8_t *a, const u_int8_t *s, size_t c)
+{
+	while (c--)
+		*a = *s++;
+	powerpc_iomb();
+}
+
+static __inline void
+__outsw(volatile u_int16_t *a, const u_int16_t *s, size_t c)
+{
+	while (c--)
+		*a = *s++;
+	powerpc_iomb();
+}
+
+static __inline void
+__outsl(volatile u_int32_t *a, const u_int32_t *s, size_t c)
+{
+	while (c--)
+		*a = *s++;
+	powerpc_iomb();
+}
+
+static __inline void
+__outsll(volatile u_int64_t *a, const u_int64_t *s, size_t c)
+{
+	while (c--)
+		*a = *s++;
+	powerpc_iomb();
+}
+
+static __inline void
+__outswrb(volatile u_int16_t *a, const u_int16_t *s, size_t c)
+{
+	while (c--)
+		__asm__ volatile("sthbrx %0, 0, %1" :: "r"(*s++), "r"(a));
+	powerpc_iomb();
+}
+
+static __inline void
+__outslrb(volatile u_int32_t *a, const u_int32_t *s, size_t c)
+{
+	while (c--)
+		__asm__ volatile("stwbrx %0, 0, %1" :: "r"(*s++), "r"(a));
+	powerpc_iomb();
+}
+
+static __inline void
+__insb(volatile u_int8_t *a, u_int8_t *d, size_t c)
+{
+	while (c--)
+		*d++ = *a;
+	powerpc_iomb();
+}
+
+static __inline void
+__insw(volatile u_int16_t *a, u_int16_t *d, size_t c)
+{
+	while (c--)
+		*d++ = *a;
+	powerpc_iomb();
+}
+
+static __inline void
+__insl(volatile u_int32_t *a, u_int32_t *d, size_t c)
+{
+	while (c--)
+		*d++ = *a;
+	powerpc_iomb();
+}
+
+static __inline void
+__insll(volatile u_int64_t *a, u_int64_t *d, size_t c)
+{
+	while (c--)
+		*d++ = *a;
+	powerpc_iomb();
+}
+
+static __inline void
+__inswrb(volatile u_int16_t *a, u_int16_t *d, size_t c)
+{
+	while (c--)
+		__asm__ volatile("lhbrx %0, 0, %1" : "=r"(*d++) : "r"(a));
+	powerpc_iomb();
+}
+
+static __inline void
+__inslrb(volatile u_int32_t *a, u_int32_t *d, size_t c)
+{
+	while (c--)
+		__asm__ volatile("lwbrx %0, 0, %1" : "=r"(*d++) : "r"(a));
+	powerpc_iomb();
+}
+
+#define	outsb(a,s,c)	(__outsb((volatile u_int8_t *)(a), s, c))
+#define	outs8(a,s,c)	outsb(a,s,c)
+#define	outsw(a,s,c)	(__outsw((volatile u_int16_t *)(a), s, c))
+#define	outs16(a,s,c)	outsw(a,s,c)
+#define	outsl(a,s,c)	(__outsl((volatile u_int32_t *)(a), s, c))
+#define	outs32(a,s,c)	outsl(a,s,c)
+#define	outsll(a,s,c)	(__outsll((volatile u_int64_t *)(a), s, c))
+#define	outs64(a,s,c)	outsll(a,s,c)
+#define	insb(a,d,c)	(__insb((volatile u_int8_t *)(a), d, c))
+#define	ins8(a,d,c)	insb(a,d,c)
+#define	insw(a,d,c)	(__insw((volatile u_int16_t *)(a), d, c))
+#define	ins16(a,d,c)	insw(a,d,c)
+#define	insl(a,d,c)	(__insl((volatile u_int32_t *)(a), d, c))
+#define	ins32(a,d,c)	insl(a,d,c)
+#define	insll(a,d,c)	(__insll((volatile u_int64_t *)(a), d, c))
+#define	ins64(a,d,c)	insll(a,d,c)
+
+#define	outs8rb(a,s,c)	outsb(a,s,c)
+#define	outswrb(a,s,c)	(__outswrb((volatile u_int16_t *)(a), s, c))
+#define	outs16rb(a,s,c)	outswrb(a,s,c)
+#define	outslrb(a,s,c)	(__outslrb((volatile u_int32_t *)(a), s, c))
+#define	outs32rb(a,s,c)	outslrb(a,s,c)
+#define	ins8rb(a,d,c)	insb(a,d,c)
+#define	inswrb(a,d,c)	(__inswrb((volatile u_int16_t *)(a), d, c))
+#define	ins16rb(a,d,c)	inswrb(a,d,c)
+#define	inslrb(a,d,c)	(__inslrb((volatile u_int32_t *)(a), d, c))
+#define	ins32rb(a,d,c)	inslrb(a,d,c)
+
+#endif /*_MACHINE_PIO_H_*/


Property changes on: trunk/sys/powerpc/include/pio.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/platform.h
===================================================================
--- trunk/sys/powerpc/include/platform.h	                        (rev 0)
+++ trunk/sys/powerpc/include/platform.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,63 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: powerpc.h,v 1.3 2000/06/01 00:49:59 matt Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/platform.h 262675 2014-03-02 02:35:46Z jhibbits $
+ */
+
+#ifndef	_MACHINE_PLATFORM_H_
+#define	_MACHINE_PLATFORM_H_
+  
+#include <machine/smp.h>
+#include <machine/pcpu.h>
+
+struct mem_region {
+	vm_offset_t	mr_start;
+	vm_size_t	mr_size;
+};
+
+void	mem_regions(struct mem_region **, int *, struct mem_region **, int *);
+vm_offset_t platform_real_maxaddr(void);
+
+u_long	platform_timebase_freq(struct cpuref *);
+  
+int	platform_smp_first_cpu(struct cpuref *);
+int	platform_smp_next_cpu(struct cpuref *);
+int	platform_smp_get_bsp(struct cpuref *);
+int	platform_smp_start_cpu(struct pcpu *);
+void	platform_smp_ap_init(void);
+  
+const char *installed_platform(void);
+void platform_probe_and_attach(void);
+
+void platform_sleep(void);
+  
+#endif	/* _MACHINE_PLATFORM_H_ */


Property changes on: trunk/sys/powerpc/include/platform.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/platformvar.h
===================================================================
--- trunk/sys/powerpc/include/platformvar.h	                        (rev 0)
+++ trunk/sys/powerpc/include/platformvar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,90 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Peter Grehan
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/platformvar.h 246732 2013-02-13 02:21:45Z rpaulo $
+ */
+
+#ifndef _MACHINE_PLATFORMVAR_H_
+#define _MACHINE_PLATFORMVAR_H_
+
+/*
+ * A PowerPC platform implementation is declared with a kernel object and
+ * an associated method table, similar to a device driver.
+ *
+ * e.g.
+ *
+ * static platform_method_t chrp_methods[] = {
+ *	PLATFORMMETHOD(platform_probe,		chrp_probe),
+ *	PLATFORMMETHOD(platform_mem_regions,	ofw_mem_regions),
+ *  ...
+ *	PLATFORMMETHOD(platform_smp_first_cpu,	chrp_smp_first_cpu),
+ *	{ 0, 0 }
+ * };
+ *
+ * static platform_def_t chrp_platform = {
+ * 	"chrp",
+ *	chrp_methods,
+ *	sizeof(chrp_platform_softc),	// or 0 if no softc
+ * };
+ *
+ * PLATFORM_DEF(chrp_platform);
+ */
+
+#include <sys/kobj.h>
+
+struct platform_kobj {
+	/*
+	 * A platform instance is a kernel object
+	 */
+	KOBJ_FIELDS;
+
+	/*
+	 * Utility elements that an instance may use
+	 */
+	struct mtx	platform_mtx;	/* available for instance use */
+	void		*platform_iptr;	/* instance data pointer */
+
+	/*
+	 * Opaque data that can be overlaid with an instance-private
+	 * structure. Platform code can test that this is large enough at
+	 * compile time with a sizeof() test againt it's softc. There
+	 * is also a run-time test when the platform kernel object is
+	 * registered.
+	 */
+#define PLATFORM_OPAQUESZ	64
+	u_int		platform_opaque[PLATFORM_OPAQUESZ];
+};
+
+typedef struct platform_kobj	*platform_t;
+typedef struct kobj_class	platform_def_t;
+#define platform_method_t	kobj_method_t
+
+#define PLATFORMMETHOD		KOBJMETHOD
+#define	PLATFORMMETHOD_END	KOBJMETHOD_END
+
+#define PLATFORM_DEF(name)	DATA_SET(platform_set, name)
+
+#endif /* _MACHINE_PLATFORMVAR_H_ */


Property changes on: trunk/sys/powerpc/include/platformvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/pmap.h
===================================================================
--- trunk/sys/powerpc/include/pmap.h	                        (rev 0)
+++ trunk/sys/powerpc/include/pmap.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,265 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2006 Semihalf, Marian Balakowicz <m8 at semihalf.com>
+ * All rights reserved.
+ *
+ * Adapted for Freescale's e500 core CPUs.
+ *
+ * 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/pmap.h 270439 2014-08-24 07:53:15Z kib $
+ */
+/*-
+ * 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.
+ *
+ *	from: $NetBSD: pmap.h,v 1.17 2000/03/30 16:18:24 jdolecek Exp $
+ */
+
+#ifndef	_MACHINE_PMAP_H_
+#define	_MACHINE_PMAP_H_
+
+#include <sys/queue.h>
+#include <sys/tree.h>
+#include <sys/_cpuset.h>
+#include <sys/_lock.h>
+#include <sys/_mutex.h>
+#include <machine/sr.h>
+#include <machine/pte.h>
+#include <machine/slb.h>
+#include <machine/tlb.h>
+
+struct pmap_md {
+	u_int		md_index;
+	vm_paddr_t      md_paddr;
+	vm_offset_t     md_vaddr;
+	vm_size_t       md_size;
+};
+
+#if defined(AIM)
+
+#if !defined(NPMAPS)
+#define	NPMAPS		32768
+#endif /* !defined(NPMAPS) */
+
+struct	slbtnode;
+struct	pmap;
+typedef	struct pmap *pmap_t;
+
+struct pvo_entry {
+	LIST_ENTRY(pvo_entry) pvo_vlink;	/* Link to common virt page */
+	LIST_ENTRY(pvo_entry) pvo_olink;	/* Link to overflow entry */
+	RB_ENTRY(pvo_entry) pvo_plink;	/* Link to pmap entries */
+	union {
+		struct	pte pte;		/* 32 bit PTE */
+		struct	lpte lpte;		/* 64 bit PTE */
+	} pvo_pte;
+	pmap_t		pvo_pmap;		/* Owning pmap */
+	vm_offset_t	pvo_vaddr;		/* VA of entry */
+	uint64_t	pvo_vpn;		/* Virtual page number */
+};
+LIST_HEAD(pvo_head, pvo_entry);
+RB_HEAD(pvo_tree, pvo_entry);
+int pvo_vaddr_compare(struct pvo_entry *, struct pvo_entry *);
+RB_PROTOTYPE(pvo_tree, pvo_entry, pvo_plink, pvo_vaddr_compare);
+
+#define	PVO_PTEGIDX_MASK	0x007UL		/* which PTEG slot */
+#define	PVO_PTEGIDX_VALID	0x008UL		/* slot is valid */
+#define	PVO_WIRED		0x010UL		/* PVO entry is wired */
+#define	PVO_MANAGED		0x020UL		/* PVO entry is managed */
+#define	PVO_BOOTSTRAP		0x080UL		/* PVO entry allocated during
+						   bootstrap */
+#define PVO_LARGE		0x200UL		/* large page */
+#define	PVO_VADDR(pvo)		((pvo)->pvo_vaddr & ~ADDR_POFF)
+#define	PVO_PTEGIDX_GET(pvo)	((pvo)->pvo_vaddr & PVO_PTEGIDX_MASK)
+#define	PVO_PTEGIDX_ISSET(pvo)	((pvo)->pvo_vaddr & PVO_PTEGIDX_VALID)
+#define	PVO_PTEGIDX_CLR(pvo)	\
+	((void)((pvo)->pvo_vaddr &= ~(PVO_PTEGIDX_VALID|PVO_PTEGIDX_MASK)))
+#define	PVO_PTEGIDX_SET(pvo, i)	\
+	((void)((pvo)->pvo_vaddr |= (i)|PVO_PTEGIDX_VALID))
+#define	PVO_VSID(pvo)		((pvo)->pvo_vpn >> 16)
+
+struct	pmap {
+	struct	mtx	pm_mtx;
+	
+    #ifdef __powerpc64__
+	struct slbtnode	*pm_slb_tree_root;
+	struct slb	**pm_slb;
+	int		pm_slb_len;
+    #else
+	register_t	pm_sr[16];
+    #endif
+	cpuset_t	pm_active;
+
+	struct pmap	*pmap_phys;
+	struct		pmap_statistics	pm_stats;
+	struct pvo_tree pmap_pvo;
+};
+
+struct	md_page {
+	u_int64_t	 mdpg_attrs;
+	vm_memattr_t	 mdpg_cache_attrs;
+	struct	pvo_head mdpg_pvoh;
+};
+
+#define	pmap_page_get_memattr(m)	((m)->md.mdpg_cache_attrs)
+#define	pmap_page_is_mapped(m)	(!LIST_EMPTY(&(m)->md.mdpg_pvoh))
+
+/*
+ * Return the VSID corresponding to a given virtual address.
+ * If no VSID is currently defined, it will allocate one, and add
+ * it to a free slot if available.
+ *
+ * NB: The PMAP MUST be locked already.
+ */
+uint64_t va_to_vsid(pmap_t pm, vm_offset_t va);
+
+/* Lock-free, non-allocating lookup routines */
+uint64_t kernel_va_to_slbv(vm_offset_t va);
+struct slb *user_va_to_slb_entry(pmap_t pm, vm_offset_t va);
+
+uint64_t allocate_user_vsid(pmap_t pm, uint64_t esid, int large);
+void	free_vsid(pmap_t pm, uint64_t esid, int large);
+void	slb_insert_user(pmap_t pm, struct slb *slb);
+void	slb_insert_kernel(uint64_t slbe, uint64_t slbv);
+
+struct slbtnode *slb_alloc_tree(void);
+void     slb_free_tree(pmap_t pm);
+struct slb **slb_alloc_user_cache(void);
+void	slb_free_user_cache(struct slb **);
+
+#else
+
+struct pmap {
+	struct mtx		pm_mtx;		/* pmap mutex */
+	tlbtid_t		pm_tid[MAXCPU];	/* TID to identify this pmap entries in TLB */
+	cpuset_t		pm_active;	/* active on cpus */
+	struct pmap_statistics	pm_stats;	/* pmap statistics */
+
+	/* Page table directory, array of pointers to page tables. */
+	pte_t			*pm_pdir[PDIR_NENTRIES];
+
+	/* List of allocated ptbl bufs (ptbl kva regions). */
+	TAILQ_HEAD(, ptbl_buf)	pm_ptbl_list;
+};
+typedef	struct pmap *pmap_t;
+
+struct pv_entry {
+	pmap_t pv_pmap;
+	vm_offset_t pv_va;
+	TAILQ_ENTRY(pv_entry) pv_link;
+};
+typedef struct pv_entry *pv_entry_t;
+
+struct md_page {
+	TAILQ_HEAD(, pv_entry) pv_list;
+};
+
+#define	pmap_page_get_memattr(m)	VM_MEMATTR_DEFAULT
+#define	pmap_page_is_mapped(m)	(!TAILQ_EMPTY(&(m)->md.pv_list))
+
+#endif /* AIM */
+
+extern	struct pmap kernel_pmap_store;
+#define	kernel_pmap	(&kernel_pmap_store)
+
+#ifdef _KERNEL
+
+#define	PMAP_LOCK(pmap)		mtx_lock(&(pmap)->pm_mtx)
+#define	PMAP_LOCK_ASSERT(pmap, type) \
+				mtx_assert(&(pmap)->pm_mtx, (type))
+#define	PMAP_LOCK_DESTROY(pmap)	mtx_destroy(&(pmap)->pm_mtx)
+#define	PMAP_LOCK_INIT(pmap)	mtx_init(&(pmap)->pm_mtx, \
+				    (pmap == kernel_pmap) ? "kernelpmap" : \
+				    "pmap", NULL, MTX_DEF)
+#define	PMAP_LOCKED(pmap)	mtx_owned(&(pmap)->pm_mtx)
+#define	PMAP_MTX(pmap)		(&(pmap)->pm_mtx)
+#define	PMAP_TRYLOCK(pmap)	mtx_trylock(&(pmap)->pm_mtx)
+#define	PMAP_UNLOCK(pmap)	mtx_unlock(&(pmap)->pm_mtx)
+
+#define	pmap_page_is_write_mapped(m)	(((m)->aflags & PGA_WRITEABLE) != 0)
+
+void		pmap_bootstrap(vm_offset_t, vm_offset_t);
+void		pmap_kenter(vm_offset_t va, vm_paddr_t pa);
+void		pmap_kenter_attr(vm_offset_t va, vm_offset_t pa, vm_memattr_t);
+void		pmap_kremove(vm_offset_t);
+void		*pmap_mapdev(vm_paddr_t, vm_size_t);
+void		*pmap_mapdev_attr(vm_offset_t, vm_size_t, vm_memattr_t);
+void		pmap_unmapdev(vm_offset_t, vm_size_t);
+void		pmap_page_set_memattr(vm_page_t, vm_memattr_t);
+void		pmap_deactivate(struct thread *);
+vm_paddr_t	pmap_kextract(vm_offset_t);
+int		pmap_dev_direct_mapped(vm_paddr_t, vm_size_t);
+boolean_t	pmap_mmu_install(char *name, int prio);
+
+#define	vtophys(va)	pmap_kextract((vm_offset_t)(va))
+
+#define PHYS_AVAIL_SZ	256	/* Allows up to 16GB Ram on pSeries with
+				 * logical memory block size of 64MB.
+				 * For more Ram increase the lmb or this value.
+				 */
+
+extern	vm_offset_t phys_avail[PHYS_AVAIL_SZ];
+extern	vm_offset_t virtual_avail;
+extern	vm_offset_t virtual_end;
+
+extern	vm_offset_t msgbuf_phys;
+
+extern	int pmap_bootstrapped;
+
+extern vm_offset_t pmap_dumpsys_map(struct pmap_md *, vm_size_t, vm_size_t *);
+extern void pmap_dumpsys_unmap(struct pmap_md *, vm_size_t, vm_offset_t);
+
+extern struct pmap_md *pmap_scan_md(struct pmap_md *);
+
+vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size);
+
+#endif
+
+#endif /* !_MACHINE_PMAP_H_ */


Property changes on: trunk/sys/powerpc/include/pmap.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/pmc_mdep.h
===================================================================
--- trunk/sys/powerpc/include/pmc_mdep.h	                        (rev 0)
+++ trunk/sys/powerpc/include/pmc_mdep.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,39 @@
+/* $MidnightBSD$ */
+/*-
+ * This file is in the public domain.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/pmc_mdep.h 263122 2014-03-14 00:12:53Z jhibbits $
+ */
+
+#ifndef _MACHINE_PMC_MDEP_H_
+#define	_MACHINE_PMC_MDEP_H_
+
+#define PMC_MDEP_CLASS_INDEX_CPU	1
+#define PMC_MDEP_CLASS_INDEX_PPC7450	1
+#define PMC_MDEP_CLASS_INDEX_PPC970	1
+
+union pmc_md_op_pmcallocate {
+	uint64_t		__pad[4];
+};
+
+/* Logging */
+#define	PMCLOG_READADDR		PMCLOG_READ32
+#define	PMCLOG_EMITADDR		PMCLOG_EMIT32
+
+#if	_KERNEL
+
+struct pmc_md_powerpc_pmc {
+	uint32_t	pm_powerpc_evsel;
+};
+
+union pmc_md_pmc {
+	struct pmc_md_powerpc_pmc	pm_powerpc;
+};
+
+#define	PMC_TRAPFRAME_TO_PC(TF)	((TF)->srr0)
+#define	PMC_TRAPFRAME_TO_FP(TF)	((TF)->fixreg[1])
+#define	PMC_TRAPFRAME_TO_SP(TF)	(0)
+
+#endif
+
+#endif /* !_MACHINE_PMC_MDEP_H_ */


Property changes on: trunk/sys/powerpc/include/pmc_mdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/proc.h
===================================================================
--- trunk/sys/powerpc/include/proc.h	                        (rev 0)
+++ trunk/sys/powerpc/include/proc.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,78 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: proc.h,v 1.2 1997/04/16 22:57:48 thorpej Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/proc.h 256007 2013-10-02 20:40:21Z nwhitehorn $
+ */
+
+#ifndef _MACHINE_PROC_H_
+#define	_MACHINE_PROC_H_
+
+/*
+ * Machine-dependent part of the proc structure
+ */
+struct mdthread {
+	int	md_spinlock_count;	/* (k) */
+	register_t md_saved_msr;	/* (k) */
+};
+
+struct mdproc {
+};
+
+#ifdef __powerpc64__
+#define	KINFO_PROC_SIZE 1088
+#define	KINFO_PROC32_SIZE 768
+#else
+#define	KINFO_PROC_SIZE 768
+#endif
+
+#ifdef _KERNEL
+
+#include <machine/pcb.h>
+
+/* Get the current kernel thread stack usage. */
+#define	GET_STACK_USAGE(total, used) do {				\
+	struct thread *td = curthread;					\
+	(total) = td->td_kstack_pages * PAGE_SIZE - sizeof(struct pcb);	\
+	(used) = (char *)td->td_kstack +				\
+	    td->td_kstack_pages * PAGE_SIZE -				\
+	    (char *)&td;						\
+} while (0)
+
+struct syscall_args {
+	u_int code;
+	struct sysent *callp;
+	register_t args[10];
+	int narg;
+};
+#endif
+
+#endif /* !_MACHINE_PROC_H_ */


Property changes on: trunk/sys/powerpc/include/proc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/profile.h
===================================================================
--- trunk/sys/powerpc/include/profile.h	                        (rev 0)
+++ trunk/sys/powerpc/include/profile.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,223 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ * 
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution at CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ *	from: NetBSD: profile.h,v 1.9 1997/04/06 08:47:37 cgd Exp
+ *	from: FreeBSD: src/sys/alpha/include/profile.h,v 1.4 1999/12/29
+ * $FreeBSD: stable/10/sys/powerpc/include/profile.h 236141 2012-05-27 10:25:20Z raj $
+ */
+
+#ifndef _MACHINE_PROFILE_H_
+#define	_MACHINE_PROFILE_H_
+
+#define	_MCOUNT_DECL	void __mcount
+
+#define	FUNCTION_ALIGNMENT	4
+
+typedef __ptrdiff_t	fptrdiff_t;
+
+/*
+ * The mcount trampoline macro, expanded in libc/gmon/mcount.c
+ *
+ * For PowerPC SVR4 ABI profiling, the compiler will insert
+ * a data declaration and code sequence at the start of a routine of the form
+ *
+ * .function_mc:       	.data
+ *			.align	2
+ *			.long	0
+ *			.text
+ *
+ * function:		mflr	%r0
+ *			addis	%r11,%r0, .function_mc at ha
+ *			stw	%r0,4(%r1)
+ *			addi	%r0,%r11, .function_mc at l
+ *			bl	_mcount
+ *
+ * The link register is saved in the LR save word in the caller's
+ * stack frame, r0 is set up to point to the allocated longword,
+ * and control is transferred to _mcount.
+ *
+ * On return from _mcount, the routine should function as it would
+ * with no profiling so _mcount must restore register state to that upon
+ * entry. Any routine called by the _mcount trampoline will save
+ * callee-save registers, so _mcount must make sure it saves volatile
+ * registers that may have state after it returns i.e. parameter registers.
+ *
+ * The FreeBSD libc mcount routine ignores the r0 longword pointer, but
+ * instead requires as parameters the current PC and called PC. The current
+ * PC is obtained from the link register, as a result of "bl _mcount" in
+ * the stub, while the caller's PC is obtained from the LR save word.
+ *
+ * On return from libc mcount, the return is done indirectly with the
+ * ctr register rather than the link register, to allow the link register
+ * to be restored to what it was on entry to the profiled routine.
+ */
+
+#ifdef __powerpc64__
+#define	MCOUNT					\
+__asm(	"	.text				\n" \
+	"	.align	2			\n" \
+	"	.globl	_mcount			\n" \
+	"	.section \".opd\",\"aw\"	\n" \
+	"	.align	3			\n" \
+	"_mcount:				\n" \
+	"	.quad .L._mcount,.TOC. at tocbase,0\n" \
+	"	.previous			\n" \
+	"	.size   _mcount,24		\n" \
+	"	.type	_mcount, at function	\n" \
+	"	.align	4			\n" \
+	".L._mcount:				\n" \
+	"	stdu	%r1,-(288+128)(%r1)	\n" \
+	"	std	%r3,48(%r1)		\n" \
+	"	std	%r4,56(%r1)		\n" \
+	"	std	%r5,64(%r1)		\n" \
+	"	std	%r6,72(%r1)		\n" \
+	"	std	%r7,80(%r1)		\n" \
+	"	std	%r8,88(%r1)		\n" \
+	"	std	%r9,96(%r1)		\n" \
+	"	std	%r10,104(%r1)		\n" \
+	"	mflr	%r4			\n" \
+	"	std	%r4,112(%r1)		\n" \
+	"	ld	%r3,0(%r1)		\n" \
+	"	ld	%r3,0(%r3)		\n" \
+	"	ld	%r3,16(%r3)		\n" \
+	"	bl	__mcount		\n" \
+	"	nop				\n" \
+	"	ld	%r4,112(%r1)		\n" \
+	"	mtlr	%r4			\n" \
+	"	ld	%r3,48(%r1)		\n" \
+	"	ld	%r4,56(%r1)		\n" \
+	"	ld	%r5,64(%r1)		\n" \
+	"	ld	%r6,72(%r1)		\n" \
+	"	ld	%r7,80(%r1)		\n" \
+	"	ld	%r8,88(%r1)		\n" \
+	"	ld	%r9,96(%r1)		\n" \
+	"	ld	%r10,104(%r1)		\n" \
+	"	addi	%r1,%r1,(288+128)	\n" \
+	"	blr				\n");
+#else
+
+#ifdef PIC
+#define _PLT "@plt"
+#else
+#define _PLT
+#endif
+
+#define	MCOUNT					\
+__asm(	"	.globl	_mcount			\n" \
+	"	.type	_mcount, at function	\n" \
+	"	.align	4			\n" \
+	"_mcount:				\n" \
+	"	stwu	%r1,-64(%r1)		\n" \
+	"	stw	%r3,16(%r1)		\n" \
+	"	stw	%r4,20(%r1)		\n" \
+	"	stw	%r5,24(%r1)		\n" \
+	"	stw	%r6,28(%r1)		\n" \
+	"	stw	%r7,32(%r1)		\n" \
+	"	stw	%r8,36(%r1)		\n" \
+	"	stw	%r9,40(%r1)		\n" \
+	"	stw	%r10,44(%r1)		\n" \
+	"	mflr	%r4			\n" \
+	"	stw	%r4,48(%r1)		\n" \
+	"	lwz	%r3,68(%r1)		\n" \
+	"	bl	__mcount" _PLT "	\n" \
+	"	lwz	%r3,68(%r1)		\n" \
+	"	mtlr	%r3			\n" \
+	"	lwz	%r4,48(%r1)		\n" \
+	"	mtctr	%r4			\n" \
+	"	lwz	%r3,16(%r1)		\n" \
+	"	lwz	%r4,20(%r1)		\n" \
+	"	lwz	%r5,24(%r1)		\n" \
+	"	lwz	%r6,28(%r1)		\n" \
+	"	lwz	%r7,32(%r1)		\n" \
+	"	lwz	%r8,36(%r1)		\n" \
+	"	lwz	%r9,40(%r1)		\n" \
+	"	lwz	%r10,44(%r1)		\n" \
+	"	addi	%r1,%r1,64		\n" \
+	"	bctr				\n" \
+	"_mcount_end:				\n" \
+	"	.size	_mcount,_mcount_end-_mcount");
+#endif
+
+#ifdef _KERNEL
+#define	MCOUNT_ENTER(s)		s = intr_disable()
+#define	MCOUNT_EXIT(s)		intr_restore(s)
+#define	MCOUNT_DECL(s)		register_t s;
+
+#ifndef COMPILING_LINT
+#ifdef AIM
+#include <machine/trap.h>
+#define	__PROFILE_VECTOR_BASE	EXC_RST
+#define	__PROFILE_VECTOR_TOP	(EXC_LAST + 0x100)
+#endif	/* AIM */
+#if defined(BOOKE)
+extern char interrupt_vector_base[];
+extern char interrupt_vector_top[];
+#define	__PROFILE_VECTOR_BASE	(uintfptr_t)interrupt_vector_base
+#define	__PROFILE_VECTOR_TOP	(uintfptr_t)interrupt_vector_top
+#endif	/* BOOKE_E500 || BOOKE_PPC4XX */
+
+#endif	/* !COMPILING_LINT */
+
+#ifndef __PROFILE_VECTOR_BASE
+#define	__PROFILE_VECTOR_BASE	0
+#endif
+#ifndef __PROFILE_VECTOR_TOP
+#define	__PROFILE_VECTOR_TOP	1
+#endif
+
+static __inline void
+powerpc_profile_interrupt(void)
+{
+}
+
+static __inline void
+powerpc_profile_userspace(void)
+{
+}
+
+#define	MCOUNT_FROMPC_USER(pc)				\
+	((pc < (uintfptr_t)VM_MAXUSER_ADDRESS) ?	\
+	    (uintfptr_t)powerpc_profile_userspace : pc)
+
+#define	MCOUNT_FROMPC_INTR(pc)				\
+	((pc >= __PROFILE_VECTOR_BASE &&		\
+	  pc < __PROFILE_VECTOR_TOP) ?			\
+	    (uintfptr_t)powerpc_profile_interrupt : ~0U)
+
+void __mcount(uintfptr_t frompc, uintfptr_t selfpc);
+
+#else	/* !_KERNEL */
+
+#ifdef __powerpc64__
+typedef u_long	uintfptr_t;
+#else
+typedef u_int	uintfptr_t;
+#endif
+
+#endif	/* _KERNEL */
+
+#endif /* !_MACHINE_PROFILE_H_ */


Property changes on: trunk/sys/powerpc/include/profile.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/psl.h
===================================================================
--- trunk/sys/powerpc/include/psl.h	                        (rev 0)
+++ trunk/sys/powerpc/include/psl.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,106 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: psl.h,v 1.5 2000/11/19 19:52:37 matt Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/psl.h 271171 2014-09-05 15:13:41Z jhibbits $
+ */
+
+#ifndef	_MACHINE_PSL_H_
+#define	_MACHINE_PSL_H_
+
+/*
+ * Machine State Register (MSR) - All cores
+ */
+#define	PSL_VEC		0x02000000UL	/* AltiVec/SPE vector unit available */
+#define	PSL_EE		0x00008000UL	/* external interrupt enable */
+#define	PSL_PR		0x00004000UL	/* privilege mode (1 == user) */
+#define	PSL_FP		0x00002000UL	/* floating point enable */
+#define	PSL_ME		0x00001000UL	/* machine check enable */
+#define	PSL_FE0		0x00000800UL	/* floating point interrupt mode 0 */
+#define	PSL_BE		0x00000200UL	/* branch trace enable */
+#define	PSL_FE1		0x00000100UL	/* floating point interrupt mode 1 */
+#define	PSL_PMM		0x00000004UL	/* performance monitor mark */
+
+/* Machine State Register - Book-E cores */
+#define PSL_UCLE	0x04000000UL	/* User mode cache lock enable */
+#define PSL_WE		0x00040000UL	/* Wait state enable */
+#define PSL_CE		0x00020000UL	/* Critical interrupt enable */
+#define PSL_UBLE	0x00000400UL	/* BTB lock enable - e500 only */
+#define PSL_DWE		0x00000400UL	/* Debug Wait Enable - 440 only*/
+#define PSL_DE		0x00000200UL	/* Debug interrupt enable */
+#define PSL_IS		0x00000020UL	/* Instruction address space */
+#define PSL_DS		0x00000010UL	/* Data address space */
+
+/* Machine State Register (MSR) - AIM cores */
+#ifdef __powerpc64__
+#define PSL_SF		0x8000000000000000UL	/* 64-bit addressing */
+#define PSL_HV		0x1000000000000000UL	/* hyper-privileged mode */
+#endif
+
+#define	PSL_POW		0x00040000UL	/* power management */
+#define	PSL_ILE		0x00010000UL	/* interrupt endian mode (1 == le) */
+#define	PSL_SE		0x00000400UL	/* single-step trace enable */
+#define	PSL_IP		0x00000040UL	/* interrupt prefix - 601 only */
+#define	PSL_IR		0x00000020UL	/* instruction address relocation */
+#define	PSL_DR		0x00000010UL	/* data address relocation */
+#define	PSL_RI		0x00000002UL	/* recoverable interrupt */
+#define	PSL_LE		0x00000001UL	/* endian mode (1 == le) */
+
+/*
+ * Floating-point exception modes:
+ */
+#define	PSL_FE_DIS	0		/* none */
+#define	PSL_FE_NONREC	PSL_FE1		/* imprecise non-recoverable */
+#define	PSL_FE_REC	PSL_FE0		/* imprecise recoverable */
+#define	PSL_FE_PREC	(PSL_FE0 | PSL_FE1) /* precise */
+#define	PSL_FE_DFLT	PSL_FE_DIS	/* default == none */
+
+#if defined(BOOKE_E500)
+/* Initial kernel MSR, use IS=1 ad DS=1. */
+#define PSL_KERNSET_INIT	(PSL_IS | PSL_DS)
+#define PSL_KERNSET		(PSL_CE | PSL_ME | PSL_EE)
+#define PSL_SRR1_MASK	0x00000000UL	/* No mask on Book-E */
+#elif defined(BOOKE_PPC4XX)
+#define PSL_KERNSET	(PSL_CE | PSL_ME | PSL_EE | PSL_FP)
+#define PSL_SRR1_MASK	0x00000000UL	/* No mask on Book-E */
+#elif defined(AIM)
+#ifdef __powerpc64__
+#define	PSL_KERNSET	(PSL_SF | PSL_EE | PSL_ME | PSL_IR | PSL_DR | PSL_RI)
+#else
+#define	PSL_KERNSET	(PSL_EE | PSL_ME | PSL_IR | PSL_DR | PSL_RI)
+#endif
+#define PSL_SRR1_MASK	0x783f0000UL	/* Bits 1-4, 10-15 (ppc32), 33-36, 42-47 (ppc64) */
+#endif
+
+#define	PSL_USERSET	(PSL_KERNSET | PSL_PR)
+#define	PSL_USERSTATIC	(~(PSL_VEC | PSL_FP | PSL_FE0 | PSL_FE1) & ~PSL_SRR1_MASK)
+
+#endif	/* _MACHINE_PSL_H_ */


Property changes on: trunk/sys/powerpc/include/psl.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/pte.h
===================================================================
--- trunk/sys/powerpc/include/pte.h	                        (rev 0)
+++ trunk/sys/powerpc/include/pte.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,284 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: pte.h,v 1.2 1998/08/31 14:43:40 tsubai Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/pte.h 255415 2013-09-09 12:44:48Z nwhitehorn $
+ */
+
+#ifndef	_MACHINE_PTE_H_
+#define	_MACHINE_PTE_H_
+
+#if defined(AIM)
+
+/*
+ * Page Table Entries
+ */
+#ifndef	LOCORE
+
+/* 32-bit PTE */
+struct pte {
+	u_int32_t pte_hi;
+	u_int32_t pte_lo;
+};
+
+struct pteg {
+	struct	pte pt[8];
+};
+
+/* 64-bit (long) PTE */
+struct lpte {
+	u_int64_t pte_hi;
+	u_int64_t pte_lo;
+};
+
+struct lpteg {
+	struct lpte pt[8];
+};
+
+#endif	/* LOCORE */
+
+/* 32-bit PTE definitions */
+
+/* High word: */
+#define	PTE_VALID	0x80000000
+#define	PTE_VSID_SHFT	7
+#define	PTE_HID		0x00000040
+#define	PTE_API		0x0000003f
+/* Low word: */
+#define	PTE_RPGN	0xfffff000
+#define	PTE_REF		0x00000100
+#define	PTE_CHG		0x00000080
+#define	PTE_WIMG	0x00000078
+#define	PTE_W		0x00000040
+#define	PTE_I		0x00000020
+#define	PTE_M		0x00000010
+#define	PTE_G		0x00000008
+#define	PTE_PP		0x00000003
+#define	PTE_SO		0x00000000	/* Super. Only       (U: XX, S: RW) */
+#define PTE_SW		0x00000001	/* Super. Write-Only (U: RO, S: RW) */
+#define	PTE_BW		0x00000002	/* Supervisor        (U: RW, S: RW) */
+#define	PTE_BR		0x00000003	/* Both Read Only    (U: RO, S: RO) */
+#define	PTE_RW		PTE_BW
+#define	PTE_RO		PTE_BR
+
+#define	PTE_EXEC	0x00000200	/* pseudo bit in attrs; page is exec */
+
+/* 64-bit PTE definitions */
+
+/* High quadword: */
+#define LPTE_VSID_SHIFT		12
+#define LPTE_AVPN_MASK		0xFFFFFFFFFFFFFF80ULL
+#define LPTE_API		0x0000000000000F80ULL
+#define LPTE_SWBITS		0x0000000000000078ULL
+#define LPTE_WIRED		0x0000000000000010ULL
+#define LPTE_LOCKED		0x0000000000000008ULL
+#define LPTE_BIG		0x0000000000000004ULL	/* 4kb/16Mb page */
+#define LPTE_HID		0x0000000000000002ULL
+#define LPTE_VALID		0x0000000000000001ULL
+
+/* Low quadword: */
+#define EXTEND_PTE(x)	UINT64_C(x)	/* make constants 64-bit */
+#define	LPTE_RPGN	0xfffffffffffff000ULL
+#define	LPTE_REF	EXTEND_PTE( PTE_REF )
+#define	LPTE_CHG	EXTEND_PTE( PTE_CHG )
+#define	LPTE_WIMG	EXTEND_PTE( PTE_WIMG )
+#define	LPTE_W		EXTEND_PTE( PTE_W )
+#define	LPTE_I		EXTEND_PTE( PTE_I )
+#define	LPTE_M		EXTEND_PTE( PTE_M )
+#define	LPTE_G		EXTEND_PTE( PTE_G )
+#define	LPTE_NOEXEC	0x0000000000000004ULL
+#define	LPTE_PP		EXTEND_PTE( PTE_PP )
+
+#define	LPTE_SO		EXTEND_PTE( PTE_SO )	/* Super. Only */
+#define	LPTE_SW		EXTEND_PTE( PTE_SW )	/* Super. Write-Only */
+#define	LPTE_BW		EXTEND_PTE( PTE_BW )	/* Supervisor */
+#define	LPTE_BR		EXTEND_PTE( PTE_BR )	/* Both Read Only */
+#define	LPTE_RW		LPTE_BW
+#define	LPTE_RO		LPTE_BR
+
+#ifndef	LOCORE
+typedef	struct pte pte_t;
+typedef	struct lpte lpte_t;
+#endif	/* LOCORE */
+
+/*
+ * Extract bits from address
+ */
+#define	ADDR_SR_SHFT	28
+#define	ADDR_PIDX	0x0ffff000UL
+#define	ADDR_PIDX_SHFT	12
+#define	ADDR_API_SHFT	22
+#define	ADDR_API_SHFT64	16
+#define	ADDR_POFF	0x00000fffUL
+
+/*
+ * Bits in DSISR:
+ */
+#define	DSISR_DIRECT	0x80000000
+#define	DSISR_NOTFOUND	0x40000000
+#define	DSISR_PROTECT	0x08000000
+#define	DSISR_INVRX	0x04000000
+#define	DSISR_STORE	0x02000000
+#define	DSISR_DABR	0x00400000
+#define	DSISR_SEGMENT	0x00200000
+#define	DSISR_EAR	0x00100000
+
+/*
+ * Bits in SRR1 on ISI:
+ */
+#define	ISSRR1_NOTFOUND	0x40000000
+#define	ISSRR1_DIRECT	0x10000000
+#define	ISSRR1_PROTECT	0x08000000
+#define	ISSRR1_SEGMENT	0x00200000
+
+#ifdef	_KERNEL
+#ifndef	LOCORE
+extern u_int dsisr(void);
+#endif	/* _KERNEL */
+#endif	/* LOCORE */
+
+#else /* BOOKE */
+
+#include <machine/tlb.h>
+
+/*
+ * 1st level - page table directory (pdir)
+ *
+ * pdir consists of 1024 entries, each being a pointer to
+ * second level entity, i.e. the actual page table (ptbl).
+ */
+#define PDIR_SHIFT	22
+#define PDIR_SIZE	(1 << PDIR_SHIFT)	/* va range mapped by pdir */
+#define PDIR_MASK	(~(PDIR_SIZE - 1))
+#define PDIR_NENTRIES	1024			/* number of page tables in pdir */
+
+/* Returns pdir entry number for given va */
+#define PDIR_IDX(va)	((va) >> PDIR_SHIFT)
+
+#define PDIR_ENTRY_SHIFT 2	/* entry size is 2^2 = 4 bytes */
+
+/*
+ * 2nd level - page table (ptbl)
+ *
+ * Page table covers 1024 page table entries. Page
+ * table entry (pte) is 32 bit wide and defines mapping
+ * for a single page.
+ */
+#define PTBL_SHIFT	PAGE_SHIFT
+#define PTBL_SIZE	PAGE_SIZE		/* va range mapped by ptbl entry */
+#define PTBL_MASK	((PDIR_SIZE - 1) & ~((1 << PAGE_SHIFT) - 1))
+#define PTBL_NENTRIES	1024			/* number of pages mapped by ptbl */
+
+/* Returns ptbl entry number for given va */
+#define PTBL_IDX(va)	(((va) & PTBL_MASK) >> PTBL_SHIFT)
+
+/* Size of ptbl in pages, 1024 entries, each sizeof(struct pte_entry). */
+#define PTBL_PAGES	2
+#define PTBL_ENTRY_SHIFT 3	/* entry size is 2^3 = 8 bytes */
+
+/*
+ * Flags for pte_remove() routine.
+ */
+#define PTBL_HOLD	0x00000001	/* do not unhold ptbl pages */
+#define PTBL_UNHOLD	0x00000002	/* unhold and attempt to free ptbl pages */
+
+#define PTBL_HOLD_FLAG(pmap)	(((pmap) == kernel_pmap) ? PTBL_HOLD : PTBL_UNHOLD)
+
+/*
+ * Page Table Entry definitions and macros.
+ */
+#ifndef	LOCORE
+struct pte {
+	vm_offset_t rpn;
+	uint32_t flags;
+};
+typedef struct pte pte_t;
+#endif
+
+/* RPN mask, TLB0 4K pages */
+#define PTE_PA_MASK	PAGE_MASK
+
+#if defined(BOOKE_E500)
+
+/* PTE bits assigned to MAS2, MAS3 flags */
+#define PTE_W		MAS2_W
+#define PTE_I		MAS2_I
+#define PTE_M		MAS2_M
+#define PTE_G		MAS2_G
+#define PTE_MAS2_MASK	(MAS2_G | MAS2_M | MAS2_I | MAS2_W)
+
+#define PTE_MAS3_SHIFT	8
+#define PTE_UX		(MAS3_UX << PTE_MAS3_SHIFT)
+#define PTE_SX		(MAS3_SX << PTE_MAS3_SHIFT)
+#define PTE_UW		(MAS3_UW << PTE_MAS3_SHIFT)
+#define PTE_SW		(MAS3_SW << PTE_MAS3_SHIFT)
+#define PTE_UR		(MAS3_UR << PTE_MAS3_SHIFT)
+#define PTE_SR		(MAS3_SR << PTE_MAS3_SHIFT)
+#define PTE_MAS3_MASK	((MAS3_UX | MAS3_SX | MAS3_UW	\
+			| MAS3_SW | MAS3_UR | MAS3_SR) << PTE_MAS3_SHIFT)
+
+#elif defined(BOOKE_PPC4XX)
+
+#define PTE_WL1		TLB_WL1
+#define PTE_IL2I	TLB_IL2I
+#define PTE_IL2D	TLB_IL2D
+
+#define PTE_W		TLB_W
+#define PTE_I		TLB_I
+#define PTE_M		TLB_M
+#define PTE_G		TLB_G
+
+#define PTE_UX		TLB_UX
+#define PTE_SX		TLB_SX
+#define PTE_UW		TLB_UW
+#define PTE_SW		TLB_SW
+#define PTE_UR		TLB_UR
+#define PTE_SR		TLB_SR
+
+#endif
+
+/* Other PTE flags */
+#define PTE_VALID	0x80000000	/* Valid */
+#define PTE_MODIFIED	0x40000000	/* Modified */
+#define PTE_WIRED	0x20000000	/* Wired */
+#define PTE_MANAGED	0x10000000	/* Managed */
+#define PTE_REFERENCED	0x04000000	/* Referenced */
+
+/* Macro argument must of pte_t type. */
+#define PTE_PA(pte)		((pte)->rpn & ~PTE_PA_MASK)
+#define PTE_ISVALID(pte)	((pte)->flags & PTE_VALID)
+#define PTE_ISWIRED(pte)	((pte)->flags & PTE_WIRED)
+#define PTE_ISMANAGED(pte)	((pte)->flags & PTE_MANAGED)
+#define PTE_ISMODIFIED(pte)	((pte)->flags & PTE_MODIFIED)
+#define PTE_ISREFERENCED(pte)	((pte)->flags & PTE_REFERENCED)
+
+#endif /* BOOKE_PPC4XX */
+#endif /* _MACHINE_PTE_H_ */


Property changes on: trunk/sys/powerpc/include/pte.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/ptrace.h
===================================================================
--- trunk/sys/powerpc/include/ptrace.h	                        (rev 0)
+++ trunk/sys/powerpc/include/ptrace.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,37 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1992, 1993
+ *	The 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.
+ * 4. 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.
+ *
+ *	@(#)ptrace.h	8.1 (Berkeley) 6/11/93
+ * $FreeBSD: stable/10/sys/powerpc/include/ptrace.h 139825 2005-01-07 02:29:27Z imp $
+ */
+
+#ifndef _MACHINE_PTRACE_H_
+#define _MACHINE_PTRACE_H_
+
+#endif


Property changes on: trunk/sys/powerpc/include/ptrace.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/reg.h
===================================================================
--- trunk/sys/powerpc/include/reg.h	                        (rev 0)
+++ trunk/sys/powerpc/include/reg.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,80 @@
+/* $MidnightBSD$ */
+/* $NetBSD: reg.h,v 1.4 2000/06/04 09:30:44 tsubai Exp $	*/
+/* $FreeBSD: stable/10/sys/powerpc/include/reg.h 283910 2015-06-02 14:54:53Z jhb $	*/
+
+#ifndef _POWERPC_REG_H_
+#define	_POWERPC_REG_H_
+
+#if defined(_KERNEL) && !defined(KLD_MODULE) && !defined(_STANDALONE)
+#include "opt_compat.h"
+#endif
+
+/* Must match struct trapframe */
+struct reg {
+	register_t fixreg[32];
+	register_t lr;
+	register_t cr;
+	register_t xer;
+	register_t ctr;
+	register_t pc;
+};
+
+/* Must match pcb.pcb_fpu */
+struct fpreg {
+	double fpreg[32];
+	double fpscr;
+};
+
+struct dbreg {
+	unsigned int	junk;
+};
+
+#ifdef __LP64__
+/* Must match struct trapframe */
+struct reg32 {
+	int32_t fixreg[32];
+	int32_t lr;
+	int32_t cr;
+	int32_t xer;
+	int32_t ctr;
+	int32_t pc;
+};
+
+struct fpreg32 {
+	struct fpreg data;
+};
+
+struct dbreg32 {
+	struct dbreg data;
+};
+
+#define __HAVE_REG32
+#endif
+
+#ifdef _KERNEL
+/*
+ * XXX these interfaces are MI, so they should be declared in a MI place.
+ */
+int	fill_regs(struct thread *, struct reg *);
+int	set_regs(struct thread *, struct reg *);
+int	fill_fpregs(struct thread *, struct fpreg *);
+int	set_fpregs(struct thread *, struct fpreg *);
+int	fill_dbregs(struct thread *, struct dbreg *);
+int	set_dbregs(struct thread *, struct dbreg *);
+
+#ifdef COMPAT_FREEBSD32
+struct image_params;
+
+int	fill_regs32(struct thread *, struct reg32 *);
+int	set_regs32(struct thread *, struct reg32 *);
+void	ppc32_setregs(struct thread *, struct image_params *, u_long);
+
+#define	fill_fpregs32(td, reg)	fill_fpregs(td,(struct fpreg *)reg)
+#define	set_fpregs32(td, reg)	set_fpregs(td,(struct fpreg *)reg)
+#define	fill_dbregs32(td, reg)	fill_dbregs(td,(struct dbreg *)reg)
+#define	set_dbregs32(td, reg)	set_dbregs(td,(struct dbreg *)reg)
+#endif
+
+#endif
+
+#endif /* _POWERPC_REG_H_ */


Property changes on: trunk/sys/powerpc/include/reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/reloc.h
===================================================================
--- trunk/sys/powerpc/include/reloc.h	                        (rev 0)
+++ trunk/sys/powerpc/include/reloc.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,31 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1998 John Birrell <jb at cimlogic.com.au>.
+ * 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 author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/reloc.h 165967 2007-01-12 07:26:21Z imp $
+ */


Property changes on: trunk/sys/powerpc/include/reloc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/resource.h
===================================================================
--- trunk/sys/powerpc/include/resource.h	                        (rev 0)
+++ trunk/sys/powerpc/include/resource.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,45 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/include/resource.h 139825 2005-01-07 02:29:27Z imp $ */
+/*-
+ * Copyright 1998 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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_RESOURCE_H_
+#define	_MACHINE_RESOURCE_H_	1
+
+/*
+ * Definitions of resource types for Intel Architecture machines
+ * with support for legacy ISA devices and drivers.
+ */
+
+#define	SYS_RES_IRQ	1	/* interrupt lines */
+#define	SYS_RES_DRQ	2	/* isa dma lines */
+#define	SYS_RES_MEMORY	3	/* i/o memory */
+#define	SYS_RES_IOPORT	4	/* i/o ports */
+
+#endif /* !_MACHINE_RESOURCE_H_ */


Property changes on: trunk/sys/powerpc/include/resource.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/rtas.h
===================================================================
--- trunk/sys/powerpc/include/rtas.h	                        (rev 0)
+++ trunk/sys/powerpc/include/rtas.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,62 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/rtas.h 222613 2011-06-02 14:12:37Z nwhitehorn $
+ */
+
+#ifndef _MACHINE_RTAS_H_
+#define _MACHINE_RTAS_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <dev/ofw/openfirm.h>
+
+/*
+ * RTAS functions are defined by 32-bit integer tokens. These vary from
+ * system to system, and can be looked up from their standardized names
+ * using rtas_token_lookup(). If RTAS is not available, rtas_token_lookup()
+ * and rtas_call_method() return -1; this can be checked in advance using
+ * rtas_exists(). Otherwise, rtas_call_method() returns one of the RTAS
+ * status codes from the bottom of this file.
+ */
+
+int rtas_exists(void);
+int rtas_call_method(cell_t token, int nargs, int nreturns, ...);
+cell_t rtas_token_lookup(const char *method);
+
+/* RTAS Status Codes: see CHRP or PAPR specification */
+#define	RTAS_OK				0
+#define	RTAS_HW_ERROR			-1
+#define	RTAS_BUSY			-2
+#define	RTAS_PARAM_ERROR		-3
+#define	RTAS_STATE_CHANGE		-7
+#define	RTAS_VENDOR_BEGIN		9000
+#define	RTAS_EXTENDED_DELAY		9900
+#define	RTAS_ISOLATION_ERROR		-9000
+#define	RTAS_VENDOR_ERROR_BEGIN		-9004
+
+#endif /* _MACHINE_RTAS_H_ */
+


Property changes on: trunk/sys/powerpc/include/rtas.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/runq.h
===================================================================
--- trunk/sys/powerpc/include/runq.h	                        (rev 0)
+++ trunk/sys/powerpc/include/runq.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,56 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 Jake Burkholder <jake at FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/runq.h 209975 2010-07-13 05:32:19Z nwhitehorn $
+ */
+
+#ifndef	_MACHINE_RUNQ_H_
+#define	_MACHINE_RUNQ_H_
+
+#ifdef __powerpc64__
+#define	RQB_LEN		(1UL)		/* Number of priority status words. */
+#define	RQB_L2BPW	(6UL)		/* Log2(sizeof(rqb_word_t) * NBBY)). */
+#else
+#define	RQB_LEN		(2)		/* Number of priority status words. */
+#define	RQB_L2BPW	(5)		/* Log2(sizeof(rqb_word_t) * NBBY)). */
+#endif
+#define	RQB_BPW		(1UL<<RQB_L2BPW) /* Bits in an rqb_word_t. */
+
+#define	RQB_BIT(pri)	(1UL << ((pri) & (RQB_BPW - 1)))
+#define	RQB_WORD(pri)	((pri) >> RQB_L2BPW)
+
+#define	RQB_FFS(word)	(ffsl(word) - 1)
+
+/*
+ * Type of run queue status word.
+ */
+#ifdef __powerpc64__
+typedef	u_int64_t	rqb_word_t;
+#else
+typedef	u_int32_t	rqb_word_t;
+#endif
+
+#endif


Property changes on: trunk/sys/powerpc/include/runq.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/sc_machdep.h
===================================================================
--- trunk/sys/powerpc/include/sc_machdep.h	                        (rev 0)
+++ trunk/sys/powerpc/include/sc_machdep.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,72 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Jake Burkholder.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/sc_machdep.h 124771 2004-01-21 05:16:23Z grehan $
+ */
+
+#ifndef	_MACHINE_SC_MACHDEP_H_
+#define	_MACHINE_SC_MACHDEP_H_
+
+/* Color attributes for foreground text */
+
+#define	FG_BLACK		0x0
+#define	FG_BLUE			0x1
+#define	FG_GREEN		0x2
+#define	FG_CYAN			0x3
+#define	FG_RED			0x4
+#define	FG_MAGENTA		0x5
+#define	FG_BROWN		0x6
+#define	FG_LIGHTGREY		0x7	/* aka white */
+#define	FG_DARKGREY		0x8
+#define	FG_LIGHTBLUE		0x9
+#define	FG_LIGHTGREEN		0xa
+#define	FG_LIGHTCYAN		0xb
+#define	FG_LIGHTRED		0xc
+#define	FG_LIGHTMAGENTA		0xd
+#define	FG_YELLOW		0xe
+#define	FG_WHITE		0xf	/* aka bright white */
+#define	FG_BLINK		0x80
+
+/* Color attributes for text background */
+
+#define	BG_BLACK		0x00
+#define	BG_BLUE			0x10
+#define	BG_GREEN		0x20
+#define	BG_CYAN			0x30
+#define	BG_RED			0x40
+#define	BG_MAGENTA		0x50
+#define	BG_BROWN		0x60
+#define	BG_LIGHTGREY		0x70
+#define	BG_DARKGREY		0x80
+#define	BG_LIGHTBLUE		0x90
+#define	BG_LIGHTGREEN		0xa0
+#define	BG_LIGHTCYAN		0xb0
+#define	BG_LIGHTRED		0xc0
+#define	BG_LIGHTMAGENTA		0xd0
+#define	BG_YELLOW		0xe0
+#define	BG_WHITE		0xf0
+
+#endif /* !_MACHINE_SC_MACHDEP_H_ */


Property changes on: trunk/sys/powerpc/include/sc_machdep.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/setjmp.h
===================================================================
--- trunk/sys/powerpc/include/setjmp.h	                        (rev 0)
+++ trunk/sys/powerpc/include/setjmp.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,25 @@
+/* $MidnightBSD$ */
+/*-
+ *	$NetBSD: setjmp.h,v 1.3 1998/09/16 23:51:27 thorpej Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/setjmp.h 104505 2002-10-05 05:47:56Z mike $
+ */
+
+#ifndef _MACHINE_SETJMP_H_
+#define	_MACHINE_SETJMP_H_
+
+#include <sys/cdefs.h>
+
+#define	_JBLEN	100
+
+/*
+ * jmp_buf and sigjmp_buf are encapsulated in different structs to force
+ * compile-time diagnostics for mismatches.  The structs are the same
+ * internally to avoid some run-time errors for mismatches.
+ */
+#if __BSD_VISIBLE || __POSIX_VISIBLE || __XSI_VISIBLE
+typedef	struct _sigjmp_buf { long _sjb[_JBLEN + 1]; } sigjmp_buf[1];
+#endif
+
+typedef	struct _jmp_buf { long _jb[_JBLEN + 1]; } jmp_buf[1];
+
+#endif /* !_MACHINE_SETJMP_H_ */


Property changes on: trunk/sys/powerpc/include/setjmp.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/sf_buf.h
===================================================================
--- trunk/sys/powerpc/include/sf_buf.h	                        (rev 0)
+++ trunk/sys/powerpc/include/sf_buf.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,81 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Alan L. Cox <alc at cs.rice.edu>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/sf_buf.h 255318 2013-09-06 17:44:13Z glebius $
+ */
+
+#ifndef _MACHINE_SF_BUF_H_
+#define _MACHINE_SF_BUF_H_
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_page.h>
+#include <machine/md_var.h>
+#include <sys/queue.h>
+
+struct vm_page;
+
+struct sf_buf {
+	LIST_ENTRY(sf_buf) list_entry;	/* list of buffers */
+	TAILQ_ENTRY(sf_buf) free_entry;	/* list of buffers */
+	struct		vm_page *m;	/* currently mapped page */
+	vm_offset_t	kva;		/* va of mapping */
+	int		ref_count;	/* usage of this mapping */
+};
+
+struct sf_buf * sf_buf_alloc(struct vm_page *m, int flags);
+void sf_buf_free(struct sf_buf *sf);
+
+/*
+ * On 32-bit OEA, the only purpose for which sf_buf is used is to implement
+ * an opaque pointer required by the machine-independent parts of the kernel.
+ * That pointer references the vm_page that is "mapped" by the sf_buf.  The
+ * actual mapping is provided by the direct virtual-to-physical mapping.  
+ *
+ * On OEA64 and Book-E, we need to do something a little more complicated. Use
+ * the runtime-detected hw_direct_map to pick between the two cases. Our
+ * friends in vm_machdep.c will do the same to ensure nothing gets confused.
+ */
+
+static __inline vm_offset_t
+sf_buf_kva(struct sf_buf *sf)
+{
+	if (hw_direct_map)
+		return (VM_PAGE_TO_PHYS((vm_page_t)sf));
+
+	return (sf->kva);
+}
+
+static __inline struct vm_page *
+sf_buf_page(struct sf_buf *sf)
+{
+	if (hw_direct_map)
+		return ((vm_page_t)sf);
+
+	return (sf->m);
+}
+
+#endif /* !_MACHINE_SF_BUF_H_ */


Property changes on: trunk/sys/powerpc/include/sf_buf.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/sigframe.h
===================================================================
--- trunk/sys/powerpc/include/sigframe.h	                        (rev 0)
+++ trunk/sys/powerpc/include/sigframe.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,40 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1999 Marcel Moolenaar
+ * 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 
+ *    in this position and unchanged.
+ * 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/sigframe.h 103616 2002-09-19 04:46:36Z grehan $
+ */
+
+#ifndef _MACHINE_SIGFRAME_H_
+#define _MACHINE_SIGFRAME_H_ 1
+
+struct sigframe {
+	ucontext_t	sf_uc;
+	siginfo_t	sf_si;
+};
+
+#endif /* _MACHINE_SIGFRAME_H_ */


Property changes on: trunk/sys/powerpc/include/sigframe.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/signal.h
===================================================================
--- trunk/sys/powerpc/include/signal.h	                        (rev 0)
+++ trunk/sys/powerpc/include/signal.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,54 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: signal.h,v 1.4 1998/09/14 02:48:34 thorpej Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/signal.h 149337 2005-08-20 16:44:41Z stefanf $
+ */
+
+#ifndef	_MACHINE_SIGNAL_H_
+#define	_MACHINE_SIGNAL_H_
+
+#include <sys/cdefs.h>
+
+typedef int sig_atomic_t;
+
+#if __BSD_VISIBLE
+#include <machine/frame.h>
+
+struct sigcontext {
+	int sc_onstack;			/* saved onstack flag */
+	int __sc_mask13;		/* saved signal mask (old style) */
+	struct trapframe sc_frame;	/* saved registers */
+	struct __sigset sc_mask;	/* saved signal mask (new style) */
+};
+#endif
+
+#endif	/* !_MACHINE_SIGNAL_H_ */


Property changes on: trunk/sys/powerpc/include/signal.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/slb.h
===================================================================
--- trunk/sys/powerpc/include/slb.h	                        (rev 0)
+++ trunk/sys/powerpc/include/slb.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,78 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2009 Nathan Whitehorn
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/slb.h 222620 2011-06-02 14:25:52Z nwhitehorn $
+ */
+
+#ifndef _MACHINE_SLB_H_
+#define	_MACHINE_SLB_H_
+
+/*
+ * Bit definitions for segment lookaside buffer entries.
+ *
+ * PowerPC Microprocessor Family: The Programming Environments for 64-bit
+ * Microprocessors, section 7.4.2.1
+ *
+ * Note that these bitmasks are relative to the values for one of the two
+ * values for slbmte, slbmfee, and slbmfev, not the internal SLB
+ * representation.
+ */
+
+#define	SLBV_KS		0x0000000000000800UL /* Supervisor-state prot key */
+#define	SLBV_KP		0x0000000000000400UL /* User-state prot key */
+#define	SLBV_N		0x0000000000000200UL /* No-execute protection */
+#define	SLBV_L		0x0000000000000100UL /* Large page selector */
+#define	SLBV_CLASS	0x0000000000000080UL /* Class selector */
+#define	SLBV_VSID_MASK	0xfffffffffffff000UL /* Virtual segment ID mask */
+#define	SLBV_VSID_SHIFT	12
+
+/*
+ * Make a predictable 1:1 map from ESIDs to VSIDs for the kernel. Hash table
+ * coverage is increased by swizzling the ESID and multiplying by a prime
+ * number (0x13bb).
+ */
+#define	KERNEL_VSID_BIT	0x0000001000000000UL /* Bit set in all kernel VSIDs */
+#define KERNEL_VSID(esid) ((((((uint64_t)esid << 8) | ((uint64_t)esid >> 28)) \
+				* 0x13bbUL) & (KERNEL_VSID_BIT - 1)) | \
+				KERNEL_VSID_BIT)
+
+#define	SLBE_VALID	0x0000000008000000UL /* SLB entry valid */
+#define	SLBE_INDEX_MASK	0x0000000000000fffUL /* SLB index mask*/
+#define	SLBE_ESID_MASK	0xfffffffff0000000UL /* Effective segment ID mask */
+#define	SLBE_ESID_SHIFT	28
+
+/*
+ * User segment for copyin/out
+ */
+#define USER_SLB_SLOT 0
+#define USER_SLB_SLBE (((USER_ADDR >> ADDR_SR_SHFT) << SLBE_ESID_SHIFT) | \
+			SLBE_VALID | USER_SLB_SLOT)
+
+struct slb {
+	uint64_t	slbv;
+	uint64_t	slbe;
+};
+
+#endif /* !_MACHINE_SLB_H_ */


Property changes on: trunk/sys/powerpc/include/slb.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/smp.h
===================================================================
--- trunk/sys/powerpc/include/smp.h	                        (rev 0)
+++ trunk/sys/powerpc/include/smp.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,63 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Marcel Moolenaar
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/smp.h 222813 2011-06-07 08:46:13Z attilio $
+ */
+
+#ifndef _MACHINE_SMP_H_
+#define _MACHINE_SMP_H_
+
+#ifdef _KERNEL
+
+#define	IPI_AST			0
+#define	IPI_PREEMPT		1
+#define	IPI_RENDEZVOUS		2
+#define	IPI_STOP		3
+#define	IPI_STOP_HARD		3
+#define	IPI_HARDCLOCK		4
+
+#ifndef LOCORE
+
+#include <sys/_cpuset.h>
+
+void	ipi_all_but_self(int ipi);
+void	ipi_cpu(int cpu, u_int ipi);
+void	ipi_selected(cpuset_t cpus, int ipi);
+
+struct cpuref {
+	uintptr_t	cr_hwref;
+	u_int		cr_cpuid;
+};
+
+void	pmap_cpu_bootstrap(int);
+void	cpudep_ap_early_bootstrap(void);
+uintptr_t cpudep_ap_bootstrap(void);
+void	cpudep_ap_setup(void);
+void	machdep_ap_bootstrap(void);
+
+#endif /* !LOCORE */
+#endif /* _KERNEL */
+#endif /* !_MACHINE_SMP_H */


Property changes on: trunk/sys/powerpc/include/smp.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/spr.h
===================================================================
--- trunk/sys/powerpc/include/spr.h	                        (rev 0)
+++ trunk/sys/powerpc/include/spr.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,783 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * 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.
+ *
+ * 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.
+ *
+ * $NetBSD: spr.h,v 1.25 2002/08/14 15:38:40 matt Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/spr.h 263122 2014-03-14 00:12:53Z jhibbits $
+ */
+#ifndef _POWERPC_SPR_H_
+#define	_POWERPC_SPR_H_
+
+#ifndef _LOCORE
+#define	mtspr(reg, val)							\
+	__asm __volatile("mtspr %0,%1" : : "K"(reg), "r"(val))
+#define	mfspr(reg)							\
+	( { register_t val;						\
+	  __asm __volatile("mfspr %0,%1" : "=r"(val) : "K"(reg));	\
+	  val; } )
+
+
+#ifndef __powerpc64__
+
+/* The following routines allow manipulation of the full 64-bit width 
+ * of SPRs on 64 bit CPUs in bridge mode */
+
+#define mtspr64(reg,valhi,vallo,scratch)				\
+	__asm __volatile("						\
+		mfmsr %0; 						\
+		insrdi %0,%5,1,0; 					\
+		mtmsrd %0; 						\
+		isync; 							\
+									\
+		sld %1,%1,%4;						\
+		or %1,%1,%2;						\
+		mtspr %3,%1;						\
+		srd %1,%1,%4;						\
+									\
+		clrldi %0,%0,1; 					\
+		mtmsrd %0; 						\
+		isync;"							\
+	: "=r"(scratch), "=r"(valhi) : "r"(vallo), "K"(reg), "r"(32), "r"(1))
+
+#define mfspr64upper(reg,scratch)					\
+	( { register_t val;						\
+	    __asm __volatile("						\
+		mfmsr %0; 						\
+		insrdi %0,%4,1,0; 					\
+		mtmsrd %0; 						\
+		isync; 							\
+									\
+		mfspr %1,%2;						\
+		srd %1,%1,%3;						\
+									\
+		clrldi %0,%0,1; 					\
+		mtmsrd %0; 						\
+		isync;" 						\
+	    : "=r"(scratch), "=r"(val) : "K"(reg), "r"(32), "r"(1));	\
+	    val; } )
+
+#endif
+
+#endif /* _LOCORE */
+
+/*
+ * Special Purpose Register declarations.
+ *
+ * The first column in the comments indicates which PowerPC
+ * architectures the SPR is valid on - 4 for 4xx series,
+ * 6 for 6xx/7xx series and 8 for 8xx and 8xxx series.
+ */
+
+#define	SPR_MQ			0x000	/* .6. 601 MQ register */
+#define	SPR_XER			0x001	/* 468 Fixed Point Exception Register */
+#define	SPR_RTCU_R		0x004	/* .6. 601 RTC Upper - Read */
+#define	SPR_RTCL_R		0x005	/* .6. 601 RTC Lower - Read */
+#define	SPR_LR			0x008	/* 468 Link Register */
+#define	SPR_CTR			0x009	/* 468 Count Register */
+#define	SPR_DSISR		0x012	/* .68 DSI exception source */
+#define	  DSISR_DIRECT		  0x80000000 /* Direct-store error exception */
+#define	  DSISR_NOTFOUND	  0x40000000 /* Translation not found */
+#define	  DSISR_PROTECT		  0x08000000 /* Memory access not permitted */
+#define	  DSISR_INVRX		  0x04000000 /* Reserve-indexed insn direct-store access */
+#define	  DSISR_STORE		  0x02000000 /* Store operation */
+#define	  DSISR_DABR		  0x00400000 /* DABR match */
+#define	  DSISR_SEGMENT		  0x00200000 /* XXX; not in 6xx PEM */
+#define	  DSISR_EAR		  0x00100000 /* eciwx/ecowx && EAR[E] == 0 */
+#define	SPR_DAR			0x013	/* .68 Data Address Register */
+#define	SPR_RTCU_W		0x014	/* .6. 601 RTC Upper - Write */
+#define	SPR_RTCL_W		0x015	/* .6. 601 RTC Lower - Write */
+#define	SPR_DEC			0x016	/* .68 DECrementer register */
+#define	SPR_SDR1		0x019	/* .68 Page table base address register */
+#define	SPR_SRR0		0x01a	/* 468 Save/Restore Register 0 */
+#define	SPR_SRR1		0x01b	/* 468 Save/Restore Register 1 */
+#define	  SRR1_ISI_PFAULT	0x40000000 /* ISI page not found */
+#define	  SRR1_ISI_NOEXECUTE	0x10000000 /* Memory marked no-execute */
+#define	  SRR1_ISI_PP		0x08000000 /* PP bits forbid access */
+#define	SPR_DECAR		0x036	/* ..8 Decrementer auto reload */
+#define	SPR_EIE			0x050	/* ..8 Exception Interrupt ??? */
+#define	SPR_EID			0x051	/* ..8 Exception Interrupt ??? */
+#define	SPR_NRI			0x052	/* ..8 Exception Interrupt ??? */
+#define	SPR_USPRG0		0x100	/* 4.. User SPR General 0 */
+#define	SPR_VRSAVE		0x100	/* .6. AltiVec VRSAVE */
+#define	SPR_SPRG0		0x110	/* 468 SPR General 0 */
+#define	SPR_SPRG1		0x111	/* 468 SPR General 1 */
+#define	SPR_SPRG2		0x112	/* 468 SPR General 2 */
+#define	SPR_SPRG3		0x113	/* 468 SPR General 3 */
+#define	SPR_SPRG4		0x114	/* 4.. SPR General 4 */
+#define	SPR_SPRG5		0x115	/* 4.. SPR General 5 */
+#define	SPR_SPRG6		0x116	/* 4.. SPR General 6 */
+#define	SPR_SPRG7		0x117	/* 4.. SPR General 7 */
+#define	SPR_SCOMC		0x114	/* ... SCOM Address Register (970) */
+#define	SPR_SCOMD		0x115	/* ... SCOM Data Register (970) */
+#define	SPR_ASR			0x118	/* ... Address Space Register (PPC64) */
+#define	SPR_EAR			0x11a	/* .68 External Access Register */
+#define	SPR_PVR			0x11f	/* 468 Processor Version Register */
+#define	  MPC601		  0x0001
+#define	  MPC603		  0x0003
+#define	  MPC604		  0x0004
+#define	  MPC602		  0x0005
+#define	  MPC603e		  0x0006
+#define	  MPC603ev		  0x0007
+#define	  MPC750		  0x0008
+#define	  MPC750CL		  0x7000	/* Nintendo Wii's Broadway */
+#define	  MPC604ev		  0x0009
+#define	  MPC7400		  0x000c
+#define	  MPC620		  0x0014
+#define	  IBM403		  0x0020
+#define	  IBM401A1		  0x0021
+#define	  IBM401B2		  0x0022
+#define	  IBM401C2		  0x0023
+#define	  IBM401D2		  0x0024
+#define	  IBM401E2		  0x0025
+#define	  IBM401F2		  0x0026
+#define	  IBM401G2		  0x0027
+#define	  IBMRS64II		  0x0033
+#define	  IBMRS64III		  0x0034
+#define	  IBMPOWER4		  0x0035
+#define	  IBMRS64III_2		  0x0036
+#define	  IBMRS64IV		  0x0037
+#define	  IBMPOWER4PLUS		  0x0038
+#define	  IBM970		  0x0039
+#define	  IBMPOWER5		  0x003a
+#define	  IBMPOWER5PLUS		  0x003b
+#define	  IBM970FX		  0x003c
+#define	  IBMPOWER6		  0x003e
+#define	  IBMPOWER7		  0x003f
+#define	  IBMPOWER3		  0x0040
+#define	  IBMPOWER3PLUS		  0x0041
+#define	  IBM970MP		  0x0044
+#define	  IBM970GX		  0x0045
+#define	  IBMPOWER7PLUS		  0x004a
+#define	  IBMPOWER8		  0x004b
+#define	  MPC860		  0x0050
+#define	  IBMCELLBE		  0x0070
+#define	  MPC8240		  0x0081
+#define	  PA6T			  0x0090
+#define	  IBM405GP		  0x4011
+#define	  IBM405L		  0x4161
+#define	  IBM750FX		  0x7000
+#define	MPC745X_P(v)	((v & 0xFFF8) == 0x8000)
+#define	  MPC7450		  0x8000
+#define	  MPC7455		  0x8001
+#define	  MPC7457		  0x8002
+#define	  MPC7447A		  0x8003
+#define	  MPC7448		  0x8004
+#define	  MPC7410		  0x800c
+#define	  MPC8245		  0x8081
+#define	  FSL_E500v1		  0x8020
+#define	  FSL_E500v2		  0x8021
+#define	  FSL_E500mc		  0x8023
+#define	  FSL_E5500		  0x8024
+
+#define	SPR_IBAT0U		0x210	/* .68 Instruction BAT Reg 0 Upper */
+#define	SPR_IBAT0U		0x210	/* .6. Instruction BAT Reg 0 Upper */
+#define	SPR_IBAT0L		0x211	/* .6. Instruction BAT Reg 0 Lower */
+#define	SPR_IBAT1U		0x212	/* .6. Instruction BAT Reg 1 Upper */
+#define	SPR_IBAT1L		0x213	/* .6. Instruction BAT Reg 1 Lower */
+#define	SPR_IBAT2U		0x214	/* .6. Instruction BAT Reg 2 Upper */
+#define	SPR_IBAT2L		0x215	/* .6. Instruction BAT Reg 2 Lower */
+#define	SPR_IBAT3U		0x216	/* .6. Instruction BAT Reg 3 Upper */
+#define	SPR_IBAT3L		0x217	/* .6. Instruction BAT Reg 3 Lower */
+#define	SPR_DBAT0U		0x218	/* .6. Data BAT Reg 0 Upper */
+#define	SPR_DBAT0L		0x219	/* .6. Data BAT Reg 0 Lower */
+#define	SPR_DBAT1U		0x21a	/* .6. Data BAT Reg 1 Upper */
+#define	SPR_DBAT1L		0x21b	/* .6. Data BAT Reg 1 Lower */
+#define	SPR_DBAT2U		0x21c	/* .6. Data BAT Reg 2 Upper */
+#define	SPR_DBAT2L		0x21d	/* .6. Data BAT Reg 2 Lower */
+#define	SPR_DBAT3U		0x21e	/* .6. Data BAT Reg 3 Upper */
+#define	SPR_DBAT3L		0x21f	/* .6. Data BAT Reg 3 Lower */
+#define	SPR_IC_CST		0x230	/* ..8 Instruction Cache CSR */
+#define	  IC_CST_IEN		0x80000000 /* I cache is ENabled   (RO) */
+#define	  IC_CST_CMD_INVALL	0x0c000000 /* I cache invalidate all */
+#define	  IC_CST_CMD_UNLOCKALL	0x0a000000 /* I cache unlock all */
+#define	  IC_CST_CMD_UNLOCK	0x08000000 /* I cache unlock block */
+#define	  IC_CST_CMD_LOADLOCK	0x06000000 /* I cache load & lock block */
+#define	  IC_CST_CMD_DISABLE	0x04000000 /* I cache disable */
+#define	  IC_CST_CMD_ENABLE	0x02000000 /* I cache enable */
+#define	  IC_CST_CCER1		0x00200000 /* I cache error type 1 (RO) */
+#define	  IC_CST_CCER2		0x00100000 /* I cache error type 2 (RO) */
+#define	  IC_CST_CCER3		0x00080000 /* I cache error type 3 (RO) */
+#define	SPR_IBAT4U		0x230	/* .6. Instruction BAT Reg 4 Upper */
+#define	SPR_IC_ADR		0x231	/* ..8 Instruction Cache Address */
+#define	SPR_IBAT4L		0x231	/* .6. Instruction BAT Reg 4 Lower */
+#define	SPR_IC_DAT		0x232	/* ..8 Instruction Cache Data */
+#define	SPR_IBAT5U		0x232	/* .6. Instruction BAT Reg 5 Upper */
+#define	SPR_IBAT5L		0x233	/* .6. Instruction BAT Reg 5 Lower */
+#define	SPR_IBAT6U		0x234	/* .6. Instruction BAT Reg 6 Upper */
+#define	SPR_IBAT6L		0x235	/* .6. Instruction BAT Reg 6 Lower */
+#define	SPR_IBAT7U		0x236	/* .6. Instruction BAT Reg 7 Upper */
+#define	SPR_IBAT7L		0x237	/* .6. Instruction BAT Reg 7 Lower */
+#define	SPR_DC_CST		0x230	/* ..8 Data Cache CSR */
+#define	  DC_CST_DEN		0x80000000 /* D cache ENabled (RO) */
+#define	  DC_CST_DFWT		0x40000000 /* D cache Force Write-Thru (RO) */
+#define	  DC_CST_LES		0x20000000 /* D cache Little Endian Swap (RO) */
+#define	  DC_CST_CMD_FLUSH	0x0e000000 /* D cache invalidate all */
+#define	  DC_CST_CMD_INVALL	0x0c000000 /* D cache invalidate all */
+#define	  DC_CST_CMD_UNLOCKALL	0x0a000000 /* D cache unlock all */
+#define	  DC_CST_CMD_UNLOCK	0x08000000 /* D cache unlock block */
+#define	  DC_CST_CMD_CLRLESWAP	0x07000000 /* D cache clr little-endian swap */
+#define	  DC_CST_CMD_LOADLOCK	0x06000000 /* D cache load & lock block */
+#define	  DC_CST_CMD_SETLESWAP	0x05000000 /* D cache set little-endian swap */
+#define	  DC_CST_CMD_DISABLE	0x04000000 /* D cache disable */
+#define	  DC_CST_CMD_CLRFWT	0x03000000 /* D cache clear forced write-thru */
+#define	  DC_CST_CMD_ENABLE	0x02000000 /* D cache enable */
+#define	  DC_CST_CMD_SETFWT	0x01000000 /* D cache set forced write-thru */
+#define	  DC_CST_CCER1		0x00200000 /* D cache error type 1 (RO) */
+#define	  DC_CST_CCER2		0x00100000 /* D cache error type 2 (RO) */
+#define	  DC_CST_CCER3		0x00080000 /* D cache error type 3 (RO) */
+#define	SPR_DBAT4U		0x238	/* .6. Data BAT Reg 4 Upper */
+#define	SPR_DC_ADR		0x231	/* ..8 Data Cache Address */
+#define	SPR_DBAT4L		0x239	/* .6. Data BAT Reg 4 Lower */
+#define	SPR_DC_DAT		0x232	/* ..8 Data Cache Data */
+#define	SPR_DBAT5U		0x23a	/* .6. Data BAT Reg 5 Upper */
+#define	SPR_DBAT5L		0x23b	/* .6. Data BAT Reg 5 Lower */
+#define	SPR_DBAT6U		0x23c	/* .6. Data BAT Reg 6 Upper */
+#define	SPR_DBAT6L		0x23d	/* .6. Data BAT Reg 6 Lower */
+#define	SPR_DBAT7U		0x23e	/* .6. Data BAT Reg 7 Upper */
+#define	SPR_DBAT7L		0x23f	/* .6. Data BAT Reg 7 Lower */
+#define	SPR_MI_CTR		0x310	/* ..8 IMMU control */
+#define	  Mx_CTR_GPM		0x80000000 /* Group Protection Mode */
+#define	  Mx_CTR_PPM		0x40000000 /* Page Protection Mode */
+#define	  Mx_CTR_CIDEF		0x20000000 /* Cache-Inhibit DEFault */
+#define	  MD_CTR_WTDEF		0x20000000 /* Write-Through DEFault */
+#define	  Mx_CTR_RSV4		0x08000000 /* Reserve 4 TLB entries */
+#define	  MD_CTR_TWAM		0x04000000 /* TableWalk Assist Mode */
+#define	  Mx_CTR_PPCS		0x02000000 /* Priv/user state compare mode */
+#define	  Mx_CTR_TLB_INDX	0x000001f0 /* TLB index mask */
+#define	  Mx_CTR_TLB_INDX_BITPOS	8	  /* TLB index shift */
+#define	SPR_MI_AP		0x312	/* ..8 IMMU access protection */
+#define	  Mx_GP_SUPER(n)	(0 << (2*(15-(n)))) /* access is supervisor */
+#define	  Mx_GP_PAGE		(1 << (2*(15-(n)))) /* access is page protect */
+#define	  Mx_GP_SWAPPED		(2 << (2*(15-(n)))) /* access is swapped */
+#define	  Mx_GP_USER		(3 << (2*(15-(n)))) /* access is user */
+#define	SPR_MI_EPN		0x313	/* ..8 IMMU effective number */
+#define	  Mx_EPN_EPN		0xfffff000 /* Effective Page Number mask */
+#define	  Mx_EPN_EV		0x00000020 /* Entry Valid */
+#define	  Mx_EPN_ASID		0x0000000f /* Address Space ID */
+#define	SPR_MI_TWC		0x315	/* ..8 IMMU tablewalk control */
+#define	  MD_TWC_L2TB		0xfffff000 /* Level-2 Tablewalk Base */
+#define	  Mx_TWC_APG		0x000001e0 /* Access Protection Group */
+#define	  Mx_TWC_G		0x00000010 /* Guarded memory */
+#define	  Mx_TWC_PS		0x0000000c /* Page Size (L1) */
+#define	  MD_TWC_WT		0x00000002 /* Write-Through */
+#define	  Mx_TWC_V		0x00000001 /* Entry Valid */
+#define	SPR_MI_RPN		0x316	/* ..8 IMMU real (phys) page number */
+#define	  Mx_RPN_RPN		0xfffff000 /* Real Page Number */
+#define	  Mx_RPN_PP		0x00000ff0 /* Page Protection */
+#define	  Mx_RPN_SPS		0x00000008 /* Small Page Size */
+#define	  Mx_RPN_SH		0x00000004 /* SHared page */
+#define	  Mx_RPN_CI		0x00000002 /* Cache Inhibit */
+#define	  Mx_RPN_V		0x00000001 /* Valid */
+#define	SPR_MD_CTR		0x318	/* ..8 DMMU control */
+#define	SPR_M_CASID		0x319	/* ..8 CASID */
+#define	  M_CASID		0x0000000f /* Current AS Id */
+#define	SPR_MD_AP		0x31a	/* ..8 DMMU access protection */
+#define	SPR_MD_EPN		0x31b	/* ..8 DMMU effective number */
+
+#define	SPR_970MMCR0		0x31b	/* ... Monitor Mode Control Register 0 (PPC 970) */
+#define	  SPR_970MMCR0_PMC1SEL(x) ((x) << 8) /* PMC1 selector (970) */
+#define	  SPR_970MMCR0_PMC2SEL(x) ((x) << 1) /* PMC2 selector (970) */
+#define	SPR_970MMCR1		0x31e	/* ... Monitor Mode Control Register 1 (PPC 970) */
+#define	  SPR_970MMCR1_PMC3SEL(x)	  (((x) & 0x1f) << 27) /* PMC 3 selector */
+#define	  SPR_970MMCR1_PMC4SEL(x)	  (((x) & 0x1f) << 22) /* PMC 4 selector */
+#define	  SPR_970MMCR1_PMC5SEL(x)	  (((x) & 0x1f) << 17) /* PMC 5 selector */
+#define	  SPR_970MMCR1_PMC6SEL(x)	  (((x) & 0x1f) << 12) /* PMC 6 selector */
+#define	  SPR_970MMCR1_PMC7SEL(x)	  (((x) & 0x1f) << 7) /* PMC 7 selector */
+#define	  SPR_970MMCR1_PMC8SEL(x)	  (((x) & 0x1f) << 2) /* PMC 8 selector */
+#define	SPR_970MMCRA		0x312	/* ... Monitor Mode Control Register 2 (PPC 970) */
+#define	SPR_970PMC1		0x313	/* ... PMC 1 */
+#define	SPR_970PMC2		0x314	/* ... PMC 2 */
+#define	SPR_970PMC3		0x315	/* ... PMC 3 */
+#define	SPR_970PMC4		0x316	/* ... PMC 4 */
+#define	SPR_970PMC5		0x317	/* ... PMC 5 */
+#define	SPR_970PMC6		0x318	/* ... PMC 6 */
+#define	SPR_970PMC7		0x319	/* ... PMC 7 */
+#define	SPR_970PMC8		0x31a	/* ... PMC 8 */
+
+#define	SPR_M_TWB		0x31c	/* ..8 MMU tablewalk base */
+#define	  M_TWB_L1TB		0xfffff000 /* level-1 translation base */
+#define	  M_TWB_L1INDX		0x00000ffc /* level-1 index */
+#define	SPR_MD_TWC		0x31d	/* ..8 DMMU tablewalk control */
+#define	SPR_MD_RPN		0x31e	/* ..8 DMMU real (phys) page number */
+#define	SPR_MD_TW		0x31f	/* ..8 MMU tablewalk scratch */
+#define	SPR_MI_CAM		0x330	/* ..8 IMMU CAM entry read */
+#define	SPR_MI_RAM0		0x331	/* ..8 IMMU RAM entry read reg 0 */
+#define	SPR_MI_RAM1		0x332	/* ..8 IMMU RAM entry read reg 1 */
+#define	SPR_MD_CAM		0x338	/* ..8 IMMU CAM entry read */
+#define	SPR_MD_RAM0		0x339	/* ..8 IMMU RAM entry read reg 0 */
+#define	SPR_MD_RAM1		0x33a	/* ..8 IMMU RAM entry read reg 1 */
+#define	SPR_UMMCR2		0x3a0	/* .6. User Monitor Mode Control Register 2 */
+#define	SPR_UMMCR0		0x3a8	/* .6. User Monitor Mode Control Register 0 */
+#define	SPR_USIA		0x3ab	/* .6. User Sampled Instruction Address */
+#define	SPR_UMMCR1		0x3ac	/* .6. User Monitor Mode Control Register 1 */
+#define	SPR_ZPR			0x3b0	/* 4.. Zone Protection Register */
+#define	SPR_MMCR2		0x3b0	/* .6. Monitor Mode Control Register 2 */
+#define	  SPR_MMCR2_THRESHMULT_32	  0x80000000 /* Multiply MMCR0 threshold by 32 */
+#define	  SPR_MMCR2_THRESHMULT_2	  0x00000000 /* Multiply MMCR0 threshold by 2 */
+#define	SPR_PID			0x3b1	/* 4.. Process ID */
+#define	SPR_PMC5		0x3b1	/* .6. Performance Counter Register 5 */
+#define	SPR_PMC6		0x3b2	/* .6. Performance Counter Register 6 */
+#define	SPR_CCR0		0x3b3	/* 4.. Core Configuration Register 0 */
+#define	SPR_IAC3		0x3b4	/* 4.. Instruction Address Compare 3 */
+#define	SPR_IAC4		0x3b5	/* 4.. Instruction Address Compare 4 */
+#define	SPR_DVC1		0x3b6	/* 4.. Data Value Compare 1 */
+#define	SPR_DVC2		0x3b7	/* 4.. Data Value Compare 2 */
+#define	SPR_MMCR0		0x3b8	/* .6. Monitor Mode Control Register 0 */
+#define	  SPR_MMCR0_FC		  0x80000000 /* Freeze counters */
+#define	  SPR_MMCR0_FCS		  0x40000000 /* Freeze counters in supervisor mode */
+#define	  SPR_MMCR0_FCP		  0x20000000 /* Freeze counters in user mode */
+#define	  SPR_MMCR0_FCM1	  0x10000000 /* Freeze counters when mark=1 */
+#define	  SPR_MMCR0_FCM0	  0x08000000 /* Freeze counters when mark=0 */
+#define	  SPR_MMCR0_PMXE	  0x04000000 /* Enable PM interrupt */
+#define	  SPR_MMCR0_FCECE	  0x02000000 /* Freeze counters after event */
+#define	  SPR_MMCR0_TBSEL_15	  0x01800000 /* Count bit 15 of TBL */
+#define	  SPR_MMCR0_TBSEL_19	  0x01000000 /* Count bit 19 of TBL */
+#define	  SPR_MMCR0_TBSEL_23	  0x00800000 /* Count bit 23 of TBL */
+#define	  SPR_MMCR0_TBSEL_31	  0x00000000 /* Count bit 31 of TBL */
+#define	  SPR_MMCR0_TBEE	  0x00400000 /* Time-base event enable */
+#define	  SPR_MMCRO_THRESHOLD(x)  ((x) << 16) /* Threshold value */
+#define	  SPR_MMCR0_PMC1CE	  0x00008000 /* PMC1 condition enable */
+#define	  SPR_MMCR0_PMCNCE	  0x00004000 /* PMCn condition enable */
+#define	  SPR_MMCR0_TRIGGER	  0x00002000 /* Trigger */
+#define	  SPR_MMCR0_PMC1SEL(x)	  (((x) & 0x3f) << 6) /* PMC1 selector */
+#define	  SPR_MMCR0_PMC2SEL(x)	  (((x) & 0x3f) << 0) /* PMC2 selector */
+#define	SPR_SGR			0x3b9	/* 4.. Storage Guarded Register */
+#define	SPR_PMC1		0x3b9	/* .6. Performance Counter Register 1 */
+#define	SPR_DCWR		0x3ba	/* 4.. Data Cache Write-through Register */
+#define	SPR_PMC2		0x3ba	/* .6. Performance Counter Register 2 */
+#define	SPR_SLER		0x3bb	/* 4.. Storage Little Endian Register */
+#define	SPR_SIA			0x3bb	/* .6. Sampled Instruction Address */
+#define	SPR_MMCR1		0x3bc	/* .6. Monitor Mode Control Register 2 */
+#define	  SPR_MMCR1_PMC3SEL(x)	  (((x) & 0x1f) << 27) /* PMC 3 selector */
+#define	  SPR_MMCR1_PMC4SEL(x)	  (((x) & 0x1f) << 22) /* PMC 4 selector */
+#define	  SPR_MMCR1_PMC5SEL(x)	  (((x) & 0x1f) << 17) /* PMC 5 selector */
+#define	  SPR_MMCR1_PMC6SEL(x)	  (((x) & 0x3f) << 11) /* PMC 6 selector */
+
+#define	SPR_SU0R		0x3bc	/* 4.. Storage User-defined 0 Register */
+#define	SPR_PMC3		0x3bd	/* .6. Performance Counter Register 3 */
+#define	SPR_PMC4		0x3be	/* .6. Performance Counter Register 4 */
+#define	SPR_DMISS		0x3d0	/* .68 Data TLB Miss Address Register */
+#define	SPR_DCMP		0x3d1	/* .68 Data TLB Compare Register */
+#define	SPR_HASH1		0x3d2	/* .68 Primary Hash Address Register */
+#define	SPR_ICDBDR		0x3d3	/* 4.. Instruction Cache Debug Data Register */
+#define	SPR_HASH2		0x3d3	/* .68 Secondary Hash Address Register */
+#define	SPR_IMISS		0x3d4	/* .68 Instruction TLB Miss Address Register */
+#define	SPR_TLBMISS		0x3d4	/* .6. TLB Miss Address Register */
+#define	SPR_DEAR		0x3d5	/* 4.. Data Error Address Register */
+#define	SPR_ICMP		0x3d5	/* .68 Instruction TLB Compare Register */
+#define	SPR_PTEHI		0x3d5	/* .6. Instruction TLB Compare Register */
+#define	SPR_EVPR		0x3d6	/* 4.. Exception Vector Prefix Register */
+#define	SPR_RPA			0x3d6	/* .68 Required Physical Address Register */
+#define	SPR_PTELO		0x3d6	/* .6. Required Physical Address Register */
+
+#define	SPR_TSR			0x150	/* ..8 Timer Status Register */
+#define	SPR_TCR			0x154	/* ..8 Timer Control Register */
+
+#define	  TSR_ENW		  0x80000000 /* Enable Next Watchdog */
+#define	  TSR_WIS		  0x40000000 /* Watchdog Interrupt Status */
+#define	  TSR_WRS_MASK		  0x30000000 /* Watchdog Reset Status */
+#define	  TSR_WRS_NONE		  0x00000000 /* No watchdog reset has occurred */
+#define	  TSR_WRS_CORE		  0x10000000 /* Core reset was forced by the watchdog */
+#define	  TSR_WRS_CHIP		  0x20000000 /* Chip reset was forced by the watchdog */
+#define	  TSR_WRS_SYSTEM	  0x30000000 /* System reset was forced by the watchdog */
+#define	  TSR_PIS		  0x08000000 /* PIT Interrupt Status */
+#define	  TSR_DIS		  0x08000000 /* Decrementer Interrupt Status */
+#define	  TSR_FIS		  0x04000000 /* FIT Interrupt Status */
+
+#define	  TCR_WP_MASK		  0xc0000000 /* Watchdog Period mask */
+#define	  TCR_WP_2_17		  0x00000000 /* 2**17 clocks */
+#define	  TCR_WP_2_21		  0x40000000 /* 2**21 clocks */
+#define	  TCR_WP_2_25		  0x80000000 /* 2**25 clocks */
+#define	  TCR_WP_2_29		  0xc0000000 /* 2**29 clocks */
+#define	  TCR_WRC_MASK		  0x30000000 /* Watchdog Reset Control mask */
+#define	  TCR_WRC_NONE		  0x00000000 /* No watchdog reset */
+#define	  TCR_WRC_CORE		  0x10000000 /* Core reset */
+#define	  TCR_WRC_CHIP		  0x20000000 /* Chip reset */
+#define	  TCR_WRC_SYSTEM	  0x30000000 /* System reset */
+#define	  TCR_WIE		  0x08000000 /* Watchdog Interrupt Enable */
+#define	  TCR_PIE		  0x04000000 /* PIT Interrupt Enable */
+#define	  TCR_DIE		  0x04000000 /* Pecrementer Interrupt Enable */
+#define	  TCR_FP_MASK		  0x03000000 /* FIT Period */
+#define	  TCR_FP_2_9		  0x00000000 /* 2**9 clocks */
+#define	  TCR_FP_2_13		  0x01000000 /* 2**13 clocks */
+#define	  TCR_FP_2_17		  0x02000000 /* 2**17 clocks */
+#define	  TCR_FP_2_21		  0x03000000 /* 2**21 clocks */
+#define	  TCR_FIE		  0x00800000 /* FIT Interrupt Enable */
+#define	  TCR_ARE		  0x00400000 /* Auto Reload Enable */
+
+#define	SPR_PIT			0x3db	/* 4.. Programmable Interval Timer */
+#define	SPR_SRR2		0x3de	/* 4.. Save/Restore Register 2 */
+#define	SPR_SRR3		0x3df	/* 4.. Save/Restore Register 3 */
+#define	SPR_HID0		0x3f0	/* ..8 Hardware Implementation Register 0 */
+#define	SPR_HID1		0x3f1	/* ..8 Hardware Implementation Register 1 */
+#define	SPR_HID2		0x3f3	/* ..8 Hardware Implementation Register 2 */
+#define	SPR_HID4		0x3f4	/* ..8 Hardware Implementation Register 4 */
+#define	SPR_HID5		0x3f6	/* ..8 Hardware Implementation Register 5 */
+#define	SPR_HID6		0x3f9	/* ..8 Hardware Implementation Register 6 */
+
+#define	SPR_CELL_TSRL		0x380	/* ... Cell BE Thread Status Register */
+#define	SPR_CELL_TSCR		0x399	/* ... Cell BE Thread Switch Register */
+
+#if defined(AIM)
+#define	SPR_DBSR		0x3f0	/* 4.. Debug Status Register */
+#define	  DBSR_IC		  0x80000000 /* Instruction completion debug event */
+#define	  DBSR_BT		  0x40000000 /* Branch Taken debug event */
+#define	  DBSR_EDE		  0x20000000 /* Exception debug event */
+#define	  DBSR_TIE		  0x10000000 /* Trap Instruction debug event */
+#define	  DBSR_UDE		  0x08000000 /* Unconditional debug event */
+#define	  DBSR_IA1		  0x04000000 /* IAC1 debug event */
+#define	  DBSR_IA2		  0x02000000 /* IAC2 debug event */
+#define	  DBSR_DR1		  0x01000000 /* DAC1 Read debug event */
+#define	  DBSR_DW1		  0x00800000 /* DAC1 Write debug event */
+#define	  DBSR_DR2		  0x00400000 /* DAC2 Read debug event */
+#define	  DBSR_DW2		  0x00200000 /* DAC2 Write debug event */
+#define	  DBSR_IDE		  0x00100000 /* Imprecise debug event */
+#define	  DBSR_IA3		  0x00080000 /* IAC3 debug event */
+#define	  DBSR_IA4		  0x00040000 /* IAC4 debug event */
+#define	  DBSR_MRR		  0x00000300 /* Most recent reset */
+#define	SPR_DBCR0		0x3f2	/* 4.. Debug Control Register 0 */
+#define	SPR_DBCR1		0x3bd	/* 4.. Debug Control Register 1 */
+#define	SPR_IAC1		0x3f4	/* 4.. Instruction Address Compare 1 */
+#define	SPR_IAC2		0x3f5	/* 4.. Instruction Address Compare 2 */
+#define	SPR_DAC1		0x3f6	/* 4.. Data Address Compare 1 */
+#define	SPR_DAC2		0x3f7	/* 4.. Data Address Compare 2 */
+#define	SPR_PIR			0x3ff	/* .6. Processor Identification Register */
+#elif defined(BOOKE)
+#define	SPR_PIR			0x11e	/* ..8 Processor Identification Register */
+#define	SPR_DBSR		0x130	/* ..8 Debug Status Register */
+#define	  DBSR_IDE		  0x80000000 /* Imprecise debug event. */
+#define	  DBSR_UDE		  0x40000000 /* Unconditional debug event. */
+#define	  DBSR_MRR		  0x30000000 /* Most recent Reset (mask). */
+#define	  DBSR_ICMP		  0x08000000 /* Instr. complete debug event. */
+#define	  DBSR_BRT		  0x04000000 /* Branch taken debug event. */
+#define	  DBSR_IRPT		  0x02000000 /* Interrupt taken debug event. */
+#define	  DBSR_TRAP		  0x01000000 /* Trap instr. debug event. */
+#define	  DBSR_IAC1		  0x00800000 /* Instr. address compare #1. */
+#define	  DBSR_IAC2		  0x00400000 /* Instr. address compare #2. */
+#define	  DBSR_IAC3		  0x00200000 /* Instr. address compare #3. */
+#define	  DBSR_IAC4		  0x00100000 /* Instr. address compare #4. */
+#define	  DBSR_DAC1R		  0x00080000 /* Data addr. read compare #1. */
+#define	  DBSR_DAC1W		  0x00040000 /* Data addr. write compare #1. */
+#define	  DBSR_DAC2R		  0x00020000 /* Data addr. read compare #2. */
+#define	  DBSR_DAC2W		  0x00010000 /* Data addr. write compare #2. */
+#define	  DBSR_RET		  0x00008000 /* Return debug event. */
+#define	SPR_DBCR0		0x134	/* ..8 Debug Control Register 0 */
+#define	SPR_DBCR1		0x135	/* ..8 Debug Control Register 1 */
+#define	SPR_IAC1		0x138	/* ..8 Instruction Address Compare 1 */
+#define	SPR_IAC2		0x139	/* ..8 Instruction Address Compare 2 */
+#define	SPR_DAC1		0x13c	/* ..8 Data Address Compare 1 */
+#define	SPR_DAC2		0x13d	/* ..8 Data Address Compare 2 */
+#endif
+
+#define	  DBCR0_EDM		  0x80000000 /* External Debug Mode */
+#define	  DBCR0_IDM		  0x40000000 /* Internal Debug Mode */
+#define	  DBCR0_RST_MASK	  0x30000000 /* ReSeT */
+#define	  DBCR0_RST_NONE	  0x00000000 /*   No action */
+#define	  DBCR0_RST_CORE	  0x10000000 /*   Core reset */
+#define	  DBCR0_RST_CHIP	  0x20000000 /*   Chip reset */
+#define	  DBCR0_RST_SYSTEM	  0x30000000 /*   System reset */
+#define	  DBCR0_IC		  0x08000000 /* Instruction Completion debug event */
+#define	  DBCR0_BT		  0x04000000 /* Branch Taken debug event */
+#define	  DBCR0_EDE		  0x02000000 /* Exception Debug Event */
+#define	  DBCR0_TDE		  0x01000000 /* Trap Debug Event */
+#define	  DBCR0_IA1		  0x00800000 /* IAC (Instruction Address Compare) 1 debug event */
+#define	  DBCR0_IA2		  0x00400000 /* IAC 2 debug event */
+#define	  DBCR0_IA12		  0x00200000 /* Instruction Address Range Compare 1-2 */
+#define	  DBCR0_IA12X		  0x00100000 /* IA12 eXclusive */
+#define	  DBCR0_IA3		  0x00080000 /* IAC 3 debug event */
+#define	  DBCR0_IA4		  0x00040000 /* IAC 4 debug event */
+#define	  DBCR0_IA34		  0x00020000 /* Instruction Address Range Compare 3-4 */
+#define	  DBCR0_IA34X		  0x00010000 /* IA34 eXclusive */
+#define	  DBCR0_IA12T		  0x00008000 /* Instruction Address Range Compare 1-2 range Toggle */
+#define	  DBCR0_IA34T		  0x00004000 /* Instruction Address Range Compare 3-4 range Toggle */
+#define	  DBCR0_FT		  0x00000001 /* Freeze Timers on debug event */
+
+#define	SPR_IABR		0x3f2	/* ..8 Instruction Address Breakpoint Register 0 */
+#define	SPR_DABR		0x3f5	/* .6. Data Address Breakpoint Register */
+#define	SPR_MSSCR0		0x3f6	/* .6. Memory SubSystem Control Register */
+#define	  MSSCR0_SHDEN		  0x80000000 /* 0: Shared-state enable */
+#define	  MSSCR0_SHDPEN3	  0x40000000 /* 1: ~SHD[01] signal enable in MEI mode */
+#define	  MSSCR0_L1INTVEN	  0x38000000 /* 2-4: L1 data cache ~HIT intervention enable */
+#define	  MSSCR0_L2INTVEN	  0x07000000 /* 5-7: L2 data cache ~HIT intervention enable*/
+#define	  MSSCR0_DL1HWF		  0x00800000 /* 8: L1 data cache hardware flush */
+#define	  MSSCR0_MBO		  0x00400000 /* 9: must be one */
+#define	  MSSCR0_EMODE		  0x00200000 /* 10: MPX bus mode (read-only) */
+#define	  MSSCR0_ABD		  0x00100000 /* 11: address bus driven (read-only) */
+#define	  MSSCR0_MBZ		  0x000fffff /* 12-31: must be zero */
+#define	  MSSCR0_L2PFE		  0x00000003 /* 30-31: L2 prefetch enable */
+#define	SPR_LDSTCR		0x3f8	/* .6. Load/Store Control Register */
+#define	SPR_L2PM		0x3f8	/* .6. L2 Private Memory Control Register */
+#define	SPR_L2CR		0x3f9	/* .6. L2 Control Register */
+#define	  L2CR_L2E		  0x80000000 /* 0: L2 enable */
+#define	  L2CR_L2PE		  0x40000000 /* 1: L2 data parity enable */
+#define	  L2CR_L2SIZ		  0x30000000 /* 2-3: L2 size */
+#define	   L2SIZ_2M		  0x00000000
+#define	   L2SIZ_256K		  0x10000000
+#define	   L2SIZ_512K		  0x20000000
+#define	   L2SIZ_1M		  0x30000000
+#define	  L2CR_L2CLK		  0x0e000000 /* 4-6: L2 clock ratio */
+#define	   L2CLK_DIS		  0x00000000 /* disable L2 clock */
+#define	   L2CLK_10		  0x02000000 /* core clock / 1   */
+#define	   L2CLK_15		  0x04000000 /*            / 1.5 */
+#define	   L2CLK_20		  0x08000000 /*            / 2   */
+#define	   L2CLK_25		  0x0a000000 /*            / 2.5 */
+#define	   L2CLK_30		  0x0c000000 /*            / 3   */
+#define	  L2CR_L2RAM		  0x01800000 /* 7-8: L2 RAM type */
+#define	   L2RAM_FLOWTHRU_BURST	  0x00000000
+#define	   L2RAM_PIPELINE_BURST	  0x01000000
+#define	   L2RAM_PIPELINE_LATE	  0x01800000
+#define	  L2CR_L2DO		  0x00400000 /* 9: L2 data-only.
+				      Setting this bit disables instruction
+				      caching. */
+#define	  L2CR_L2I		  0x00200000 /* 10: L2 global invalidate. */
+#define	  L2CR_L2IO_7450	  0x00010000 /* 11: L2 instruction-only (MPC745x). */
+#define	  L2CR_L2CTL		  0x00100000 /* 11: L2 RAM control (ZZ enable).
+				      Enables automatic operation of the
+				      L2ZZ (low-power mode) signal. */
+#define	  L2CR_L2WT		  0x00080000 /* 12: L2 write-through. */
+#define	  L2CR_L2TS		  0x00040000 /* 13: L2 test support. */
+#define	  L2CR_L2OH		  0x00030000 /* 14-15: L2 output hold. */
+#define	  L2CR_L2DO_7450	  0x00010000 /* 15: L2 data-only (MPC745x). */
+#define	  L2CR_L2SL		  0x00008000 /* 16: L2 DLL slow. */
+#define	  L2CR_L2DF		  0x00004000 /* 17: L2 differential clock. */
+#define	  L2CR_L2BYP		  0x00002000 /* 18: L2 DLL bypass. */
+#define	  L2CR_L2FA		  0x00001000 /* 19: L2 flush assist (for software flush). */
+#define	  L2CR_L2HWF		  0x00000800 /* 20: L2 hardware flush. */
+#define	  L2CR_L2IO		  0x00000400 /* 21: L2 instruction-only. */
+#define	  L2CR_L2CLKSTP		  0x00000200 /* 22: L2 clock stop. */
+#define	  L2CR_L2DRO		  0x00000100 /* 23: L2DLL rollover checkstop enable. */
+#define	  L2CR_L2IP		  0x00000001 /* 31: L2 global invalidate in */
+					     /*     progress (read only). */
+#define	SPR_L3CR		0x3fa	/* .6. L3 Control Register */
+#define	  L3CR_L3E		  0x80000000 /* 0: L3 enable */
+#define	  L3CR_L3PE		  0x40000000 /* 1: L3 data parity enable */
+#define	  L3CR_L3APE		  0x20000000
+#define	  L3CR_L3SIZ		  0x10000000 /* 3: L3 size (0=1MB, 1=2MB) */
+#define	  L3CR_L3CLKEN		  0x08000000 /* 4: Enables L3_CLK[0:1] */
+#define	  L3CR_L3CLK		  0x03800000
+#define	  L3CR_L3IO		  0x00400000
+#define	  L3CR_L3CLKEXT		  0x00200000
+#define	  L3CR_L3CKSPEXT	  0x00100000
+#define	  L3CR_L3OH1		  0x00080000
+#define	  L3CR_L3SPO		  0x00040000
+#define	  L3CR_L3CKSP		  0x00030000
+#define	  L3CR_L3PSP		  0x0000e000
+#define	  L3CR_L3REP		  0x00001000
+#define	  L3CR_L3HWF		  0x00000800
+#define	  L3CR_L3I		  0x00000400 /* 21: L3 global invalidate */
+#define	  L3CR_L3RT		  0x00000300
+#define	  L3CR_L3NIRCA		  0x00000080
+#define	  L3CR_L3DO		  0x00000040
+#define	  L3CR_PMEN		  0x00000004
+#define	  L3CR_PMSIZ		  0x00000003
+
+#define	SPR_DCCR		0x3fa	/* 4.. Data Cache Cachability Register */
+#define	SPR_ICCR		0x3fb	/* 4.. Instruction Cache Cachability Register */
+#define	SPR_THRM1		0x3fc	/* .6. Thermal Management Register */
+#define	SPR_THRM2		0x3fd	/* .6. Thermal Management Register */
+#define	  SPR_THRM_TIN		  0x80000000 /* Thermal interrupt bit (RO) */
+#define	  SPR_THRM_TIV		  0x40000000 /* Thermal interrupt valid (RO) */
+#define	  SPR_THRM_THRESHOLD(x)	  ((x) << 23) /* Thermal sensor threshold */
+#define	  SPR_THRM_TID		  0x00000004 /* Thermal interrupt direction */
+#define	  SPR_THRM_TIE		  0x00000002 /* Thermal interrupt enable */
+#define	  SPR_THRM_VALID		  0x00000001 /* Valid bit */
+#define	SPR_THRM3		0x3fe	/* .6. Thermal Management Register */
+#define	  SPR_THRM_TIMER(x)	  ((x) << 1) /* Sampling interval timer */
+#define	  SPR_THRM_ENABLE	  0x00000001 /* TAU Enable */
+#define	SPR_FPECR		0x3fe	/* .6. Floating-Point Exception Cause Register */
+
+/* Time Base Register declarations */
+#define	TBR_TBL			0x10c	/* 468 Time Base Lower - read */
+#define	TBR_TBU			0x10d	/* 468 Time Base Upper - read */
+#define	TBR_TBWL		0x11c	/* 468 Time Base Lower - supervisor, write */
+#define	TBR_TBWU		0x11d	/* 468 Time Base Upper - supervisor, write */
+
+/* Performance counter declarations */
+#define	PMC_OVERFLOW		0x80000000 /* Counter has overflowed */
+
+/* The first five countable [non-]events are common to many PMC's */
+#define	PMCN_NONE		 0 /* Count nothing */
+#define	PMCN_CYCLES		 1 /* Processor cycles */
+#define	PMCN_ICOMP		 2 /* Instructions completed */
+#define	PMCN_TBLTRANS		 3 /* TBL bit transitions */
+#define	PCMN_IDISPATCH		 4 /* Instructions dispatched */
+
+/* Similar things for the 970 PMC direct counters */
+#define	PMC970N_NONE		0x8 /* Count nothing */
+#define	PMC970N_CYCLES		0xf /* Processor cycles */
+#define	PMC970N_ICOMP		0x9 /* Instructions completed */
+
+#if defined(AIM)
+
+#define	SPR_ESR			0x3d4	/* 4.. Exception Syndrome Register */
+#define	  ESR_MCI		  0x80000000 /* Machine check - instruction */
+#define	  ESR_PIL		  0x08000000 /* Program interrupt - illegal */
+#define	  ESR_PPR		  0x04000000 /* Program interrupt - privileged */
+#define	  ESR_PTR		  0x02000000 /* Program interrupt - trap */
+#define	  ESR_ST		  0x01000000 /* Store operation */
+#define	  ESR_DST		  0x00800000 /* Data storage interrupt - store fault */
+#define	  ESR_DIZ		  0x00800000 /* Data/instruction storage interrupt - zone fault */
+#define	  ESR_U0F		  0x00008000 /* Data storage interrupt - U0 fault */
+
+#elif defined(BOOKE)
+
+#define	SPR_MCSR		0x23c	/* ..8 Machine Check Syndrome register */
+
+#define	SPR_ESR			0x003e	/* ..8 Exception Syndrome Register */
+#define	  ESR_PIL		  0x08000000 /* Program interrupt - illegal */
+#define	  ESR_PPR		  0x04000000 /* Program interrupt - privileged */
+#define	  ESR_PTR		  0x02000000 /* Program interrupt - trap */
+#define	  ESR_ST		  0x00800000 /* Store operation */
+#define	  ESR_DLK		  0x00200000 /* Data storage, D cache locking */
+#define	  ESR_ILK		  0x00100000 /* Data storage, I cache locking */
+#define	  ESR_BO		  0x00020000 /* Data/instruction storage, byte ordering */
+#define	  ESR_SPE		  0x00000080 /* SPE exception bit */
+
+#define	SPR_CSRR0		0x03a	/* ..8 58 Critical SRR0 */
+#define	SPR_CSRR1		0x03b	/* ..8 59 Critical SRR1 */
+#define	SPR_MCSRR0		0x23a	/* ..8 570 Machine check SRR0 */
+#define	SPR_MCSRR1		0x23b	/* ..8 571 Machine check SRR1 */
+
+#define	SPR_MMUCR		0x3b2	/* 4.. MMU Control Register */
+#define	  MMUCR_SWOA		(0x80000000 >> 7)
+#define	  MMUCR_U1TE		(0x80000000 >> 9)
+#define	  MMUCR_U2SWOAE		(0x80000000 >> 10)
+#define	  MMUCR_DULXE		(0x80000000 >> 12)
+#define	  MMUCR_IULXE		(0x80000000 >> 13)
+#define	  MMUCR_STS		(0x80000000 >> 15)
+#define	  MMUCR_STID_MASK	(0xFF000000 >> 24)
+
+#define	SPR_MMUCSR0		0x3f4	/* ..8 1012 MMU Control and Status Register 0 */
+#define	  MMUCSR0_L2TLB0_FI	0x04	/*  TLB0 flash invalidate */
+#define	  MMUCSR0_L2TLB1_FI	0x02	/*  TLB1 flash invalidate */
+
+#define	SPR_SVR			0x3ff	/* ..8 1023 System Version Register */
+#define	  SVR_MPC8533		  0x8034
+#define	  SVR_MPC8533E		  0x803c
+#define	  SVR_MPC8541		  0x8072
+#define	  SVR_MPC8541E		  0x807a
+#define	  SVR_MPC8548		  0x8031
+#define	  SVR_MPC8548E		  0x8039
+#define	  SVR_MPC8555		  0x8071
+#define	  SVR_MPC8555E		  0x8079
+#define	  SVR_MPC8572		  0x80e0
+#define	  SVR_MPC8572E		  0x80e8
+#define	  SVR_P1011		  0x80e5
+#define	  SVR_P1011E		  0x80ed
+#define	  SVR_P1020		  0x80e4
+#define	  SVR_P1020E		  0x80ec
+#define	  SVR_P2010		  0x80e3
+#define	  SVR_P2010E		  0x80eb
+#define	  SVR_P2020		  0x80e2
+#define	  SVR_P2020E		  0x80ea
+#define	  SVR_P2041		  0x8210
+#define	  SVR_P2041E		  0x8218
+#define	  SVR_P3041		  0x8211
+#define	  SVR_P3041E		  0x8219
+#define	  SVR_P4040		  0x8200
+#define	  SVR_P4040E		  0x8208
+#define	  SVR_P4080		  0x8201
+#define	  SVR_P4080E		  0x8209
+#define	  SVR_P5020		  0x8220
+#define	  SVR_P5020E		  0x8228
+#define	SVR_VER(svr)		(((svr) >> 16) & 0xffff)
+
+#define	SPR_PID0		0x030	/* ..8 Process ID Register 0 */
+#define	SPR_PID1		0x279	/* ..8 Process ID Register 1 */
+#define	SPR_PID2		0x27a	/* ..8 Process ID Register 2 */
+
+#define	SPR_TLB0CFG		0x2B0	/* ..8 TLB 0 Config Register */
+#define	SPR_TLB1CFG		0x2B1	/* ..8 TLB 1 Config Register */
+#define	  TLBCFG_ASSOC_MASK	0xff000000 /* Associativity of TLB */
+#define	  TLBCFG_ASSOC_SHIFT	24
+#define	  TLBCFG_NENTRY_MASK	0x00000fff /* Number of entries in TLB */
+
+#define	SPR_IVPR		0x03f	/* ..8 Interrupt Vector Prefix Register */
+#define	SPR_IVOR0		0x190	/* ..8 Critical input */
+#define	SPR_IVOR1		0x191	/* ..8 Machine check */
+#define	SPR_IVOR2		0x192
+#define	SPR_IVOR3		0x193
+#define	SPR_IVOR4		0x194
+#define	SPR_IVOR5		0x195
+#define	SPR_IVOR6		0x196
+#define	SPR_IVOR7		0x197
+#define	SPR_IVOR8		0x198
+#define	SPR_IVOR9		0x199
+#define	SPR_IVOR10		0x19a
+#define	SPR_IVOR11		0x19b
+#define	SPR_IVOR12		0x19c
+#define	SPR_IVOR13		0x19d
+#define	SPR_IVOR14		0x19e
+#define	SPR_IVOR15		0x19f
+#define	SPR_IVOR32		0x210
+#define	SPR_IVOR33		0x211
+#define	SPR_IVOR34		0x212
+#define	SPR_IVOR35		0x213
+
+#define	SPR_MAS0		0x270	/* ..8 MMU Assist Register 0 Book-E/e500 */
+#define	SPR_MAS1		0x271	/* ..8 MMU Assist Register 1 Book-E/e500 */
+#define	SPR_MAS2		0x272	/* ..8 MMU Assist Register 2 Book-E/e500 */
+#define	SPR_MAS3		0x273	/* ..8 MMU Assist Register 3 Book-E/e500 */
+#define	SPR_MAS4		0x274	/* ..8 MMU Assist Register 4 Book-E/e500 */
+#define	SPR_MAS5		0x275	/* ..8 MMU Assist Register 5 Book-E */
+#define	SPR_MAS6		0x276	/* ..8 MMU Assist Register 6 Book-E/e500 */
+#define	SPR_MAS7		0x3B0	/* ..8 MMU Assist Register 7 Book-E/e500 */
+#define	SPR_MAS8		0x155	/* ..8 MMU Assist Register 8 Book-E/e500 */
+
+#define	SPR_L1CFG0		0x203	/* ..8 L1 cache configuration register 0 */
+#define	SPR_L1CFG1		0x204	/* ..8 L1 cache configuration register 1 */
+
+#define	SPR_CCR1		0x378
+#define	  CCR1_L2COBE		0x00000040
+
+#define	DCR_L2DCDCRAI		0x0000	/* L2 D-Cache DCR Address Pointer */
+#define	DCR_L2DCDCRDI		0x0001	/* L2 D-Cache DCR Data Indirect */
+#define	DCR_L2CR0		0x00	/* L2 Cache Configuration Register 0 */
+#define	  L2CR0_AS		0x30000000
+
+#define	SPR_L1CSR0		0x3F2	/* ..8 L1 Cache Control and Status Register 0 */
+#define	  L1CSR0_DCPE		0x00010000	/* Data Cache Parity Enable */
+#define	  L1CSR0_DCLFR		0x00000100	/* Data Cache Lock Bits Flash Reset */
+#define	  L1CSR0_DCFI		0x00000002	/* Data Cache Flash Invalidate */
+#define	  L1CSR0_DCE		0x00000001	/* Data Cache Enable */
+#define	SPR_L1CSR1		0x3F3	/* ..8 L1 Cache Control and Status Register 1 */
+#define	  L1CSR1_ICPE		0x00010000	/* Instruction Cache Parity Enable */
+#define	  L1CSR1_ICUL		0x00000400      /* Instr Cache Unable to Lock */
+#define	  L1CSR1_ICLFR		0x00000100	/* Instruction Cache Lock Bits Flash Reset */
+#define	  L1CSR1_ICFI		0x00000002	/* Instruction Cache Flash Invalidate */
+#define	  L1CSR1_ICE		0x00000001	/* Instruction Cache Enable */
+
+#define	SPR_L2CSR0		0x3F9	/* ..8 L2 Cache Control and Status Register 0 */
+#define	  L2CSR0_L2E		0x80000000	/* L2 Cache Enable */
+#define	  L2CSR0_L2PE		0x40000000	/* L2 Cache Parity Enable */
+#define	  L2CSR0_L2FI		0x00200000	/* L2 Cache Flash Invalidate */
+#define	  L2CSR0_L2LFC		0x00000400	/* L2 Cache Lock Flags Clear */
+
+#define	SPR_BUCSR		0x3F5	/* ..8 Branch Unit Control and Status Register */
+#define	  BUCSR_BPEN		0x00000001	/* Branch Prediction Enable */
+#define	  BUCSR_BBFI		0x00000200	/* Branch Buffer Flash Invalidate */
+
+#endif /* BOOKE */
+#endif /* !_POWERPC_SPR_H_ */


Property changes on: trunk/sys/powerpc/include/spr.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/sr.h
===================================================================
--- trunk/sys/powerpc/include/sr.h	                        (rev 0)
+++ trunk/sys/powerpc/include/sr.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,63 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2002 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/sr.h 214574 2010-10-30 23:07:30Z nwhitehorn $
+ */
+
+#ifndef _MACHINE_SR_H_
+#define	_MACHINE_SR_H_
+
+/*
+ * Bit definitions for segment registers.
+ *
+ * PowerPC Microprocessor Family: The Programming Environments for 32-bit
+ * Microprocessors, section 2.3.5
+ */
+
+#define	SR_TYPE		0x80000000	/* Type selector */
+#define	SR_KS		0x40000000	/* Supervisor-state protection key */
+#define	SR_KP		0x20000000	/* User-state protection key */
+#define	SR_N		0x10000000	/* No-execute protection */
+#define	SR_VSID_MASK	0x00ffffff	/* Virtual Segment ID mask */
+
+/* Kernel segment register usage */
+#define	USER_SR		12
+#define	KERNEL_SR	13
+#define	KERNEL2_SR	14
+#define	KERNEL3_SR	15
+#define	KERNEL_VSIDBITS	0xfffffUL
+#define	KERNEL_SEGMENT	(0xfffff0 + KERNEL_SR)
+#define	KERNEL2_SEGMENT	(0xfffff0 + KERNEL2_SR)
+#define	EMPTY_SEGMENT	0xfffff0
+#ifdef __powerpc64__
+#define	USER_ADDR	0xcffffffff0000000UL
+#else
+#define	USER_ADDR	((uintptr_t)USER_SR << ADDR_SR_SHFT)
+#endif
+#define	SEGMENT_LENGTH	0x10000000UL
+#define	SEGMENT_INVMASK	0x0fffffffUL
+#define	SEGMENT_MASK	~SEGMENT_INVMASK
+
+#endif /* !_MACHINE_SR_H_ */


Property changes on: trunk/sys/powerpc/include/sr.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/stack.h
===================================================================
--- trunk/sys/powerpc/include/stack.h	                        (rev 0)
+++ trunk/sys/powerpc/include/stack.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,37 @@
+/* $MidnightBSD$ */
+/*-
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution at CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/stack.h 174195 2007-12-02 20:40:35Z rwatson $
+ */
+
+#ifndef _MACHINE_STACK_H_
+#define	_MACHINE_STACK_H_
+
+extern int trapexit[];
+extern int asttrapexit[];
+extern int end[];
+
+#endif /* !_MACHINE_STACK_H_ */


Property changes on: trunk/sys/powerpc/include/stack.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/stdarg.h
===================================================================
--- trunk/sys/powerpc/include/stdarg.h	                        (rev 0)
+++ trunk/sys/powerpc/include/stdarg.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,151 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2002 David E. O'Brien.  All rights reserved.
+ * Copyright (c) 2000 Tsubai Masanari.  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. 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.
+ *
+ *	$NetBSD: stdarg.h,v 1.5 2000/02/27 17:50:21 tsubai Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/stdarg.h 162487 2006-09-21 01:37:02Z kan $
+ */
+
+#ifndef _MACHINE_STDARG_H_
+#define	_MACHINE_STDARG_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+#ifndef _VA_LIST_DECLARED
+#define	_VA_LIST_DECLARED
+typedef	__va_list	va_list;
+#endif
+
+#if defined(__GNUCLIKE_BUILTIN_STDARG)
+
+#define	va_start(ap, last) \
+	__builtin_va_start((ap), (last))
+
+#define	va_arg(ap, type) \
+	__builtin_va_arg((ap), type)
+
+#if __ISO_C_VISIBLE >= 1999
+#define	va_copy(dest, src) \
+	__builtin_va_copy((dest), (src))
+
+#define	__va_copy(dest, src) \
+	va_copy((dest), (src))
+#endif
+
+#define	va_end(ap) \
+	__builtin_va_end(ap)
+
+#else	/* !__GNUCLIKE_BUILTIN_STDARG */
+
+#ifdef __lint__
+
+#define	va_start(ap, last)	((ap) = *(va_list *)0)
+#define	va_arg(ap, type)	(*(type *)(void *)&(ap))
+
+#else
+
+#if defined(__GNUC_VA_LIST_COMPATIBILITY)
+#define	va_start(ap, last)						\
+	(__builtin_next_arg(last),					\
+	 __builtin_memcpy((void *)&(ap), __builtin_saveregs (),		\
+	 sizeof(__gnuc_va_list)))
+#else
+#define	va_start(ap, last)						\
+	(__builtin_next_arg(last),					\
+	 (ap).__stack = __va_stack_args,				\
+	 (ap).__base = __va_reg_args,					\
+	 (ap).__gpr = __va_first_gpr,					\
+	 (ap).__fpr = __va_first_fpr)
+#endif
+
+#define	__va_first_gpr	(__builtin_args_info(0))
+#define	__va_first_fpr	(__builtin_args_info(1) - 32 - 1)
+#define	__va_stack_args							\
+	((char *)__builtin_saveregs() +					\
+	 (__va_first_gpr >= 8 ? __va_first_gpr - 8 : 0) * sizeof(int))
+#define	__va_reg_args							\
+	((char *)__builtin_frame_address(0) + __builtin_args_info(4))
+
+#define	__INTEGER_TYPE_CLASS	1
+#define	__REAL_TYPE_CLASS	8
+#define	__RECORD_TYPE_CLASS	12
+
+#define	__va_longlong(type)						\
+	(__builtin_classify_type(*(type *)0) == __INTEGER_TYPE_CLASS &&	\
+	 sizeof(type) == 8)
+
+#define	__va_double(type)						\
+	(__builtin_classify_type(*(type *)0) == __REAL_TYPE_CLASS)
+
+#define	__va_struct(type)						\
+	(__builtin_classify_type(*(type *)0) >= __RECORD_TYPE_CLASS)
+
+#define	__va_size(type)							\
+	((sizeof(type) + sizeof(int) - 1) / sizeof(int) * sizeof(int))
+
+#define	__va_savedgpr(ap, type)						\
+	((ap).__base + (ap).__gpr * sizeof(int) - sizeof(type))
+
+#define	__va_savedfpr(ap, type)						\
+	((ap).__base + 8 * sizeof(int) + (ap).__fpr * sizeof(double) -	\
+	 sizeof(type))
+
+#define	__va_stack(ap, type)						\
+	((ap).__stack += __va_size(type) +				\
+			(__va_longlong(type) ? (int)(ap).__stack & 4 : 0), \
+	 (ap).__stack - sizeof(type))
+
+#define	__va_gpr(ap, type)						\
+	((ap).__gpr += __va_size(type) / sizeof(int) +			\
+		      (__va_longlong(type) ? (ap).__gpr & 1 : 0),	\
+	 (ap).__gpr <= 8 ? __va_savedgpr(ap, type) : __va_stack(ap, type))
+
+#define	__va_fpr(ap, type)						\
+	((ap).__fpr++,							\
+	 (ap).__fpr <= 8 ? __va_savedfpr(ap, type) : __va_stack(ap, type))
+
+#define	va_arg(ap, type)						\
+	(*(type *)(__va_struct(type) ? (*(void **)__va_gpr(ap, void *)) : \
+		   __va_double(type) ? __va_fpr(ap, type) :		\
+		   __va_gpr(ap, type)))
+
+#endif /* __lint__ */
+
+#define	va_end(ap)	
+
+#if __ISO_C_VISIBLE >= 1999
+#if !defined(_ANSI_SOURCE) &&						\
+    (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) ||		\
+     defined(_ISOC99_SOURCE) || (__STDC_VERSION__ - 0) >= 199901L)
+#define	va_copy(dest, src)						\
+	((dest) = (src))
+#endif
+#endif
+
+#endif /* __GNUCLIKE_BUILTIN_STDARG */
+
+#endif /* _MACHINE_STDARG_H_ */


Property changes on: trunk/sys/powerpc/include/stdarg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/sysarch.h
===================================================================
--- trunk/sys/powerpc/include/sysarch.h	                        (rev 0)
+++ trunk/sys/powerpc/include/sysarch.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,44 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1993 The 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/sysarch.h 190703 2009-04-04 22:05:36Z marcel $
+ */
+
+#ifndef _MACHINE_SYSARCH_H_
+#define	_MACHINE_SYSARCH_H_
+
+#ifndef _KERNEL
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int	sysarch(int, void *);
+__END_DECLS
+#endif
+
+#endif /* !_MACHINE_SYSARCH_H_ */


Property changes on: trunk/sys/powerpc/include/sysarch.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/tlb.h
===================================================================
--- trunk/sys/powerpc/include/tlb.h	                        (rev 0)
+++ trunk/sys/powerpc/include/tlb.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,218 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2006-2012 Semihalf.
+ * 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/tlb.h 265996 2014-05-14 00:51:26Z ian $
+ */
+
+#ifndef	_MACHINE_TLB_H_
+#define	_MACHINE_TLB_H_
+
+#if defined(BOOKE_E500)
+
+/*  PowerPC E500 MAS registers */
+#define MAS0_TLBSEL(x)		((x << 28) & 0x10000000)
+#define MAS0_ESEL(x)		((x << 16) & 0x000F0000)
+
+#define MAS0_TLBSEL1		0x10000000
+#define MAS0_TLBSEL0		0x00000000
+#define MAS0_ESEL_TLB1MASK	0x000F0000
+#define MAS0_ESEL_TLB0MASK	0x00030000
+#define MAS0_ESEL_SHIFT		16
+#define MAS0_NV_MASK		0x00000003
+#define MAS0_NV_SHIFT		0
+
+#define MAS1_VALID		0x80000000
+#define MAS1_IPROT		0x40000000
+#define MAS1_TID_MASK		0x00FF0000
+#define MAS1_TID_SHIFT		16
+#define MAS1_TS_MASK		0x00001000
+#define MAS1_TS_SHIFT		12
+#define MAS1_TSIZE_MASK		0x00000F00
+#define MAS1_TSIZE_SHIFT	8
+
+#define	TLB_SIZE_4K		1
+#define	TLB_SIZE_16K		2
+#define	TLB_SIZE_64K		3
+#define	TLB_SIZE_256K		4
+#define	TLB_SIZE_1M		5
+#define	TLB_SIZE_4M		6
+#define	TLB_SIZE_16M		7
+#define	TLB_SIZE_64M		8
+#define	TLB_SIZE_256M		9
+#define	TLB_SIZE_1G		10
+#define	TLB_SIZE_4G		11
+
+#define	MAS2_EPN_MASK		0xFFFFF000
+#define	MAS2_EPN_SHIFT		12
+#define	MAS2_X0			0x00000040
+#define	MAS2_X1			0x00000020
+#define	MAS2_W			0x00000010
+#define	MAS2_I			0x00000008
+#define	MAS2_M			0x00000004
+#define	MAS2_G			0x00000002
+#define	MAS2_E			0x00000001
+
+#define	MAS3_RPN		0xFFFFF000
+#define	MAS3_RPN_SHIFT		12
+#define	MAS3_U0			0x00000200
+#define	MAS3_U1			0x00000100
+#define	MAS3_U2			0x00000080
+#define	MAS3_U3			0x00000040
+#define	MAS3_UX			0x00000020
+#define	MAS3_SX			0x00000010
+#define	MAS3_UW			0x00000008
+#define	MAS3_SW			0x00000004
+#define	MAS3_UR			0x00000002
+#define	MAS3_SR			0x00000001
+
+#define MAS4_TLBSELD1		0x10000000
+#define MAS4_TLBSELD0		0x00000000
+#define MAS4_TIDSELD_MASK	0x00030000
+#define MAS4_TIDSELD_SHIFT	16
+#define MAS4_TSIZED_MASK	0x00000F00
+#define MAS4_TSIZED_SHIFT	8
+#define MAS4_X0D		0x00000040
+#define MAS4_X1D		0x00000020
+#define MAS4_WD			0x00000010
+#define MAS4_ID			0x00000008
+#define MAS4_MD			0x00000004
+#define MAS4_GD			0x00000002
+#define MAS4_ED			0x00000001
+
+#define MAS6_SPID0_MASK		0x00FF0000
+#define MAS6_SPID0_SHIFT	16
+#define MAS6_SAS		0x00000001
+
+#define MAS1_GETTID(mas1)	(((mas1) & MAS1_TID_MASK) >> MAS1_TID_SHIFT)
+
+#define MAS2_TLB0_ENTRY_IDX_MASK	0x0007f000
+#define MAS2_TLB0_ENTRY_IDX_SHIFT	12
+
+/*
+ * Maximum number of TLB1 entries used for a permanent mapping of kernel
+ * region (kernel image plus statically allocated data).
+ */
+#define KERNEL_REGION_MAX_TLB_ENTRIES   4
+
+#define _TLB_ENTRY_IO	(MAS2_I | MAS2_G)
+#ifdef SMP
+#define _TLB_ENTRY_MEM	(MAS2_M)
+#else
+#define _TLB_ENTRY_MEM	(0)
+#endif
+
+#if !defined(LOCORE)
+typedef struct tlb_entry {
+	vm_paddr_t phys;
+	vm_offset_t virt;
+	vm_size_t size;
+	uint32_t mas1;
+	uint32_t mas2;
+	uint32_t mas3;
+} tlb_entry_t;
+
+void tlb0_print_tlbentries(void);
+
+void tlb1_inval_entry(unsigned int);
+void tlb1_init(void);
+void tlb1_print_entries(void);
+void tlb1_print_tlbentries(void);
+#endif /* !LOCORE */
+
+#elif defined(BOOKE_PPC4XX)
+
+/* TLB Words */
+#define	TLB_PAGEID		0
+#define	TLB_XLAT		1
+#define	TLB_ATTRIB		2
+
+/* Page identification fields */
+#define	TLB_EPN_MASK		(0xFFFFFC00 >> 0)
+#define	TLB_VALID		(0x80000000 >> 22)
+#define	TLB_TS			(0x80000000 >> 23)
+#define	TLB_SIZE_1K		(0x00000000 >> 24)
+#define	TLB_SIZE_MASK		(0xF0000000 >> 24)
+
+/* Translation fields */
+#define	TLB_RPN_MASK		(0xFFFFFC00 >> 0)
+#define	TLB_ERPN_MASK		(0xF0000000 >> 28)
+
+/* Storage attribute and access control fields */
+#define	TLB_WL1			(0x80000000 >> 11)
+#define	TLB_IL1I		(0x80000000 >> 12)
+#define	TLB_IL1D		(0x80000000 >> 13)
+#define	TLB_IL2I		(0x80000000 >> 14)
+#define	TLB_IL2D		(0x80000000 >> 15)
+#define	TLB_U0			(0x80000000 >> 16)
+#define	TLB_U1			(0x80000000 >> 17)
+#define	TLB_U2			(0x80000000 >> 18)
+#define	TLB_U3			(0x80000000 >> 19)
+#define	TLB_W			(0x80000000 >> 20)
+#define	TLB_I			(0x80000000 >> 21)
+#define	TLB_M			(0x80000000 >> 22)
+#define	TLB_G			(0x80000000 >> 23)
+#define	TLB_E			(0x80000000 >> 24)
+#define	TLB_UX			(0x80000000 >> 26)
+#define	TLB_UW			(0x80000000 >> 27)
+#define	TLB_UR			(0x80000000 >> 28)
+#define	TLB_SX			(0x80000000 >> 29)
+#define	TLB_SW			(0x80000000 >> 30)
+#define	TLB_SR			(0x80000000 >> 31)
+#define	TLB_SIZE		64
+
+#define	TLB_SIZE_4K		(0x10000000 >> 24)
+#define	TLB_SIZE_16K		(0x20000000 >> 24)
+#define	TLB_SIZE_64K		(0x30000000 >> 24)
+#define	TLB_SIZE_256K		(0x40000000 >> 24)
+#define	TLB_SIZE_1M		(0x50000000 >> 24)
+#define	TLB_SIZE_16M		(0x70000000 >> 24)
+#define	TLB_SIZE_256M		(0x90000000 >> 24)
+#define	TLB_SIZE_1G		(0xA0000000 >> 24)
+
+#endif /* BOOKE_E500 */
+
+#define TID_KERNEL	0	/* TLB TID to use for kernel (shared) translations */
+#define TID_KRESERVED	1	/* Number of TIDs reserved for kernel */
+#define TID_URESERVED	0	/* Number of TIDs reserved for user */
+#define TID_MIN		(TID_KRESERVED + TID_URESERVED)
+#define TID_MAX		255
+#define TID_NONE	-1
+
+#define TLB_UNLOCKED	0
+
+#if !defined(LOCORE)
+
+typedef int tlbtid_t;
+
+struct pmap;
+
+void tlb_lock(uint32_t *);
+void tlb_unlock(uint32_t *);
+
+#endif /* !LOCORE */
+
+#endif	/* _MACHINE_TLB_H_ */


Property changes on: trunk/sys/powerpc/include/tlb.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/trap.h
===================================================================
--- trunk/sys/powerpc/include/trap.h	                        (rev 0)
+++ trunk/sys/powerpc/include/trap.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,131 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ * $NetBSD: trap.h,v 1.7 2002/02/22 13:51:40 kleink Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/trap.h 266005 2014-05-14 04:57:55Z ian $
+ */
+
+#ifndef	_POWERPC_TRAP_H_
+#define	_POWERPC_TRAP_H_
+
+#define	EXC_RSVD	0x0000		/* Reserved */
+#define	EXC_RST		0x0100		/* Reset; all but IBM4xx */
+#define	EXC_MCHK	0x0200		/* Machine Check */
+#define	EXC_DSI		0x0300		/* Data Storage Interrupt */
+#define	EXC_DSE		0x0380		/* Data Segment Interrupt */
+#define	EXC_ISI		0x0400		/* Instruction Storage Interrupt */
+#define	EXC_ISE		0x0480		/* Instruction Segment Interrupt */
+#define	EXC_EXI		0x0500		/* External Interrupt */
+#define	EXC_ALI		0x0600		/* Alignment Interrupt */
+#define	EXC_PGM		0x0700		/* Program Interrupt */
+#define	EXC_FPU		0x0800		/* Floating-point Unavailable */
+#define	EXC_DECR	0x0900		/* Decrementer Interrupt */
+#define	EXC_SC		0x0c00		/* System Call */
+#define	EXC_TRC		0x0d00		/* Trace */
+#define	EXC_FPA		0x0e00		/* Floating-point Assist */
+
+/* The following is only available on the 601: */
+#define	EXC_RUNMODETRC	0x2000		/* Run Mode/Trace Exception */
+
+/* The following are only available on 970(G5): */
+#define	EXC_VECAST_G5	0x1700		/* AltiVec Assist */
+
+/* The following are only available on 7400(G4): */
+#define	EXC_VEC		0x0f20		/* AltiVec Unavailable */
+#define	EXC_VECAST_G4	0x1600		/* AltiVec Assist */
+
+/* The following are only available on 604/750/7400: */
+#define	EXC_PERF	0x0f00		/* Performance Monitoring */
+#define	EXC_BPT		0x1300		/* Instruction Breakpoint */
+#define	EXC_SMI		0x1400		/* System Managment Interrupt */
+
+/* The following are only available on 750/7400: */
+#define	EXC_THRM	0x1700		/* Thermal Management Interrupt */
+
+/* And these are only on the 603: */
+#define	EXC_IMISS	0x1000		/* Instruction translation miss */
+#define	EXC_DLMISS	0x1100		/* Data load translation miss */
+#define	EXC_DSMISS	0x1200		/* Data store translation miss */
+
+/* The following are available on 4xx and 85xx */
+#define	EXC_CRIT	0x0100		/* Critical Input Interrupt */
+#define	EXC_PIT		0x1000		/* Programmable Interval Timer */
+#define	EXC_FIT		0x1010		/* Fixed Interval Timer */
+#define	EXC_WDOG	0x1020		/* Watchdog Timer */
+#define	EXC_DTMISS	0x1100		/* Data TLB Miss */
+#define	EXC_ITMISS	0x1200		/* Instruction TLB Miss */
+#define	EXC_APU		0x1300		/* Auxiliary Processing Unit */
+#define	EXC_DEBUG	0x2000		/* Debug trap */
+
+#define	EXC_LAST	0x2f00		/* Last possible exception vector */
+
+#define	EXC_AST		0x3000		/* Fake AST vector */
+
+/* Trap was in user mode */
+#define	EXC_USER	0x10000
+
+
+/*
+ * EXC_ALI sets bits in the DSISR and DAR to provide enough
+ * information to recover from the unaligned access without needing to
+ * parse the offending instruction. This includes certain bits of the
+ * opcode, and information about what registers are used. The opcode
+ * indicator values below come from Appendix F of Book III of "The
+ * PowerPC Architecture".
+ */
+
+#define EXC_ALI_OPCODE_INDICATOR(dsisr) ((dsisr >> 10) & 0x7f)
+#define EXC_ALI_LFD	0x09
+#define EXC_ALI_STFD	0x0b
+
+/* Macros to extract register information */
+#define EXC_ALI_RST(dsisr) ((dsisr >> 5) & 0x1f)   /* source or target */
+#define EXC_ALI_RA(dsisr) (dsisr & 0x1f)
+
+/*
+ * SRR1 bits for program exception traps. These identify what caused
+ * the program exception. See section 6.5.9 of the Power ISA Version
+ * 2.05.
+ */
+
+#define	EXC_PGM_FPENABLED	(1UL << 20)
+#define	EXC_PGM_ILLEGAL		(1UL << 19)
+#define	EXC_PGM_PRIV		(1UL << 18)
+#define	EXC_PGM_TRAP		(1UL << 17)
+
+#ifndef LOCORE
+struct	trapframe;
+struct	pcb;
+void    trap(struct trapframe *);
+int	ppc_instr_emulate(struct trapframe *, struct pcb *);
+#endif
+
+#endif	/* _POWERPC_TRAP_H_ */


Property changes on: trunk/sys/powerpc/include/trap.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/ucontext.h
===================================================================
--- trunk/sys/powerpc/include/ucontext.h	                        (rev 0)
+++ trunk/sys/powerpc/include/ucontext.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,89 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ * $NetBSD: signal.h,v 1.4 1998/09/14 02:48:34 thorpej Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/ucontext.h 234542 2012-04-21 14:39:47Z nwhitehorn $
+ */
+
+#ifndef	_MACHINE_UCONTEXT_H_
+#define	_MACHINE_UCONTEXT_H_
+
+typedef struct __mcontext {
+	int		mc_vers;
+	int		mc_flags;
+#define _MC_FP_VALID	0x01
+#define _MC_AV_VALID	0x02
+	int		mc_onstack;	  	/* saved onstack flag */
+	int		mc_len;			/* sizeof(__mcontext) */
+	uint64_t	mc_avec[32*2];		/* vector register file */
+	uint32_t	mc_av[2];
+	register_t	mc_frame[42];
+	uint64_t	mc_fpreg[33];
+} mcontext_t __aligned(16);
+
+#if defined(_KERNEL) && defined(__powerpc64__)
+typedef struct __mcontext32 {
+	int		mc_vers;
+	int		mc_flags;
+#define _MC_FP_VALID	0x01
+#define _MC_AV_VALID	0x02
+	int		mc_onstack;	  	/* saved onstack flag */
+	int		mc_len;			/* sizeof(__mcontext) */
+	uint64_t	mc_avec[32*2];		/* vector register file */
+	uint32_t	mc_av[2];
+	uint32_t	mc_frame[42];
+	uint64_t	mc_fpreg[33];
+} mcontext32_t __aligned(16);
+#endif
+
+/* GPRs and supervisor-level regs */
+#define mc_gpr		mc_frame
+#define mc_lr		mc_frame[32]
+#define mc_cr		mc_frame[33]
+#define mc_xer		mc_frame[34]
+#define	mc_ctr		mc_frame[35]
+#define mc_srr0		mc_frame[36]
+#define mc_srr1		mc_frame[37]
+#define mc_exc		mc_frame[38]
+#define mc_dar		mc_frame[39]
+#define mc_dsisr	mc_frame[40]
+
+/* floating-point state */
+#define mc_fpscr	mc_fpreg[32]
+
+/* altivec state */
+#define mc_vscr		mc_av[0]
+#define mc_vrsave	mc_av[1]
+
+#define _MC_VERSION	0x1
+#define _MC_VERSION_KSE 0xee	/* partial ucontext for libpthread */
+
+#endif	/* !_MACHINE_UCONTEXT_H_ */


Property changes on: trunk/sys/powerpc/include/ucontext.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/varargs.h
===================================================================
--- trunk/sys/powerpc/include/varargs.h	                        (rev 0)
+++ trunk/sys/powerpc/include/varargs.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,81 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2002 David E. O'Brien.  All rights reserved.
+ * Copyright (c) 2000 Tsubai Masanari.  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. 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.
+
+ *	$NetBSD: varargs.h,v 1.5 2000/02/27 17:50:22 tsubai Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/varargs.h 143063 2005-03-02 21:33:29Z joerg $
+ */
+
+#ifndef _MACHINE_VARARGS_H_
+#define	_MACHINE_VARARGS_H_
+
+#ifndef _SYS_CDEFS_H_
+#error this file needs sys/cdefs.h as a prerequisite
+#endif
+
+#if defined(__GNUCLIKE_BUILTIN_VARARGS)
+
+#include <sys/_types.h>
+
+#ifndef _VA_LIST_DECLARED
+#define	_VA_LIST_DECLARED
+typedef	__va_list	va_list;
+#endif
+
+typedef int __builtin_va_alist_t __attribute__((__mode__(__word__)));
+
+#define	va_alist		__builtin_va_alist
+#define	va_dcl			__builtin_va_alist_t __builtin_va_alist; ...
+#define	va_start(ap)		__builtin_varargs_start(ap)
+#define	va_arg(ap, type)	__builtin_va_arg((ap), type)
+#define	va_end(ap)		__builtin_va_end(ap)
+
+#else	/* !  __GNUCLIKE_BUILTIN_VARARGS */
+
+#include <machine/stdarg.h>
+
+#ifdef __GNUCLIKE_BUILTIN_VAALIST
+#define	va_alist	__builtin_va_alist
+#define	va_dcl		int __builtin_va_alist; ...
+#else
+#error this file needs to be ported to your compiler
+#endif
+
+#undef va_start
+
+#ifdef __lint__
+#define	va_start(ap)	((ap) = *(va_list *)0)
+#else
+#define	va_start(ap)							\
+	((ap).__stack = __va_stack_args,				\
+	 (ap).__base = __va_reg_args,					\
+	 (ap).__gpr = __va_first_gpr,					\
+	 (ap).__fpr = __va_first_fpr)
+#endif
+
+#endif /* __GNUCLIKE_BUILTIN_VARARGS */
+
+#endif /* _MACHINE_VARARGS_H_ */


Property changes on: trunk/sys/powerpc/include/varargs.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/vdso.h
===================================================================
--- trunk/sys/powerpc/include/vdso.h	                        (rev 0)
+++ trunk/sys/powerpc/include/vdso.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,42 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2012 Konstantin Belousov <kib at FreeBSD.ORG>.
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/vdso.h 237433 2012-06-22 07:06:40Z kib $
+ */
+
+#ifndef _POWERPC_VDSO_H
+#define	_POWERPC_VDSO_H
+
+#define	VDSO_TIMEHANDS_MD			\
+	uint32_t	th_res[8];
+
+#ifdef _KERNEL
+#ifdef COMPAT_FREEBSD32
+
+#define	VDSO_TIMEHANDS_MD32	VDSO_TIMEHANDS_MD
+
+#endif
+#endif
+#endif


Property changes on: trunk/sys/powerpc/include/vdso.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/vm.h
===================================================================
--- trunk/sys/powerpc/include/vm.h	                        (rev 0)
+++ trunk/sys/powerpc/include/vm.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,44 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Alan L. Cox <alc at cs.rice.edu>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/include/vm.h 233671 2012-03-29 16:51:22Z jhb $
+ */
+
+#ifndef _MACHINE_VM_H_
+#define	_MACHINE_VM_H_
+
+#include <machine/pte.h>
+
+/* Memory attributes. */
+#define	VM_MEMATTR_DEFAULT		0
+#define	VM_MEMATTR_UNCACHEABLE		0x01
+#define	VM_MEMATTR_CACHEABLE		0x02
+#define	VM_MEMATTR_WRITE_COMBINING	0x04
+#define	VM_MEMATTR_WRITE_BACK		0x08
+#define	VM_MEMATTR_WRITE_THROUGH	0x10
+#define	VM_MEMATTR_PREFETCHABLE		0x20
+
+#endif /* !_MACHINE_VM_H_ */


Property changes on: trunk/sys/powerpc/include/vm.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/include/vmparam.h
===================================================================
--- trunk/sys/powerpc/include/vmparam.h	                        (rev 0)
+++ trunk/sys/powerpc/include/vmparam.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,201 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: vmparam.h,v 1.11 2000/02/11 19:25:16 thorpej Exp $
+ * $FreeBSD: stable/10/sys/powerpc/include/vmparam.h 266204 2014-05-16 01:30:30Z ian $
+ */
+
+#ifndef _MACHINE_VMPARAM_H_
+#define	_MACHINE_VMPARAM_H_
+
+#define	USRSTACK	SHAREDPAGE
+
+#ifndef	MAXTSIZ
+#define	MAXTSIZ		(64*1024*1024)		/* max text size */
+#endif
+
+#ifndef	DFLDSIZ
+#define	DFLDSIZ		(128*1024*1024)		/* default data size */
+#endif
+
+#ifndef	MAXDSIZ
+#define	MAXDSIZ		(1*1024*1024*1024)	/* max data size */
+#endif
+
+#ifndef	DFLSSIZ
+#define	DFLSSIZ		(8*1024*1024)		/* default stack size */
+#endif
+
+#ifndef	MAXSSIZ
+#define	MAXSSIZ		(64*1024*1024)		/* max stack size */
+#endif
+
+#ifdef AIM
+#define	VM_MAXUSER_ADDRESS32	((vm_offset_t)0xfffff000)
+#else
+#define	VM_MAXUSER_ADDRESS32	((vm_offset_t)0x7ffff000)
+#endif
+
+/*
+ * Would like to have MAX addresses = 0, but this doesn't (currently) work
+ */
+#if !defined(LOCORE)
+#ifdef __powerpc64__
+#define	VM_MIN_ADDRESS		(0x0000000000000000UL)
+#define	VM_MAXUSER_ADDRESS	(0xfffffffffffff000UL)
+#define	VM_MAX_ADDRESS		(0xffffffffffffffffUL)
+#else
+#define	VM_MIN_ADDRESS		((vm_offset_t)0)
+#define	VM_MAXUSER_ADDRESS	VM_MAXUSER_ADDRESS32
+#define	VM_MAX_ADDRESS		((vm_offset_t)0xffffffff)
+#endif
+#define	SHAREDPAGE		(VM_MAXUSER_ADDRESS - PAGE_SIZE)
+#else /* LOCORE */
+#if !defined(__powerpc64__) && defined(BOOKE)
+#define	VM_MIN_ADDRESS		0
+#define	VM_MAXUSER_ADDRESS	0x7ffff000
+#endif
+#endif /* LOCORE */
+
+#define	FREEBSD32_SHAREDPAGE	(VM_MAXUSER_ADDRESS32 - PAGE_SIZE)
+#define	FREEBSD32_USRSTACK	FREEBSD32_SHAREDPAGE
+
+#ifdef AIM
+#define	KERNBASE		0x00100000UL	/* start of kernel virtual */
+
+#ifdef __powerpc64__
+#define	VM_MIN_KERNEL_ADDRESS		0xc000000000000000UL
+#define	VM_MAX_KERNEL_ADDRESS		0xc0000001c7ffffffUL
+#define	VM_MAX_SAFE_KERNEL_ADDRESS	VM_MAX_KERNEL_ADDRESS
+#else
+#define	VM_MIN_KERNEL_ADDRESS	((vm_offset_t)KERNEL_SR << ADDR_SR_SHFT)
+#define	VM_MAX_SAFE_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + 2*SEGMENT_LENGTH -1)
+#define	VM_MAX_KERNEL_ADDRESS	(VM_MIN_KERNEL_ADDRESS + 3*SEGMENT_LENGTH - 1)
+#endif
+
+/*
+ * Use the direct-mapped BAT registers for UMA small allocs. This
+ * takes pressure off the small amount of available KVA.
+ */
+#define UMA_MD_SMALL_ALLOC
+
+#else /* Book-E */
+
+#define	KERNBASE		0xc0000000	/* start of kernel virtual */
+
+#define	VM_MIN_KERNEL_ADDRESS	KERNBASE
+#define	VM_MAX_KERNEL_ADDRESS	0xf8000000
+#define	VM_MAX_SAFE_KERNEL_ADDRESS	VM_MAX_KERNEL_ADDRESS
+
+#endif /* AIM/E500 */
+
+#if !defined(LOCORE)
+struct pmap_physseg {
+	struct pv_entry *pvent;
+	char *attrs;
+};
+#endif
+
+#define	VM_PHYSSEG_MAX		16	/* 1? */
+
+/*
+ * The physical address space is densely populated on 32-bit systems,
+ * but may not be on 64-bit ones.
+ */
+#ifdef __powerpc64__
+#define	VM_PHYSSEG_SPARSE
+#else
+#define	VM_PHYSSEG_DENSE
+#endif
+
+/*
+ * Create three free page pools: VM_FREEPOOL_DEFAULT is the default pool
+ * from which physical pages are allocated and VM_FREEPOOL_DIRECT is
+ * the pool from which physical pages for small UMA objects are
+ * allocated.
+ */
+#define	VM_NFREEPOOL		3
+#define	VM_FREEPOOL_CACHE	2
+#define	VM_FREEPOOL_DEFAULT	0
+#define	VM_FREEPOOL_DIRECT	1
+
+/*
+ * Create one free page list.
+ */
+#define	VM_NFREELIST		1
+#define	VM_FREELIST_DEFAULT	0
+
+/*
+ * The largest allocation size is 4MB.
+ */
+#define	VM_NFREEORDER		11
+
+/*
+ * Disable superpage reservations.
+ */
+#ifndef	VM_NRESERVLEVEL
+#define	VM_NRESERVLEVEL		0
+#endif
+
+#ifndef VM_INITIAL_PAGEIN
+#define	VM_INITIAL_PAGEIN	16
+#endif
+
+#ifndef SGROWSIZ
+#define	SGROWSIZ	(128UL*1024)		/* amount to grow stack */
+#endif
+
+/*
+ * How many physical pages per kmem arena virtual page.
+ */
+#ifndef VM_KMEM_SIZE_SCALE
+#define	VM_KMEM_SIZE_SCALE	(3)
+#endif
+
+/*
+ * Optional floor (in bytes) on the size of the kmem arena.
+ */
+#ifndef VM_KMEM_SIZE_MIN
+#define	VM_KMEM_SIZE_MIN	(12 * 1024 * 1024)
+#endif
+
+/*
+ * Optional ceiling (in bytes) on the size of the kmem arena: 40% of the
+ * usable KVA space.
+ */
+#ifndef VM_KMEM_SIZE_MAX
+#define VM_KMEM_SIZE_MAX	((VM_MAX_SAFE_KERNEL_ADDRESS - \
+    VM_MIN_KERNEL_ADDRESS + 1) * 2 / 5)
+#endif
+
+#define	ZERO_REGION_SIZE	(64 * 1024)	/* 64KB */
+
+#endif /* _MACHINE_VMPARAM_H_ */


Property changes on: trunk/sys/powerpc/include/vmparam.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mambo/mambo.c
===================================================================
--- trunk/sys/powerpc/mambo/mambo.c	                        (rev 0)
+++ trunk/sys/powerpc/mambo/mambo.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,100 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2008 by Nathan Whitehorn. 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mambo/mambo.c 266160 2014-05-15 17:30:16Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <sys/rman.h>
+
+/*
+ * Mambo interface
+ */
+static int	mambobus_probe(device_t);
+static int	mambobus_attach(device_t);
+
+static device_method_t  mambobus_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		mambobus_probe),
+	DEVMETHOD(device_attach,	mambobus_attach),
+
+	/* Bus interface */
+	DEVMETHOD(bus_add_child,	bus_generic_add_child),
+	DEVMETHOD(bus_read_ivar,	bus_generic_read_ivar),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+	DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
+	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
+	DEVMETHOD(bus_activate_resource,bus_generic_activate_resource),
+
+	DEVMETHOD_END
+};
+
+static driver_t mambobus_driver = {
+	"mambo",
+	mambobus_methods,
+	0
+};
+
+static devclass_t mambobus_devclass;
+
+DRIVER_MODULE(mambo, ofwbus, mambobus_driver, mambobus_devclass, 0, 0);
+
+static int
+mambobus_probe(device_t dev)
+{
+	const char *name = ofw_bus_get_name(dev);
+
+	if (name && !strcmp(name, "mambo")) {
+		device_set_desc(dev, "Mambo Simulator");
+		return (0);
+	}
+
+	return (ENXIO);
+}
+
+static int
+mambobus_attach(device_t dev)
+{
+	bus_generic_probe(dev);
+	return (bus_generic_attach(dev));
+}
+


Property changes on: trunk/sys/powerpc/mambo/mambo.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mambo/mambo_console.c
===================================================================
--- trunk/sys/powerpc/mambo/mambo_console.c	                        (rev 0)
+++ trunk/sys/powerpc/mambo/mambo_console.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,186 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008 by Nathan Whitehorn. 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.
+ *
+ * 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 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mambo/mambo_console.c 314667 2017-03-04 13:03:31Z avg $");
+
+#include <sys/param.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/priv.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/consio.h>
+#include <sys/tty.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <ddb/ddb.h>
+
+#include "mambocall.h"
+
+#define MAMBOBURSTLEN	128	/* max number of bytes to write in one chunk */
+
+#define MAMBO_CONSOLE_WRITE	0
+#define MAMBO_CONSOLE_READ	60
+
+static tsw_outwakeup_t mambotty_outwakeup;
+
+static struct ttydevsw mambo_ttydevsw = {
+	.tsw_flags	= TF_NOPREFIX,
+	.tsw_outwakeup	= mambotty_outwakeup,
+};
+
+static int			polltime;
+static struct callout		mambo_callout;
+static struct tty 		*tp = NULL;
+
+#if defined(KDB)
+static int			alt_break_state;
+#endif
+
+static void	mambo_timeout(void *);
+
+static cn_probe_t	mambo_cnprobe;
+static cn_init_t	mambo_cninit;
+static cn_term_t	mambo_cnterm;
+static cn_getc_t	mambo_cngetc;
+static cn_putc_t	mambo_cnputc;
+static cn_grab_t	mambo_cngrab;
+static cn_ungrab_t	mambo_cnungrab;
+
+CONSOLE_DRIVER(mambo);
+
+static void
+cn_drvinit(void *unused)
+{
+
+	if (mambo_consdev.cn_pri != CN_DEAD &&
+	    mambo_consdev.cn_name[0] != '\0') {
+		if (OF_finddevice("/mambo") == -1)
+			return;
+
+		tp = tty_alloc(&mambo_ttydevsw, NULL);
+		tty_init_console(tp, 0);
+		tty_makedev(tp, NULL, "%s", "mambocons");
+
+		polltime = 1;
+
+		callout_init(&mambo_callout, 1);
+		callout_reset(&mambo_callout, polltime, mambo_timeout, NULL);
+	}
+}
+
+SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL);
+
+static void
+mambotty_outwakeup(struct tty *tp)
+{
+	int len;
+	u_char buf[MAMBOBURSTLEN];
+
+	for (;;) {
+		len = ttydisc_getc(tp, buf, sizeof buf);
+		if (len == 0)
+			break;
+		mambocall(MAMBO_CONSOLE_WRITE, buf, (register_t)len, 1UL);
+	}
+}
+
+static void
+mambo_timeout(void *v)
+{
+	int 	c;
+
+	tty_lock(tp);
+	while ((c = mambo_cngetc(NULL)) != -1)
+		ttydisc_rint(tp, c, 0);
+	ttydisc_rint_done(tp);
+	tty_unlock(tp);
+
+	callout_reset(&mambo_callout, polltime, mambo_timeout, NULL);
+}
+
+static void
+mambo_cnprobe(struct consdev *cp)
+{
+	if (OF_finddevice("/mambo") == -1) {
+		cp->cn_pri = CN_DEAD;
+		return;
+	}
+
+	cp->cn_pri = CN_NORMAL;
+}
+
+static void
+mambo_cninit(struct consdev *cp)
+{
+
+	/* XXX: This is the alias, but that should be good enough */
+	strcpy(cp->cn_name, "mambocons");
+}
+
+static void
+mambo_cnterm(struct consdev *cp)
+{
+}
+
+static void
+mambo_cngrab(struct consdev *cp)
+{
+}
+
+static void
+mambo_cnungrab(struct consdev *cp)
+{
+}
+
+static int
+mambo_cngetc(struct consdev *cp)
+{
+	int ch;
+
+	ch = mambocall(MAMBO_CONSOLE_READ);
+
+	if (ch > 0 && ch < 0xff) {
+#if defined(KDB)
+		kdb_alt_break(ch, &alt_break_state);
+#endif
+		return (ch);
+	}
+
+	return (-1);
+}
+
+static void
+mambo_cnputc(struct consdev *cp, int c)
+{
+	char cbuf;
+
+	cbuf = c;
+	mambocall(MAMBO_CONSOLE_WRITE, &cbuf, 1UL, 1UL);
+}


Property changes on: trunk/sys/powerpc/mambo/mambo_console.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mambo/mambo_disk.c
===================================================================
--- trunk/sys/powerpc/mambo/mambo_disk.c	                        (rev 0)
+++ trunk/sys/powerpc/mambo/mambo_disk.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,278 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Nathan Whitehorn.  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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mambo/mambo_disk.c 210677 2010-07-31 13:22:34Z nwhitehorn $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <geom/geom_disk.h>
+
+#include <powerpc/mambo/mambocall.h>
+
+struct mambodisk_softc {
+	device_t dev;
+	struct mtx sc_mtx;
+	struct disk *disk;
+	struct proc *p;
+	struct bio_queue_head bio_queue;
+	int running;
+	int maxblocks;
+};
+
+#define MAMBO_DISK_READ		116
+#define	MAMBO_DISK_WRITE	117
+#define MAMBO_DISK_INFO		118
+
+#define MAMBO_INFO_STATUS	1
+#define MAMBO_INFO_BLKSZ	2
+#define MAMBO_INFO_DEVSZ	3
+
+/* bus entry points */
+static void mambodisk_identify(driver_t *driver, device_t parent);
+static int mambodisk_probe(device_t dev);
+static int mambodisk_attach(device_t dev);
+
+/* disk routines */
+static int mambodisk_open(struct disk *dp);
+static int mambodisk_close(struct disk *dp);
+static void mambodisk_strategy(struct bio *bp);
+static void mambodisk_task(void *arg);
+
+#define MBODISK_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
+#define	MBODISK_UNLOCK(_sc)	mtx_unlock(&(_sc)->sc_mtx)
+#define MBODISK_LOCK_INIT(_sc) \
+	mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
+	    "mambodisk", MTX_DEF)
+#define MBODISK_LOCK_DESTROY(_sc)	mtx_destroy(&_sc->sc_mtx);
+#define MBODISK_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define MBODISK_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+static void
+mambodisk_identify(driver_t *driver, device_t parent)
+{
+	int i = 0;
+
+	for (i = 0; mambocall(MAMBO_DISK_INFO,MAMBO_INFO_DEVSZ,i) > 0; i++)
+		BUS_ADD_CHILD(parent,0,"mambodisk",i);
+}
+
+static int
+mambodisk_probe(device_t dev)
+{
+	device_set_desc(dev, "Mambo Simulated Block Device");
+	return (0);
+}
+
+static int
+mambodisk_attach(device_t dev)
+{
+	struct mambodisk_softc *sc;
+	struct disk *d;
+	intmax_t mb;
+	char unit;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+	MBODISK_LOCK_INIT(sc);
+
+	d = sc->disk = disk_alloc();
+	d->d_open = mambodisk_open;
+	d->d_close = mambodisk_close;
+	d->d_strategy = mambodisk_strategy;
+	d->d_name = "mambodisk";
+	d->d_drv1 = sc;
+	d->d_maxsize = MAXPHYS;		/* Maybe ask bridge? */
+
+	d->d_sectorsize = 512;
+	sc->maxblocks = mambocall(MAMBO_DISK_INFO,MAMBO_INFO_BLKSZ,d->d_unit)
+	    / 512;
+
+	d->d_unit = device_get_unit(dev);
+	d->d_mediasize = mambocall(MAMBO_DISK_INFO,MAMBO_INFO_DEVSZ,d->d_unit)
+	    * 1024ULL; /* Mambo gives size in KB */
+
+	mb = d->d_mediasize >> 20;	/* 1MiB == 1 << 20 */
+	unit = 'M';
+	if (mb >= 10240) {		/* 1GiB = 1024 MiB */
+		unit = 'G';
+		mb /= 1024;
+	}
+	device_printf(dev, "%ju%cB, %d byte sectors\n", mb, unit, 
+	    d->d_sectorsize);
+	disk_create(d, DISK_VERSION);
+	bioq_init(&sc->bio_queue);
+
+	sc->running = 1;
+	kproc_create(&mambodisk_task, sc, &sc->p, 0, 0, "task: mambo hd");
+
+	return (0);
+}
+
+static int
+mambodisk_detach(device_t dev)
+{
+	struct mambodisk_softc *sc = device_get_softc(dev);
+
+	/* kill thread */
+	MBODISK_LOCK(sc);
+	sc->running = 0;
+	wakeup(sc);
+	MBODISK_UNLOCK(sc);
+
+	/* wait for thread to finish.  XXX probably want timeout.  -sorbo */
+	MBODISK_LOCK(sc);
+	while (sc->running != -1)
+		msleep(sc, &sc->sc_mtx, PRIBIO, "detach", 0);
+	MBODISK_UNLOCK(sc);
+
+	/* kill disk */
+	disk_destroy(sc->disk);
+	/* XXX destroy anything in queue */
+
+	MBODISK_LOCK_DESTROY(sc);
+
+	return (0);
+}
+
+static int
+mambodisk_open(struct disk *dp)
+{
+	return (0);
+}
+
+static int
+mambodisk_close(struct disk *dp)
+{
+	return (0);
+}
+
+static void
+mambodisk_strategy(struct bio *bp)
+{
+	struct mambodisk_softc *sc;
+
+	sc = (struct mambodisk_softc *)bp->bio_disk->d_drv1;
+	MBODISK_LOCK(sc);
+	bioq_disksort(&sc->bio_queue, bp);
+	wakeup(sc);
+	MBODISK_UNLOCK(sc);
+}
+
+static void
+mambodisk_task(void *arg)
+{
+	struct mambodisk_softc *sc = (struct mambodisk_softc*)arg;
+	struct bio *bp;
+	size_t sz;
+	int result;
+	daddr_t block, end;
+	device_t dev;
+	u_long unit;
+
+	dev = sc->dev;
+	unit = device_get_unit(dev);
+
+	while (sc->running) {
+		MBODISK_LOCK(sc);
+		do {
+			bp = bioq_first(&sc->bio_queue);
+			if (bp == NULL)
+				msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);
+		} while (bp == NULL && sc->running);
+		if (bp)
+			bioq_remove(&sc->bio_queue, bp);
+		MBODISK_UNLOCK(sc);
+		if (!sc->running)
+			break;
+		sz = sc->disk->d_sectorsize;
+		end = bp->bio_pblkno + (bp->bio_bcount / sz);
+		for (block = bp->bio_pblkno; block < end;) {
+			u_long numblocks;
+			char *vaddr = bp->bio_data + 
+			    (block - bp->bio_pblkno) * sz;
+
+			numblocks = end - block;
+			if (numblocks > sc->maxblocks)
+				numblocks = sc->maxblocks;
+
+			if (bp->bio_cmd == BIO_READ) {
+				result = mambocall(MAMBO_DISK_READ, vaddr, 
+				  (u_long)block, (numblocks << 16) | unit);
+			} else if (bp->bio_cmd == BIO_WRITE) {
+				result = mambocall(MAMBO_DISK_WRITE, vaddr, 
+				  (u_long)block, (numblocks << 16) | unit);
+			} else {
+				result = 1;
+			}
+		
+			if (result)
+				break;
+
+			block += numblocks;
+		}
+		if (block < end) {
+			bp->bio_error = EIO;
+			bp->bio_resid = (end - block) * sz;
+			bp->bio_flags |= BIO_ERROR;
+		}
+		biodone(bp);
+	}
+
+	/* tell parent we're done */
+	MBODISK_LOCK(sc);
+	sc->running = -1;
+	wakeup(sc);
+	MBODISK_UNLOCK(sc);
+
+	kproc_exit(0);
+}
+
+static device_method_t mambodisk_methods[] = {
+	DEVMETHOD(device_identify,	mambodisk_identify),
+	DEVMETHOD(device_probe,		mambodisk_probe),
+	DEVMETHOD(device_attach,	mambodisk_attach),
+	DEVMETHOD(device_detach,	mambodisk_detach),
+	{0, 0},
+};
+
+static driver_t mambodisk_driver = {
+	"mambodisk",
+	mambodisk_methods,
+	sizeof(struct mambodisk_softc),
+};
+static devclass_t mambodisk_devclass;
+
+DRIVER_MODULE(mambodisk, mambo, mambodisk_driver, mambodisk_devclass, 0, 0);


Property changes on: trunk/sys/powerpc/mambo/mambo_disk.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mambo/mambocall.S
===================================================================
--- trunk/sys/powerpc/mambo/mambocall.S	                        (rev 0)
+++ trunk/sys/powerpc/mambo/mambocall.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,40 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2008 by Nathan Whitehorn. 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/mambo/mambocall.S 210677 2010-07-31 13:22:34Z nwhitehorn $
+ */
+
+#include <machine/asm.h>	
+
+	.text
+
+ASENTRY(mambocall)
+	/*
+	 * Use the special Mambo callout opcode and whatever arguments we
+	 * were passed. Then return whatever Mambo returned. 
+	 */
+	.long 0x000EAEB0
+	blr
+


Property changes on: trunk/sys/powerpc/mambo/mambocall.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mambo/mambocall.h
===================================================================
--- trunk/sys/powerpc/mambo/mambocall.h	                        (rev 0)
+++ trunk/sys/powerpc/mambo/mambocall.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,34 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2008 by Nathan Whitehorn. 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/mambo/mambocall.h 210677 2010-07-31 13:22:34Z nwhitehorn $
+ */
+
+#ifndef _MAMBO_MAMBOCALL_H_
+#define _MAMBO_MAMBOCALL_H_
+
+long mambocall(int op, ...);
+
+#endif /* _MAMBO_MAMBOCALL_H_ */


Property changes on: trunk/sys/powerpc/mambo/mambocall.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/atpic.c
===================================================================
--- trunk/sys/powerpc/mpc85xx/atpic.c	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/atpic.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,365 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Marcel Moolenaar
+ *
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mpc85xx/atpic.c 265969 2014-05-13 18:06:26Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpuset.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/pio.h>
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+#include <dev/ic/i8259.h>
+
+#include <isa/isareg.h>
+#include <isa/isavar.h>
+
+#include "pic_if.h"
+
+#define	ATPIC_MASTER	0
+#define	ATPIC_SLAVE	1
+
+struct atpic_softc {
+	device_t	sc_dev;
+
+	/* I/O port resources for master & slave. */
+	struct resource	*sc_res[2];
+	int		sc_rid[2];
+
+	/* Our "routing" interrupt */
+	struct resource *sc_ires;
+	void		*sc_icookie;
+	int		sc_irid;
+
+	int		sc_vector[16];
+	uint8_t		sc_mask[2];
+};
+
+static int	atpic_isa_attach(device_t);
+static void	atpic_isa_identify(driver_t *, device_t);
+static int	atpic_isa_probe(device_t);
+
+static void atpic_config(device_t, u_int, enum intr_trigger,
+    enum intr_polarity);
+static void atpic_dispatch(device_t, struct trapframe *);
+static void atpic_enable(device_t, u_int, u_int);
+static void atpic_eoi(device_t, u_int);
+static void atpic_ipi(device_t, u_int);
+static void atpic_mask(device_t, u_int);
+static void atpic_unmask(device_t, u_int);
+
+static void atpic_ofw_translate_code(device_t, u_int irq, int code,
+    enum intr_trigger *trig, enum intr_polarity *pol);
+
+static device_method_t atpic_isa_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_identify, 	atpic_isa_identify),
+	DEVMETHOD(device_probe,		atpic_isa_probe),
+	DEVMETHOD(device_attach,	atpic_isa_attach),
+
+	/* PIC interface */
+	DEVMETHOD(pic_config,		atpic_config),
+	DEVMETHOD(pic_dispatch,		atpic_dispatch),
+	DEVMETHOD(pic_enable,		atpic_enable),
+	DEVMETHOD(pic_eoi,		atpic_eoi),
+	DEVMETHOD(pic_ipi,		atpic_ipi),
+	DEVMETHOD(pic_mask,		atpic_mask),
+	DEVMETHOD(pic_unmask,		atpic_unmask),
+
+	DEVMETHOD(pic_translate_code,	atpic_ofw_translate_code),
+
+	{ 0, 0 },
+};
+
+static driver_t atpic_isa_driver = {
+	"atpic",
+	atpic_isa_methods,
+	sizeof(struct atpic_softc)
+};
+
+static devclass_t atpic_devclass;
+
+DRIVER_MODULE(atpic, isa, atpic_isa_driver, atpic_devclass, 0, 0);
+
+static struct isa_pnp_id atpic_ids[] = {
+	{ 0x0000d041 /* PNP0000 */, "AT interrupt controller" },
+	{ 0 }
+};
+
+static __inline uint8_t
+atpic_read(struct atpic_softc *sc, int icu, int ofs)
+{
+	uint8_t val;
+
+	val = bus_read_1(sc->sc_res[icu], ofs);
+	return (val);
+}
+
+static __inline void
+atpic_write(struct atpic_softc *sc, int icu, int ofs, uint8_t val)
+{
+
+	bus_write_1(sc->sc_res[icu], ofs, val);
+	bus_barrier(sc->sc_res[icu], ofs, 2 - ofs,
+	    BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
+}
+
+static void
+atpic_intr(void *arg)
+{
+
+	atpic_dispatch(arg, NULL);
+}
+
+static void
+atpic_isa_identify(driver_t *drv, device_t parent)
+{
+	device_t child;
+
+	child = BUS_ADD_CHILD(parent, ISA_ORDER_SENSITIVE, drv->name, -1);
+	device_set_driver(child, drv);
+	isa_set_logicalid(child, atpic_ids[0].ip_id);
+	isa_set_vendorid(child, atpic_ids[0].ip_id);
+
+	bus_set_resource(child, SYS_RES_IOPORT, ATPIC_MASTER, IO_ICU1, 2);
+	bus_set_resource(child, SYS_RES_IOPORT, ATPIC_SLAVE, IO_ICU2, 2);
+
+	/* ISA interrupts are routed through external interrupt 0. */
+	bus_set_resource(child, SYS_RES_IRQ, 0, 16, 1);
+}
+
+static int
+atpic_isa_probe(device_t dev)
+{
+	int res;
+
+	res = ISA_PNP_PROBE(device_get_parent(dev), dev, atpic_ids);
+	if (res > 0)
+		return (res);
+
+	device_set_desc(dev, "PC/AT compatible PIC");
+	return (res);
+}
+
+static void
+atpic_init(struct atpic_softc *sc, int icu)
+{
+
+	sc->sc_mask[icu] = 0xff - ((icu == ATPIC_MASTER) ? 4 : 0);
+
+	atpic_write(sc, icu, 0, ICW1_RESET | ICW1_IC4);
+	atpic_write(sc, icu, 1, (icu == ATPIC_SLAVE) ? 8 : 0);
+	atpic_write(sc, icu, 1, (icu == ATPIC_SLAVE) ? 2 : 4);
+	atpic_write(sc, icu, 1, ICW4_8086);
+	atpic_write(sc, icu, 1, sc->sc_mask[icu]);
+	atpic_write(sc, icu, 0, OCW3_SEL | OCW3_RR);
+}
+
+static int
+atpic_isa_attach(device_t dev)
+{
+	struct atpic_softc *sc;
+	int error;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+
+	error = ENXIO;
+
+	sc->sc_rid[ATPIC_MASTER] = 0;
+	sc->sc_res[ATPIC_MASTER] = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+	    &sc->sc_rid[ATPIC_MASTER], RF_ACTIVE);
+	if (sc->sc_res[ATPIC_MASTER] == NULL)
+		goto fail;
+
+	sc->sc_rid[ATPIC_SLAVE] = 1;
+	sc->sc_res[ATPIC_SLAVE] = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+	    &sc->sc_rid[ATPIC_SLAVE], RF_ACTIVE);
+	if (sc->sc_res[ATPIC_SLAVE] == NULL)
+		goto fail;
+
+	sc->sc_irid = 0;
+	sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
+	    RF_ACTIVE);
+	if (sc->sc_ires == NULL)
+		goto fail;
+
+	error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_MISC | INTR_MPSAFE,
+	    NULL, atpic_intr, dev, &sc->sc_icookie);
+	if (error)
+		goto fail;
+
+	atpic_init(sc, ATPIC_SLAVE);
+	atpic_init(sc, ATPIC_MASTER);
+
+	powerpc_register_pic(dev, 0, 16, 0, TRUE);
+	return (0);
+
+ fail:
+	if (sc->sc_ires != NULL)
+		bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
+		    sc->sc_ires);
+	if (sc->sc_res[ATPIC_SLAVE] != NULL)
+		bus_release_resource(dev, SYS_RES_IOPORT,
+		    sc->sc_rid[ATPIC_SLAVE], sc->sc_res[ATPIC_SLAVE]);
+	if (sc->sc_res[ATPIC_MASTER] != NULL)
+		bus_release_resource(dev, SYS_RES_IOPORT,
+		    sc->sc_rid[ATPIC_MASTER], sc->sc_res[ATPIC_MASTER]);
+	return (error);
+}
+
+
+/*
+ * PIC interface.
+ */
+
+static void
+atpic_config(device_t dev, u_int irq, enum intr_trigger trig,
+    enum intr_polarity pol)
+{
+}
+
+static void
+atpic_dispatch(device_t dev, struct trapframe *tf)
+{
+	struct atpic_softc *sc;
+	uint8_t irq;
+
+	sc = device_get_softc(dev);
+	atpic_write(sc, ATPIC_MASTER, 0, OCW3_SEL | OCW3_P);
+	irq = atpic_read(sc, ATPIC_MASTER, 0);
+	atpic_write(sc, ATPIC_MASTER, 0, OCW3_SEL | OCW3_RR);
+	if ((irq & 0x80) == 0)
+		return;
+
+	if (irq == 0x82) {
+		atpic_write(sc, ATPIC_SLAVE, 0, OCW3_SEL | OCW3_P);
+		irq = atpic_read(sc, ATPIC_SLAVE, 0) + 8;
+		atpic_write(sc, ATPIC_SLAVE, 0, OCW3_SEL | OCW3_RR);
+		if ((irq & 0x80) == 0)
+			return;
+	}
+
+	powerpc_dispatch_intr(sc->sc_vector[irq & 0x0f], tf);
+}
+
+static void
+atpic_enable(device_t dev, u_int irq, u_int vector)
+{
+	struct atpic_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->sc_vector[irq] = vector;
+	atpic_unmask(dev, irq);
+}
+
+static void
+atpic_eoi(device_t dev, u_int irq)
+{
+	struct atpic_softc *sc;
+
+	sc = device_get_softc(dev);
+	if (irq > 7)
+		atpic_write(sc, ATPIC_SLAVE, 0, OCW2_EOI);
+	atpic_write(sc, ATPIC_MASTER, 0, OCW2_EOI);
+}
+
+static void
+atpic_ipi(device_t dev, u_int cpu)
+{
+	/* No SMP support. */
+}
+
+static void
+atpic_mask(device_t dev, u_int irq)
+{
+	struct atpic_softc *sc;
+
+	sc = device_get_softc(dev);
+	if (irq > 7) {
+		sc->sc_mask[ATPIC_SLAVE] |= 1 << (irq - 8);
+		atpic_write(sc, ATPIC_SLAVE, 1, sc->sc_mask[ATPIC_SLAVE]);
+	} else {
+		sc->sc_mask[ATPIC_MASTER] |= 1 << irq;
+		atpic_write(sc, ATPIC_MASTER, 1, sc->sc_mask[ATPIC_MASTER]);
+	}
+}
+
+static void
+atpic_unmask(device_t dev, u_int irq)
+{
+	struct atpic_softc *sc;
+
+	sc = device_get_softc(dev);
+	if (irq > 7) {
+		sc->sc_mask[ATPIC_SLAVE] &= ~(1 << (irq - 8));
+		atpic_write(sc, ATPIC_SLAVE, 1, sc->sc_mask[ATPIC_SLAVE]);
+	} else {
+		sc->sc_mask[ATPIC_MASTER] &= ~(1 << irq);
+		atpic_write(sc, ATPIC_MASTER, 1, sc->sc_mask[ATPIC_MASTER]);
+	}
+}
+
+static void
+atpic_ofw_translate_code(device_t dev, u_int irq, int code,
+    enum intr_trigger *trig, enum intr_polarity *pol)
+{
+	switch (code) {
+	case 0:
+		/* Active L level */
+		*trig = INTR_TRIGGER_LEVEL;
+		*pol = INTR_POLARITY_LOW;
+		break;
+	case 1:
+		/* Active H level */
+		*trig = INTR_TRIGGER_LEVEL;
+		*pol = INTR_POLARITY_HIGH;
+		break;
+	case 2:
+		/* H to L edge */
+		*trig = INTR_TRIGGER_EDGE;
+		*pol = INTR_POLARITY_LOW;
+		break;
+	case 3:
+		/* L to H edge */
+		*trig = INTR_TRIGGER_EDGE;
+		*pol = INTR_POLARITY_HIGH;
+		break;
+	default:
+		*trig = INTR_TRIGGER_CONFORM;
+		*pol = INTR_POLARITY_CONFORM;
+	}
+}
+


Property changes on: trunk/sys/powerpc/mpc85xx/atpic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/ds1553_bus_fdt.c
===================================================================
--- trunk/sys/powerpc/mpc85xx/ds1553_bus_fdt.c	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/ds1553_bus_fdt.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,128 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2006-2008 Semihalf, Grzegorz Bernacki
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * From: FreeBSD: src/sys/powerpc/mpc85xx/ds1553_bus_lbc.c,v 1.2 2009/06/24 15:48:20 raj
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mpc85xx/ds1553_bus_fdt.c 209908 2010-07-11 21:08:29Z raj $");
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "ds1553_reg.h"
+#include "clock_if.h"
+
+static devclass_t rtc_devclass;
+
+static int rtc_attach(device_t dev);
+static int rtc_probe(device_t dev);
+
+static device_method_t rtc_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		rtc_probe),
+	DEVMETHOD(device_attach,	rtc_attach),
+
+	/* clock interface */
+	DEVMETHOD(clock_gettime,	ds1553_gettime),
+	DEVMETHOD(clock_settime,	ds1553_settime),
+
+	{ 0, 0 }
+};
+
+static driver_t rtc_driver = {
+	"rtc",
+	rtc_methods,
+	sizeof(struct ds1553_softc),
+};
+
+DRIVER_MODULE(rtc, lbc, rtc_driver, rtc_devclass, 0, 0);
+
+static int
+rtc_probe(device_t dev)
+{
+
+	if (!ofw_bus_is_compatible(dev, "dallas,ds1553"))
+		return (ENXIO);
+
+	device_set_desc(dev, "Dallas Semiconductor DS1553 RTC");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+rtc_attach(device_t dev)
+{
+	struct timespec ts;
+	struct ds1553_softc *sc;
+	int error;
+
+	sc = device_get_softc(dev);
+	bzero(sc, sizeof(struct ds1553_softc));
+
+	mtx_init(&sc->sc_mtx, "rtc_mtx", NULL, MTX_SPIN);
+
+	sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
+	    RF_ACTIVE);
+	if (sc->res == NULL) {
+		device_printf(dev, "cannot allocate resources\n");
+		mtx_destroy(&sc->sc_mtx);
+		return (ENXIO);
+	}
+
+	sc->sc_bst = rman_get_bustag(sc->res);
+	sc->sc_bsh = rman_get_bushandle(sc->res);
+
+	if ((error = ds1553_attach(dev)) != 0) {
+		device_printf(dev, "cannot attach time of day clock\n");
+		bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
+		mtx_destroy(&sc->sc_mtx);
+		return (error);
+	}
+
+	clock_register(dev, 1000000);
+
+	if (bootverbose) {
+		ds1553_gettime(dev, &ts);
+		device_printf(dev, "current time: %ld.%09ld\n",
+		    (long)ts.tv_sec, ts.tv_nsec);
+	}
+
+	return (0);
+}


Property changes on: trunk/sys/powerpc/mpc85xx/ds1553_bus_fdt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/ds1553_core.c
===================================================================
--- trunk/sys/powerpc/mpc85xx/ds1553_core.c	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/ds1553_core.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,195 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2006-2008 Semihalf, Grzegorz Bernacki
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mpc85xx/ds1553_core.c 194632 2009-06-22 15:48:47Z raj $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+
+#include <powerpc/mpc85xx/ds1553_reg.h>
+
+static uint8_t ds1553_direct_read(device_t, bus_size_t);
+static void ds1553_direct_write(device_t, bus_size_t, uint8_t);
+
+int
+ds1553_attach(device_t dev)
+{
+	struct ds1553_softc *sc;
+	uint8_t sec, flags;
+
+	sc = device_get_softc(dev);
+
+	if (mtx_initialized(&sc->sc_mtx) == 0) {
+		device_printf(dev, "%s: mutex not initialized\n", __func__);
+		return (ENXIO);
+	}
+
+	if (sc->sc_read == NULL)
+		sc->sc_read = ds1553_direct_read;
+	if (sc->sc_write == NULL)
+		sc->sc_write = ds1553_direct_write;
+
+	sc->year_offset = POSIX_BASE_YEAR;
+
+	mtx_lock_spin(&sc->sc_mtx);
+
+	/* Turn RTC on if it was not on */
+	sec = (*sc->sc_read)(dev, DS1553_OFF_SECONDS);
+	if (sec & DS1553_BIT_OSC) {
+		sec &= ~(DS1553_BIT_OSC);
+		(*sc->sc_write)(dev, DS1553_OFF_SECONDS, sec);
+	}
+
+	/* Low-battery check */
+	flags = (*sc->sc_read)(dev, DS1553_OFF_FLAGS);
+	if (flags & DS1553_BIT_BLF)
+		device_printf(dev, "voltage-low detected.\n");
+
+	mtx_unlock_spin(&sc->sc_mtx);
+
+	return (0);
+}
+
+/*
+ * Get time of day and convert it to a struct timespec.
+ * Return 0 on success, an error number otherwise.
+ */
+int
+ds1553_gettime(device_t dev, struct timespec *ts)
+{
+	struct clocktime ct;
+	struct ds1553_softc *sc;
+	uint8_t control;
+
+	sc = device_get_softc(dev);
+
+	mtx_lock_spin(&sc->sc_mtx);
+
+	control = (*sc->sc_read)(dev, DS1553_OFF_CONTROL) | DS1553_BIT_READ;
+	(*sc->sc_write)(dev, DS1553_OFF_CONTROL, control);
+
+	ct.nsec = 0;
+	ct.sec = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_SECONDS) &
+	    DS1553_MASK_SECONDS);
+	ct.min = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_MINUTES) &
+	    DS1553_MASK_MINUTES);
+	ct.hour = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_HOURS) &
+	    DS1553_MASK_HOUR);
+	ct.dow = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_DAYOFWEEK) &
+	    DS1553_MASK_DAYOFWEEK) - 1;
+	ct.day = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_DATE) &
+	    DS1553_MASK_DATE);
+	ct.mon = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_MONTH) &
+	    DS1553_MASK_MONTH);
+	ct.year = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_YEAR));
+
+	control &= ~DS1553_BIT_READ;
+	(*sc->sc_write)(dev, DS1553_OFF_CONTROL, control);
+
+	ct.year += sc->year_offset;
+
+	mtx_unlock_spin(&sc->sc_mtx);
+
+	return (clock_ct_to_ts(&ct, ts));
+}
+
+/*
+ * Set the time of day clock based on the value of the struct timespec arg.
+ * Return 0 on success, an error number otherwise.
+ */
+int
+ds1553_settime(device_t dev, struct timespec *ts)
+{
+	struct clocktime ct;
+	struct ds1553_softc *sc;
+	uint8_t control;
+
+	sc = device_get_softc(dev);
+	bzero(&ct, sizeof(struct clocktime));
+
+	/* Accuracy is only one second. */
+	if (ts->tv_nsec >= 500000000)
+		ts->tv_sec++;
+	ts->tv_nsec = 0;
+	clock_ts_to_ct(ts, &ct);
+
+	ct.year -= sc->year_offset;
+
+	mtx_lock_spin(&sc->sc_mtx);
+
+	/* Halt updates to external registers */
+	control = (*sc->sc_read)(dev, DS1553_OFF_CONTROL) | DS1553_BIT_WRITE;
+	(*sc->sc_write)(dev, DS1553_OFF_CONTROL, control);
+
+	(*sc->sc_write)(dev, DS1553_OFF_SECONDS, TOBCD(ct.sec) &
+	    DS1553_MASK_SECONDS);
+	(*sc->sc_write)(dev, DS1553_OFF_MINUTES, TOBCD(ct.min) &
+	    DS1553_MASK_MINUTES);
+	(*sc->sc_write)(dev, DS1553_OFF_HOURS, TOBCD(ct.hour) &
+	    DS1553_MASK_HOUR);
+	(*sc->sc_write)(dev, DS1553_OFF_DAYOFWEEK, TOBCD(ct.dow + 1) &
+	    DS1553_MASK_DAYOFWEEK);
+	(*sc->sc_write)(dev, DS1553_OFF_DATE, TOBCD(ct.day) &
+	    DS1553_MASK_DATE);
+	(*sc->sc_write)(dev, DS1553_OFF_MONTH, TOBCD(ct.mon) &
+	    DS1553_MASK_MONTH);
+	(*sc->sc_write)(dev, DS1553_OFF_YEAR, TOBCD(ct.year));
+
+	/* Resume updates to external registers */
+	control &= ~DS1553_BIT_WRITE;
+	(*sc->sc_write)(dev, DS1553_OFF_CONTROL, control);
+
+	mtx_unlock_spin(&sc->sc_mtx);
+
+	return (0);
+}
+
+static uint8_t
+ds1553_direct_read(device_t dev, bus_size_t off)
+{
+	struct ds1553_softc *sc;
+
+	sc = device_get_softc(dev);
+	return (bus_space_read_1(sc->sc_bst, sc->sc_bsh, off));
+}
+
+static void
+ds1553_direct_write(device_t dev, bus_size_t off, uint8_t val)
+{
+	struct ds1553_softc *sc;
+
+	sc = device_get_softc(dev);
+	bus_space_write_1(sc->sc_bst, sc->sc_bsh, off, val);
+}


Property changes on: trunk/sys/powerpc/mpc85xx/ds1553_core.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/ds1553_reg.h
===================================================================
--- trunk/sys/powerpc/mpc85xx/ds1553_reg.h	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/ds1553_reg.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,108 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2006-2008 Semihalf, Grzegorz Bernacki
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/mpc85xx/ds1553_reg.h 194632 2009-06-22 15:48:47Z raj $
+ */
+
+#ifndef _DEV_RTC_DS1553_H_
+#define _DEV_RTC_DS1553_H_
+
+/* DS1553 registers */
+#define DS1553_NVRAM_SIZE		0x1ff0
+#define DS1553_OFF_FLAGS		0x1ff0
+#define DS1553_OFF_ALARM_SECONDS	0x1ff2
+#define DS1553_OFF_ALARM_MINUTES	0x1ff3
+#define DS1553_OFF_ALARM_HOURS		0x1ff4
+#define DS1553_OFF_ALARM_DATE		0x1ff5
+#define DS1553_OFF_INTERRUPTS		0x1ff6
+#define DS1553_OFF_WATCHDOG		0x1ff7
+#define DS1553_OFF_CONTROL		0x1ff8
+#define DS1553_OFF_SECONDS		0x1ff9
+#define DS1553_OFF_MINUTES		0x1ffa
+#define DS1553_OFF_HOURS		0x1ffb
+#define DS1553_OFF_DAYOFWEEK		0x1ffc
+#define DS1553_OFF_DATE			0x1ffd
+#define DS1553_OFF_MONTH		0x1ffe
+#define DS1553_OFF_YEAR			0x1fff
+
+/* dayofweek register's bits */
+#define DS1553_BIT_FREQ_TEST		0x40 /* frequency test bit */
+
+/* seconds register's bit */
+#define DS1553_BIT_OSC			0x80 /* oscillator start/stop bit */
+
+/* control register's bits */
+#define DS1553_BIT_WRITE		0x80 /* write */
+#define DS1553_BIT_READ			0x40 /* read */
+
+/* watchdog register's bits */
+#define DS1553_BIT_WATCHDOG		0x80 /* watchdog steering bit */
+#define DS1553_BIT_BMB4			0x40 /* watchdog multiplier bit4 */
+#define DS1553_BIT_BMB3			0x20 /* watchdog multiplier bit3 */
+#define DS1553_BIT_BMB2			0x10 /* watchdog multiplier bit2 */
+#define DS1553_BIT_BMB1			0x8  /* watchdog multiplier bit1 */
+#define DS1553_BIT_BMB0			0x4  /* watchdog multiplier bit0 */
+#define DS1553_BIT_RB1			0x2  /* watchdog resolution bit1 */
+#define DS1553_BIT_RB0			0x1  /* watchdog resolution bit0 */
+
+/* alarm seconds/minutes/hours/date register's bit */
+#define DS1553_BIT_AM			0x80 /* alarm mask bit */
+
+/* flag register's bits */
+#define DS1553_BIT_BLF			0x10 /* battery flag */
+#define DS1553_BIT_WF			0x80 /* watchdog flag */
+
+/* register's mask */
+#define DS1553_MASK_MONTH		0x1f
+#define DS1553_MASK_DATE		0x3f
+#define DS1553_MASK_DAYOFWEEK		0x7
+#define DS1553_MASK_HOUR		0x3f
+#define DS1553_MASK_MINUTES		0x7f
+#define DS1553_MASK_SECONDS		0x7f
+
+struct ds1553_softc {
+
+	bus_space_tag_t		sc_bst;	/* bus space tag */
+	bus_space_handle_t	sc_bsh;	/* bus space handle */
+
+	int			rid;	/* resource id */
+	struct resource		*res;
+	struct mtx		sc_mtx;	/* hardware mutex */
+
+	uint32_t		year_offset;
+	/* read/write functions */
+	uint8_t			(*sc_read)(device_t, bus_size_t);
+	void			(*sc_write)(device_t, bus_size_t, uint8_t);
+};
+
+/* device interface */
+int ds1553_attach(device_t);
+
+/* clock interface */
+int ds1553_gettime(device_t, struct timespec *);
+int ds1553_settime(device_t, struct timespec *);
+
+#endif /* _DEV_RTC_DS1553_H_ */


Property changes on: trunk/sys/powerpc/mpc85xx/ds1553_reg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/fsl_sdhc.c
===================================================================
--- trunk/sys/powerpc/mpc85xx/fsl_sdhc.c	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/fsl_sdhc.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,1305 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011-2012 Semihalf
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * Driver for Freescale integrated eSDHC controller.
+ * Limitations:
+ * 	- No support for multi-block transfers.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mpc85xx/fsl_sdhc.c 321946 2017-08-02 20:27:30Z marius $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/vmparam.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmcreg.h>
+#include <dev/mmc/mmcbrvar.h>
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+#include "opt_platform.h"
+
+#include "mmcbr_if.h"
+
+#include "fsl_sdhc.h"
+
+#ifdef DEBUG
+#define	DPRINTF(fmt, arg...)	printf("DEBUG %s(): " fmt, __FUNCTION__, ##arg)
+#else
+#define	DPRINTF(fmt, arg...)
+#endif
+
+
+/*****************************************************************************
+ * Register the driver
+ *****************************************************************************/
+/* Forward declarations */
+static int	fsl_sdhc_probe(device_t);
+static int	fsl_sdhc_attach(device_t);
+static int	fsl_sdhc_detach(device_t);
+
+static int	fsl_sdhc_read_ivar(device_t, device_t, int, uintptr_t *);
+static int	fsl_sdhc_write_ivar(device_t, device_t, int, uintptr_t);
+
+static int	fsl_sdhc_update_ios(device_t, device_t);
+static int	fsl_sdhc_request(device_t, device_t, struct mmc_request *);
+static int	fsl_sdhc_get_ro(device_t, device_t);
+static int	fsl_sdhc_acquire_host(device_t, device_t);
+static int	fsl_sdhc_release_host(device_t, device_t);
+
+static device_method_t fsl_sdhc_methods[] = {
+	/* device_if */
+	DEVMETHOD(device_probe, fsl_sdhc_probe),
+	DEVMETHOD(device_attach, fsl_sdhc_attach),
+	DEVMETHOD(device_detach, fsl_sdhc_detach),
+
+	/* Bus interface */
+	DEVMETHOD(bus_read_ivar, fsl_sdhc_read_ivar),
+	DEVMETHOD(bus_write_ivar, fsl_sdhc_write_ivar),
+
+	/* OFW bus interface */
+	DEVMETHOD(ofw_bus_get_compat,   ofw_bus_gen_get_compat),
+	DEVMETHOD(ofw_bus_get_model,    ofw_bus_gen_get_model),
+	DEVMETHOD(ofw_bus_get_name,     ofw_bus_gen_get_name),
+	DEVMETHOD(ofw_bus_get_node,     ofw_bus_gen_get_node),
+	DEVMETHOD(ofw_bus_get_type,     ofw_bus_gen_get_type),
+
+	/* mmcbr_if */
+	DEVMETHOD(mmcbr_update_ios, fsl_sdhc_update_ios),
+	DEVMETHOD(mmcbr_request, fsl_sdhc_request),
+	DEVMETHOD(mmcbr_get_ro, fsl_sdhc_get_ro),
+	DEVMETHOD(mmcbr_acquire_host, fsl_sdhc_acquire_host),
+	DEVMETHOD(mmcbr_release_host, fsl_sdhc_release_host),
+
+	DEVMETHOD_END
+};
+
+/* kobj_class definition */
+static driver_t fsl_sdhc_driver = {
+	"sdhci",
+	fsl_sdhc_methods,
+	sizeof(struct fsl_sdhc_softc)
+};
+
+static devclass_t fsl_sdhc_devclass;
+
+DRIVER_MODULE(sdhci, simplebus, fsl_sdhc_driver, fsl_sdhc_devclass, NULL, NULL);
+MODULE_DEPEND(sdhci_fsl, sdhci, 1, 1, 1);
+MMC_DECLARE_BRIDGE(sdhci_fsl);
+
+/*****************************************************************************
+ * Private methods
+ *****************************************************************************/
+static inline int
+read4(struct fsl_sdhc_softc *sc, unsigned int offset)
+{
+
+	return bus_space_read_4(sc->bst, sc->bsh, offset);
+}
+
+static inline void
+write4(struct fsl_sdhc_softc *sc, unsigned int offset, int value)
+{
+
+	bus_space_write_4(sc->bst, sc->bsh, offset, value);
+}
+
+static inline void
+set_bit(struct fsl_sdhc_softc *sc, uint32_t offset, uint32_t mask)
+{
+	uint32_t x = read4(sc, offset);
+
+	write4(sc, offset, x | mask);
+}
+
+static inline void
+clear_bit(struct fsl_sdhc_softc *sc, uint32_t offset, uint32_t mask)
+{
+	uint32_t x = read4(sc, offset);
+
+	write4(sc, offset, x & ~mask);
+}
+
+static int
+wait_for_bit_clear(struct fsl_sdhc_softc *sc, enum sdhc_reg_off reg,
+    uint32_t bit)
+{
+	uint32_t timeout = 10;
+	uint32_t stat;
+
+	stat = read4(sc, reg);
+	while (stat & bit) {
+		if (timeout == 0) {
+			return (-1);
+		}
+		--timeout;
+		DELAY(1000);
+		stat = read4(sc, reg);
+	}
+
+	return (0);
+}
+
+static int
+wait_for_free_line(struct fsl_sdhc_softc *sc, enum sdhc_line line)
+{
+	uint32_t timeout = 100;
+	uint32_t stat;
+
+	stat = read4(sc, SDHC_PRSSTAT);
+	while (stat & line) {
+		if (timeout == 0) {
+			return (-1);
+		}
+		--timeout;
+		DELAY(1000);
+		stat = read4(sc, SDHC_PRSSTAT);
+	}
+
+	return (0);
+}
+
+static uint32_t
+get_platform_clock(struct fsl_sdhc_softc *sc)
+{
+	device_t self, parent;
+	phandle_t node;
+	uint32_t clock;
+
+	self = sc->self;
+	node = ofw_bus_get_node(self);
+
+	/* Get sdhci node properties */
+	if((OF_getprop(node, "clock-frequency", (void *)&clock,
+	    sizeof(clock)) <= 0) || (clock == 0)) {
+
+		/*
+		 * Trying to get clock from parent device (soc) if correct
+		 * clock cannot be acquired from sdhci node.
+		 */
+		parent = device_get_parent(self);
+		node = ofw_bus_get_node(parent);
+
+		/* Get soc properties */
+		if ((OF_getprop(node, "bus-frequency", (void *)&clock,
+		    sizeof(clock)) <= 0) || (clock == 0)) {
+			device_printf(self,"Cannot acquire correct sdhci "
+			    "frequency from DTS.\n");
+
+			return (0);
+		}
+	}
+
+	DPRINTF("Acquired clock: %d from DTS\n", clock);
+
+	return (clock);
+}
+
+/**
+ * Set clock driving card.
+ * @param sc
+ * @param clock Desired clock frequency in Hz
+ */
+static void
+set_clock(struct fsl_sdhc_softc *sc, uint32_t clock)
+{
+	uint32_t base_clock;
+	uint32_t divisor, prescaler = 1;
+	uint32_t round = 0;
+
+	if (clock == sc->slot.clock)
+		return;
+
+	if (clock == 0) {
+		clear_bit(sc, SDHC_SYSCTL, MASK_CLOCK_CONTROL | SYSCTL_PEREN |
+		    SYSCTL_HCKEN | SYSCTL_IPGEN);
+		return;
+	}
+
+	base_clock = sc->platform_clock;
+	round = base_clock & 0x2;
+	base_clock >>= 2;
+	base_clock += round;
+	round = 0;
+
+	/* SD specification 1.1 doesn't allow frequences above 50 MHz */
+	if (clock > FSL_SDHC_MAX_CLOCK)
+		clock = FSL_SDHC_MAX_CLOCK;
+
+	/*
+	 * divisor = ceil(base_clock / clock)
+	 * TODO: Reconsider symmetric rounding here instead of ceiling.
+	 */
+	divisor = (base_clock + clock - 1) / clock;
+
+	while (divisor > 16) {
+		round = divisor & 0x1;
+		divisor >>= 1;
+
+		prescaler <<= 1;
+	}
+	divisor += round - 1;
+
+	/* Turn off the clock. */
+	clear_bit(sc, SDHC_SYSCTL, MASK_CLOCK_CONTROL);
+
+	/* Write clock settings. */
+	set_bit(sc, SDHC_SYSCTL, (prescaler << SHIFT_SDCLKFS) |
+	    (divisor << SHIFT_DVS));
+
+	/*
+	 * Turn on clocks.
+	 * TODO: This actually disables clock automatic gating off feature of
+	 * the controller which eventually should be enabled but as for now
+	 * it prevents controller from generating card insertion/removal
+	 * interrupts correctly.
+	 */
+	set_bit(sc, SDHC_SYSCTL, SYSCTL_PEREN | SYSCTL_HCKEN | SYSCTL_IPGEN);
+
+	sc->slot.clock = clock;
+
+	DPRINTF("given clock = %d, computed clock = %d\n", clock,
+	    (base_clock / prescaler) / (divisor + 1));
+}
+
+static inline void
+send_80_clock_ticks(struct fsl_sdhc_softc *sc)
+{
+	int err;
+
+	err = wait_for_free_line(sc, SDHC_CMD_LINE | SDHC_DAT_LINE);
+	if (err != 0) {
+		device_printf(sc->self, "Can't acquire data/cmd lines\n");
+		return;
+	}
+
+	set_bit(sc, SDHC_SYSCTL, SYSCTL_INITA);
+	err = wait_for_bit_clear(sc, SDHC_SYSCTL, SYSCTL_INITA);
+	if (err != 0) {
+		device_printf(sc->self, "Can't send 80 clocks to the card.\n");
+	}
+}
+
+static void
+set_bus_width(struct fsl_sdhc_softc *sc, enum mmc_bus_width width)
+{
+
+	DPRINTF("setting bus width to %d\n", width);
+	switch (width) {
+	case bus_width_1:
+		set_bit(sc, SDHC_PROCTL, DTW_1);
+		break;
+	case bus_width_4:
+		set_bit(sc, SDHC_PROCTL, DTW_4);
+		break;
+	case bus_width_8:
+		set_bit(sc, SDHC_PROCTL, DTW_8);
+		break;
+	default:
+		device_printf(sc->self, "Unsupported bus width\n");
+	}
+}
+
+static void
+reset_controller_all(struct fsl_sdhc_softc *sc)
+{
+	uint32_t count = 5;
+
+	set_bit(sc, SDHC_SYSCTL, SYSCTL_RSTA);
+	while (read4(sc, SDHC_SYSCTL) & SYSCTL_RSTA) {
+		DELAY(FSL_SDHC_RESET_DELAY);
+		--count;
+		if (count == 0) {
+			device_printf(sc->self,
+			    "Can't reset the controller\n");
+			return;
+		}
+	}
+}
+
+static void
+reset_controller_dat_cmd(struct fsl_sdhc_softc *sc)
+{
+	int err;
+
+	set_bit(sc, SDHC_SYSCTL, SYSCTL_RSTD | SYSCTL_RSTC);
+	err = wait_for_bit_clear(sc, SDHC_SYSCTL, SYSCTL_RSTD | SYSCTL_RSTC);
+	if (err != 0) {
+		device_printf(sc->self, "Can't reset data & command part!\n");
+		return;
+	}
+}
+
+static void
+init_controller(struct fsl_sdhc_softc *sc)
+{
+
+	/* Enable interrupts. */
+#ifdef FSL_SDHC_NO_DMA
+	write4(sc, SDHC_IRQSTATEN, MASK_IRQ_ALL & ~IRQ_DINT & ~IRQ_DMAE);
+	write4(sc, SDHC_IRQSIGEN, MASK_IRQ_ALL & ~IRQ_DINT & ~IRQ_DMAE);
+#else
+	write4(sc, SDHC_IRQSTATEN, MASK_IRQ_ALL & ~IRQ_BRR & ~IRQ_BWR);
+	write4(sc, SDHC_IRQSIGEN, MASK_IRQ_ALL & ~IRQ_BRR & ~IRQ_BWR);
+
+	/* Write DMA address */
+	write4(sc, SDHC_DSADDR, sc->dma_phys);
+
+	/* Enable snooping and fix for AHB2MAG bypass. */
+	write4(sc, SDHC_DCR, DCR_SNOOP | DCR_AHB2MAG_BYPASS);
+#endif
+	/* Set data timeout. */
+	set_bit(sc, SDHC_SYSCTL, 0xe << SHIFT_DTOCV);
+
+	/* Set water-mark levels (FIFO buffer size). */
+	write4(sc, SDHC_WML, (FSL_SDHC_FIFO_BUF_WORDS << 16) |
+	    FSL_SDHC_FIFO_BUF_WORDS);
+}
+
+static void
+init_mmc_host_struct(struct fsl_sdhc_softc *sc)
+{
+	struct mmc_host *host = &sc->mmc_host;
+
+	/* Clear host structure. */
+	bzero(host, sizeof(struct mmc_host));
+
+	/* Calculate minimum and maximum operating frequencies. */
+	host->f_min = sc->platform_clock / FSL_SDHC_MAX_DIV;
+	host->f_max = FSL_SDHC_MAX_CLOCK;
+
+	/* Set operation conditions (voltage). */
+	host->host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340;
+
+	/* Set additional host controller capabilities. */
+	host->caps = MMC_CAP_4_BIT_DATA;
+
+	/* Set mode. */
+	host->mode = mode_sd;
+}
+
+static void
+card_detect_task(void *arg, int pending)
+{
+	struct fsl_sdhc_softc *sc = (struct fsl_sdhc_softc *)arg;
+	int err;
+	int insert;
+
+	insert = read4(sc, SDHC_PRSSTAT) & PRSSTAT_CINS;
+
+	mtx_lock(&sc->mtx);
+
+	if (insert) {
+		if (sc->child != NULL) {
+			mtx_unlock(&sc->mtx);
+			return;
+		}
+
+		sc->child = device_add_child(sc->self, "mmc", -1);
+		if (sc->child == NULL) {
+			device_printf(sc->self, "Couldn't add MMC bus!\n");
+			mtx_unlock(&sc->mtx);
+			return;
+		}
+
+		/* Initialize MMC bus host structure. */
+		init_mmc_host_struct(sc);
+		device_set_ivars(sc->child, &sc->mmc_host);
+
+	} else {
+		if (sc->child == NULL) {
+			mtx_unlock(&sc->mtx);
+			return;
+		}
+	}
+
+	mtx_unlock(&sc->mtx);
+
+	if (insert) {
+		if ((err = device_probe_and_attach(sc->child)) != 0) {
+			device_printf(sc->self, "MMC bus failed on probe "
+			    "and attach! error %d\n", err);
+			device_delete_child(sc->self, sc->child);
+			sc->child = NULL;
+		}
+	} else {
+		if (device_delete_child(sc->self, sc->child) != 0)
+			device_printf(sc->self, "Could not delete MMC bus!\n");
+		sc->child = NULL;
+	}
+}
+
+static void
+card_detect_delay(void *arg)
+{
+	struct fsl_sdhc_softc *sc = arg;
+
+	taskqueue_enqueue(taskqueue_swi_giant, &sc->card_detect_task);
+}
+
+static void
+finalize_request(struct fsl_sdhc_softc *sc)
+{
+
+	DPRINTF("finishing request %x\n", sc->request);
+
+	sc->request->done(sc->request);
+	sc->request = NULL;
+}
+
+/**
+ * Read response from card.
+ * @todo Implement Auto-CMD responses being held in R3 for multi-block xfers.
+ * @param sc
+ */
+static void
+get_response(struct fsl_sdhc_softc *sc)
+{
+	struct mmc_command *cmd = sc->request->cmd;
+	int i;
+	uint32_t val;
+	uint8_t ext = 0;
+
+	if (cmd->flags & MMC_RSP_136) {
+		/* CRC is stripped, need to shift one byte left. */
+		for (i = 0; i < 4; i++) {
+			val = read4(sc, SDHC_CMDRSP0 + i * 4);
+			cmd->resp[3 - i] = (val << 8) + ext;
+			ext = val >> 24;
+		}
+	} else {
+		cmd->resp[0] = read4(sc, SDHC_CMDRSP0);
+	}
+}
+
+#ifdef FSL_SDHC_NO_DMA
+/**
+ * Read all content of a fifo buffer.
+ * @warning Assumes data buffer is 32-bit aligned.
+ * @param sc
+ */
+static void
+read_block_pio(struct fsl_sdhc_softc *sc)
+{
+	struct mmc_data *data = sc->request->cmd->data;
+	size_t left = min(FSL_SDHC_FIFO_BUF_SIZE, data->len);
+	uint8_t *buf = data->data;
+	uint32_t word;
+
+	buf += sc->data_offset;
+	bus_space_read_multi_4(sc->bst, sc->bsh, SDHC_DATPORT, (uint32_t *)buf,
+	    left >> 2);
+
+	sc->data_offset += left;
+
+	/* Handle 32-bit unaligned size case. */
+	left &= 0x3;
+	if (left > 0) {
+		buf = (uint8_t *)data->data + (sc->data_offset & ~0x3);
+		word = read4(sc, SDHC_DATPORT);
+		while (left > 0) {
+			*(buf++) = word;
+			word >>= 8;
+			--left;
+		}
+	}
+}
+
+/**
+ * Write a fifo buffer.
+ * @warning Assumes data buffer size is 32-bit aligned.
+ * @param sc
+ */
+static void
+write_block_pio(struct fsl_sdhc_softc *sc)
+{
+	struct mmc_data *data = sc->request->cmd->data;
+	size_t left = min(FSL_SDHC_FIFO_BUF_SIZE, data->len);
+	uint8_t *buf = data->data;
+	uint32_t word = 0;
+
+	DPRINTF("sc->data_offset %d\n", sc->data_offset);
+
+	buf += sc->data_offset;
+	bus_space_write_multi_4(sc->bst, sc->bsh, SDHC_DATPORT, (uint32_t *)buf,
+	    left >> 2);
+
+	sc->data_offset += left;
+
+	/* Handle 32-bit unaligned size case. */
+	left &= 0x3;
+	if (left > 0) {
+		buf = (uint8_t *)data->data + (sc->data_offset & ~0x3);
+		while (left > 0) {
+			word += *(buf++);
+			word <<= 8;
+			--left;
+		}
+		write4(sc, SDHC_DATPORT, word);
+	}
+}
+
+static void
+pio_read_transfer(struct fsl_sdhc_softc *sc)
+{
+
+	while (read4(sc, SDHC_PRSSTAT) & PRSSTAT_BREN) {
+		read_block_pio(sc);
+
+		/*
+		 * TODO: should we check here whether data_offset >= data->len?
+		 */
+	}
+}
+
+static void
+pio_write_transfer(struct fsl_sdhc_softc *sc)
+{
+
+	while (read4(sc, SDHC_PRSSTAT) & PRSSTAT_BWEN) {
+		write_block_pio(sc);
+
+		/*
+		 * TODO: should we check here whether data_offset >= data->len?
+		 */
+	}
+}
+#endif /* FSL_SDHC_USE_DMA */
+
+static inline void
+handle_command_intr(struct fsl_sdhc_softc *sc, uint32_t irq_stat)
+{
+	struct mmc_command *cmd = sc->request->cmd;
+
+	/* Handle errors. */
+	if (irq_stat & IRQ_CTOE) {
+		cmd->error = MMC_ERR_TIMEOUT;
+	} else if (irq_stat & IRQ_CCE) {
+		cmd->error = MMC_ERR_BADCRC;
+	} else if (irq_stat & (IRQ_CEBE | IRQ_CIE)) {
+		cmd->error = MMC_ERR_FIFO;
+	}
+
+	if (cmd->error) {
+		device_printf(sc->self, "Error interrupt occured\n");
+		reset_controller_dat_cmd(sc);
+		return;
+	}
+
+	if (sc->command_done)
+		return;
+
+	if (irq_stat & IRQ_CC) {
+		sc->command_done = 1;
+
+		if (cmd->flags & MMC_RSP_PRESENT)
+			get_response(sc);
+	}
+}
+
+static inline void
+handle_data_intr(struct fsl_sdhc_softc *sc, uint32_t irq_stat)
+{
+	struct mmc_command *cmd = sc->request->cmd;
+
+	/* Handle errors. */
+	if (irq_stat & IRQ_DTOE) {
+		cmd->error = MMC_ERR_TIMEOUT;
+	} else if (irq_stat & (IRQ_DCE | IRQ_DEBE)) {
+		cmd->error = MMC_ERR_BADCRC;
+	} else if (irq_stat & IRQ_ERROR_DATA_MASK) {
+		cmd->error = MMC_ERR_FAILED;
+	}
+
+	if (cmd->error) {
+		device_printf(sc->self, "Error interrupt occured\n");
+		sc->data_done = 1;
+		reset_controller_dat_cmd(sc);
+		return;
+	}
+
+	if (sc->data_done)
+		return;
+
+#ifdef FSL_SDHC_NO_DMA
+	if (irq_stat & IRQ_BRR) {
+		pio_read_transfer(sc);
+	}
+
+	if (irq_stat & IRQ_BWR) {
+		pio_write_transfer(sc);
+	}
+#else
+	if (irq_stat & IRQ_DINT) {
+		struct mmc_data *data = sc->request->cmd->data;
+
+		/* Synchronize DMA. */
+		if (data->flags & MMC_DATA_READ) {
+			bus_dmamap_sync(sc->dma_tag, sc->dma_map,
+			    BUS_DMASYNC_POSTREAD);
+			memcpy(data->data, sc->dma_mem, data->len);
+		} else {
+			bus_dmamap_sync(sc->dma_tag, sc->dma_map,
+			    BUS_DMASYNC_POSTWRITE);
+		}
+
+		/*
+		 * TODO: For multiple block transfers, address of dma memory
+		 * in DSADDR register should be set to the beginning of the
+		 * segment here. Also offset to data pointer should be handled.
+		 */
+	}
+#endif
+
+	if (irq_stat & IRQ_TC)
+		sc->data_done = 1;
+}
+
+static void
+interrupt_handler(void *arg)
+{
+	struct fsl_sdhc_softc *sc = (struct fsl_sdhc_softc *)arg;
+	uint32_t irq_stat;
+
+	mtx_lock(&sc->mtx);
+
+	irq_stat = read4(sc, SDHC_IRQSTAT);
+
+	/* Card interrupt. */
+	if (irq_stat & IRQ_CINT) {
+		DPRINTF("Card interrupt recievied\n");
+
+	}
+
+	/* Card insertion interrupt. */
+	if (irq_stat & IRQ_CINS) {
+		clear_bit(sc, SDHC_IRQSIGEN, IRQ_CINS);
+		clear_bit(sc, SDHC_IRQSTATEN, IRQ_CINS);
+		set_bit(sc, SDHC_IRQSIGEN, IRQ_CRM);
+		set_bit(sc, SDHC_IRQSTATEN, IRQ_CRM);
+
+		callout_reset(&sc->card_detect_callout, hz / 2,
+		    card_detect_delay, sc);
+	}
+
+	/* Card removal interrupt. */
+	if (irq_stat & IRQ_CRM) {
+		clear_bit(sc, SDHC_IRQSIGEN, IRQ_CRM);
+		clear_bit(sc, SDHC_IRQSTATEN, IRQ_CRM);
+		set_bit(sc, SDHC_IRQSIGEN, IRQ_CINS);
+		set_bit(sc, SDHC_IRQSTATEN, IRQ_CINS);
+
+		callout_stop(&sc->card_detect_callout);
+		taskqueue_enqueue(taskqueue_swi_giant, &sc->card_detect_task);
+	}
+
+	/* Handle request interrupts. */
+	if (sc->request) {
+		handle_command_intr(sc, irq_stat);
+		handle_data_intr(sc, irq_stat);
+
+		/*
+		 * Finalize request when transfer is done successfully
+		 * or was interrupted due to error.
+		 */  
+		if ((sc->data_done && sc->command_done) ||
+		    (sc->request->cmd->error))
+			finalize_request(sc);
+	}
+
+	/* Clear status register. */
+	write4(sc, SDHC_IRQSTAT, irq_stat);
+
+	mtx_unlock(&sc->mtx);
+}
+
+#ifndef FSL_SDHC_NO_DMA
+static void
+dma_get_phys_addr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+
+	if (error != 0)
+		return;
+
+	/* Get first segment's physical address. */
+	*(bus_addr_t *)arg = segs->ds_addr;
+}
+
+static int
+init_dma(struct fsl_sdhc_softc *sc)
+{
+	device_t self = sc->self;
+	int err;
+
+	err = bus_dma_tag_create(bus_get_dma_tag(self),
+	    FSL_SDHC_DMA_BLOCK_SIZE, 0, BUS_SPACE_MAXADDR_32BIT,
+	    BUS_SPACE_MAXADDR, NULL, NULL, FSL_SDHC_DMA_BLOCK_SIZE, 1,
+	    FSL_SDHC_DMA_BLOCK_SIZE, BUS_DMA_ALLOCNOW, NULL, NULL,
+	    &sc->dma_tag);
+
+	if (err) {
+		device_printf(self, "Could not create DMA tag!\n");
+		return (-1);
+	}
+
+	err = bus_dmamem_alloc(sc->dma_tag, (void **)&(sc->dma_mem),
+	    BUS_DMA_NOWAIT | BUS_DMA_NOCACHE, &sc->dma_map);
+	if (err) {
+		device_printf(self, "Could not allocate DMA memory!\n");
+		goto fail1;
+	}
+
+	err = bus_dmamap_load(sc->dma_tag, sc->dma_map, (void *)sc->dma_mem,
+	    FSL_SDHC_DMA_BLOCK_SIZE, dma_get_phys_addr, &sc->dma_phys, 0);
+	if (err) {
+		device_printf(self, "Could not load DMA map!\n");
+		goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	bus_dmamem_free(sc->dma_tag, sc->dma_mem, sc->dma_map);
+fail1:
+	bus_dma_tag_destroy(sc->dma_tag);
+
+	return (-1);
+}
+#endif /* FSL_SDHC_NO_DMA */
+
+static uint32_t
+set_xfertyp_register(const struct mmc_command *cmd)
+{
+	uint32_t xfertyp = 0;
+
+	/* Set command index. */
+	xfertyp |= cmd->opcode << CMDINX_SHIFT;
+
+	/* Set command type. */
+	if (cmd->opcode == MMC_STOP_TRANSMISSION)
+		xfertyp |= CMDTYP_ABORT;
+
+	/* Set data preset select. */
+	if (cmd->data) {
+		xfertyp |= XFERTYP_DPSEL;
+
+		/* Set transfer direction. */
+		if (cmd->data->flags & MMC_DATA_READ)
+			xfertyp |= XFERTYP_DTDSEL;
+	}
+
+	/* Set command index check. */
+	if (cmd->flags & MMC_RSP_OPCODE)
+		xfertyp |= XFERTYP_CICEN;
+
+	/* Set command CRC check. */
+	if (cmd->flags & MMC_RSP_CRC)
+		xfertyp |= XFERTYP_CCCEN;
+
+	/* Set response type */
+	if (!(cmd->flags & MMC_RSP_PRESENT))
+		xfertyp |= RSPTYP_NONE;
+	else if (cmd->flags & MMC_RSP_136)
+		xfertyp |= RSPTYP_136;
+	else if (cmd->flags & MMC_RSP_BUSY)
+		xfertyp |= RSPTYP_48_BUSY;
+	else
+		xfertyp |= RSPTYP_48;
+
+#ifndef FSL_SDHC_NO_DMA
+	/* Enable DMA */
+	xfertyp |= XFERTYP_DMAEN;
+#endif
+
+	return (xfertyp);
+}
+
+static uint32_t
+set_blkattr_register(const struct mmc_data *data)
+{
+
+	if (data->len <= FSL_SDHC_MAX_BLOCK_SIZE) {
+		/* One block transfer. */
+		return (BLKATTR_BLOCK_COUNT(1) | ((data->len) &
+		    BLKATTR_BLKSZE));
+	}
+
+	/* TODO: Write code here for multi-block transfers. */
+	return (0);
+}
+
+/**
+ * Initiate data transfer. Interrupt handler will finalize it.
+ * @todo Implement multi-block transfers.
+ * @param sc
+ * @param cmd
+ */
+static int
+start_data(struct fsl_sdhc_softc *sc, struct mmc_data *data)
+{
+	uint32_t reg;
+
+	if ((uint32_t)data->data & 0x3) {
+		device_printf(sc->self, "32-bit unaligned data pointer in "
+		    "request\n");
+		return (-1);
+	}
+
+	sc->data_done = 0;
+
+#ifdef FSL_SDHC_NO_DMA
+	sc->data_ptr = data->data;
+	sc->data_offset = 0;
+#else
+	/* Write DMA address register. */
+	write4(sc, SDHC_DSADDR, sc->dma_phys);
+
+	/* Synchronize DMA. */
+	if (data->flags & MMC_DATA_READ) {
+		bus_dmamap_sync(sc->dma_tag, sc->dma_map,
+		    BUS_DMASYNC_PREREAD);
+	} else {
+		memcpy(sc->dma_mem, data->data, data->len);
+		bus_dmamap_sync(sc->dma_tag, sc->dma_map,
+		    BUS_DMASYNC_PREWRITE);
+	}
+#endif
+	/* Set block size and count. */
+	reg = set_blkattr_register(data);
+	if (reg == 0) {
+		device_printf(sc->self, "Requested unsupported multi-block "
+		    "transfer.\n");
+		return (-1);
+	}
+	write4(sc, SDHC_BLKATTR, reg);
+
+	return (0);
+}
+
+static int
+start_command(struct fsl_sdhc_softc *sc, struct mmc_command *cmd)
+{
+	struct mmc_request *req = sc->request;
+	uint32_t mask;
+	uint32_t xfertyp;
+	int err;
+
+	DPRINTF("opcode %d, flags 0x%08x\n", cmd->opcode, cmd->flags);
+	DPRINTF("PRSSTAT = 0x%08x\n", read4(sc, SDHC_PRSSTAT));
+
+	sc->command_done = 0;
+
+	cmd->error = MMC_ERR_NONE;
+
+	/* TODO: should we check here for card presence and clock settings? */
+
+	/* Always wait for free CMD line. */
+	mask = SDHC_CMD_LINE;
+	/* Wait for free DAT if we have data or busy signal. */
+	if (cmd->data || (cmd->flags & MMC_RSP_BUSY))
+		mask |= SDHC_DAT_LINE;
+	/* We shouldn't wait for DAT for stop commands. */
+	if (cmd == req->stop)
+		mask &= ~SDHC_DAT_LINE;
+	err = wait_for_free_line(sc, mask);
+	if (err != 0) {
+		device_printf(sc->self, "Controller never released inhibit "
+		    "bit(s).\n");
+		reset_controller_dat_cmd(sc);
+		cmd->error = MMC_ERR_FAILED;
+		sc->request = NULL;
+		req->done(req);
+		return (-1);
+	}
+
+	xfertyp = set_xfertyp_register(cmd);
+
+	if (cmd->data != NULL) {
+		err = start_data(sc, cmd->data);
+		if (err != 0) {
+			device_printf(sc->self,
+			    "Data transfer request failed\n");
+			reset_controller_dat_cmd(sc);
+			cmd->error = MMC_ERR_FAILED;
+			sc->request = NULL;
+			req->done(req);
+			return (-1);
+		}
+	}
+
+	write4(sc, SDHC_CMDARG, cmd->arg);
+	write4(sc, SDHC_XFERTYP, xfertyp);
+
+	DPRINTF("XFERTYP = 0x%08x\n", xfertyp);
+	DPRINTF("CMDARG = 0x%08x\n", cmd->arg);
+
+	return (0);
+}
+
+#ifdef DEBUG
+static void
+dump_registers(struct fsl_sdhc_softc *sc)
+{
+	printf("PRSSTAT = 0x%08x\n", read4(sc, SDHC_PRSSTAT));
+	printf("PROCTL = 0x%08x\n", read4(sc, SDHC_PROCTL));
+	printf("PMUXCR = 0x%08x\n", ccsr_read4(OCP85XX_PMUXCR));
+	printf("HOSTCAPBLT = 0x%08x\n", read4(sc, SDHC_HOSTCAPBLT));
+	printf("IRQSTAT = 0x%08x\n", read4(sc, SDHC_IRQSTAT));
+	printf("IRQSTATEN = 0x%08x\n", read4(sc, SDHC_IRQSTATEN));
+	printf("IRQSIGEN = 0x%08x\n", read4(sc, SDHC_IRQSIGEN));
+	printf("WML = 0x%08x\n", read4(sc, SDHC_WML));
+	printf("DSADDR = 0x%08x\n", read4(sc, SDHC_DSADDR));
+	printf("XFERTYP = 0x%08x\n", read4(sc, SDHC_XFERTYP));
+	printf("ECMCR = 0x%08x\n", ccsr_read4(OCP85XX_ECMCR));
+	printf("DCR = 0x%08x\n", read4(sc, SDHC_DCR));
+}
+#endif
+
+/*****************************************************************************
+ * Public methods
+ *****************************************************************************/
+/*
+ * Device interface methods.
+ */
+static int
+fsl_sdhc_probe(device_t self)
+{
+	static const char *desc =
+	    "Freescale Enhanced Secure Digital Host Controller";
+
+	if (!ofw_bus_is_compatible(self, "fsl,p2020-esdhc") &&
+	    !ofw_bus_is_compatible(self, "fsl,esdhc"))
+		return (ENXIO);
+
+	device_set_desc(self, desc);
+
+	return (BUS_PROBE_VENDOR);
+}
+
+static int
+fsl_sdhc_attach(device_t self)
+{
+	struct fsl_sdhc_softc *sc;
+
+	sc = device_get_softc(self);
+
+	sc->self = self;
+
+	mtx_init(&sc->mtx, device_get_nameunit(self), NULL, MTX_DEF);
+
+	/* Setup memory resource */
+	sc->mem_rid = 0;
+	sc->mem_resource = bus_alloc_resource_any(self, SYS_RES_MEMORY,
+	    &sc->mem_rid, RF_ACTIVE);
+	if (sc->mem_resource == NULL) {
+		device_printf(self, "Could not allocate memory.\n");
+		goto fail;
+	}
+	sc->bst = rman_get_bustag(sc->mem_resource);
+	sc->bsh = rman_get_bushandle(sc->mem_resource);
+
+	/* Setup interrupt resource. */
+	sc->irq_rid = 0;
+	sc->irq_resource = bus_alloc_resource_any(self, SYS_RES_IRQ,
+	    &sc->irq_rid, RF_ACTIVE);
+	if (sc->irq_resource == NULL) {
+		device_printf(self, "Could not allocate interrupt.\n");
+		goto fail;
+	}
+	if (bus_setup_intr(self, sc->irq_resource, INTR_TYPE_MISC |
+	    INTR_MPSAFE, NULL, interrupt_handler, sc, &sc->ihl) != 0) {
+		device_printf(self, "Could not setup interrupt.\n");
+		goto fail;
+	}
+
+	/* Setup DMA. */
+#ifndef FSL_SDHC_NO_DMA
+	if (init_dma(sc) != 0) {
+		device_printf(self, "Could not setup DMA\n");
+	}
+#endif
+	sc->bus_busy = 0;
+	sc->platform_clock = get_platform_clock(sc);
+	if (sc->platform_clock == 0) {
+		device_printf(self, "Could not get platform clock.\n");
+		goto fail;
+	}
+	sc->command_done = 1;
+	sc->data_done = 1;
+
+	/* Init card detection task. */
+	TASK_INIT(&sc->card_detect_task, 0, card_detect_task, sc);
+	callout_init(&sc->card_detect_callout, 1);
+
+	reset_controller_all(sc);
+	init_controller(sc);
+	set_clock(sc, 400000);
+	send_80_clock_ticks(sc);
+
+#ifdef DEBUG
+	dump_registers(sc);
+#endif
+
+	return (0);
+
+fail:
+	fsl_sdhc_detach(self);
+	return (ENXIO);
+}
+
+static int
+fsl_sdhc_detach(device_t self)
+{
+	struct fsl_sdhc_softc *sc = device_get_softc(self);
+	int err;
+
+	if (sc->child)
+		device_delete_child(self, sc->child);
+
+	taskqueue_drain(taskqueue_swi_giant, &sc->card_detect_task);
+
+#ifndef FSL_SDHC_NO_DMA
+	bus_dmamap_unload(sc->dma_tag, sc->dma_map);
+	bus_dmamem_free(sc->dma_tag, sc->dma_mem, sc->dma_map);
+	bus_dma_tag_destroy(sc->dma_tag);
+#endif
+
+	if (sc->ihl != NULL) {
+		err = bus_teardown_intr(self, sc->irq_resource, sc->ihl);
+		if (err)
+			return (err);
+	}
+	if (sc->irq_resource != NULL) {
+		err = bus_release_resource(self, SYS_RES_IRQ, sc->irq_rid,
+		    sc->irq_resource);
+		if (err)
+			return (err);
+
+	}
+	if (sc->mem_resource != NULL) {
+		err = bus_release_resource(self, SYS_RES_MEMORY, sc->mem_rid,
+		    sc->mem_resource);
+		if (err)
+			return (err);
+	}
+
+	mtx_destroy(&sc->mtx);
+
+	return (0);
+}
+
+
+/*
+ * Bus interface methods.
+ */
+static int
+fsl_sdhc_read_ivar(device_t self, device_t child, int index,
+    uintptr_t *result)
+{
+	struct mmc_host *host = device_get_ivars(child);
+
+	switch (index) {
+	case MMCBR_IVAR_BUS_MODE:
+		*(int *)result = host->ios.bus_mode;
+		break;
+	case MMCBR_IVAR_BUS_WIDTH:
+		*(int *)result = host->ios.bus_width;
+		break;
+	case MMCBR_IVAR_CHIP_SELECT:
+		*(int *)result = host->ios.chip_select;
+		break;
+	case MMCBR_IVAR_CLOCK:
+		*(int *)result = host->ios.clock;
+		break;
+	case MMCBR_IVAR_F_MIN:
+		*(int *)result = host->f_min;
+		break;
+	case MMCBR_IVAR_F_MAX:
+		*(int *)result = host->f_max;
+		break;
+	case MMCBR_IVAR_HOST_OCR:
+		*(int *)result = host->host_ocr;
+		break;
+	case MMCBR_IVAR_MODE:
+		*(int *)result = host->mode;
+		break;
+	case MMCBR_IVAR_OCR:
+		*(int *)result = host->ocr;
+		break;
+	case MMCBR_IVAR_POWER_MODE:
+		*(int *)result = host->ios.power_mode;
+		break;
+	case MMCBR_IVAR_VDD:
+		*(int *)result = host->ios.vdd;
+		break;
+	default:
+		return (EINVAL);
+	}
+
+	return (0);
+}
+
+static int
+fsl_sdhc_write_ivar(device_t self, device_t child, int index,
+    uintptr_t value)
+{
+	struct mmc_host *host = device_get_ivars(child);
+
+	switch (index) {
+	case MMCBR_IVAR_BUS_MODE:
+		host->ios.bus_mode = value;
+		break;
+	case MMCBR_IVAR_BUS_WIDTH:
+		host->ios.bus_width = value;
+		break;
+	case MMCBR_IVAR_CHIP_SELECT:
+		host->ios.chip_select = value;
+		break;
+	case MMCBR_IVAR_CLOCK:
+		host->ios.clock = value;
+		break;
+	case MMCBR_IVAR_MODE:
+		host->mode = value;
+		break;
+	case MMCBR_IVAR_OCR:
+		host->ocr = value;
+		break;
+	case MMCBR_IVAR_POWER_MODE:
+		host->ios.power_mode = value;
+		break;
+	case MMCBR_IVAR_VDD:
+		host->ios.vdd = value;
+		break;
+	case MMCBR_IVAR_HOST_OCR:
+	case MMCBR_IVAR_F_MIN:
+	case MMCBR_IVAR_F_MAX:
+	default:
+		/* Instance variable not writable. */
+		return (EINVAL);
+	}
+
+	return (0);
+}
+
+
+/*
+ * MMC bridge methods.
+ */
+static int
+fsl_sdhc_update_ios(device_t self, device_t reqdev)
+{
+	struct fsl_sdhc_softc *sc = device_get_softc(self);
+	struct mmc_host *host = device_get_ivars(reqdev);
+	struct mmc_ios *ios = &host->ios;
+
+	mtx_lock(&sc->mtx);
+
+	/* Full reset on bus power down to clear from any state. */
+	if (ios->power_mode == power_off) {
+		reset_controller_all(sc);
+		init_controller(sc);
+	}
+
+	set_clock(sc, ios->clock);
+	set_bus_width(sc, ios->bus_width);
+
+	mtx_unlock(&sc->mtx);
+
+	return (0);
+}
+
+static int
+fsl_sdhc_request(device_t self, device_t reqdev, struct mmc_request *req)
+{
+	struct fsl_sdhc_softc *sc = device_get_softc(self);
+	int err;
+
+	mtx_lock(&sc->mtx);
+
+	sc->request = req;
+	err = start_command(sc, req->cmd);
+
+	mtx_unlock(&sc->mtx);
+
+	return (err);
+}
+
+static int
+fsl_sdhc_get_ro(device_t self, device_t reqdev)
+{
+	struct fsl_sdhc_softc *sc = device_get_softc(self);
+
+	/* Wouldn't it be faster using branching (if {}) ?? */
+	return (((read4(sc, SDHC_PRSSTAT) & PRSSTAT_WPSPL) >> 19) ^ 0x1);
+}
+
+static int
+fsl_sdhc_acquire_host(device_t self, device_t reqdev)
+{
+	struct fsl_sdhc_softc *sc = device_get_softc(self);
+	int retval = 0;
+
+	mtx_lock(&sc->mtx);
+
+	while (sc->bus_busy)
+		retval = mtx_sleep(sc, &sc->mtx, PZERO, "sdhcah", 0);
+	++(sc->bus_busy);
+
+	mtx_unlock(&sc->mtx);
+
+	return (retval);
+}
+
+static int
+fsl_sdhc_release_host(device_t self, device_t reqdev)
+{
+	struct fsl_sdhc_softc *sc = device_get_softc(self);
+
+	mtx_lock(&sc->mtx);
+	--(sc->bus_busy);
+	mtx_unlock(&sc->mtx);
+	wakeup(sc);
+
+	return (0);
+}


Property changes on: trunk/sys/powerpc/mpc85xx/fsl_sdhc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/fsl_sdhc.h
===================================================================
--- trunk/sys/powerpc/mpc85xx/fsl_sdhc.h	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/fsl_sdhc.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,293 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011-2012 Semihalf
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/mpc85xx/fsl_sdhc.h 321946 2017-08-02 20:27:30Z marius $
+ */
+
+#ifndef FSL_SDHC_H_
+#define FSL_SDHC_H_
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmcreg.h>
+#include <dev/mmc/mmcbrvar.h>
+
+/*****************************************************************************
+ * Private defines
+ *****************************************************************************/
+struct slot {
+	uint32_t	clock;
+};
+
+struct fsl_sdhc_softc {
+	device_t		self;
+	device_t		child;
+
+	bus_space_handle_t	bsh;
+	bus_space_tag_t		bst;
+
+	struct resource		*mem_resource;
+	int			mem_rid;
+	struct resource		*irq_resource;
+	int			irq_rid;
+	void			*ihl;
+
+	bus_dma_tag_t		dma_tag;
+	bus_dmamap_t		dma_map;
+	uint32_t*		dma_mem;
+	bus_addr_t		dma_phys;
+
+	struct mtx		mtx;
+
+	struct task		card_detect_task;
+	struct callout		card_detect_callout;
+
+	struct mmc_host		mmc_host;
+
+	struct slot		slot;
+	uint32_t		bus_busy;
+	uint32_t		platform_clock;
+
+	struct mmc_request	*request;
+	int			data_done;
+	int			command_done;
+	int			use_dma;
+	uint32_t*		data_ptr;
+	uint32_t		data_offset;
+};
+
+#define FSL_SDHC_RESET_DELAY 50
+
+#define	FSL_SDHC_BASE_CLOCK_DIV		(2)
+#define	FSL_SDHC_MAX_DIV		(FSL_SDHC_BASE_CLOCK_DIV * 256 * 16)
+#define	FSL_SDHC_MIN_DIV		(FSL_SDHC_BASE_CLOCK_DIV * 2)
+#define	FSL_SDHC_MAX_CLOCK		(50000000)
+
+#define	FSL_SDHC_MAX_BLOCK_COUNT	(65535)
+#define	FSL_SDHC_MAX_BLOCK_SIZE		(4096)
+
+#define FSL_SDHC_FIFO_BUF_SIZE		(64)	/* Water-mark level. */
+#define FSL_SDHC_FIFO_BUF_WORDS		(FSL_SDHC_FIFO_BUF_SIZE / 4)
+
+#define FSL_SDHC_DMA_SEGMENT_SIZE	(1024)
+#define	FSL_SDHC_DMA_ALIGNMENT		(4)
+#define	FSL_SDHC_DMA_BLOCK_SIZE		FSL_SDHC_MAX_BLOCK_SIZE
+
+/*
+ * Offsets of SD HC registers
+ */
+enum sdhc_reg_off {
+	SDHC_DSADDR	= 0x000,
+	SDHC_BLKATTR	= 0x004,
+	SDHC_CMDARG	= 0x008,
+	SDHC_XFERTYP	= 0x00c,
+	SDHC_CMDRSP0	= 0x010,
+	SDHC_CMDRSP1	= 0x014,
+	SDHC_CMDRSP2	= 0x018,
+	SDHC_CMDRSP3	= 0x01c,
+	SDHC_DATPORT	= 0x020,
+	SDHC_PRSSTAT	= 0x024,
+	SDHC_PROCTL	= 0x028,
+	SDHC_SYSCTL	= 0x02c,
+	SDHC_IRQSTAT	= 0x030,
+	SDHC_IRQSTATEN	= 0x034,
+	SDHC_IRQSIGEN	= 0x038,
+	SDHC_AUTOC12ERR	= 0x03c,
+	SDHC_HOSTCAPBLT	= 0x040,
+	SDHC_WML	= 0x044,
+	SDHC_FEVT	= 0x050,
+	SDHC_HOSTVER	= 0x0fc,
+	SDHC_DCR	= 0x40c
+};
+
+enum sysctl_bit {
+	SYSCTL_INITA	= 0x08000000,
+	SYSCTL_RSTD	= 0x04000000,
+	SYSCTL_RSTC	= 0x02000000,
+	SYSCTL_RSTA	= 0x01000000,
+	SYSCTL_DTOCV	= 0x000f0000,
+	SYSCTL_SDCLKFS	= 0x0000ff00,
+	SYSCTL_DVS	= 0x000000f0,
+	SYSCTL_PEREN	= 0x00000004,
+	SYSCTL_HCKEN	= 0x00000002,
+	SYSCTL_IPGEN	= 0x00000001
+};
+
+#define HEX_LEFT_SHIFT(x)	(4 * x)
+enum sysctl_shift {
+	SHIFT_DTOCV	= HEX_LEFT_SHIFT(4),
+	SHIFT_SDCLKFS	= HEX_LEFT_SHIFT(2),
+	SHIFT_DVS	= HEX_LEFT_SHIFT(1)
+};
+
+enum proctl_bit {
+	PROCTL_WECRM	= 0x04000000,
+	PROCTL_WECINS	= 0x02000000,
+	PROCTL_WECINT	= 0x01000000,
+	PROCTL_RWCTL	= 0x00040000,
+	PROCTL_CREQ	= 0x00020000,
+	PROCTL_SABGREQ	= 0x00010000,
+	PROCTL_CDSS	= 0x00000080,
+	PROCTL_CDTL	= 0x00000040,
+	PROCTL_EMODE	= 0x00000030,
+	PROCTL_D3CD	= 0x00000008,
+	PROCTL_DTW	= 0x00000006
+};
+
+enum dtw {
+	DTW_1	= 0x00000000,
+	DTW_4	= 0x00000002,
+	DTW_8	= 0x00000004
+};
+
+enum prsstat_bit {
+	PRSSTAT_DLSL	= 0xff000000,
+	PRSSTAT_CLSL	= 0x00800000,
+	PRSSTAT_WPSPL	= 0x00080000,
+	PRSSTAT_CDPL	= 0x00040000,
+	PRSSTAT_CINS	= 0x00010000,
+	PRSSTAT_BREN	= 0x00000800,
+	PRSSTAT_BWEN	= 0x00000400,
+	PRSSTAT_RTA	= 0x00000200,
+	PRSSTAT_WTA	= 0x00000100,
+	PRSSTAT_SDOFF	= 0x00000080,
+	PRSSTAT_PEROFF	= 0x00000040,
+	PRSSTAT_HCKOFF	= 0x00000020,
+	PRSSTAT_IPGOFF	= 0x00000010,
+	PRSSTAT_DLA	= 0x00000004,
+	PRSSTAT_CDIHB	= 0x00000002,
+	PRSSTAT_CIHB	= 0x00000001
+
+};
+
+enum irq_bits {
+	IRQ_DMAE	= 0x10000000,
+	IRQ_AC12E	= 0x01000000,
+	IRQ_DEBE	= 0x00400000,
+	IRQ_DCE		= 0x00200000,
+	IRQ_DTOE	= 0x00100000,
+	IRQ_CIE		= 0x00080000,
+	IRQ_CEBE	= 0x00040000,
+	IRQ_CCE		= 0x00020000,
+	IRQ_CTOE	= 0x00010000,
+	IRQ_CINT	= 0x00000100,
+	IRQ_CRM		= 0x00000080,
+	IRQ_CINS	= 0x00000040,
+	IRQ_BRR		= 0x00000020,
+	IRQ_BWR		= 0x00000010,
+	IRQ_DINT	= 0x00000008,
+	IRQ_BGE		= 0x00000004,
+	IRQ_TC		= 0x00000002,
+	IRQ_CC		= 0x00000001
+};
+
+enum irq_masks {
+	IRQ_ERROR_DATA_MASK	= IRQ_DMAE | IRQ_DEBE | IRQ_DCE | IRQ_DTOE,
+	IRQ_ERROR_CMD_MASK	= IRQ_AC12E | IRQ_CIE | IRQ_CTOE | IRQ_CCE |
+				  IRQ_CEBE
+};
+
+enum dcr_bits {
+	DCR_PRI			= 0x0000c000,
+	DCR_SNOOP		= 0x00000040,
+	DCR_AHB2MAG_BYPASS	= 0x00000020,
+	DCR_RD_SAFE		= 0x00000004,
+	DCR_RD_PFE		= 0x00000002,
+	DCR_RD_PF_SIZE		= 0x00000001
+};
+
+#define	DCR_PRI_SHIFT	(14)
+
+enum xfertyp_bits {
+	XFERTYP_CMDINX	= 0x3f000000,
+	XFERTYP_CMDTYP	= 0x00c00000,
+	XFERTYP_DPSEL	= 0x00200000,
+	XFERTYP_CICEN	= 0x00100000,
+	XFERTYP_CCCEN	= 0x00080000,
+	XFERTYP_RSPTYP	= 0x00030000,
+	XFERTYP_MSBSEL	= 0x00000020,
+	XFERTYP_DTDSEL	= 0x00000010,
+	XFERTYP_AC12EN	= 0x00000004,
+	XFERTYP_BCEN	= 0x00000002,
+	XFERTYP_DMAEN	= 0x00000001
+};
+
+#define	CMDINX_SHIFT	(24)
+
+enum xfertyp_cmdtyp {
+	CMDTYP_NORMAL	= 0x00000000,
+	CMDYTP_SUSPEND	= 0x00400000,
+	CMDTYP_RESUME	= 0x00800000,
+	CMDTYP_ABORT	= 0x00c00000
+};
+
+enum xfertyp_rsptyp {
+	RSPTYP_NONE	= 0x00000000,
+	RSPTYP_136	= 0x00010000,
+	RSPTYP_48	= 0x00020000,
+	RSPTYP_48_BUSY	= 0x00030000
+};
+
+enum blkattr_bits {
+	BLKATTR_BLKSZE	= 0x00001fff,
+	BLKATTR_BLKCNT	= 0xffff0000
+};
+#define	BLKATTR_BLOCK_COUNT(x)	(x << 16)
+
+enum wml_bits {
+	WR_WML	= 0x00ff0000,
+	RD_WML	= 0x000000ff,
+};
+
+enum sdhc_bit_mask {
+	MASK_CLOCK_CONTROL	= 0x0000ffff,
+	MASK_IRQ_ALL		= IRQ_DMAE | IRQ_AC12E | IRQ_DEBE | IRQ_DCE |
+				  IRQ_DTOE | IRQ_CIE | IRQ_CEBE | IRQ_CCE |
+				  IRQ_CTOE | IRQ_CINT | IRQ_CRM | IRQ_CINS |
+				  IRQ_BRR | IRQ_BWR | IRQ_DINT | IRQ_BGE |
+				  IRQ_TC | IRQ_CC,
+};
+
+enum sdhc_line {
+	SDHC_DAT_LINE	= 0x2,
+	SDHC_CMD_LINE	= 0x1
+};
+
+#endif /* FSL_SDHC_H_ */


Property changes on: trunk/sys/powerpc/mpc85xx/fsl_sdhc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/i2c.c
===================================================================
--- trunk/sys/powerpc/mpc85xx/i2c.c	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/i2c.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,428 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008-2009 Semihalf, Michal Hajduk
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mpc85xx/i2c.c 289666 2015-10-20 21:20:34Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+#include "iicbus_if.h"
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#define I2C_ADDR_REG		0x00 /* I2C slave address register */
+#define I2C_FDR_REG		0x04 /* I2C frequency divider register */
+#define I2C_CONTROL_REG		0x08 /* I2C control register */
+#define I2C_STATUS_REG		0x0C /* I2C status register */
+#define I2C_DATA_REG		0x10 /* I2C data register */
+#define I2C_DFSRR_REG		0x14 /* I2C Digital Filter Sampling rate */
+#define I2C_ENABLE		0x80 /* Module enable - interrupt disable */
+#define I2CSR_RXAK		0x01 /* Received acknowledge */
+#define I2CSR_MCF		(1<<7) /* Data transfer */
+#define I2CSR_MASS		(1<<6) /* Addressed as a slave */
+#define I2CSR_MBB		(1<<5) /* Bus busy */
+#define I2CSR_MAL		(1<<4) /* Arbitration lost */
+#define I2CSR_SRW		(1<<2) /* Slave read/write */
+#define I2CSR_MIF		(1<<1) /* Module interrupt */
+#define I2CCR_MEN		(1<<7) /* Module enable */
+#define I2CCR_MSTA		(1<<5) /* Master/slave mode */
+#define I2CCR_MTX		(1<<4) /* Transmit/receive mode */
+#define I2CCR_TXAK		(1<<3) /* Transfer acknowledge */
+#define I2CCR_RSTA		(1<<2) /* Repeated START */
+
+#define I2C_BAUD_RATE_FAST	0x31
+#define I2C_BAUD_RATE_DEF	0x3F
+#define I2C_DFSSR_DIV		0x10
+
+#ifdef  DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+struct i2c_softc {
+	device_t		dev;
+	device_t		iicbus;
+	struct resource		*res;
+	struct mtx		mutex;
+	int			rid;
+	bus_space_handle_t	bsh;
+	bus_space_tag_t		bst;
+};
+
+static int i2c_probe(device_t);
+static int i2c_attach(device_t);
+
+static int i2c_repeated_start(device_t dev, u_char slave, int timeout);
+static int i2c_start(device_t dev, u_char slave, int timeout);
+static int i2c_stop(device_t dev);
+static int i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr);
+static int i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay);
+static int i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout);
+
+static device_method_t i2c_methods[] = {
+	DEVMETHOD(device_probe,			i2c_probe),
+	DEVMETHOD(device_attach,		i2c_attach),
+
+	DEVMETHOD(iicbus_callback,		iicbus_null_callback),
+	DEVMETHOD(iicbus_repeated_start,	i2c_repeated_start),
+	DEVMETHOD(iicbus_start,			i2c_start),
+	DEVMETHOD(iicbus_stop,			i2c_stop),
+	DEVMETHOD(iicbus_reset,			i2c_reset),
+	DEVMETHOD(iicbus_read,			i2c_read),
+	DEVMETHOD(iicbus_write,			i2c_write),
+	DEVMETHOD(iicbus_transfer,		iicbus_transfer_gen),
+
+	{ 0, 0 }
+};
+
+static driver_t i2c_driver = {
+	"i2c",
+	i2c_methods,
+	sizeof(struct i2c_softc),
+};
+static devclass_t  i2c_devclass;
+
+DRIVER_MODULE(i2c, simplebus, i2c_driver, i2c_devclass, 0, 0);
+DRIVER_MODULE(iicbus, i2c, iicbus_driver, iicbus_devclass, 0, 0);
+
+static __inline void
+i2c_write_reg(struct i2c_softc *sc, bus_size_t off, uint8_t val)
+{
+
+	bus_space_write_1(sc->bst, sc->bsh, off, val);
+}
+
+static __inline uint8_t
+i2c_read_reg(struct i2c_softc *sc, bus_size_t off)
+{
+
+	return (bus_space_read_1(sc->bst, sc->bsh, off));
+}
+
+static __inline void
+i2c_flag_set(struct i2c_softc *sc, bus_size_t off, uint8_t mask)
+{
+	uint8_t status;
+
+	status = i2c_read_reg(sc, off);
+	status |= mask;
+	i2c_write_reg(sc, off, status);
+}
+
+static int
+i2c_do_wait(device_t dev, struct i2c_softc *sc, int write, int start)
+{
+	int err;
+	uint8_t status;
+
+	status = i2c_read_reg(sc, I2C_STATUS_REG);
+	if (status & I2CSR_MIF) {
+		if (write && start && (status & I2CSR_RXAK)) {
+			debugf("no ack %s", start ?
+			    "after sending slave address" : "");
+			err = IIC_ENOACK;
+			goto error;
+		}
+		if (status & I2CSR_MAL) {
+			debugf("arbitration lost");
+			err = IIC_EBUSERR;
+			goto error;
+		}
+		if (!write && !(status & I2CSR_MCF)) {
+			debugf("transfer unfinished");
+			err = IIC_EBUSERR;
+			goto error;
+		}
+	}
+
+	return (IIC_NOERR);
+
+error:
+	i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
+	i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK);
+	return (err);
+}
+
+static int
+i2c_probe(device_t dev)
+{
+	struct i2c_softc *sc;
+
+	if (!ofw_bus_is_compatible(dev, "fsl-i2c"))
+		return (ENXIO);
+
+	sc = device_get_softc(dev);
+	sc->rid = 0;
+
+	sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
+	    RF_ACTIVE);
+	if (sc->res == NULL) {
+		device_printf(dev, "could not allocate resources\n");
+		return (ENXIO);
+	}
+
+	sc->bst = rman_get_bustag(sc->res);
+	sc->bsh = rman_get_bushandle(sc->res);
+
+	/* Enable I2C */
+	i2c_write_reg(sc, I2C_CONTROL_REG, I2C_ENABLE);
+	bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
+	device_set_desc(dev, "I2C bus controller");
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+i2c_attach(device_t dev)
+{
+	struct i2c_softc *sc;
+	sc = device_get_softc(dev);
+
+	sc->dev = dev;
+	sc->rid = 0;
+
+	mtx_init(&sc->mutex, device_get_nameunit(dev), "I2C", MTX_DEF);
+
+	sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
+	    RF_ACTIVE);
+	if (sc->res == NULL) {
+		device_printf(dev, "could not allocate resources");
+		mtx_destroy(&sc->mutex);
+		return (ENXIO);
+	}
+
+	sc->bst = rman_get_bustag(sc->res);
+	sc->bsh = rman_get_bushandle(sc->res);
+
+	sc->iicbus = device_add_child(dev, "iicbus", -1);
+	if (sc->iicbus == NULL) {
+		device_printf(dev, "could not add iicbus child");
+		mtx_destroy(&sc->mutex);
+		return (ENXIO);
+	}
+
+	bus_generic_attach(dev);
+	return (IIC_NOERR);
+}
+static int
+i2c_repeated_start(device_t dev, u_char slave, int timeout)
+{
+	struct i2c_softc *sc;
+	int error;
+	
+	sc = device_get_softc(dev);
+
+	mtx_lock(&sc->mutex);
+	/* Set repeated start condition */
+	i2c_flag_set(sc, I2C_CONTROL_REG ,I2CCR_RSTA);
+	/* Write target address - LSB is R/W bit */
+	i2c_write_reg(sc, I2C_DATA_REG, slave);
+	DELAY(1250);
+
+	error = i2c_do_wait(dev, sc, 1, 1);
+	mtx_unlock(&sc->mutex);
+
+	if (error)
+		return (error);
+
+	return (IIC_NOERR);
+}
+
+static int
+i2c_start(device_t dev, u_char slave, int timeout)
+{
+	struct i2c_softc *sc;
+	uint8_t status;
+	int error;
+
+	sc = device_get_softc(dev);
+	DELAY(1000);
+
+	mtx_lock(&sc->mutex);
+	status = i2c_read_reg(sc, I2C_STATUS_REG);
+	/* Check if bus is idle or busy */
+	if (status & I2CSR_MBB) {
+		debugf("bus busy");
+		mtx_unlock(&sc->mutex);
+		i2c_stop(dev);
+		return (IIC_EBUSERR);
+	}
+
+	/* Set start condition */
+	i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_MSTA | I2CCR_MTX);
+	/* Write target address - LSB is R/W bit */
+	i2c_write_reg(sc, I2C_DATA_REG, slave);
+	DELAY(1250);
+
+	error = i2c_do_wait(dev, sc, 1, 1);
+
+	mtx_unlock(&sc->mutex);
+	if (error)
+		return (error);
+
+	return (IIC_NOERR);
+}
+
+static int
+i2c_stop(device_t dev)
+{
+	struct i2c_softc *sc;
+
+	sc = device_get_softc(dev);
+	mtx_lock(&sc->mutex);
+	i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK);
+	DELAY(1000);
+	mtx_unlock(&sc->mutex);
+
+	return (IIC_NOERR);
+}
+
+static int
+i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr)
+{
+	struct i2c_softc *sc;
+	uint8_t baud_rate;
+
+	sc = device_get_softc(dev);
+
+	switch (speed) {
+	case IIC_FAST:
+		baud_rate = I2C_BAUD_RATE_FAST;
+		break;
+	case IIC_SLOW:
+	case IIC_UNKNOWN:
+	case IIC_FASTEST:
+	default:
+		baud_rate = I2C_BAUD_RATE_DEF;
+		break;
+	}
+
+	mtx_lock(&sc->mutex);
+	i2c_write_reg(sc, I2C_CONTROL_REG, 0x0);
+	i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
+	DELAY(1000);
+	i2c_write_reg(sc, I2C_FDR_REG, baud_rate);
+	i2c_write_reg(sc, I2C_DFSRR_REG, I2C_DFSSR_DIV);
+	i2c_write_reg(sc, I2C_CONTROL_REG, I2C_ENABLE);
+	DELAY(1000);
+	mtx_unlock(&sc->mutex);
+
+	return (IIC_NOERR);
+}
+
+static int
+i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay)
+{
+	struct i2c_softc *sc;
+	int error;
+
+	sc = device_get_softc(dev);
+	*read = 0;
+
+	mtx_lock(&sc->mutex);
+	if (len) {
+		if (len == 1)
+			i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
+			    I2CCR_MSTA | I2CCR_TXAK);
+
+		else
+			i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
+			    I2CCR_MSTA);
+
+		/* dummy read */
+		i2c_read_reg(sc, I2C_DATA_REG);
+		DELAY(1000);
+	}
+
+	while (*read < len) {
+		DELAY(1000);
+		error = i2c_do_wait(dev, sc, 0, 0);
+		if (error) {
+			mtx_unlock(&sc->mutex);
+			return (error);
+		}
+		if ((*read == len - 2) && last) {
+			i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
+			    I2CCR_MSTA | I2CCR_TXAK);
+		}
+
+		if ((*read == len - 1) && last) {
+			i2c_write_reg(sc, I2C_CONTROL_REG,  I2CCR_MEN |
+			    I2CCR_TXAK);
+		}
+
+		*buf++ = i2c_read_reg(sc, I2C_DATA_REG);
+		(*read)++;
+		DELAY(1250);
+	}
+	mtx_unlock(&sc->mutex);
+
+	return (IIC_NOERR);
+}
+
+static int
+i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout)
+{
+	struct i2c_softc *sc;
+	int error;
+
+	sc = device_get_softc(dev);
+	*sent = 0;
+
+	mtx_lock(&sc->mutex);
+	while (*sent < len) {
+		i2c_write_reg(sc, I2C_DATA_REG, *buf++);
+		DELAY(1250);
+
+		error = i2c_do_wait(dev, sc, 1, 0);
+		if (error) {
+			mtx_unlock(&sc->mutex);
+			return (error);
+		}
+
+		(*sent)++;
+	}
+	mtx_unlock(&sc->mutex);
+
+	return (IIC_NOERR);
+}


Property changes on: trunk/sys/powerpc/mpc85xx/i2c.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/isa.c
===================================================================
--- trunk/sys/powerpc/mpc85xx/isa.c	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/isa.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,85 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Marcel Moolenaar
+ *
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mpc85xx/isa.c 221526 2011-05-06 13:48:53Z jhb $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+
+#include <machine/intr_machdep.h>
+#include <machine/resource.h>
+
+#include <isa/isareg.h>
+#include <isa/isavar.h>
+#include <isa/isa_common.h>
+
+void
+isa_init(device_t dev)
+{
+}
+
+struct resource *
+isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
+    u_long start, u_long end, u_long count, u_int flags)
+{
+	struct isa_device* idev = DEVTOISA(child);
+	struct resource_list *rl = &idev->id_resources;
+	int isdefault, passthrough, rids;
+
+	isdefault = (start == 0UL && end == ~0UL) ? 1 : 0;
+	passthrough = (device_get_parent(child) != bus) ? 1 : 0;
+
+	if (!passthrough && !isdefault &&
+	    resource_list_find(rl, type, *rid) == NULL) {
+		switch (type) {
+		case SYS_RES_IOPORT:	rids = ISA_PNP_NPORT; break;
+		case SYS_RES_IRQ:	rids = ISA_PNP_NIRQ; break;
+		case SYS_RES_MEMORY:	rids = ISA_PNP_NMEM; break;
+		default:		rids = 0; break;
+		}
+		if (*rid < 0 || *rid >= rids)
+			return (NULL);
+
+		resource_list_add(rl, type, *rid, start, end, count);
+	}
+
+	return (resource_list_alloc(rl, bus, child, type, rid, start, end,
+	    count, flags));
+}
+
+int
+isa_release_resource(device_t bus, device_t child, int type, int rid,
+    struct resource *r)
+{
+	struct isa_device* idev = DEVTOISA(child);
+	struct resource_list *rl = &idev->id_resources;
+
+	return (resource_list_release(rl, bus, child, type, rid, r));
+}


Property changes on: trunk/sys/powerpc/mpc85xx/isa.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/lbc.c
===================================================================
--- trunk/sys/powerpc/mpc85xx/lbc.c	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/lbc.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,826 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006-2008, Juniper Networks, Inc.
+ * Copyright (c) 2008 Semihalf, Rafal Czubak
+ * Copyright (c) 2009 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Semihalf
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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. 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mpc85xx/lbc.c 266160 2014-05-15 17:30:16Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ktr.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+#include "ofw_bus_if.h"
+#include "lbc.h"
+
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__);	\
+    printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+static MALLOC_DEFINE(M_LBC, "localbus", "localbus devices information");
+
+static int lbc_probe(device_t);
+static int lbc_attach(device_t);
+static int lbc_shutdown(device_t);
+static struct resource *lbc_alloc_resource(device_t, device_t, int, int *,
+    u_long, u_long, u_long, u_int);
+static int lbc_print_child(device_t, device_t);
+static int lbc_release_resource(device_t, device_t, int, int,
+    struct resource *);
+static const struct ofw_bus_devinfo *lbc_get_devinfo(device_t, device_t);
+
+/*
+ * Bus interface definition
+ */
+static device_method_t lbc_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		lbc_probe),
+	DEVMETHOD(device_attach,	lbc_attach),
+	DEVMETHOD(device_shutdown,	lbc_shutdown),
+
+	/* Bus interface */
+	DEVMETHOD(bus_print_child,	lbc_print_child),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	NULL),
+
+	DEVMETHOD(bus_alloc_resource,	lbc_alloc_resource),
+	DEVMETHOD(bus_release_resource,	lbc_release_resource),
+	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+
+	/* OFW bus interface */
+	DEVMETHOD(ofw_bus_get_devinfo,	lbc_get_devinfo),
+	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
+	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
+	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
+	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
+	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
+
+	{ 0, 0 }
+};
+
+static driver_t lbc_driver = {
+	"lbc",
+	lbc_methods,
+	sizeof(struct lbc_softc)
+};
+
+devclass_t lbc_devclass;
+
+DRIVER_MODULE(lbc, ofwbus, lbc_driver, lbc_devclass, 0, 0);
+
+/*
+ * Calculate address mask used by OR(n) registers. Use memory region size to
+ * determine mask value. The size must be a power of two and within the range
+ * of 32KB - 4GB. Otherwise error code is returned. Value representing
+ * 4GB size can be passed as 0xffffffff.
+ */
+static uint32_t
+lbc_address_mask(uint32_t size)
+{
+	int n = 15;
+
+	if (size == ~0UL)
+		return (0);
+
+	while (n < 32) {
+		if (size == (1UL << n))
+			break;
+		n++;
+	}
+
+	if (n == 32)
+		return (EINVAL);
+
+	return (0xffff8000 << (n - 15));
+}
+
+static void
+lbc_banks_unmap(struct lbc_softc *sc)
+{
+	int r;
+
+	r = 0;
+	while (r < LBC_DEV_MAX) {
+		if (sc->sc_range[r].size == 0)
+			return;
+
+		pmap_unmapdev(sc->sc_range[r].kva, sc->sc_range[r].size);
+		law_disable(OCP85XX_TGTIF_LBC, sc->sc_range[r].addr,
+		    sc->sc_range[r].size);
+		r++;
+	}
+}
+
+static int
+lbc_banks_map(struct lbc_softc *sc)
+{
+	vm_paddr_t end, start;
+	vm_size_t size;
+	u_int i, r, ranges, s;
+	int error;
+
+	bzero(sc->sc_range, sizeof(sc->sc_range));
+
+	/*
+	 * Determine number of discontiguous address ranges to program.
+	 */
+	ranges = 0;
+	for (i = 0; i < LBC_DEV_MAX; i++) {
+		size = sc->sc_banks[i].size;
+		if (size == 0)
+			continue;
+
+		start = sc->sc_banks[i].addr;
+		for (r = 0; r < ranges; r++) {
+			/* Avoid wrap-around bugs. */
+			end = sc->sc_range[r].addr - 1 + sc->sc_range[r].size;
+			if (start > 0 && end == start - 1) {
+				sc->sc_range[r].size += size;
+				break;
+			}
+			/* Avoid wrap-around bugs. */
+			end = start - 1 + size;
+			if (sc->sc_range[r].addr > 0 &&
+			    end == sc->sc_range[r].addr - 1) {
+				sc->sc_range[r].addr = start;
+				sc->sc_range[r].size += size;
+				break;
+			}
+		}
+		if (r == ranges) {
+			/* New range; add using insertion sort */
+			r = 0;
+			while (r < ranges && sc->sc_range[r].addr < start)
+				r++;
+			for (s = ranges; s > r; s--)
+				sc->sc_range[s] = sc->sc_range[s-1];
+			sc->sc_range[r].addr = start;
+			sc->sc_range[r].size = size;
+			ranges++;
+		}
+	}
+
+	/*
+	 * Ranges are sorted so quickly go over the list to merge ranges
+	 * that grew toward each other while building the ranges.
+	 */
+	r = 0;
+	while (r < ranges - 1) {
+		end = sc->sc_range[r].addr + sc->sc_range[r].size;
+		if (end != sc->sc_range[r+1].addr) {
+			r++;
+			continue;
+		}
+		sc->sc_range[r].size += sc->sc_range[r+1].size;
+		for (s = r + 1; s < ranges - 1; s++)
+			sc->sc_range[s] = sc->sc_range[s+1];
+		bzero(&sc->sc_range[s], sizeof(sc->sc_range[s]));
+		ranges--;
+	}
+
+	/*
+	 * Configure LAW for the LBC ranges and map the physical memory
+	 * range into KVA.
+	 */
+	for (r = 0; r < ranges; r++) {
+		start = sc->sc_range[r].addr;
+		size = sc->sc_range[r].size;
+		error = law_enable(OCP85XX_TGTIF_LBC, start, size);
+		if (error)
+			return (error);
+		sc->sc_range[r].kva = (vm_offset_t)pmap_mapdev(start, size);
+	}
+
+	/* XXX: need something better here? */
+	if (ranges == 0)
+		return (EINVAL);
+
+	/* Assign KVA to banks based on the enclosing range. */
+	for (i = 0; i < LBC_DEV_MAX; i++) {
+		size = sc->sc_banks[i].size;
+		if (size == 0)
+			continue;
+
+		start = sc->sc_banks[i].addr;
+		for (r = 0; r < ranges; r++) {
+			end = sc->sc_range[r].addr - 1 + sc->sc_range[r].size;
+			if (start >= sc->sc_range[r].addr &&
+			    start - 1 + size <= end)
+				break;
+		}
+		if (r < ranges) {
+			sc->sc_banks[i].kva = sc->sc_range[r].kva +
+			    (start - sc->sc_range[r].addr);
+		}
+	}
+
+	return (0);
+}
+
+static int
+lbc_banks_enable(struct lbc_softc *sc)
+{
+	u_long size;
+	uint32_t regval;
+	int error, i;
+
+	for (i = 0; i < LBC_DEV_MAX; i++) {
+		size = sc->sc_banks[i].size;
+		if (size == 0)
+			continue;
+
+		/*
+		 * Compute and program BR value.
+		 */
+		regval = sc->sc_banks[i].addr;
+		switch (sc->sc_banks[i].width) {
+		case 8:
+			regval |= (1 << 11);
+			break;
+		case 16:
+			regval |= (2 << 11);
+			break;
+		case 32:
+			regval |= (3 << 11);
+			break;
+		default:
+			error = EINVAL;
+			goto fail;
+		}
+		regval |= (sc->sc_banks[i].decc << 9);
+		regval |= (sc->sc_banks[i].wp << 8);
+		regval |= (sc->sc_banks[i].msel << 5);
+		regval |= (sc->sc_banks[i].atom << 2);
+		regval |= 1;
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+		    LBC85XX_BR(i), regval);
+
+		/*
+		 * Compute and program OR value.
+		 */
+		regval = lbc_address_mask(size);
+		switch (sc->sc_banks[i].msel) {
+		case LBCRES_MSEL_GPCM:
+			/* TODO Add flag support for option registers */
+			regval |= 0x0ff7;
+			break;
+		case LBCRES_MSEL_FCM:
+			/* TODO Add flag support for options register */
+			regval |= 0x0796;
+			break;
+		case LBCRES_MSEL_UPMA:
+		case LBCRES_MSEL_UPMB:
+		case LBCRES_MSEL_UPMC:
+			printf("UPM mode not supported yet!");
+			error = ENOSYS;
+			goto fail;
+		}
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+		    LBC85XX_OR(i), regval);
+	}
+
+	return (0);
+
+fail:
+	lbc_banks_unmap(sc);
+	return (error);
+}
+
+static void
+fdt_lbc_fixup(phandle_t node, struct lbc_softc *sc, struct lbc_devinfo *di)
+{
+	pcell_t width;
+	int bank;
+
+	if (OF_getprop(node, "bank-width", (void *)&width, sizeof(width)) <= 0)
+		return;
+
+	bank = di->di_bank;
+	if (sc->sc_banks[bank].size == 0)
+		return;
+
+	/* Express width in bits. */
+	sc->sc_banks[bank].width = width * 8;
+}
+
+static int
+fdt_lbc_reg_decode(phandle_t node, struct lbc_softc *sc,
+    struct lbc_devinfo *di)
+{
+	u_long start, end, count;
+	pcell_t *reg, *regptr;
+	pcell_t addr_cells, size_cells;
+	int tuple_size, tuples;
+	int i, rv, bank;
+
+	if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
+		return (ENXIO);
+
+	tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
+	tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)&reg);
+	debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells);
+	debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size);
+	if (tuples <= 0)
+		/* No 'reg' property in this node. */
+		return (0);
+
+	regptr = reg;
+	for (i = 0; i < tuples; i++) {
+
+		bank = fdt_data_get((void *)reg, 1);
+		di->di_bank = bank;
+		reg += 1;
+
+		/* Get address/size. */
+		rv = fdt_data_to_res(reg, addr_cells - 1, size_cells, &start,
+		    &count);
+		if (rv != 0) {
+			resource_list_free(&di->di_res);
+			goto out;
+		}
+		reg += addr_cells - 1 + size_cells;
+
+		/* Calculate address range relative to VA base. */
+		start = sc->sc_banks[bank].kva + start;
+		end = start + count - 1;
+
+		debugf("reg addr bank = %d, start = %lx, end = %lx, "
+		    "count = %lx\n", bank, start, end, count);
+
+		/* Use bank (CS) cell as rid. */
+		resource_list_add(&di->di_res, SYS_RES_MEMORY, bank, start,
+		    end, count);
+	}
+	rv = 0;
+out:
+	free(regptr, M_OFWPROP);
+	return (rv);
+}
+
+static void
+lbc_intr(void *arg)
+{
+	struct lbc_softc *sc = arg;
+	uint32_t ltesr;
+
+	ltesr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR);
+	sc->sc_ltesr = ltesr;
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ltesr);
+	wakeup(sc->sc_dev);
+}
+
+static int
+lbc_probe(device_t dev)
+{
+
+	if (!(ofw_bus_is_compatible(dev, "fsl,lbc") ||
+	    ofw_bus_is_compatible(dev, "fsl,elbc")))
+		return (ENXIO);
+
+	device_set_desc(dev, "Freescale Local Bus Controller");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+lbc_attach(device_t dev)
+{
+	struct lbc_softc *sc;
+	struct lbc_devinfo *di;
+	struct rman *rm;
+	u_long offset, start, size;
+	device_t cdev;
+	phandle_t node, child;
+	pcell_t *ranges, *rangesptr;
+	int tuple_size, tuples;
+	int par_addr_cells;
+	int bank, error, i;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+
+	sc->sc_mrid = 0;
+	sc->sc_mres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_mrid,
+	    RF_ACTIVE);
+	if (sc->sc_mres == NULL)
+		return (ENXIO);
+
+	sc->sc_bst = rman_get_bustag(sc->sc_mres);
+	sc->sc_bsh = rman_get_bushandle(sc->sc_mres);
+
+	for (bank = 0; bank < LBC_DEV_MAX; bank++) {
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_BR(bank), 0);
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_OR(bank), 0);
+	}
+
+	/*
+	 * Initialize configuration register:
+	 * - enable Local Bus
+	 * - set data buffer control signal function
+	 * - disable parity byte select
+	 * - set ECC parity type
+	 * - set bus monitor timing and timer prescale
+	 */
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LBCR, 0);
+
+	/*
+	 * Initialize clock ratio register:
+	 * - disable PLL bypass mode
+	 * - configure LCLK delay cycles for the assertion of LALE
+	 * - set system clock divider
+	 */
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LCRR, 0x00030008);
+
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEDR, 0);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ~0);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEIR, 0x64080001);
+
+	sc->sc_irid = 0;
+	sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
+	    RF_ACTIVE | RF_SHAREABLE);
+	if (sc->sc_ires != NULL) {
+		error = bus_setup_intr(dev, sc->sc_ires,
+		    INTR_TYPE_MISC | INTR_MPSAFE, NULL, lbc_intr, sc,
+		    &sc->sc_icookie);
+		if (error) {
+			device_printf(dev, "could not activate interrupt\n");
+			bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
+			    sc->sc_ires);
+			sc->sc_ires = NULL;
+		}
+	}
+
+	sc->sc_ltesr = ~0;
+
+	rangesptr = NULL;
+
+	rm = &sc->sc_rman;
+	rm->rm_type = RMAN_ARRAY;
+	rm->rm_descr = "Local Bus Space";
+	rm->rm_start = 0UL;
+	rm->rm_end = ~0UL;
+	error = rman_init(rm);
+	if (error)
+		goto fail;
+
+	error = rman_manage_region(rm, rm->rm_start, rm->rm_end);
+	if (error) {
+		rman_fini(rm);
+		goto fail;
+	}
+
+	/*
+	 * Process 'ranges' property.
+	 */
+	node = ofw_bus_get_node(dev);
+	if ((fdt_addrsize_cells(node, &sc->sc_addr_cells,
+	    &sc->sc_size_cells)) != 0) {
+		error = ENXIO;
+		goto fail;
+	}
+
+	par_addr_cells = fdt_parent_addr_cells(node);
+	if (par_addr_cells > 2) {
+		device_printf(dev, "unsupported parent #addr-cells\n");
+		error = ERANGE;
+		goto fail;
+	}
+	tuple_size = sizeof(pcell_t) * (sc->sc_addr_cells + par_addr_cells +
+	    sc->sc_size_cells);
+
+	tuples = OF_getprop_alloc(node, "ranges", tuple_size,
+	    (void **)&ranges);
+	if (tuples < 0) {
+		device_printf(dev, "could not retrieve 'ranges' property\n");
+		error = ENXIO;
+		goto fail;
+	}
+	rangesptr = ranges;
+
+	debugf("par addr_cells = %d, addr_cells = %d, size_cells = %d, "
+	    "tuple_size = %d, tuples = %d\n", par_addr_cells,
+	    sc->sc_addr_cells, sc->sc_size_cells, tuple_size, tuples);
+
+	start = 0;
+	size = 0;
+	for (i = 0; i < tuples; i++) {
+
+		/* The first cell is the bank (chip select) number. */
+		bank = fdt_data_get((void *)ranges, 1);
+		if (bank < 0 || bank > LBC_DEV_MAX) {
+			device_printf(dev, "bank out of range: %d\n", bank);
+			error = ERANGE;
+			goto fail;
+		}
+		ranges += 1;
+
+		/*
+		 * Remaining cells of the child address define offset into
+		 * this CS.
+		 */
+		offset = fdt_data_get((void *)ranges, sc->sc_addr_cells - 1);
+		ranges += sc->sc_addr_cells - 1;
+
+		/* Parent bus start address of this bank. */
+		start = fdt_data_get((void *)ranges, par_addr_cells);
+		ranges += par_addr_cells;
+
+		size = fdt_data_get((void *)ranges, sc->sc_size_cells);
+		ranges += sc->sc_size_cells;
+		debugf("bank = %d, start = %lx, size = %lx\n", bank,
+		    start, size);
+
+		sc->sc_banks[bank].addr = start + offset;
+		sc->sc_banks[bank].size = size;
+
+		/*
+		 * Attributes for the bank.
+		 *
+		 * XXX Note there are no DT bindings defined for them at the
+		 * moment, so we need to provide some defaults.
+		 */
+		sc->sc_banks[bank].width = 16;
+		sc->sc_banks[bank].msel = LBCRES_MSEL_GPCM;
+		sc->sc_banks[bank].decc = LBCRES_DECC_DISABLED;
+		sc->sc_banks[bank].atom = LBCRES_ATOM_DISABLED;
+		sc->sc_banks[bank].wp = 0;
+	}
+
+	/*
+	 * Initialize mem-mappings for the LBC banks (i.e. chip selects).
+	 */
+	error = lbc_banks_map(sc);
+	if (error)
+		goto fail;
+
+	/*
+	 * Walk the localbus and add direct subordinates as our children.
+	 */
+	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
+
+		di = malloc(sizeof(*di), M_LBC, M_WAITOK | M_ZERO);
+
+		if (ofw_bus_gen_setup_devinfo(&di->di_ofw, child) != 0) {
+			free(di, M_LBC);
+			device_printf(dev, "could not set up devinfo\n");
+			continue;
+		}
+
+		resource_list_init(&di->di_res);
+
+		if (fdt_lbc_reg_decode(child, sc, di)) {
+			device_printf(dev, "could not process 'reg' "
+			    "property\n");
+			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
+			free(di, M_LBC);
+			continue;
+		}
+
+		fdt_lbc_fixup(child, sc, di);
+
+		/* Add newbus device for this FDT node */
+		cdev = device_add_child(dev, NULL, -1);
+		if (cdev == NULL) {
+			device_printf(dev, "could not add child: %s\n",
+			    di->di_ofw.obd_name);
+			resource_list_free(&di->di_res);
+			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
+			free(di, M_LBC);
+			continue;
+		}
+		debugf("added child name='%s', node=%p\n", di->di_ofw.obd_name,
+		    (void *)child);
+		device_set_ivars(cdev, di);
+	}
+
+	/*
+	 * Enable the LBC.
+	 */
+	lbc_banks_enable(sc);
+
+	free(rangesptr, M_OFWPROP);
+	return (bus_generic_attach(dev));
+
+fail:
+	free(rangesptr, M_OFWPROP);
+	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mrid, sc->sc_mres);
+	return (error);
+}
+
+static int
+lbc_shutdown(device_t dev)
+{
+
+	/* TODO */
+	return(0);
+}
+
+static struct resource *
+lbc_alloc_resource(device_t bus, device_t child, int type, int *rid,
+    u_long start, u_long end, u_long count, u_int flags)
+{
+	struct lbc_softc *sc;
+	struct lbc_devinfo *di;
+	struct resource_list_entry *rle;
+	struct resource *res;
+	struct rman *rm;
+	int needactivate;
+
+	/* We only support default allocations. */
+	if (start != 0ul || end != ~0ul)
+		return (NULL);
+
+	sc = device_get_softc(bus);
+	if (type == SYS_RES_IRQ)
+		return (bus_alloc_resource(bus, type, rid, start, end, count,
+		    flags));
+
+	/*
+	 * Request for the default allocation with a given rid: use resource
+	 * list stored in the local device info.
+	 */
+	if ((di = device_get_ivars(child)) == NULL)
+		return (NULL);
+
+	if (type == SYS_RES_IOPORT)
+		type = SYS_RES_MEMORY;
+
+	rid = &di->di_bank;
+
+	rle = resource_list_find(&di->di_res, type, *rid);
+	if (rle == NULL) {
+		device_printf(bus, "no default resources for "
+		    "rid = %d, type = %d\n", *rid, type);
+		return (NULL);
+	}
+	start = rle->start;
+	count = rle->count;
+	end = start + count - 1;
+
+	sc = device_get_softc(bus);
+
+	needactivate = flags & RF_ACTIVE;
+	flags &= ~RF_ACTIVE;
+
+	rm = &sc->sc_rman;
+
+	res = rman_reserve_resource(rm, start, end, count, flags, child);
+	if (res == NULL) {
+		device_printf(bus, "failed to reserve resource %#lx - %#lx "
+		    "(%#lx)\n", start, end, count);
+		return (NULL);
+	}
+
+	rman_set_rid(res, *rid);
+	rman_set_bustag(res, &bs_be_tag);
+	rman_set_bushandle(res, rman_get_start(res));
+
+	if (needactivate)
+		if (bus_activate_resource(child, type, *rid, res)) {
+			device_printf(child, "resource activation failed\n");
+			rman_release_resource(res);
+			return (NULL);
+		}
+
+	return (res);
+}
+
+static int
+lbc_print_child(device_t dev, device_t child)
+{
+	struct lbc_devinfo *di;
+	struct resource_list *rl;
+	int rv;
+
+	di = device_get_ivars(child);
+	rl = &di->di_res;
+
+	rv = 0;
+	rv += bus_print_child_header(dev, child);
+	rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
+	rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+	rv += bus_print_child_footer(dev, child);
+
+	return (rv);
+}
+
+static int
+lbc_release_resource(device_t dev, device_t child, int type, int rid,
+    struct resource *res)
+{
+	int err;
+
+	if (rman_get_flags(res) & RF_ACTIVE) {
+		err = bus_deactivate_resource(child, type, rid, res);
+		if (err)
+			return (err);
+	}
+
+	return (rman_release_resource(res));
+}
+
+static const struct ofw_bus_devinfo *
+lbc_get_devinfo(device_t bus, device_t child)
+{
+	struct lbc_devinfo *di;
+
+	di = device_get_ivars(child);
+	return (&di->di_ofw);
+}
+
+void
+lbc_write_reg(device_t child, u_int off, uint32_t val)
+{
+	device_t dev;
+	struct lbc_softc *sc;
+
+	dev = device_get_parent(child);
+
+	if (off >= 0x1000) {
+		device_printf(dev, "%s(%s): invalid offset %#x\n",
+		    __func__, device_get_nameunit(child), off);
+		return;
+	}
+
+	sc = device_get_softc(dev);
+
+	if (off == LBC85XX_LTESR && sc->sc_ltesr != ~0u) {
+		sc->sc_ltesr ^= (val & sc->sc_ltesr);
+		return;
+	}
+
+	if (off == LBC85XX_LTEATR && (val & 1) == 0)
+		sc->sc_ltesr = ~0u;
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
+}
+
+uint32_t
+lbc_read_reg(device_t child, u_int off)
+{
+	device_t dev;
+	struct lbc_softc *sc;
+	uint32_t val;
+
+	dev = device_get_parent(child);
+
+	if (off >= 0x1000) {
+		device_printf(dev, "%s(%s): invalid offset %#x\n",
+		    __func__, device_get_nameunit(child), off);
+		return (~0U);
+	}
+
+	sc = device_get_softc(dev);
+
+	if (off == LBC85XX_LTESR && sc->sc_ltesr != ~0U)
+		val = sc->sc_ltesr;
+	else
+		val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, off);
+	return (val);
+}


Property changes on: trunk/sys/powerpc/mpc85xx/lbc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/lbc.h
===================================================================
--- trunk/sys/powerpc/mpc85xx/lbc.h	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/lbc.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,139 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006-2008, Juniper Networks, Inc.
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/mpc85xx/lbc.h 238045 2012-07-03 00:06:14Z marcel $
+ */
+
+#ifndef _MACHINE_LBC_H_
+#define	_MACHINE_LBC_H_
+
+/* Maximum number of devices on Local Bus */
+#define	LBC_DEV_MAX	8
+
+/* Local access registers */
+#define	LBC85XX_BR(n)	(0x0 + (8 * n))	/* Base register 0-7 */
+#define	LBC85XX_OR(n)	(0x4 + (8 * n))	/* Options register 0-7 */
+#define	LBC85XX_MAR	0x068		/* UPM address register */
+#define	LBC85XX_MAMR	0x070		/* UPMA mode register */
+#define	LBC85XX_MBMR	0x074		/* UPMB mode register */
+#define	LBC85XX_MCMR	0x078		/* UPMC mode register */
+#define	LBC85XX_MRTPR	0x084		/* Memory refresh timer prescaler */
+#define	LBC85XX_MDR	0x088		/* UPM data register */
+#define	LBC85XX_LSOR	0x090		/* Special operation initiation */
+#define	LBC85XX_LURT	0x0a0		/* UPM refresh timer */
+#define	LBC85XX_LSRT	0x0a4		/* SDRAM refresh timer */
+#define	LBC85XX_LTESR	0x0b0		/* Transfer error status register */
+#define	LBC85XX_LTEDR	0x0b4		/* Transfer error disable register */
+#define	LBC85XX_LTEIR	0x0b8		/* Transfer error interrupt register */
+#define	LBC85XX_LTEATR	0x0bc		/* Transfer error attributes register */
+#define	LBC85XX_LTEAR	0x0c0		/* Transfer error address register */
+#define	LBC85XX_LTECCR	0x0c4		/* Transfer error ECC register */
+#define	LBC85XX_LBCR	0x0d0		/* Configuration register */
+#define	LBC85XX_LCRR	0x0d4		/* Clock ratio register */
+#define	LBC85XX_FMR	0x0e0		/* Flash mode register */
+#define	LBC85XX_FIR	0x0e4		/* Flash instruction register */
+#define	LBC85XX_FCR	0x0e8		/* Flash command register */
+#define	LBC85XX_FBAR	0x0ec		/* Flash block address register */
+#define	LBC85XX_FPAR	0x0f0		/* Flash page address register */
+#define	LBC85XX_FBCR	0x0f4		/* Flash byte count register */
+#define	LBC85XX_FECC0	0x100		/* Flash ECC block 0 register */
+#define	LBC85XX_FECC1	0x104		/* Flash ECC block 0 register */
+#define	LBC85XX_FECC2	0x108		/* Flash ECC block 0 register */
+#define	LBC85XX_FECC3	0x10c		/* Flash ECC block 0 register */
+
+/* LBC machine select */
+#define	LBCRES_MSEL_GPCM	0
+#define	LBCRES_MSEL_FCM		1
+#define	LBCRES_MSEL_UPMA	8
+#define	LBCRES_MSEL_UPMB	9
+#define	LBCRES_MSEL_UPMC	10
+
+/* LBC data error checking modes */
+#define	LBCRES_DECC_DISABLED	0
+#define	LBCRES_DECC_NORMAL	1
+#define	LBCRES_DECC_RMW		2
+
+/* LBC atomic operation modes */
+#define	LBCRES_ATOM_DISABLED	0
+#define	LBCRES_ATOM_RAWA	1
+#define	LBCRES_ATOM_WARA	2
+
+struct lbc_memrange {
+	vm_paddr_t	addr;
+	vm_size_t	size;
+	vm_offset_t	kva;
+};
+
+struct lbc_bank {
+	vm_paddr_t	addr;		/* physical addr of the bank */
+	vm_size_t	size;		/* bank size */
+	vm_offset_t	kva;		/* VA of the bank */
+
+	/*
+	 * XXX the following bank attributes do not have properties specified
+	 * in the LBC DTS bindings yet (11.2009), so they are mainly a
+	 * placeholder for future extensions.
+	 */
+	int		width;		/* data bus width */
+	uint8_t		msel;		/* machine select */
+	uint8_t		atom;		/* atomic op mode */
+	uint8_t		wp;		/* write protect */
+	uint8_t		decc;		/* data error checking */
+};
+
+struct lbc_softc {
+	device_t		sc_dev;
+
+	struct resource		*sc_mres;
+	bus_space_handle_t	sc_bsh;
+	bus_space_tag_t		sc_bst;
+	int			sc_mrid;
+
+	int			sc_irid;
+	struct resource		*sc_ires;
+	void			*sc_icookie;
+
+	struct rman		sc_rman;
+
+	int			sc_addr_cells;
+	int			sc_size_cells;
+
+	struct lbc_memrange	sc_range[LBC_DEV_MAX];
+	struct lbc_bank		sc_banks[LBC_DEV_MAX];
+
+	uint32_t		sc_ltesr;
+};
+
+struct lbc_devinfo {
+	struct ofw_bus_devinfo	di_ofw;
+	struct resource_list	di_res;
+	int			di_bank;
+};
+
+uint32_t	lbc_read_reg(device_t child, u_int off);
+void		lbc_write_reg(device_t child, u_int off, uint32_t val);
+
+#endif /* _MACHINE_LBC_H_ */


Property changes on: trunk/sys/powerpc/mpc85xx/lbc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/mpc85xx.c
===================================================================
--- trunk/sys/powerpc/mpc85xx/mpc85xx.c	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/mpc85xx.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,183 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008 Semihalf, Rafal Jaworowski
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mpc85xx/mpc85xx.c 265996 2014-05-14 00:51:26Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/pio.h>
+#include <machine/spr.h>
+
+#include <dev/fdt/fdt_common.h>
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+/*
+ * MPC85xx system specific routines
+ */
+
+uint32_t
+ccsr_read4(uintptr_t addr)
+{
+	volatile uint32_t *ptr = (void *)addr;
+
+	return (*ptr);
+}
+
+void
+ccsr_write4(uintptr_t addr, uint32_t val)
+{
+	volatile uint32_t *ptr = (void *)addr;
+
+	*ptr = val;
+	powerpc_iomb();
+}
+
+int
+law_getmax(void)
+{
+	uint32_t ver;
+
+	ver = SVR_VER(mfspr(SPR_SVR));
+	if (ver == SVR_MPC8555E || ver == SVR_MPC8555)
+		return (8);
+	if (ver == SVR_MPC8548E || ver == SVR_MPC8548 ||
+	    ver == SVR_MPC8533E || ver == SVR_MPC8533)
+		return (10);
+
+	return (12);
+}
+
+#define	_LAW_SR(trgt,size)	(0x80000000 | (trgt << 20) | (ffsl(size) - 2))
+#define	_LAW_BAR(addr)		(addr >> 12)
+
+int
+law_enable(int trgt, u_long addr, u_long size)
+{
+	uint32_t bar, sr;
+	int i, law_max;
+
+	if (size == 0)
+		return (0);
+
+	law_max = law_getmax();
+	bar = _LAW_BAR(addr);
+	sr = _LAW_SR(trgt, size);
+
+	/* Bail if already programmed. */
+	for (i = 0; i < law_max; i++)
+		if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
+		    bar == ccsr_read4(OCP85XX_LAWBAR(i)))
+			return (0);
+
+	/* Find an unused access window. */
+	for (i = 0; i < law_max; i++)
+		if ((ccsr_read4(OCP85XX_LAWSR(i)) & 0x80000000) == 0)
+			break;
+
+	if (i == law_max)
+		return (ENOSPC);
+
+	ccsr_write4(OCP85XX_LAWBAR(i), bar);
+	ccsr_write4(OCP85XX_LAWSR(i), sr);
+	return (0);
+}
+
+int
+law_disable(int trgt, u_long addr, u_long size)
+{
+	uint32_t bar, sr;
+	int i, law_max;
+
+	law_max = law_getmax();
+	bar = _LAW_BAR(addr);
+	sr = _LAW_SR(trgt, size);
+
+	/* Find and disable requested LAW. */
+	for (i = 0; i < law_max; i++)
+		if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
+		    bar == ccsr_read4(OCP85XX_LAWBAR(i))) {
+			ccsr_write4(OCP85XX_LAWBAR(i), 0);
+			ccsr_write4(OCP85XX_LAWSR(i), 0);
+			return (0);
+		}
+
+	return (ENOENT);
+}
+
+int
+law_pci_target(struct resource *res, int *trgt_mem, int *trgt_io)
+{
+	u_long start;
+	uint32_t ver;
+	int trgt, rv;
+
+	ver = SVR_VER(mfspr(SPR_SVR));
+
+	start = rman_get_start(res) & 0xf000;
+
+	rv = 0;
+	trgt = -1;
+	switch (start) {
+	case 0x8000:
+		trgt = 0;
+		break;
+	case 0x9000:
+		trgt = 1;
+		break;
+	case 0xa000:
+		if (ver == SVR_MPC8548E || ver == SVR_MPC8548)
+			trgt = 3;
+		else
+			trgt = 2;
+		break;
+	case 0xb000:
+		if (ver == SVR_MPC8548E || ver == SVR_MPC8548)
+			rv = EINVAL;
+		else
+			trgt = 3;
+		break;
+	default:
+		rv = ENXIO;
+	}
+	if (rv == 0) {
+		*trgt_mem = trgt;
+		*trgt_io = trgt;
+	}
+	return (rv);
+}
+


Property changes on: trunk/sys/powerpc/mpc85xx/mpc85xx.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/mpc85xx.h
===================================================================
--- trunk/sys/powerpc/mpc85xx/mpc85xx.h	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/mpc85xx.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,88 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008 Semihalf, Rafal Jaworowski
+ * Copyright 2006 by Juniper Networks.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/mpc85xx/mpc85xx.h 266003 2014-05-14 04:14:58Z ian $
+ */
+
+#ifndef _MPC85XX_H_
+#define _MPC85XX_H_
+
+/*
+ * Configuration control and status registers
+ */
+extern vm_offset_t		ccsrbar_va;
+#define CCSRBAR_VA		ccsrbar_va
+#define	OCP85XX_CCSRBAR		(CCSRBAR_VA + 0x0)
+#define	OCP85XX_BPTR		(CCSRBAR_VA + 0x20)
+
+/*
+ * E500 Coherency Module registers
+ */
+#define	OCP85XX_EEBPCR		(CCSRBAR_VA + 0x1010)
+
+/*
+ * Local access registers
+ */
+#define	OCP85XX_LAWBAR(n)	(CCSRBAR_VA + 0xc08 + 0x20 * (n))
+#define	OCP85XX_LAWSR(n)	(CCSRBAR_VA + 0xc10 + 0x20 * (n))
+
+#define	OCP85XX_TGTIF_LBC	4
+#define	OCP85XX_TGTIF_RAM_INTL	11
+#define	OCP85XX_TGTIF_RIO	12
+#define	OCP85XX_TGTIF_RAM1	15
+#define	OCP85XX_TGTIF_RAM2	22
+
+/*
+ * L2 cache registers
+ */
+#define OCP85XX_L2CTL		(CCSRBAR_VA + 0x20000)
+
+/*
+ * Power-On Reset configuration
+ */
+#define	OCP85XX_PORDEVSR	(CCSRBAR_VA + 0xe000c)
+#define OCP85XX_PORDEVSR_IO_SEL	0x00780000
+#define OCP85XX_PORDEVSR_IO_SEL_SHIFT 19
+
+#define	OCP85XX_PORDEVSR2	(CCSRBAR_VA + 0xe0014)
+
+/*
+ * Status Registers.
+ */
+#define	OCP85XX_RSTCR		(CCSRBAR_VA + 0xe00b0)
+
+/*
+ * Prototypes.
+ */
+uint32_t ccsr_read4(uintptr_t addr);
+void ccsr_write4(uintptr_t addr, uint32_t val);
+int law_enable(int trgt, u_long addr, u_long size);
+int law_disable(int trgt, u_long addr, u_long size);
+int law_getmax(void);
+int law_pci_target(struct resource *, int *, int *);
+
+#endif /* _MPC85XX_H_ */


Property changes on: trunk/sys/powerpc/mpc85xx/mpc85xx.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/pci_mpc85xx.c
===================================================================
--- trunk/sys/powerpc/mpc85xx/pci_mpc85xx.c	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/pci_mpc85xx.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,828 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2006-2007 by Juniper Networks.
+ * Copyright 2008 Semihalf.
+ * Copyright 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Semihalf
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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. 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.
+ *
+ * From: FreeBSD: src/sys/powerpc/mpc85xx/pci_ocp.c,v 1.9 2010/03/23 23:46:28 marcel
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mpc85xx/pci_mpc85xx.c 266160 2014-05-15 17:30:16Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ktr.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/endian.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
+
+#include <powerpc/ofw/ofw_pci.h>
+
+#include "ofw_bus_if.h"
+#include "pcib_if.h"
+
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+#define	REG_CFG_ADDR	0x0000
+#define	CONFIG_ACCESS_ENABLE	0x80000000
+
+#define	REG_CFG_DATA	0x0004
+#define	REG_INT_ACK	0x0008
+
+#define	REG_POTAR(n)	(0x0c00 + 0x20 * (n))
+#define	REG_POTEAR(n)	(0x0c04 + 0x20 * (n))
+#define	REG_POWBAR(n)	(0x0c08 + 0x20 * (n))
+#define	REG_POWAR(n)	(0x0c10 + 0x20 * (n))
+
+#define	REG_PITAR(n)	(0x0e00 - 0x20 * (n))
+#define	REG_PIWBAR(n)	(0x0e08 - 0x20 * (n))
+#define	REG_PIWBEAR(n)	(0x0e0c - 0x20 * (n))
+#define	REG_PIWAR(n)	(0x0e10 - 0x20 * (n))
+
+#define	REG_PEX_MES_DR	0x0020
+#define	REG_PEX_MES_IER	0x0028
+#define	REG_PEX_ERR_DR	0x0e00
+#define	REG_PEX_ERR_EN	0x0e08
+
+#define PCIR_LTSSM	0x404
+#define LTSSM_STAT_L0	0x16
+
+#define	DEVFN(b, s, f)	((b << 16) | (s << 8) | f)
+
+struct fsl_pcib_softc {
+	struct ofw_pci_softc pci_sc;
+	device_t	sc_dev;
+
+	int		sc_iomem_target;
+	bus_addr_t	sc_iomem_alloc, sc_iomem_start, sc_iomem_end;
+	int		sc_ioport_target;
+	bus_addr_t	sc_ioport_alloc, sc_ioport_start, sc_ioport_end;
+
+	struct resource *sc_res;
+	bus_space_handle_t sc_bsh;
+	bus_space_tag_t	sc_bst;
+	int		sc_rid;
+
+	int		sc_busnr;
+	int		sc_pcie;
+	uint8_t		sc_pcie_capreg;		/* PCI-E Capability Reg Set */
+
+	/* Devices that need special attention. */
+	int		sc_devfn_tundra;
+	int		sc_devfn_via_ide;
+};
+
+/* Local forward declerations. */
+static uint32_t fsl_pcib_cfgread(struct fsl_pcib_softc *, u_int, u_int, u_int,
+    u_int, int);
+static void fsl_pcib_cfgwrite(struct fsl_pcib_softc *, u_int, u_int, u_int,
+    u_int, uint32_t, int);
+static int fsl_pcib_decode_win(phandle_t, struct fsl_pcib_softc *);
+static void fsl_pcib_err_init(device_t);
+static void fsl_pcib_inbound(struct fsl_pcib_softc *, int, int, u_long,
+    u_long, u_long);
+static int fsl_pcib_init(struct fsl_pcib_softc *, int, int);
+static void fsl_pcib_outbound(struct fsl_pcib_softc *, int, int, u_long,
+    u_long, u_long);
+
+/* Forward declerations. */
+static int fsl_pcib_attach(device_t);
+static int fsl_pcib_detach(device_t);
+static int fsl_pcib_probe(device_t);
+
+static int fsl_pcib_maxslots(device_t);
+static uint32_t fsl_pcib_read_config(device_t, u_int, u_int, u_int, u_int, int);
+static void fsl_pcib_write_config(device_t, u_int, u_int, u_int, u_int,
+    uint32_t, int);
+
+/* Configuration r/w mutex. */
+struct mtx pcicfg_mtx;
+static int mtx_initialized = 0;
+
+/*
+ * Bus interface definitions.
+ */
+static device_method_t fsl_pcib_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		fsl_pcib_probe),
+	DEVMETHOD(device_attach,	fsl_pcib_attach),
+	DEVMETHOD(device_detach,	fsl_pcib_detach),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_maxslots,	fsl_pcib_maxslots),
+	DEVMETHOD(pcib_read_config,	fsl_pcib_read_config),
+	DEVMETHOD(pcib_write_config,	fsl_pcib_write_config),
+
+	DEVMETHOD_END
+};
+
+static devclass_t fsl_pcib_devclass;
+
+DEFINE_CLASS_1(pcib, fsl_pcib_driver, fsl_pcib_methods,
+    sizeof(struct fsl_pcib_softc), ofw_pci_driver);
+DRIVER_MODULE(pcib, ofwbus, fsl_pcib_driver, fsl_pcib_devclass, 0, 0);
+
+static int
+fsl_pcib_probe(device_t dev)
+{
+
+	if (ofw_bus_get_type(dev) == NULL ||
+	    strcmp(ofw_bus_get_type(dev), "pci") != 0)
+		return (ENXIO);
+
+	if (!(ofw_bus_is_compatible(dev, "fsl,mpc8540-pci") ||
+	    ofw_bus_is_compatible(dev, "fsl,mpc8548-pcie")))
+		return (ENXIO);
+
+	device_set_desc(dev, "Freescale Integrated PCI/PCI-E Controller");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+fsl_pcib_attach(device_t dev)
+{
+	struct fsl_pcib_softc *sc;
+	phandle_t node;
+	uint32_t cfgreg;
+	int maxslot, error;
+	uint8_t ltssm, capptr;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+
+	sc->sc_rid = 0;
+	sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
+	    RF_ACTIVE);
+	if (sc->sc_res == NULL) {
+		device_printf(dev, "could not map I/O memory\n");
+		return (ENXIO);
+	}
+	sc->sc_bst = rman_get_bustag(sc->sc_res);
+	sc->sc_bsh = rman_get_bushandle(sc->sc_res);
+	sc->sc_busnr = 0;
+
+	if (!mtx_initialized) {
+		mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
+		mtx_initialized = 1;
+	}
+
+	cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_VENDOR, 2);
+	if (cfgreg != 0x1057 && cfgreg != 0x1957)
+		goto err;
+
+	capptr = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_CAP_PTR, 1);
+	while (capptr != 0) {
+		cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, capptr, 2);
+		switch (cfgreg & 0xff) {
+		case PCIY_PCIX:
+			break;
+		case PCIY_EXPRESS:
+			sc->sc_pcie = 1;
+			sc->sc_pcie_capreg = capptr;
+			break;
+		}
+		capptr = (cfgreg >> 8) & 0xff;
+	}
+
+	node = ofw_bus_get_node(dev);
+
+	/*
+	 * Initialize generic OF PCI interface (ranges, etc.)
+	 */
+
+	error = ofw_pci_init(dev);
+	if (error)
+		return (error);
+
+	/*
+	 * Configure decode windows for PCI(E) access.
+	 */
+	if (fsl_pcib_decode_win(node, sc) != 0)
+		goto err;
+
+	cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_COMMAND, 2);
+	cfgreg |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
+	    PCIM_CMD_PORTEN;
+	fsl_pcib_cfgwrite(sc, 0, 0, 0, PCIR_COMMAND, cfgreg, 2);
+
+	sc->sc_devfn_tundra = -1;
+	sc->sc_devfn_via_ide = -1;
+
+
+	/*
+	 * Scan bus using firmware configured, 0 based bus numbering.
+	 */
+	sc->sc_busnr = 0;
+	maxslot = (sc->sc_pcie) ? 0 : PCI_SLOTMAX;
+	fsl_pcib_init(sc, sc->sc_busnr, maxslot);
+
+	if (sc->sc_pcie) {
+		ltssm = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_LTSSM, 1);
+		if (ltssm < LTSSM_STAT_L0) {
+			if (bootverbose)
+				printf("PCI %d: no PCIE link, skipping\n",
+				    device_get_unit(dev));
+			return (0);
+		}
+	}
+
+	fsl_pcib_err_init(dev);
+
+	return (ofw_pci_attach(dev));
+
+err:
+	return (ENXIO);
+}
+
+static uint32_t
+fsl_pcib_cfgread(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
+    u_int reg, int bytes)
+{
+	uint32_t addr, data;
+
+	if (bus == sc->sc_busnr - 1)
+		bus = 0;
+
+	addr = CONFIG_ACCESS_ENABLE;
+	addr |= (bus & 0xff) << 16;
+	addr |= (slot & 0x1f) << 11;
+	addr |= (func & 0x7) << 8;
+	addr |= reg & 0xfc;
+	if (sc->sc_pcie)
+		addr |= (reg & 0xf00) << 16;
+
+	mtx_lock_spin(&pcicfg_mtx);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr);
+
+	switch (bytes) {
+	case 1:
+		data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
+		    REG_CFG_DATA + (reg & 3));
+		break;
+	case 2:
+		data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh,
+		    REG_CFG_DATA + (reg & 2)));
+		break;
+	case 4:
+		data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+		    REG_CFG_DATA));
+		break;
+	default:
+		data = ~0;
+		break;
+	}
+	mtx_unlock_spin(&pcicfg_mtx);
+	return (data);
+}
+
+static void
+fsl_pcib_cfgwrite(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
+    u_int reg, uint32_t data, int bytes)
+{
+	uint32_t addr;
+
+	if (bus == sc->sc_busnr - 1)
+		bus = 0;
+
+	addr = CONFIG_ACCESS_ENABLE;
+	addr |= (bus & 0xff) << 16;
+	addr |= (slot & 0x1f) << 11;
+	addr |= (func & 0x7) << 8;
+	addr |= reg & 0xfc;
+	if (sc->sc_pcie)
+		addr |= (reg & 0xf00) << 16;
+
+	mtx_lock_spin(&pcicfg_mtx);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr);
+
+	switch (bytes) {
+	case 1:
+		bus_space_write_1(sc->sc_bst, sc->sc_bsh,
+		    REG_CFG_DATA + (reg & 3), data);
+		break;
+	case 2:
+		bus_space_write_2(sc->sc_bst, sc->sc_bsh,
+		    REG_CFG_DATA + (reg & 2), htole16(data));
+		break;
+	case 4:
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+		    REG_CFG_DATA, htole32(data));
+		break;
+	}
+	mtx_unlock_spin(&pcicfg_mtx);
+}
+
+#if 0
+static void
+dump(struct fsl_pcib_softc *sc)
+{
+	unsigned int i;
+
+#define RD(o)	bus_space_read_4(sc->sc_bst, sc->sc_bsh, o)
+	for (i = 0; i < 5; i++) {
+		printf("POTAR%u  =0x%08x\n", i, RD(REG_POTAR(i)));
+		printf("POTEAR%u =0x%08x\n", i, RD(REG_POTEAR(i)));
+		printf("POWBAR%u =0x%08x\n", i, RD(REG_POWBAR(i)));
+		printf("POWAR%u  =0x%08x\n", i, RD(REG_POWAR(i)));
+	}
+	printf("\n");
+	for (i = 1; i < 4; i++) {
+		printf("PITAR%u  =0x%08x\n", i, RD(REG_PITAR(i)));
+		printf("PIWBAR%u =0x%08x\n", i, RD(REG_PIWBAR(i)));
+		printf("PIWBEAR%u=0x%08x\n", i, RD(REG_PIWBEAR(i)));
+		printf("PIWAR%u  =0x%08x\n", i, RD(REG_PIWAR(i)));
+	}
+	printf("\n");
+#undef RD
+
+	for (i = 0; i < 0x48; i += 4) {
+		printf("cfg%02x=0x%08x\n", i, fsl_pcib_cfgread(sc, 0, 0, 0,
+		    i, 4));
+	}
+}
+#endif
+
+static int
+fsl_pcib_maxslots(device_t dev)
+{
+	struct fsl_pcib_softc *sc = device_get_softc(dev);
+
+	return ((sc->sc_pcie) ? 0 : PCI_SLOTMAX);
+}
+
+static uint32_t
+fsl_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
+    u_int reg, int bytes)
+{
+	struct fsl_pcib_softc *sc = device_get_softc(dev);
+	u_int devfn;
+
+	if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10)
+		return (~0);
+	devfn = DEVFN(bus, slot, func);
+	if (devfn == sc->sc_devfn_tundra)
+		return (~0);
+	if (devfn == sc->sc_devfn_via_ide && reg == PCIR_INTPIN)
+		return (1);
+	return (fsl_pcib_cfgread(sc, bus, slot, func, reg, bytes));
+}
+
+static void
+fsl_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+    u_int reg, uint32_t val, int bytes)
+{
+	struct fsl_pcib_softc *sc = device_get_softc(dev);
+
+	if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10)
+		return;
+	fsl_pcib_cfgwrite(sc, bus, slot, func, reg, val, bytes);
+}
+
+static void
+fsl_pcib_init_via(struct fsl_pcib_softc *sc, uint16_t device, int bus,
+    int slot, int fn)
+{
+
+	if (device == 0x0686) {
+		fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x52, 0x34, 1);
+		fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x77, 0x00, 1);
+		fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x83, 0x98, 1);
+		fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x85, 0x03, 1);
+	} else if (device == 0x0571) {
+		sc->sc_devfn_via_ide = DEVFN(bus, slot, fn);
+		fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x40, 0x0b, 1);
+	}
+}
+
+static int
+fsl_pcib_init_bar(struct fsl_pcib_softc *sc, int bus, int slot, int func,
+    int barno)
+{
+	bus_addr_t *allocp;
+	uint32_t addr, mask, size;
+	int reg, width;
+
+	reg = PCIR_BAR(barno);
+
+	if (DEVFN(bus, slot, func) == sc->sc_devfn_via_ide) {
+		switch (barno) {
+		case 0:	addr = 0x1f0; break;
+		case 1: addr = 0x3f4; break;
+		case 2: addr = 0x170; break;
+		case 3: addr = 0x374; break;
+		case 4: addr = 0xcc0; break;
+		default: return (1);
+		}
+		fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
+		return (1);
+	}
+
+	fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4);
+	size = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, reg, 4);
+	if (size == 0)
+		return (1);
+	width = ((size & 7) == 4) ? 2 : 1;
+
+	if (size & 1) {		/* I/O port */
+		allocp = &sc->sc_ioport_alloc;
+		size &= ~3;
+		if ((size & 0xffff0000) == 0)
+			size |= 0xffff0000;
+	} else {		/* memory */
+		allocp = &sc->sc_iomem_alloc;
+		size &= ~15;
+	}
+	mask = ~size;
+	size = mask + 1;
+	/* Sanity check (must be a power of 2). */
+	if (size & mask)
+		return (width);
+
+	addr = (*allocp + mask) & ~mask;
+	*allocp = addr + size;
+
+	if (bootverbose)
+		printf("PCI %u:%u:%u:%u: reg %x: size=%08x: addr=%08x\n",
+		    device_get_unit(sc->sc_dev), bus, slot, func, reg,
+		    size, addr);
+
+	fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
+	if (width == 2)
+		fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg + 4,
+		    0, 4);
+	return (width);
+}
+
+static int
+fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int maxslot)
+{
+	int secbus;
+	int old_pribus, old_secbus, old_subbus;
+	int new_pribus, new_secbus, new_subbus;
+	int slot, func, maxfunc;
+	int bar, maxbar;
+	uint16_t vendor, device;
+	uint8_t command, hdrtype, class, subclass;
+
+	secbus = bus;
+	for (slot = 0; slot <= maxslot; slot++) {
+		maxfunc = 0;
+		for (func = 0; func <= maxfunc; func++) {
+			hdrtype = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+			    func, PCIR_HDRTYPE, 1);
+
+			if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
+				continue;
+
+			if (func == 0 && (hdrtype & PCIM_MFDEV))
+				maxfunc = PCI_FUNCMAX;
+
+			vendor = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+			    func, PCIR_VENDOR, 2);
+			device = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+			    func, PCIR_DEVICE, 2);
+
+			if (vendor == 0x1957 && device == 0x3fff) {
+				sc->sc_devfn_tundra = DEVFN(bus, slot, func);
+				continue;
+			}
+
+			command = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+			    func, PCIR_COMMAND, 1);
+			command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_COMMAND, command, 1);
+
+			if (vendor == 0x1106)
+				fsl_pcib_init_via(sc, device, bus, slot, func);
+
+			/* Program the base address registers. */
+			maxbar = (hdrtype & PCIM_HDRTYPE) ? 1 : 6;
+			bar = 0;
+			while (bar < maxbar)
+				bar += fsl_pcib_init_bar(sc, bus, slot, func,
+				    bar);
+
+			/* Put a placeholder interrupt value */
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_INTLINE, PCI_INVALID_IRQ, 1);
+
+			command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_COMMAND, command, 1);
+
+			/*
+			 * Handle PCI-PCI bridges
+			 */
+			class = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+			    func, PCIR_CLASS, 1);
+			subclass = fsl_pcib_read_config(sc->sc_dev, bus, slot,
+			    func, PCIR_SUBCLASS, 1);
+
+			/* Allow only proper PCI-PCI briges */
+			if (class != PCIC_BRIDGE)
+				continue;
+			if (subclass != PCIS_BRIDGE_PCI)
+				continue;
+
+			secbus++;
+
+			/* Program I/O decoder. */
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_IOBASEL_1, sc->sc_ioport_start >> 8, 1);
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_IOLIMITL_1, sc->sc_ioport_end >> 8, 1);
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_IOBASEH_1, sc->sc_ioport_start >> 16, 2);
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_IOLIMITH_1, sc->sc_ioport_end >> 16, 2);
+
+			/* Program (non-prefetchable) memory decoder. */
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_MEMBASE_1, sc->sc_iomem_start >> 16, 2);
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_MEMLIMIT_1, sc->sc_iomem_end >> 16, 2);
+
+			/* Program prefetchable memory decoder. */
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_PMBASEL_1, 0x0010, 2);
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_PMLIMITL_1, 0x000f, 2);
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_PMBASEH_1, 0x00000000, 4);
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_PMLIMITH_1, 0x00000000, 4);
+
+			/* Read currect bus register configuration */
+			old_pribus = fsl_pcib_read_config(sc->sc_dev, bus,
+			    slot, func, PCIR_PRIBUS_1, 1);
+			old_secbus = fsl_pcib_read_config(sc->sc_dev, bus,
+			    slot, func, PCIR_SECBUS_1, 1);
+			old_subbus = fsl_pcib_read_config(sc->sc_dev, bus,
+			    slot, func, PCIR_SUBBUS_1, 1);
+
+			if (bootverbose)
+				printf("PCI: reading firmware bus numbers for "
+				    "secbus = %d (bus/sec/sub) = (%d/%d/%d)\n",
+				    secbus, old_pribus, old_secbus, old_subbus);
+
+			new_pribus = bus;
+			new_secbus = secbus;
+
+			secbus = fsl_pcib_init(sc, secbus,
+			    (subclass == PCIS_BRIDGE_PCI) ? PCI_SLOTMAX : 0);
+
+			new_subbus = secbus;
+
+			if (bootverbose)
+				printf("PCI: translate firmware bus numbers "
+				    "for secbus %d (%d/%d/%d) -> (%d/%d/%d)\n",
+				    secbus, old_pribus, old_secbus, old_subbus,
+				    new_pribus, new_secbus, new_subbus);
+
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_PRIBUS_1, new_pribus, 1);
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_SECBUS_1, new_secbus, 1);
+			fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
+			    PCIR_SUBBUS_1, new_subbus, 1);
+		}
+	}
+
+	return (secbus);
+}
+
+static void
+fsl_pcib_inbound(struct fsl_pcib_softc *sc, int wnd, int tgt, u_long start,
+    u_long size, u_long pci_start)
+{
+	uint32_t attr, bar, tar;
+
+	KASSERT(wnd > 0, ("%s: inbound window 0 is invalid", __func__));
+
+	switch (tgt) {
+	/* XXX OCP85XX_TGTIF_RAM2, OCP85XX_TGTIF_RAM_INTL should be handled */
+	case OCP85XX_TGTIF_RAM1:
+		attr = 0xa0f55000 | (ffsl(size) - 2);
+		break;
+	default:
+		attr = 0;
+		break;
+	}
+	tar = start >> 12;
+	bar = pci_start >> 12;
+
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PITAR(wnd), tar);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBEAR(wnd), 0);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBAR(wnd), bar);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWAR(wnd), attr);
+}
+
+static void
+fsl_pcib_outbound(struct fsl_pcib_softc *sc, int wnd, int res, u_long start,
+    u_long size, u_long pci_start)
+{
+	uint32_t attr, bar, tar;
+
+	switch (res) {
+	case SYS_RES_MEMORY:
+		attr = 0x80044000 | (ffsl(size) - 2);
+		break;
+	case SYS_RES_IOPORT:
+		attr = 0x80088000 | (ffsl(size) - 2);
+		break;
+	default:
+		attr = 0x0004401f;
+		break;
+	}
+	bar = start >> 12;
+	tar = pci_start >> 12;
+
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTAR(wnd), tar);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTEAR(wnd), 0);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWBAR(wnd), bar);
+	bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWAR(wnd), attr);
+}
+
+
+static void
+fsl_pcib_err_init(device_t dev)
+{
+	struct fsl_pcib_softc *sc;
+	uint16_t sec_stat, dsr;
+	uint32_t dcr, err_en;
+
+	sc = device_get_softc(dev);
+
+	sec_stat = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_SECSTAT_1, 2);
+	if (sec_stat)
+		fsl_pcib_cfgwrite(sc, 0, 0, 0, PCIR_SECSTAT_1, 0xffff, 2);
+	if (sc->sc_pcie) {
+		/* Clear error bits */
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_MES_IER,
+		    0xffffffff);
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_MES_DR,
+		    0xffffffff);
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_DR,
+		    0xffffffff);
+
+		dsr = fsl_pcib_cfgread(sc, 0, 0, 0,
+		    sc->sc_pcie_capreg + PCIER_DEVICE_STA, 2);
+		if (dsr)
+			fsl_pcib_cfgwrite(sc, 0, 0, 0,
+			    sc->sc_pcie_capreg + PCIER_DEVICE_STA,
+			    0xffff, 2);
+
+		/* Enable all errors reporting */
+		err_en = 0x00bfff00;
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_EN,
+		    err_en);
+
+		/* Enable error reporting: URR, FER, NFER */
+		dcr = fsl_pcib_cfgread(sc, 0, 0, 0,
+		    sc->sc_pcie_capreg + PCIER_DEVICE_CTL, 4);
+		dcr |= PCIEM_CTL_URR_ENABLE | PCIEM_CTL_FER_ENABLE |
+		    PCIEM_CTL_NFER_ENABLE;
+		fsl_pcib_cfgwrite(sc, 0, 0, 0,
+		    sc->sc_pcie_capreg + PCIER_DEVICE_CTL, dcr, 4);
+	}
+}
+
+static int
+fsl_pcib_detach(device_t dev)
+{
+
+	if (mtx_initialized) {
+		mtx_destroy(&pcicfg_mtx);
+		mtx_initialized = 0;
+	}
+	return (bus_generic_detach(dev));
+}
+
+static int
+fsl_pcib_decode_win(phandle_t node, struct fsl_pcib_softc *sc)
+{
+	device_t dev;
+	int error, i, trgt;
+
+	dev = sc->sc_dev;
+
+	fsl_pcib_outbound(sc, 0, -1, 0, 0, 0);
+
+	/*
+	 * Configure LAW decode windows.
+	 */
+	error = law_pci_target(sc->sc_res, &sc->sc_iomem_target,
+	    &sc->sc_ioport_target);
+	if (error != 0) {
+		device_printf(dev, "could not retrieve PCI LAW target info\n");
+		return (error);
+	}
+
+	for (i = 0; i < sc->pci_sc.sc_nrange; i++) {
+		switch (sc->pci_sc.sc_range[i].pci_hi &
+		    OFW_PCI_PHYS_HI_SPACEMASK) {
+		case OFW_PCI_PHYS_HI_SPACE_CONFIG:
+			continue;
+		case OFW_PCI_PHYS_HI_SPACE_IO:
+			trgt = sc->sc_ioport_target;
+			fsl_pcib_outbound(sc, 2, SYS_RES_IOPORT,
+			    sc->pci_sc.sc_range[i].host,
+			    sc->pci_sc.sc_range[i].size,
+			    sc->pci_sc.sc_range[i].pci);
+			sc->sc_ioport_start = sc->pci_sc.sc_range[i].host;
+			sc->sc_ioport_end = sc->pci_sc.sc_range[i].host +
+			    sc->pci_sc.sc_range[i].size;
+			sc->sc_ioport_alloc = 0x1000 + sc->pci_sc.sc_range[i].pci;
+			break;
+		case OFW_PCI_PHYS_HI_SPACE_MEM32:
+		case OFW_PCI_PHYS_HI_SPACE_MEM64:
+			trgt = sc->sc_iomem_target;
+			fsl_pcib_outbound(sc, 1, SYS_RES_MEMORY,
+			    sc->pci_sc.sc_range[i].host,
+			    sc->pci_sc.sc_range[i].size,
+			    sc->pci_sc.sc_range[i].pci);
+			sc->sc_iomem_start = sc->pci_sc.sc_range[i].host;
+			sc->sc_iomem_end = sc->pci_sc.sc_range[i].host +
+			    sc->pci_sc.sc_range[i].size;
+			sc->sc_iomem_alloc = sc->pci_sc.sc_range[i].pci;
+			break;
+		default:
+			panic("Unknown range type %#x\n",
+			    sc->pci_sc.sc_range[i].pci_hi &
+			    OFW_PCI_PHYS_HI_SPACEMASK);
+		}
+		error = law_enable(trgt, sc->pci_sc.sc_range[i].host,
+		    sc->pci_sc.sc_range[i].size);
+		if (error != 0) {
+			device_printf(dev, "could not program LAW for range "
+			    "%d\n", i);
+			return (error);
+		}
+	}
+
+	/*
+	 * Set outbout and inbound windows.
+	 */
+	fsl_pcib_outbound(sc, 3, -1, 0, 0, 0);
+	fsl_pcib_outbound(sc, 4, -1, 0, 0, 0);
+
+	fsl_pcib_inbound(sc, 1, -1, 0, 0, 0);
+	fsl_pcib_inbound(sc, 2, -1, 0, 0, 0);
+	fsl_pcib_inbound(sc, 3, OCP85XX_TGTIF_RAM1, 0,
+	    2U * 1024U * 1024U * 1024U, 0);
+
+	return (0);
+}
+


Property changes on: trunk/sys/powerpc/mpc85xx/pci_mpc85xx.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/mpc85xx/platform_mpc85xx.c
===================================================================
--- trunk/sys/powerpc/mpc85xx/platform_mpc85xx.c	                        (rev 0)
+++ trunk/sys/powerpc/mpc85xx/platform_mpc85xx.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,410 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008-2012 Semihalf.
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/mpc85xx/platform_mpc85xx.c 266020 2014-05-14 14:17:51Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/hid.h>
+#include <machine/platform.h>
+#include <machine/platformvar.h>
+#include <machine/smp.h>
+#include <machine/spr.h>
+#include <machine/vmparam.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <powerpc/mpc85xx/mpc85xx.h>
+
+#include "platform_if.h"
+
+#ifdef SMP
+extern void *ap_pcpu;
+extern vm_paddr_t kernload;		/* Kernel physical load address */
+extern uint8_t __boot_page[];		/* Boot page body */
+extern uint32_t bp_ntlb1s;
+extern uint32_t bp_tlb1[];
+extern uint32_t bp_tlb1_end[];
+#endif
+
+extern uint32_t *bootinfo;
+vm_offset_t ccsrbar_va;
+
+static int cpu, maxcpu;
+
+static int mpc85xx_probe(platform_t);
+static int mpc85xx_attach(platform_t);
+static void mpc85xx_mem_regions(platform_t, struct mem_region *phys,
+    int *physsz, struct mem_region *avail, int *availsz);
+static u_long mpc85xx_timebase_freq(platform_t, struct cpuref *cpuref);
+static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref);
+static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref);
+static int mpc85xx_smp_get_bsp(platform_t, struct cpuref *cpuref);
+static int mpc85xx_smp_start_cpu(platform_t, struct pcpu *cpu);
+
+static void mpc85xx_reset(platform_t);
+
+static platform_method_t mpc85xx_methods[] = {
+	PLATFORMMETHOD(platform_probe,		mpc85xx_probe),
+	PLATFORMMETHOD(platform_attach,		mpc85xx_attach),
+	PLATFORMMETHOD(platform_mem_regions,	mpc85xx_mem_regions),
+	PLATFORMMETHOD(platform_timebase_freq,	mpc85xx_timebase_freq),
+
+	PLATFORMMETHOD(platform_smp_first_cpu,	mpc85xx_smp_first_cpu),
+	PLATFORMMETHOD(platform_smp_next_cpu,	mpc85xx_smp_next_cpu),
+	PLATFORMMETHOD(platform_smp_get_bsp,	mpc85xx_smp_get_bsp),
+	PLATFORMMETHOD(platform_smp_start_cpu,	mpc85xx_smp_start_cpu),
+
+	PLATFORMMETHOD(platform_reset,		mpc85xx_reset),
+
+	PLATFORMMETHOD_END
+};
+
+static platform_def_t mpc85xx_platform = {
+	"mpc85xx",
+	mpc85xx_methods,
+	0
+};
+
+PLATFORM_DEF(mpc85xx_platform);
+
+static int
+mpc85xx_probe(platform_t plat)
+{
+	u_int pvr = mfpvr() >> 16;
+
+	if ((pvr & 0xfff0) == FSL_E500v1)
+		return (BUS_PROBE_DEFAULT);
+
+	return (ENXIO);
+}
+
+static int
+mpc85xx_attach(platform_t plat)
+{
+	phandle_t cpus, child, ccsr;
+	const char *soc_name_guesses[] = {"/soc", "soc", NULL};
+	const char **name;
+	pcell_t ranges[6], acells, pacells, scells;
+	uint32_t sr;
+	uint64_t ccsrbar, ccsrsize;
+	int i, law_max, tgt;
+
+	if ((cpus = OF_finddevice("/cpus")) != -1) {
+		for (maxcpu = 0, child = OF_child(cpus); child != 0;
+		    child = OF_peer(child), maxcpu++)
+			;
+	} else
+		maxcpu = 1;
+
+	/*
+	 * Locate CCSR region. Irritatingly, there is no way to find it
+	 * unless you already know where it is. Try to infer its location
+	 * from the device tree.
+	 */
+
+	ccsr = -1;
+	for (name = soc_name_guesses; *name != NULL && ccsr == -1; name++)
+		ccsr = OF_finddevice(*name);
+	if (ccsr == -1) {
+		char type[64];
+
+	 	/* That didn't work. Search for devices of type "soc" */
+		child = OF_child(OF_peer(0));
+		for (OF_child(child); child != 0; child = OF_peer(child)) {
+			if (OF_getprop(child, "device_type", type, sizeof(type))
+			    <= 0)
+				continue;
+
+			if (strcmp(type, "soc") == 0) {
+				ccsr = child;
+				break;
+			}
+		}
+	}
+
+	if (ccsr == -1)
+		panic("Could not locate CCSR window!");
+
+	OF_getprop(ccsr, "#size-cells", &scells, sizeof(scells));
+	OF_getprop(ccsr, "#address-cells", &acells, sizeof(acells));
+	OF_searchprop(OF_parent(ccsr), "#address-cells", &pacells,
+	    sizeof(pacells));
+	OF_getprop(ccsr, "ranges", ranges, sizeof(ranges));
+	ccsrbar = ccsrsize = 0;
+	for (i = acells; i < acells + pacells; i++) {
+		ccsrbar <<= 32;
+		ccsrbar |= ranges[i];
+	}
+	for (i = acells + pacells; i < acells + pacells + scells; i++) {
+		ccsrsize <<= 32;
+		ccsrsize |= ranges[i];
+	}
+	ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize);
+
+	/*
+	 * Clear local access windows. Skip DRAM entries, so we don't shoot
+	 * ourselves in the foot.
+	 */
+	law_max = law_getmax();
+	for (i = 0; i < law_max; i++) {
+		sr = ccsr_read4(OCP85XX_LAWSR(i));
+		if ((sr & 0x80000000) == 0)
+			continue;
+		tgt = (sr & 0x01f00000) >> 20;
+		if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 ||
+		    tgt == OCP85XX_TGTIF_RAM_INTL)
+			continue;
+
+		ccsr_write4(OCP85XX_LAWSR(i), sr & 0x7fffffff);
+	}
+
+	return (0);
+}
+
+void
+mpc85xx_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
+    struct mem_region *avail, int *availsz)
+{
+
+	ofw_mem_regions(phys, physsz, avail, availsz);
+}
+
+static u_long
+mpc85xx_timebase_freq(platform_t plat, struct cpuref *cpuref)
+{
+	u_long ticks;
+	phandle_t cpus, child;
+	pcell_t freq;
+
+	if (bootinfo != NULL) {
+		if (bootinfo[0] == 1) {
+			/* Backward compatibility. See 8-STABLE. */
+			ticks = bootinfo[3] >> 3;
+		} else {
+			/* Compatibility with Juniper's loader. */
+			ticks = bootinfo[5] >> 3;
+		}
+	} else
+		ticks = 0;
+
+	if ((cpus = OF_finddevice("/cpus")) == -1)
+		goto out;
+
+	if ((child = OF_child(cpus)) == 0)
+		goto out;
+
+	switch (OF_getproplen(child, "timebase-frequency")) {
+	case 4:
+	{
+		uint32_t tbase;
+		OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase));
+		ticks = tbase;
+		return (ticks);
+	}
+	case 8:
+	{
+		uint64_t tbase;
+		OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase));
+		ticks = tbase;
+		return (ticks);
+	}
+	default:
+		break;
+	}
+
+	freq = 0;
+	if (OF_getprop(child, "bus-frequency", (void *)&freq,
+	    sizeof(freq)) <= 0)
+		goto out;
+
+	/*
+	 * Time Base and Decrementer are updated every 8 CCB bus clocks.
+	 * HID0[SEL_TBCLK] = 0
+	 */
+	if (freq != 0)
+		ticks = freq / 8;
+
+out:
+	if (ticks <= 0)
+		panic("Unable to determine timebase frequency!");
+
+	return (ticks);
+}
+
+static int
+mpc85xx_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
+{
+
+	cpu = 0;
+	cpuref->cr_cpuid = cpu;
+	cpuref->cr_hwref = cpuref->cr_cpuid;
+	if (bootverbose)
+		printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid);
+	cpu++;
+
+	return (0);
+}
+
+static int
+mpc85xx_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
+{
+
+	if (cpu >= maxcpu)
+		return (ENOENT);
+
+	cpuref->cr_cpuid = cpu++;
+	cpuref->cr_hwref = cpuref->cr_cpuid;
+	if (bootverbose)
+		printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid);
+
+	return (0);
+}
+
+static int
+mpc85xx_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
+{
+
+	cpuref->cr_cpuid = mfspr(SPR_PIR);
+	cpuref->cr_hwref = cpuref->cr_cpuid;
+
+	return (0);
+}
+
+static int
+mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc)
+{
+#ifdef SMP
+	uint32_t *tlb1;
+	uint32_t bptr, eebpcr;
+	int i, timeout;
+
+	eebpcr = ccsr_read4(OCP85XX_EEBPCR);
+	if ((eebpcr & (1 << (pc->pc_cpuid + 24))) != 0) {
+		printf("SMP: CPU %d already out of hold-off state!\n",
+		    pc->pc_cpuid);
+		return (ENXIO);
+	}
+
+	ap_pcpu = pc;
+
+	i = 0;
+	tlb1 = bp_tlb1;
+	while (i < bp_ntlb1s && tlb1 < bp_tlb1_end) {
+		mtspr(SPR_MAS0, MAS0_TLBSEL(1) | MAS0_ESEL(i));
+		__asm __volatile("isync; tlbre");
+		tlb1[0] = mfspr(SPR_MAS1);
+		tlb1[1] = mfspr(SPR_MAS2);
+		tlb1[2] = mfspr(SPR_MAS3);
+		i++;
+		tlb1 += 3;
+	}
+	if (i < bp_ntlb1s)
+		bp_ntlb1s = i;
+
+	/*
+	 * Set BPTR to the physical address of the boot page
+	 */
+	bptr = ((uint32_t)__boot_page - KERNBASE) + kernload;
+	KASSERT((bptr & 0xfff) == 0,
+	    ("%s: boot page is not aligned (%#x)", __func__, bptr));
+	bptr = (bptr >> 12) | 0x80000000u;
+	ccsr_write4(OCP85XX_BPTR, bptr);
+	__asm __volatile("isync; msync");
+
+	/* Flush caches to have our changes hit DRAM. */
+	cpu_flush_dcache(__boot_page, 4096);
+
+	/*
+	 * Release AP from hold-off state
+	 */
+	eebpcr |= (1 << (pc->pc_cpuid + 24));
+	ccsr_write4(OCP85XX_EEBPCR, eebpcr);
+	__asm __volatile("isync; msync");
+
+	timeout = 500;
+	while (!pc->pc_awake && timeout--)
+		DELAY(1000);	/* wait 1ms */
+
+	/*
+	 * Disable boot page translation so that the 4K page at the default
+	 * address (= 0xfffff000) isn't permanently remapped and thus not
+	 * usable otherwise.
+	 */
+	ccsr_write4(OCP85XX_BPTR, 0);
+	__asm __volatile("isync; msync");
+
+	if (!pc->pc_awake)
+		printf("SMP: CPU %d didn't wake up.\n", pc->pc_cpuid);
+	return ((pc->pc_awake) ? 0 : EBUSY);
+#else
+	/* No SMP support */
+	return (ENXIO);
+#endif
+}
+
+static void
+mpc85xx_reset(platform_t plat)
+{
+
+	/*
+	 * Try the dedicated reset register first.
+	 * If the SoC doesn't have one, we'll fall
+	 * back to using the debug control register.
+	 */
+	ccsr_write4(OCP85XX_RSTCR, 2);
+
+	/* Clear DBCR0, disables debug interrupts and events. */
+	mtspr(SPR_DBCR0, 0);
+	__asm __volatile("isync");
+
+	/* Enable Debug Interrupts in MSR. */
+	mtmsr(mfmsr() | PSL_DE);
+
+	/* Enable debug interrupts and issue reset. */
+	mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM | DBCR0_RST_SYSTEM);
+
+	printf("Reset failed...\n");
+	while (1)
+		;
+}
+


Property changes on: trunk/sys/powerpc/mpc85xx/platform_mpc85xx.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/ofw_machdep.c
===================================================================
--- trunk/sys/powerpc/ofw/ofw_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/ofw/ofw_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,590 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ * $NetBSD: ofw_machdep.c,v 1.5 2000/05/23 13:25:43 tsubai Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ofw/ofw_machdep.c 266020 2014-05-14 14:17:51Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/disk.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/smp.h>
+#include <sys/stat.h>
+
+#include <net/ethernet.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_page.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+#include <machine/platform.h>
+#include <machine/ofw_machdep.h>
+#include <machine/trap.h>
+
+#ifdef AIM
+extern register_t ofmsr[5];
+extern void	*openfirmware_entry;
+static void	*fdt;
+int		ofw_real_mode;
+extern char     save_trap_init[0x2f00];          /* EXC_LAST */
+char            save_trap_of[0x2f00];            /* EXC_LAST */
+
+int		ofwcall(void *);
+static int	openfirmware(void *args);
+
+__inline void
+ofw_save_trap_vec(char *save_trap_vec)
+{
+	if (!ofw_real_mode)
+                return;
+
+	bcopy((void *)EXC_RST, save_trap_vec, EXC_LAST - EXC_RST);
+}
+
+static __inline void
+ofw_restore_trap_vec(char *restore_trap_vec)
+{
+	if (!ofw_real_mode)
+                return;
+
+	bcopy(restore_trap_vec, (void *)EXC_RST, EXC_LAST - EXC_RST);
+	__syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
+}
+
+/*
+ * Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback.
+ */
+register_t	ofw_sprg0_save;
+
+static __inline void
+ofw_sprg_prepare(void)
+{
+	if (ofw_real_mode)
+		return;
+	
+	/*
+	 * Assume that interrupt are disabled at this point, or
+	 * SPRG1-3 could be trashed
+	 */
+	__asm __volatile("mfsprg0 %0\n\t"
+			 "mtsprg0 %1\n\t"
+	    		 "mtsprg1 %2\n\t"
+	    		 "mtsprg2 %3\n\t"
+			 "mtsprg3 %4\n\t"
+			 : "=&r"(ofw_sprg0_save)
+			 : "r"(ofmsr[1]),
+			 "r"(ofmsr[2]),
+			 "r"(ofmsr[3]),
+			 "r"(ofmsr[4]));
+}
+
+static __inline void
+ofw_sprg_restore(void)
+{
+#if 0
+	if (ofw_real_mode)
+		return;
+#endif
+	
+	/*
+	 * Note that SPRG1-3 contents are irrelevant. They are scratch
+	 * registers used in the early portion of trap handling when
+	 * interrupts are disabled.
+	 *
+	 * PCPU data cannot be used until this routine is called !
+	 */
+	__asm __volatile("mtsprg0 %0" :: "r"(ofw_sprg0_save));
+}
+#endif
+
+static int
+parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
+{
+	cell_t address_cells, size_cells;
+	cell_t OFmem[4 * PHYS_AVAIL_SZ];
+	int sz, i, j;
+	int apple_hack_mode;
+	phandle_t phandle;
+
+	sz = 0;
+	apple_hack_mode = 0;
+
+	/*
+	 * Get #address-cells from root node, defaulting to 1 if it cannot
+	 * be found.
+	 */
+	phandle = OF_finddevice("/");
+	if (OF_getprop(phandle, "#address-cells", &address_cells, 
+	    sizeof(address_cells)) < (ssize_t)sizeof(address_cells))
+		address_cells = 1;
+	if (OF_getprop(phandle, "#size-cells", &size_cells, 
+	    sizeof(size_cells)) < (ssize_t)sizeof(size_cells))
+		size_cells = 1;
+
+	/*
+	 * Get memory.
+	 */
+	if (node == -1 || (sz = OF_getprop(node, prop,
+	    OFmem, sizeof(OFmem))) <= 0)
+		panic("Physical memory map not found");
+
+	i = 0;
+	j = 0;
+	while (i < sz/sizeof(cell_t)) {
+	      #ifndef __powerpc64__
+		/* On 32-bit PPC, ignore regions starting above 4 GB */
+		if (address_cells > 1 && OFmem[i] > 0) {
+			i += address_cells + size_cells;
+			continue;
+		}
+	      #endif
+
+		output[j].mr_start = OFmem[i++];
+		if (address_cells == 2) {
+			#ifdef __powerpc64__
+			output[j].mr_start <<= 32;
+			#endif
+			output[j].mr_start += OFmem[i++];
+		}
+			
+		output[j].mr_size = OFmem[i++];
+		if (size_cells == 2) {
+			#ifdef __powerpc64__
+			output[j].mr_size <<= 32;
+			#endif
+			output[j].mr_size += OFmem[i++];
+		}
+
+	      #ifndef __powerpc64__
+		/*
+		 * Check for memory regions extending above 32-bit
+		 * memory space, and restrict them to stay there.
+		 */
+		if (((uint64_t)output[j].mr_start +
+		    (uint64_t)output[j].mr_size) >
+		    BUS_SPACE_MAXADDR_32BIT) {
+			output[j].mr_size = BUS_SPACE_MAXADDR_32BIT -
+			    output[j].mr_start;
+		}
+	      #endif
+
+		j++;
+	}
+	sz = j*sizeof(output[0]);
+
+	return (sz);
+}
+
+/*
+ * This is called during powerpc_init, before the system is really initialized.
+ * It shall provide the total and the available regions of RAM.
+ * Both lists must have a zero-size entry as terminator.
+ * The available regions need not take the kernel into account, but needs
+ * to provide space for two additional entry beyond the terminating one.
+ */
+void
+ofw_mem_regions(struct mem_region *memp, int *memsz,
+		struct mem_region *availp, int *availsz)
+{
+	phandle_t phandle;
+	int asz, msz;
+	int res;
+	char name[31];
+
+	asz = msz = 0;
+
+	/*
+	 * Get memory from all the /memory nodes.
+	 */
+	for (phandle = OF_child(OF_peer(0)); phandle != 0;
+	    phandle = OF_peer(phandle)) {
+		if (OF_getprop(phandle, "name", name, sizeof(name)) <= 0)
+			continue;
+		if (strncmp(name, "memory", sizeof(name)) != 0)
+			continue;
+
+		res = parse_ofw_memory(phandle, "reg", &memp[msz]);
+		msz += res/sizeof(struct mem_region);
+		if (OF_getproplen(phandle, "available") >= 0)
+			res = parse_ofw_memory(phandle, "available",
+			    &availp[asz]);
+		else
+			res = parse_ofw_memory(phandle, "reg", &availp[asz]);
+		asz += res/sizeof(struct mem_region);
+	}
+
+	*memsz = msz;
+	*availsz = asz;
+}
+
+#ifdef AIM
+void
+OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *))
+{
+	if (ofmsr[0] & PSL_DR)
+		ofw_real_mode = 0;
+	else
+		ofw_real_mode = 1;
+
+	fdt = fdt_ptr;
+
+	#ifdef FDT_DTB_STATIC
+	/* Check for a statically included blob */
+	if (fdt == NULL)
+		fdt = &fdt_static_dtb;
+	#endif
+}
+
+boolean_t
+OF_bootstrap()
+{
+	boolean_t status = FALSE;
+
+	if (openfirmware_entry != NULL) {
+		if (ofw_real_mode) {
+			status = OF_install(OFW_STD_REAL, 0);
+		} else {
+			#ifdef __powerpc64__
+			status = OF_install(OFW_STD_32BIT, 0);
+			#else
+			status = OF_install(OFW_STD_DIRECT, 0);
+			#endif
+		}
+
+		if (status != TRUE)
+			return status;
+
+		OF_init(openfirmware);
+	} else if (fdt != NULL) {
+		status = OF_install(OFW_FDT, 0);
+
+		if (status != TRUE)
+			return status;
+
+		OF_init(fdt);
+	} 
+
+	return (status);
+}
+
+void
+ofw_quiesce(void)
+{
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+	} args;
+
+	KASSERT(!pmap_bootstrapped, ("Cannot call ofw_quiesce after VM is up"));
+
+	args.name = (cell_t)(uintptr_t)"quiesce";
+	args.nargs = 0;
+	args.nreturns = 0;
+	openfirmware(&args);
+}
+
+static int
+openfirmware_core(void *args)
+{
+	int		result;
+	register_t	oldmsr;
+
+	/*
+	 * Turn off exceptions - we really don't want to end up
+	 * anywhere unexpected with PCPU set to something strange
+	 * or the stack pointer wrong.
+	 */
+	oldmsr = intr_disable();
+
+	ofw_sprg_prepare();
+
+	/* Save trap vectors */
+	ofw_save_trap_vec(save_trap_of);
+
+	/* Restore initially saved trap vectors */
+	ofw_restore_trap_vec(save_trap_init);
+
+#if defined(AIM) && !defined(__powerpc64__)
+	/*
+	 * Clear battable[] translations
+	 */
+	if (!(cpu_features & PPC_FEATURE_64))
+		__asm __volatile("mtdbatu 2, %0\n"
+				 "mtdbatu 3, %0" : : "r" (0));
+	isync();
+#endif
+
+	result = ofwcall(args);
+
+	/* Restore trap vecotrs */
+	ofw_restore_trap_vec(save_trap_of);
+
+	ofw_sprg_restore();
+
+	intr_restore(oldmsr);
+
+	return (result);
+}
+
+#ifdef SMP
+struct ofw_rv_args {
+	void *args;
+	int retval;
+	volatile int in_progress;
+};
+
+static void
+ofw_rendezvous_dispatch(void *xargs)
+{
+	struct ofw_rv_args *rv_args = xargs;
+
+	/* NOTE: Interrupts are disabled here */
+
+	if (PCPU_GET(cpuid) == 0) {
+		/*
+		 * Execute all OF calls on CPU 0
+		 */
+		rv_args->retval = openfirmware_core(rv_args->args);
+		rv_args->in_progress = 0;
+	} else {
+		/*
+		 * Spin with interrupts off on other CPUs while OF has
+		 * control of the machine.
+		 */
+		while (rv_args->in_progress)
+			cpu_spinwait();
+	}
+}
+#endif
+
+static int
+openfirmware(void *args)
+{
+	int result;
+	#ifdef SMP
+	struct ofw_rv_args rv_args;
+
+	rv_args.args = args;
+	rv_args.in_progress = 1;
+	smp_rendezvous(smp_no_rendevous_barrier, ofw_rendezvous_dispatch,
+	    smp_no_rendevous_barrier, &rv_args);
+	result = rv_args.retval;
+	#else
+	result = openfirmware_core(args);
+	#endif
+
+	return (result);
+}
+
+void
+OF_reboot()
+{
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t arg;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"interpret";
+	args.nargs = 1;
+	args.nreturns = 0;
+	args.arg = (cell_t)(uintptr_t)"reset-all";
+	openfirmware_core(&args); /* Don't do rendezvous! */
+
+	for (;;);	/* just in case */
+}
+
+#endif /* AIM */
+
+void
+OF_getetheraddr(device_t dev, u_char *addr)
+{
+	phandle_t	node;
+
+	node = ofw_bus_get_node(dev);
+	OF_getprop(node, "local-mac-address", addr, ETHER_ADDR_LEN);
+}
+
+/*
+ * Return a bus handle and bus tag that corresponds to the register
+ * numbered regno for the device referenced by the package handle
+ * dev. This function is intended to be used by console drivers in
+ * early boot only. It works by mapping the address of the device's
+ * register in the address space of its parent and recursively walk
+ * the device tree upward this way.
+ */
+static void
+OF_get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep, int *pcip)
+{
+	char type[64];
+	uint32_t addr, size;
+	int pci, res;
+
+	res = OF_getprop(node, "#address-cells", &addr, sizeof(addr));
+	if (res == -1)
+		addr = 2;
+	res = OF_getprop(node, "#size-cells", &size, sizeof(size));
+	if (res == -1)
+		size = 1;
+	pci = 0;
+	if (addr == 3 && size == 2) {
+		res = OF_getprop(node, "device_type", type, sizeof(type));
+		if (res != -1) {
+			type[sizeof(type) - 1] = '\0';
+			pci = (strcmp(type, "pci") == 0) ? 1 : 0;
+		}
+	}
+	if (addrp != NULL)
+		*addrp = addr;
+	if (sizep != NULL)
+		*sizep = size;
+	if (pcip != NULL)
+		*pcip = pci;
+}
+
+int
+OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
+    bus_space_handle_t *handle)
+{
+	uint32_t cell[32];
+	bus_addr_t addr, raddr, baddr;
+	bus_size_t size, rsize;
+	uint32_t c, nbridge, naddr, nsize;
+	phandle_t bridge, parent;
+	u_int spc, rspc, prefetch;
+	int pci, pcib, res;
+
+	/* Sanity checking. */
+	if (dev == 0)
+		return (EINVAL);
+	bridge = OF_parent(dev);
+	if (bridge == 0)
+		return (EINVAL);
+	if (regno < 0)
+		return (EINVAL);
+	if (tag == NULL || handle == NULL)
+		return (EINVAL);
+
+	/* Assume big-endian unless we find a PCI device */
+	*tag = &bs_be_tag;
+
+	/* Get the requested register. */
+	OF_get_addr_props(bridge, &naddr, &nsize, &pci);
+	if (pci)
+		*tag = &bs_le_tag;
+	res = OF_getprop(dev, (pci) ? "assigned-addresses" : "reg",
+	    cell, sizeof(cell));
+	if (res == -1)
+		return (ENXIO);
+	if (res % sizeof(cell[0]))
+		return (ENXIO);
+	res /= sizeof(cell[0]);
+	regno *= naddr + nsize;
+	if (regno + naddr + nsize > res)
+		return (EINVAL);
+	spc = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK : ~0;
+	prefetch = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_PREFETCHABLE : 0;
+	addr = 0;
+	for (c = 0; c < naddr; c++)
+		addr = ((uint64_t)addr << 32) | cell[regno++];
+	size = 0;
+	for (c = 0; c < nsize; c++)
+		size = ((uint64_t)size << 32) | cell[regno++];
+
+	/*
+	 * Map the address range in the bridge's decoding window as given
+	 * by the "ranges" property. If a node doesn't have such property
+	 * then no mapping is done.
+	 */
+	parent = OF_parent(bridge);
+	while (parent != 0) {
+		OF_get_addr_props(parent, &nbridge, NULL, &pcib);
+		if (pcib)
+			*tag = &bs_le_tag;
+		res = OF_getprop(bridge, "ranges", cell, sizeof(cell));
+		if (res == -1)
+			goto next;
+		if (res % sizeof(cell[0]))
+			return (ENXIO);
+		res /= sizeof(cell[0]);
+		regno = 0;
+		while (regno < res) {
+			rspc = (pci)
+			    ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK
+			    : ~0;
+			if (rspc != spc) {
+				regno += naddr + nbridge + nsize;
+				continue;
+			}
+			raddr = 0;
+			for (c = 0; c < naddr; c++)
+				raddr = ((uint64_t)raddr << 32) | cell[regno++];
+			rspc = (pcib)
+			    ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK
+			    : ~0;
+			baddr = 0;
+			for (c = 0; c < nbridge; c++)
+				baddr = ((uint64_t)baddr << 32) | cell[regno++];
+			rsize = 0;
+			for (c = 0; c < nsize; c++)
+				rsize = ((uint64_t)rsize << 32) | cell[regno++];
+			if (addr < raddr || addr >= raddr + rsize)
+				continue;
+			addr = addr - raddr + baddr;
+			if (rspc != ~0)
+				spc = rspc;
+		}
+
+	next:
+		bridge = parent;
+		parent = OF_parent(bridge);
+		OF_get_addr_props(bridge, &naddr, &nsize, &pci);
+	}
+
+	return (bus_space_map(*tag, addr, size,
+	    prefetch ? BUS_SPACE_MAP_PREFETCHABLE : 0, handle));
+}
+


Property changes on: trunk/sys/powerpc/ofw/ofw_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/ofw_pci.c
===================================================================
--- trunk/sys/powerpc/ofw/ofw_pci.c	                        (rev 0)
+++ trunk/sys/powerpc/ofw/ofw_pci.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,562 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ofw/ofw_pci.c 266128 2014-05-15 14:26:11Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <powerpc/ofw/ofw_pci.h>
+
+#include "pcib_if.h"
+
+/*
+ * Bus interface.
+ */
+static int		ofw_pci_read_ivar(device_t, device_t, int,
+			    uintptr_t *);
+static struct		resource * ofw_pci_alloc_resource(device_t bus,
+			    device_t child, int type, int *rid, u_long start,
+			    u_long end, u_long count, u_int flags);
+static int		ofw_pci_release_resource(device_t bus, device_t child,
+    			    int type, int rid, struct resource *res);
+static int		ofw_pci_activate_resource(device_t bus, device_t child,
+			    int type, int rid, struct resource *res);
+static int		ofw_pci_deactivate_resource(device_t bus,
+    			    device_t child, int type, int rid,
+    			    struct resource *res);
+static int		ofw_pci_adjust_resource(device_t bus, device_t child,
+			    int type, struct resource *res, u_long start,
+			    u_long end);
+
+/*
+ * pcib interface.
+ */
+static int		ofw_pci_maxslots(device_t);
+static int		ofw_pci_route_interrupt(device_t, device_t, int);
+
+/*
+ * ofw_bus interface
+ */
+static phandle_t ofw_pci_get_node(device_t bus, device_t dev);
+
+/*
+ * local methods
+ */
+
+static int ofw_pci_nranges(phandle_t node);
+static int ofw_pci_fill_ranges(phandle_t node, struct ofw_pci_range *ranges);
+
+/*
+ * Driver methods.
+ */
+static device_method_t	ofw_pci_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_attach,	ofw_pci_attach),
+
+	/* Bus interface */
+	DEVMETHOD(bus_print_child,	bus_generic_print_child),
+	DEVMETHOD(bus_read_ivar,	ofw_pci_read_ivar),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+	DEVMETHOD(bus_alloc_resource,	ofw_pci_alloc_resource),
+	DEVMETHOD(bus_release_resource,	ofw_pci_release_resource),
+	DEVMETHOD(bus_activate_resource,	ofw_pci_activate_resource),
+	DEVMETHOD(bus_deactivate_resource,	ofw_pci_deactivate_resource),
+	DEVMETHOD(bus_adjust_resource,	ofw_pci_adjust_resource),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_maxslots,	ofw_pci_maxslots),
+	DEVMETHOD(pcib_route_interrupt,	ofw_pci_route_interrupt),
+
+	/* ofw_bus interface */
+	DEVMETHOD(ofw_bus_get_node,     ofw_pci_get_node),
+
+	DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(ofw_pci, ofw_pci_driver, ofw_pci_methods, 0);
+
+int
+ofw_pci_init(device_t dev)
+{
+	struct		ofw_pci_softc *sc;
+	phandle_t	node;
+	u_int32_t	busrange[2];
+	struct		ofw_pci_range *rp;
+	int		error;
+
+	node = ofw_bus_get_node(dev);
+	sc = device_get_softc(dev);
+	sc->sc_initialized = 1;
+
+	if (OF_getprop(node, "reg", &sc->sc_pcir, sizeof(sc->sc_pcir)) == -1)
+		return (ENXIO);
+
+	if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
+		busrange[0] = 0;
+
+	sc->sc_dev = dev;
+	sc->sc_node = node;
+	sc->sc_bus = busrange[0];
+
+	if (sc->sc_quirks & OFW_PCI_QUIRK_RANGES_ON_CHILDREN) {
+		phandle_t c;
+		int n, i;
+		
+		sc->sc_nrange = 0;
+		for (c = OF_child(node); c != 0; c = OF_peer(c)) {
+			n = ofw_pci_nranges(c);
+			if (n > 0)
+				sc->sc_nrange += n;
+		}
+		if (sc->sc_nrange == 0)
+			return (ENXIO);
+		sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]),
+		    M_DEVBUF, M_WAITOK);
+		i = 0;
+		for (c = OF_child(node); c != 0; c = OF_peer(c)) {
+			n = ofw_pci_fill_ranges(c, &sc->sc_range[i]);
+			if (n > 0)
+				i += n;
+		}
+		KASSERT(i == sc->sc_nrange, ("range count mismatch"));
+	} else {
+		sc->sc_nrange = ofw_pci_nranges(node);
+		if (sc->sc_nrange <= 0) {
+			device_printf(dev, "could not get ranges\n");
+			return (ENXIO);
+		}
+		sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]),
+		    M_DEVBUF, M_WAITOK);
+		ofw_pci_fill_ranges(node, sc->sc_range);
+	}
+		
+	sc->sc_io_rman.rm_type = RMAN_ARRAY;
+	sc->sc_io_rman.rm_descr = "PCI I/O Ports";
+	error = rman_init(&sc->sc_io_rman);
+	if (error) {
+		device_printf(dev, "rman_init() failed. error = %d\n", error);
+		return (error);
+	}
+
+	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+	sc->sc_mem_rman.rm_descr = "PCI Memory";
+	error = rman_init(&sc->sc_mem_rman);
+	if (error) {
+		device_printf(dev, "rman_init() failed. error = %d\n", error);
+		return (error);
+	}
+
+	for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
+	       rp->pci_hi != 0; rp++) {
+		error = 0;
+
+		switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+		case OFW_PCI_PHYS_HI_SPACE_CONFIG:
+			break;
+		case OFW_PCI_PHYS_HI_SPACE_IO:
+			error = rman_manage_region(&sc->sc_io_rman, rp->pci,
+			    rp->pci + rp->size - 1);
+			break;
+		case OFW_PCI_PHYS_HI_SPACE_MEM32:
+		case OFW_PCI_PHYS_HI_SPACE_MEM64:
+			error = rman_manage_region(&sc->sc_mem_rman, rp->pci,
+			    rp->pci + rp->size - 1);
+			break;
+		}
+
+		if (error) {
+			device_printf(dev, 
+			    "rman_manage_region(%x, %#jx, %#jx) failed. "
+			    "error = %d\n", rp->pci_hi &
+			    OFW_PCI_PHYS_HI_SPACEMASK, rp->pci,
+			    rp->pci + rp->size - 1, error);
+			return (error);
+		}
+	}
+
+	ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
+
+	return (error);
+}
+
+int
+ofw_pci_attach(device_t dev)
+{
+	struct ofw_pci_softc *sc;
+	int error;
+
+	sc = device_get_softc(dev);
+	if (!sc->sc_initialized) {
+		error = ofw_pci_init(dev);
+		if (error)
+			return (error);
+	}
+
+	device_add_child(dev, "pci", device_get_unit(dev));
+	return (bus_generic_attach(dev));
+}
+
+static int
+ofw_pci_maxslots(device_t dev)
+{
+
+	return (PCI_SLOTMAX);
+}
+
+static int
+ofw_pci_route_interrupt(device_t bus, device_t dev, int pin)
+{
+	struct ofw_pci_softc *sc;
+	struct ofw_pci_register reg;
+	uint32_t pintr, mintr[2];
+	int intrcells;
+	phandle_t iparent;
+
+	sc = device_get_softc(bus);
+	pintr = pin;
+
+	/* Fabricate imap information in case this isn't an OFW device */
+	bzero(&reg, sizeof(reg));
+	reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
+	    (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
+	    (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
+
+	intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev),
+	    &sc->sc_pci_iinfo, &reg, sizeof(reg), &pintr, sizeof(pintr),
+	    mintr, sizeof(mintr), &iparent);
+	if (intrcells) {
+		pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr);
+		return (pintr);
+	}
+
+	/* Maybe it's a real interrupt, not an intpin */
+	if (pin > 4)
+		return (pin);
+
+	device_printf(bus, "could not route pin %d for device %d.%d\n",
+	    pin, pci_get_slot(dev), pci_get_function(dev));
+	return (PCI_INVALID_IRQ);
+}
+
+static int
+ofw_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+	struct	ofw_pci_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	switch (which) {
+	case PCIB_IVAR_DOMAIN:
+		*result = device_get_unit(dev);
+		return (0);
+	case PCIB_IVAR_BUS:
+		*result = sc->sc_bus;
+		return (0);
+	}
+
+	return (ENOENT);
+}
+
+static struct resource *
+ofw_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+    u_long start, u_long end, u_long count, u_int flags)
+{
+	struct			ofw_pci_softc *sc;
+	struct			resource *rv;
+	struct			rman *rm;
+	int			needactivate;
+
+	needactivate = flags & RF_ACTIVE;
+	flags &= ~RF_ACTIVE;
+
+	sc = device_get_softc(bus);
+
+	switch (type) {
+	case SYS_RES_MEMORY:
+		rm = &sc->sc_mem_rman;
+		break;
+
+	case SYS_RES_IOPORT:
+		rm = &sc->sc_io_rman;
+		break;
+
+	case SYS_RES_IRQ:
+		return (bus_alloc_resource(bus, type, rid, start, end, count,
+		    flags));
+
+	default:
+		device_printf(bus, "unknown resource request from %s\n",
+		    device_get_nameunit(child));
+		return (NULL);
+	}
+
+	rv = rman_reserve_resource(rm, start, end, count, flags, child);
+	if (rv == NULL) {
+		device_printf(bus, "failed to reserve resource for %s\n",
+		    device_get_nameunit(child));
+		return (NULL);
+	}
+
+	rman_set_rid(rv, *rid);
+
+	if (needactivate) {
+		if (bus_activate_resource(child, type, *rid, rv) != 0) {
+			device_printf(bus,
+			    "failed to activate resource for %s\n",
+			    device_get_nameunit(child));
+			rman_release_resource(rv);
+			return (NULL);
+		}
+	}
+
+	return (rv);
+}
+
+static int
+ofw_pci_release_resource(device_t bus, device_t child, int type, int rid,
+    struct resource *res)
+{
+	if (rman_get_flags(res) & RF_ACTIVE) {
+		int error = bus_deactivate_resource(child, type, rid, res);
+		if (error)
+			return error;
+	}
+
+	return (rman_release_resource(res));
+}
+
+static int
+ofw_pci_activate_resource(device_t bus, device_t child, int type, int rid,
+    struct resource *res)
+{
+	struct ofw_pci_softc *sc;
+	void	*p;
+
+	sc = device_get_softc(bus);
+
+	if (type == SYS_RES_IRQ) {
+		return (bus_activate_resource(bus, type, rid, res));
+	}
+	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
+		struct ofw_pci_range *rp;
+		vm_offset_t start;
+		int space;
+
+		start = (vm_offset_t)rman_get_start(res);
+
+		/*
+		 * Map this through the ranges list
+		 */
+		for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
+		       rp->pci_hi != 0; rp++) {
+			if (start < rp->pci || start >= rp->pci + rp->size)
+				continue;
+
+			switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+			case OFW_PCI_PHYS_HI_SPACE_IO:
+				space = SYS_RES_IOPORT;
+				break;
+			case OFW_PCI_PHYS_HI_SPACE_MEM32:
+			case OFW_PCI_PHYS_HI_SPACE_MEM64:
+				space = SYS_RES_MEMORY;
+				break;
+			default:
+				space = -1;
+			}
+
+			if (type == space) {
+				start += (rp->host - rp->pci);
+				break;
+			}
+		}
+
+		if (bootverbose)
+			printf("ofw_pci mapdev: start %zx, len %ld\n", start,
+			    rman_get_size(res));
+
+		p = pmap_mapdev(start, (vm_size_t)rman_get_size(res));
+		if (p == NULL)
+			return (ENOMEM);
+
+		rman_set_virtual(res, p);
+		rman_set_bustag(res, &bs_le_tag);
+		rman_set_bushandle(res, (u_long)p);
+	}
+
+	return (rman_activate_resource(res));
+}
+
+static int
+ofw_pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
+    struct resource *res)
+{
+	/*
+	 * If this is a memory resource, unmap it.
+	 */
+	if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
+		u_int32_t psize;
+
+		psize = rman_get_size(res);
+		pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize);
+	}
+
+	return (rman_deactivate_resource(res));
+}
+
+static int
+ofw_pci_adjust_resource(device_t bus, device_t child, int type,
+    struct resource *res, u_long start, u_long end)
+{
+	struct rman *rm = NULL;
+	struct ofw_pci_softc *sc = device_get_softc(bus);
+
+	KASSERT(!(rman_get_flags(res) & RF_ACTIVE),
+	    ("active resources cannot be adjusted"));
+	if (rman_get_flags(res) & RF_ACTIVE)
+		return (EINVAL);
+
+	switch (type) {
+	case SYS_RES_MEMORY:
+		rm = &sc->sc_mem_rman;
+		break;
+	case SYS_RES_IOPORT:
+		rm = &sc->sc_io_rman;
+		break;
+	default:
+		return (ENXIO);
+	}
+
+	if (!rman_is_region_manager(res, rm))
+		return (EINVAL);
+
+	return (rman_adjust_resource(res, start, end));
+}
+	
+
+static phandle_t
+ofw_pci_get_node(device_t bus, device_t dev)
+{
+	struct ofw_pci_softc *sc;
+
+	sc = device_get_softc(bus);
+	/* We only have one child, the PCI bus, which needs our own node. */
+
+	return (sc->sc_node);
+}
+
+static int
+ofw_pci_nranges(phandle_t node)
+{
+	int host_address_cells = 1, pci_address_cells = 3, size_cells = 2;
+	ssize_t nbase_ranges;
+
+	OF_getprop(OF_parent(node), "#address-cells", &host_address_cells,
+	    sizeof(host_address_cells));
+	OF_getprop(node, "#address-cells", &pci_address_cells,
+	    sizeof(pci_address_cells));
+	OF_getprop(node, "#size-cells", &size_cells, sizeof(size_cells));
+
+	nbase_ranges = OF_getproplen(node, "ranges");
+	if (nbase_ranges <= 0)
+		return (-1);
+
+	return (nbase_ranges / sizeof(cell_t) /
+	    (pci_address_cells + host_address_cells + size_cells));
+}
+
+static int
+ofw_pci_fill_ranges(phandle_t node, struct ofw_pci_range *ranges)
+{
+	int host_address_cells = 1, pci_address_cells = 3, size_cells = 2;
+	cell_t *base_ranges;
+	ssize_t nbase_ranges;
+	int nranges;
+	int i, j, k;
+
+	OF_getprop(OF_parent(node), "#address-cells", &host_address_cells,
+	    sizeof(host_address_cells));
+	OF_getprop(node, "#address-cells", &pci_address_cells,
+	    sizeof(pci_address_cells));
+	OF_getprop(node, "#size-cells", &size_cells, sizeof(size_cells));
+
+	nbase_ranges = OF_getproplen(node, "ranges");
+	if (nbase_ranges <= 0)
+		return (-1);
+	nranges = nbase_ranges / sizeof(cell_t) /
+	    (pci_address_cells + host_address_cells + size_cells);
+
+	base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
+	OF_getprop(node, "ranges", base_ranges, nbase_ranges);
+
+	for (i = 0, j = 0; i < nranges; i++) {
+		ranges[i].pci_hi = base_ranges[j++];
+		ranges[i].pci = 0;
+		for (k = 0; k < pci_address_cells - 1; k++) {
+			ranges[i].pci <<= 32;
+			ranges[i].pci |= base_ranges[j++];
+		}
+		ranges[i].host = 0;
+		for (k = 0; k < host_address_cells; k++) {
+			ranges[i].host <<= 32;
+			ranges[i].host |= base_ranges[j++];
+		}
+		ranges[i].size = 0;
+		for (k = 0; k < size_cells; k++) {
+			ranges[i].size <<= 32;
+			ranges[i].size |= base_ranges[j++];
+		}
+	}
+
+	free(base_ranges, M_DEVBUF);
+	return (nranges);
+}
+


Property changes on: trunk/sys/powerpc/ofw/ofw_pci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/ofw_pci.h
===================================================================
--- trunk/sys/powerpc/ofw/ofw_pci.h	                        (rev 0)
+++ trunk/sys/powerpc/ofw/ofw_pci.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,77 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ofw/ofw_pci.h 265954 2014-05-13 16:59:50Z ian $
+ */
+
+#ifndef POWERPC_OFW_OFW_PCI_H
+#define POWERPC_OFW_OFW_PCI_H
+
+/*
+ * Export class definition for inheritance purposes
+ */
+DECLARE_CLASS(ofw_pci_driver);
+
+struct ofw_pci_range {
+	uint32_t	pci_hi;
+	uint64_t	pci;
+	uint64_t	host;
+	uint64_t	size;
+};
+
+/*
+ * Quirks for some adapters
+ */
+enum {
+	OFW_PCI_QUIRK_RANGES_ON_CHILDREN = 1,
+};
+
+struct ofw_pci_softc {
+	device_t		sc_dev;
+	phandle_t		sc_node;
+	int			sc_bus;
+	int			sc_initialized;
+
+	int			sc_quirks;
+
+	struct ofw_pci_register	sc_pcir;
+
+	struct ofw_pci_range	*sc_range;
+	int			sc_nrange;
+
+	struct rman		sc_io_rman;
+	struct rman		sc_mem_rman;
+	bus_space_tag_t		sc_memt;
+	bus_dma_tag_t		sc_dmat;
+
+	struct ofw_bus_iinfo    sc_pci_iinfo;
+};
+
+int ofw_pci_init(device_t dev);
+int ofw_pci_attach(device_t dev);
+
+#endif // POWERPC_OFW_OFW_PCI_H
+


Property changes on: trunk/sys/powerpc/ofw/ofw_pci.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/ofw_pcib_pci.c
===================================================================
--- trunk/sys/powerpc/ofw/ofw_pcib_pci.c	                        (rev 0)
+++ trunk/sys/powerpc/ofw/ofw_pcib_pci.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,176 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2000 BSDi
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ofw/ofw_pcib_pci.c 266128 2014-05-15 14:26:11Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
+
+#include <machine/intr_machdep.h>
+
+#include "pcib_if.h"
+
+static int	ofw_pcib_pci_probe(device_t bus);
+static int	ofw_pcib_pci_attach(device_t bus);
+static phandle_t ofw_pcib_pci_get_node(device_t bus, device_t dev);
+static int	ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev,
+		    int intpin);
+
+static device_method_t ofw_pcib_pci_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		ofw_pcib_pci_probe),
+	DEVMETHOD(device_attach,	ofw_pcib_pci_attach),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_route_interrupt,	ofw_pcib_pci_route_interrupt),
+
+	/* ofw_bus interface */
+	DEVMETHOD(ofw_bus_get_node,	ofw_pcib_pci_get_node),
+
+	DEVMETHOD_END
+};
+
+static devclass_t pcib_devclass;
+
+struct ofw_pcib_softc {
+        /*
+         * This is here so that we can use pci bridge methods, too - the
+         * generic routines only need the dev, secbus and subbus members
+         * filled.
+         */
+        struct pcib_softc       ops_pcib_sc;
+	phandle_t		ops_node;
+        struct ofw_bus_iinfo    ops_iinfo;
+};
+
+DEFINE_CLASS_1(pcib, ofw_pcib_pci_driver, ofw_pcib_pci_methods,
+    sizeof(struct ofw_pcib_softc), pcib_driver);
+DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_pci_driver, pcib_devclass, 0, 0);
+
+static int
+ofw_pcib_pci_probe(device_t dev)
+{
+
+	if ((pci_get_class(dev) != PCIC_BRIDGE) ||
+	    (pci_get_subclass(dev) != PCIS_BRIDGE_PCI)) {
+		return (ENXIO);
+	}
+
+	if (ofw_bus_get_node(dev) == -1)
+		return (ENXIO);
+
+	device_set_desc(dev, "OFW PCI-PCI bridge");
+	return (0);
+}
+
+static int
+ofw_pcib_pci_attach(device_t dev)
+{
+	struct ofw_pcib_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->ops_pcib_sc.dev = dev;
+	sc->ops_node = ofw_bus_get_node(dev);
+
+	ofw_bus_setup_iinfo(sc->ops_node, &sc->ops_iinfo,
+	    sizeof(cell_t));
+
+	pcib_attach_common(dev);
+
+	device_add_child(dev, "pci", -1);
+
+	return (bus_generic_attach(dev));
+}
+
+static phandle_t
+ofw_pcib_pci_get_node(device_t bridge, device_t dev)
+{
+	/* We have only one child, the PCI bus, so pass it our node */
+
+	return (ofw_bus_get_node(bridge));
+}
+
+static int
+ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, int intpin)
+{
+	struct ofw_pcib_softc *sc;
+	struct ofw_bus_iinfo *ii;
+	struct ofw_pci_register reg;
+	cell_t pintr, mintr[2];
+	int intrcells;
+	phandle_t iparent;
+
+	sc = device_get_softc(bridge);
+	ii = &sc->ops_iinfo;
+	if (ii->opi_imapsz > 0) {
+		pintr = intpin;
+
+		/* Fabricate imap information if this isn't an OFW device */
+		bzero(&reg, sizeof(reg));
+		reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
+		    (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
+		    (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
+
+		intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, &reg,
+		    sizeof(reg), &pintr, sizeof(pintr), mintr, sizeof(mintr),
+		    &iparent);
+		if (intrcells) {
+			/*
+			 * If we've found a mapping, return it and don't map
+			 * it again on higher levels - that causes problems
+			 * in some cases, and never seems to be required.
+			 */
+			mintr[0] = ofw_bus_map_intr(dev, iparent, intrcells,
+			    mintr);
+			return (mintr[0]);
+		}
+	} else if (intpin >= 1 && intpin <= 4) {
+		/*
+		 * When an interrupt map is missing, we need to do the
+		 * standard PCI swizzle and continue mapping at the parent.
+		 */
+		return (pcib_route_interrupt(bridge, dev, intpin));
+	}
+	return (PCIB_ROUTE_INTERRUPT(device_get_parent(device_get_parent(
+	    bridge)), bridge, intpin));
+}
+


Property changes on: trunk/sys/powerpc/ofw/ofw_pcib_pci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/ofw_pcibus.c
===================================================================
--- trunk/sys/powerpc/ofw/ofw_pcibus.c	                        (rev 0)
+++ trunk/sys/powerpc/ofw/ofw_pcibus.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,367 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1997, Stefan Esser <se at freebsd.org>
+ * Copyright (c) 2000, Michael Smith <msmith at freebsd.org>
+ * Copyright (c) 2000, BSDi
+ * Copyright (c) 2003, Thomas Moestl <tmm at FreeBSD.org>
+ * 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 unmodified, 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ofw/ofw_pcibus.c 330938 2018-03-14 19:04:40Z jhb $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/libkern.h>
+#include <sys/module.h>
+#include <sys/pciio.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/resource.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pci_private.h>
+
+#include "ofw_pcibus.h"
+#include "pcib_if.h"
+#include "pci_if.h"
+
+typedef uint32_t ofw_pci_intr_t;
+
+/* Methods */
+static device_probe_t ofw_pcibus_probe;
+static device_attach_t ofw_pcibus_attach;
+static pci_assign_interrupt_t ofw_pcibus_assign_interrupt;
+static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo;
+static bus_child_deleted_t ofw_pcibus_child_deleted;
+static int ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child,
+    char *buf, size_t buflen);
+
+static void ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno);
+static void ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno);
+
+static device_method_t ofw_pcibus_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		ofw_pcibus_probe),
+	DEVMETHOD(device_attach,	ofw_pcibus_attach),
+
+	/* Bus interface */
+	DEVMETHOD(bus_child_deleted,	ofw_pcibus_child_deleted),
+	DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_child_pnpinfo_str_method),
+
+	/* PCI interface */
+	DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt),
+
+	/* ofw_bus interface */
+	DEVMETHOD(ofw_bus_get_devinfo,	ofw_pcibus_get_devinfo),
+	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
+	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
+	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
+	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
+	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
+
+	DEVMETHOD_END
+};
+
+static devclass_t pci_devclass;
+
+DEFINE_CLASS_1(pci, ofw_pcibus_driver, ofw_pcibus_methods,
+    sizeof(struct pci_softc), pci_driver);
+DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0);
+MODULE_VERSION(ofw_pcibus, 1);
+MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1);
+
+static int ofw_devices_only = 0;
+TUNABLE_INT("hw.pci.ofw_devices_only", &ofw_devices_only);
+
+static int
+ofw_pcibus_probe(device_t dev)
+{
+
+	if (ofw_bus_get_node(dev) == -1)
+		return (ENXIO);
+	device_set_desc(dev, "OFW PCI bus");
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ofw_pcibus_attach(device_t dev)
+{
+	u_int busno, domain;
+	int error;
+
+	error = pci_attach_common(dev);
+	if (error)
+		return (error);
+	domain = pcib_get_domain(dev);
+	busno = pcib_get_bus(dev);
+
+	/*
+	 * Attach those children represented in the device tree.
+	 */
+
+	ofw_pcibus_enum_devtree(dev, domain, busno);
+
+	/*
+	 * We now attach any laggard devices. FDT, for instance, allows
+	 * the device tree to enumerate only some PCI devices. Apple's
+	 * OF device tree on some Grackle-based hardware can also miss
+	 * functions on multi-function cards.
+	 */
+
+	if (!ofw_devices_only)
+		ofw_pcibus_enum_bus(dev, domain, busno);
+
+	return (bus_generic_attach(dev));
+}
+
+static void
+ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno)
+{
+	device_t pcib;
+	struct ofw_pci_register pcir;
+	struct ofw_pcibus_devinfo *dinfo;
+	phandle_t node, child;
+	u_int func, slot;
+	int intline;
+
+	pcib = device_get_parent(dev);
+	node = ofw_bus_get_node(dev);
+
+	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
+		if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1)
+			continue;
+		slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi);
+		func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi);
+
+		/* Some OFW device trees contain dupes. */
+		if (pci_find_dbsf(domain, busno, slot, func) != NULL)
+			continue;
+
+		/*
+		 * The preset in the intline register is usually bogus.  Reset
+		 * it such that the PCI code will reroute the interrupt if
+		 * needed.
+		 */
+
+		intline = PCI_INVALID_IRQ;
+		if (OF_getproplen(child, "interrupts") > 0)
+			intline = 0;
+		PCIB_WRITE_CONFIG(pcib, busno, slot, func, PCIR_INTLINE,
+		    intline, 1);
+
+		/*
+		 * Now set up the PCI and OFW bus layer devinfo and add it
+		 * to the PCI bus.
+		 */
+
+		dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib,
+		    domain, busno, slot, func, sizeof(*dinfo));
+		if (dinfo == NULL)
+			continue;
+		if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) !=
+		    0) {
+			pci_freecfg((struct pci_devinfo *)dinfo);
+			continue;
+		}
+		dinfo->opd_dma_tag = NULL;
+		pci_add_child(dev, (struct pci_devinfo *)dinfo);
+
+		/*
+		 * Some devices don't have an intpin set, but do have
+		 * interrupts. These are fully specified, and set in the
+		 * interrupts property, so add that value to the device's
+		 * resource list.
+		 */
+		if (dinfo->opd_dinfo.cfg.intpin == 0)
+			ofw_bus_intr_to_rl(dev, child, &dinfo->opd_dinfo.resources);
+	}
+}
+
+/*
+ * The following is an almost exact clone of pci_add_children(), with the
+ * addition that it (a) will not add children that have already been added,
+ * and (b) will set up the OFW devinfo to point to invalid values. This is
+ * to handle non-enumerated PCI children as exist in FDT and on the second
+ * function of the Rage 128 in my Blue & White G3.
+ */
+
+static void
+ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno)
+{
+	device_t pcib;
+	struct ofw_pcibus_devinfo *dinfo;
+	int maxslots;
+	int s, f, pcifunchigh;
+	uint8_t hdrtype;
+
+	pcib = device_get_parent(dev);
+
+	maxslots = PCIB_MAXSLOTS(pcib);
+	for (s = 0; s <= maxslots; s++) {
+		pcifunchigh = 0;
+		f = 0;
+		DELAY(1);
+		hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1);
+		if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
+			continue;
+		if (hdrtype & PCIM_MFDEV)
+			pcifunchigh = PCI_FUNCMAX;
+		for (f = 0; f <= pcifunchigh; f++) {
+			/* Filter devices we have already added */
+			if (pci_find_dbsf(domain, busno, s, f) != NULL)
+				continue;
+
+			dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(
+			    pcib, domain, busno, s, f, sizeof(*dinfo));
+			if (dinfo == NULL)
+				continue;
+
+			dinfo->opd_dma_tag = NULL;
+			dinfo->opd_obdinfo.obd_node = -1;
+
+			dinfo->opd_obdinfo.obd_name = NULL;
+			dinfo->opd_obdinfo.obd_compat = NULL;
+			dinfo->opd_obdinfo.obd_type = NULL;
+			dinfo->opd_obdinfo.obd_model = NULL;
+
+			/*
+			 * For non OFW-devices, don't believe 0 
+			 * for an interrupt.
+			 */
+			if (dinfo->opd_dinfo.cfg.intline == 0) {
+				dinfo->opd_dinfo.cfg.intline = PCI_INVALID_IRQ;
+				PCIB_WRITE_CONFIG(pcib, busno, s, f, 
+				    PCIR_INTLINE, PCI_INVALID_IRQ, 1);
+			}
+
+			pci_add_child(dev, (struct pci_devinfo *)dinfo);
+		}
+	}
+}
+
+static void
+ofw_pcibus_child_deleted(device_t dev, device_t child)
+{
+	struct ofw_pcibus_devinfo *dinfo;
+
+	dinfo = device_get_ivars(dev);
+	ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo);
+	pci_child_deleted(dev, child);
+}
+
+static int
+ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf,
+    size_t buflen)
+{
+	pci_child_pnpinfo_str_method(cbdev, child, buf, buflen);
+
+	if (ofw_bus_get_node(child) != -1)  {
+		strlcat(buf, " ", buflen); /* Separate info */
+		ofw_bus_gen_child_pnpinfo_str(cbdev, child, buf, buflen);
+	}
+
+	return (0);
+}
+	
+static int
+ofw_pcibus_assign_interrupt(device_t dev, device_t child)
+{
+	ofw_pci_intr_t intr[2];
+	phandle_t node, iparent;
+	int isz, icells;
+
+	node = ofw_bus_get_node(child);
+
+	if (node == -1) {
+		/* Non-firmware enumerated child, use standard routing */
+	
+		intr[0] = pci_get_intpin(child);
+		return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, 
+		    intr[0]));
+	}
+	
+	/*
+	 * Try to determine the node's interrupt parent so we know which
+	 * PIC to use.
+	 */
+
+	iparent = -1;
+	if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) < 0)
+		iparent = -1;
+	icells = 1;
+	if (iparent != -1)
+		OF_getprop(OF_node_from_xref(iparent), "#interrupt-cells",
+		    &icells, sizeof(icells));
+	
+	/*
+	 * Any AAPL,interrupts property gets priority and is
+	 * fully specified (i.e. does not need routing)
+	 */
+
+	isz = OF_getprop(node, "AAPL,interrupts", intr, sizeof(intr));
+	if (isz == sizeof(intr[0])*icells)
+		return ((iparent == -1) ? intr[0] : ofw_bus_map_intr(dev,
+		    iparent, icells, intr));
+
+	isz = OF_getprop(node, "interrupts", intr, sizeof(intr));
+	if (isz == sizeof(intr[0])*icells) {
+		if (iparent != -1)
+			intr[0] = ofw_bus_map_intr(dev, iparent, icells, intr);
+	} else {
+		/* No property: our best guess is the intpin. */
+		intr[0] = pci_get_intpin(child);
+	}
+	
+	/*
+	 * If we got intr from a property, it may or may not be an intpin.
+	 * For on-board devices, it frequently is not, and is completely out
+	 * of the valid intpin range.  For PCI slots, it hopefully is,
+	 * otherwise we will have trouble interfacing with non-OFW buses
+	 * such as cardbus.
+	 * Since we cannot tell which it is without violating layering, we
+	 * will always use the route_interrupt method, and treat exceptions
+	 * on the level they become apparent.
+	 */
+	return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr[0]));
+}
+
+static const struct ofw_bus_devinfo *
+ofw_pcibus_get_devinfo(device_t bus, device_t dev)
+{
+	struct ofw_pcibus_devinfo *dinfo;
+
+	dinfo = device_get_ivars(dev);
+	return (&dinfo->opd_obdinfo);
+}
+


Property changes on: trunk/sys/powerpc/ofw/ofw_pcibus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/ofw_pcibus.h
===================================================================
--- trunk/sys/powerpc/ofw/ofw_pcibus.h	                        (rev 0)
+++ trunk/sys/powerpc/ofw/ofw_pcibus.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,52 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ofw/ofw_pcibus.h 259257 2013-12-12 12:36:40Z andreast $
+ */
+
+#ifndef POWERPC_OFW_OFW_PCIBUS_H
+#define POWERPC_OFW_OFW_PCIBUS_H
+
+#include <sys/bus.h>
+#include <sys/pciio.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/pci/pcivar.h>
+
+/*
+ * Export class definition for inheritance purposes
+ */
+DECLARE_CLASS(ofw_pcibus_driver);	/* PCI Bus Enumerators */
+
+struct ofw_pcibus_devinfo {
+        struct pci_devinfo      opd_dinfo;
+        struct ofw_bus_devinfo  opd_obdinfo;
+	bus_dma_tag_t		opd_dma_tag;
+};
+
+#endif // POWERPC_OFW_OFW_PCIBUS_H
+


Property changes on: trunk/sys/powerpc/ofw/ofw_pcibus.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/ofw_real.c
===================================================================
--- trunk/sys/powerpc/ofw/ofw_real.c	                        (rev 0)
+++ trunk/sys/powerpc/ofw/ofw_real.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,1103 @@
+/* $MidnightBSD$ */
+/*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai 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.
+ */
+/*-
+ * Copyright (C) 2000 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ofw/ofw_real.c 262586 2014-02-28 00:39:35Z brueffer $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+#include <machine/ofw_machdep.h>
+#include <machine/pmap.h>
+#include <machine/stdarg.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofwvar.h>
+#include "ofw_if.h"
+
+static int ofw_real_init(ofw_t, void *openfirm);
+static int ofw_real_test(ofw_t, const char *name);
+static phandle_t ofw_real_peer(ofw_t, phandle_t node);
+static phandle_t ofw_real_child(ofw_t, phandle_t node);
+static phandle_t ofw_real_parent(ofw_t, phandle_t node);
+static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
+static ssize_t ofw_real_getproplen(ofw_t, phandle_t package, 
+    const char *propname);
+static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname, 
+    void *buf, size_t buflen);
+static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous, 
+    char *buf, size_t);
+static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
+    const void *buf, size_t len);
+static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
+static phandle_t ofw_real_finddevice(ofw_t, const char *device);
+static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf, 
+    size_t len);
+static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf, 
+    size_t len);
+static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method, 
+    int nargs, int nreturns, cell_t *args_and_returns);
+static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns,
+    cell_t *returns);
+static ihandle_t ofw_real_open(ofw_t, const char *device);
+static void ofw_real_close(ofw_t, ihandle_t instance);
+static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
+static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr, 
+    size_t len);
+static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
+static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
+static void ofw_real_release(ofw_t, void *virt, size_t size);
+static void ofw_real_enter(ofw_t);
+static void ofw_real_exit(ofw_t);
+
+static ofw_method_t ofw_real_methods[] = {
+	OFWMETHOD(ofw_init,			ofw_real_init),
+	OFWMETHOD(ofw_peer,			ofw_real_peer),
+	OFWMETHOD(ofw_child,			ofw_real_child),
+	OFWMETHOD(ofw_parent,			ofw_real_parent),
+	OFWMETHOD(ofw_instance_to_package,	ofw_real_instance_to_package),
+	OFWMETHOD(ofw_getproplen,		ofw_real_getproplen),
+	OFWMETHOD(ofw_getprop,			ofw_real_getprop),
+	OFWMETHOD(ofw_nextprop,			ofw_real_nextprop),
+	OFWMETHOD(ofw_setprop,			ofw_real_setprop),
+	OFWMETHOD(ofw_canon,			ofw_real_canon),
+	OFWMETHOD(ofw_finddevice,		ofw_real_finddevice),
+	OFWMETHOD(ofw_instance_to_path,		ofw_real_instance_to_path),
+	OFWMETHOD(ofw_package_to_path,		ofw_real_package_to_path),
+
+	OFWMETHOD(ofw_test,			ofw_real_test),
+	OFWMETHOD(ofw_call_method,		ofw_real_call_method),
+	OFWMETHOD(ofw_interpret,		ofw_real_interpret),
+	OFWMETHOD(ofw_open,			ofw_real_open),
+	OFWMETHOD(ofw_close,			ofw_real_close),
+	OFWMETHOD(ofw_read,			ofw_real_read),
+	OFWMETHOD(ofw_write,			ofw_real_write),
+	OFWMETHOD(ofw_seek,			ofw_real_seek),
+	OFWMETHOD(ofw_claim,			ofw_real_claim),
+	OFWMETHOD(ofw_release,			ofw_real_release),
+	OFWMETHOD(ofw_enter,			ofw_real_enter),
+	OFWMETHOD(ofw_exit,			ofw_real_exit),
+
+	{ 0, 0 }
+};
+
+static ofw_def_t ofw_real = {
+	OFW_STD_REAL,
+	ofw_real_methods,
+	0
+};
+OFW_DEF(ofw_real);
+
+static ofw_def_t ofw_32bit = {
+	OFW_STD_32BIT,
+	ofw_real_methods,
+	0
+};
+OFW_DEF(ofw_32bit);
+
+static MALLOC_DEFINE(M_OFWREAL, "ofwreal",
+    "Open Firmware Real Mode Bounce Page");
+
+static int (*openfirmware)(void *);
+
+static vm_offset_t	of_bounce_phys;
+static caddr_t		of_bounce_virt;
+static off_t		of_bounce_offset;
+static size_t		of_bounce_size;
+static struct mtx	of_bounce_mtx;
+
+extern int		ofw_real_mode;
+
+/*
+ * After the VM is up, allocate a wired, low memory bounce page.
+ */
+
+static void ofw_real_bounce_alloc(void *);
+
+SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY, 
+    ofw_real_bounce_alloc, NULL);
+
+static void
+ofw_real_start(void)
+{
+	mtx_lock(&of_bounce_mtx);
+	of_bounce_offset = 0;
+}
+	
+static void
+ofw_real_stop(void)
+{
+	mtx_unlock(&of_bounce_mtx);
+}
+
+static void
+ofw_real_bounce_alloc(void *junk)
+{
+	/*
+	 * Check that ofw_real is actually in use before allocating wads 
+	 * of memory. Do this by checking if our mutex has been set up.
+	 */
+	if (!mtx_initialized(&of_bounce_mtx))
+		return;
+
+	/*
+	 * Allocate a page of contiguous, wired physical memory that can
+	 * fit into a 32-bit address space and accessed from real mode.
+	 */
+
+	mtx_lock(&of_bounce_mtx);
+
+	of_bounce_virt = contigmalloc(4 * PAGE_SIZE, M_OFWREAL, 0, 0,
+	    ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
+	    4 * PAGE_SIZE);
+
+	of_bounce_phys = vtophys(of_bounce_virt);
+	of_bounce_size = 4 * PAGE_SIZE;
+
+	/*
+	 * For virtual-mode OF, direct map this physical address so that
+	 * we have a 32-bit virtual address to give OF.
+	 */
+
+	if (!ofw_real_mode && !hw_direct_map) 
+		pmap_kenter(of_bounce_phys, of_bounce_phys);
+
+	mtx_unlock(&of_bounce_mtx);
+}
+
+static cell_t
+ofw_real_map(const void *buf, size_t len)
+{
+	static char emergency_buffer[255];
+	cell_t phys;
+
+	mtx_assert(&of_bounce_mtx, MA_OWNED);
+
+	if (of_bounce_virt == NULL) {
+		/*
+		 * If we haven't set up the MMU, then buf is guaranteed
+		 * to be accessible to OF, because the only memory we
+		 * can use right now is memory mapped by firmware.
+		 */
+		if (!pmap_bootstrapped)
+			return (cell_t)(uintptr_t)buf;
+
+		/*
+		 * XXX: It is possible for us to get called before the VM has
+		 * come online, but after the MMU is up. We don't have the
+		 * bounce buffer yet, but can no longer presume a 1:1 mapping.
+		 * Copy into the emergency buffer, and reset at the end.
+		 */
+		of_bounce_virt = emergency_buffer;
+		of_bounce_phys = (vm_offset_t)of_bounce_virt;
+		of_bounce_size = sizeof(emergency_buffer);
+	}
+
+	/*
+	 * Make sure the bounce page offset satisfies any reasonable
+	 * alignment constraint.
+	 */
+	of_bounce_offset += sizeof(register_t) - (of_bounce_offset % sizeof(register_t));
+
+	if (of_bounce_offset + len > of_bounce_size) {
+		panic("Oversize Open Firmware call!");
+		return 0;
+	}
+
+	if (buf != NULL)
+		memcpy(of_bounce_virt + of_bounce_offset, buf, len);
+	else
+		return (0);
+
+	phys = of_bounce_phys + of_bounce_offset;
+
+	of_bounce_offset += len;
+
+	return (phys);
+}
+
+static void
+ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
+{
+	mtx_assert(&of_bounce_mtx, MA_OWNED);
+
+	if (of_bounce_virt == NULL)
+		return;
+
+	if (physaddr == 0)
+		return;
+
+	memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
+}
+
+/* Initialiser */
+
+static int
+ofw_real_init(ofw_t ofw, void *openfirm)
+{
+	openfirmware = (int (*)(void *))openfirm;
+
+	mtx_init(&of_bounce_mtx, "OF Bounce Page", NULL, MTX_DEF);
+	of_bounce_virt = NULL;
+	return (0);
+}
+
+/*
+ * Generic functions
+ */
+
+/* Test to see if a service exists. */
+static int
+ofw_real_test(ofw_t ofw, const char *name)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t service;
+		cell_t missing;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"test";
+	args.nargs = 1;
+	args.nreturns = 1;
+
+	ofw_real_start();
+
+	args.service = ofw_real_map(name, strlen(name) + 1);
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.service == 0 || openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	return (args.missing);
+}
+
+/*
+ * Device tree functions
+ */
+
+/* Return the next sibling of this node or 0. */
+static phandle_t
+ofw_real_peer(ofw_t ofw, phandle_t node)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t node;
+		cell_t next;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"peer";
+	args.nargs = 1;
+	args.nreturns = 1;
+
+	args.node = node;
+	ofw_real_start();
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	return (args.next);
+}
+
+/* Return the first child of this node or 0. */
+static phandle_t
+ofw_real_child(ofw_t ofw, phandle_t node)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t node;
+		cell_t child;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"child";
+	args.nargs = 1;
+	args.nreturns = 1;
+
+	args.node = node;
+	ofw_real_start();
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	return (args.child);
+}
+
+/* Return the parent of this node or 0. */
+static phandle_t
+ofw_real_parent(ofw_t ofw, phandle_t node)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t node;
+		cell_t parent;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"parent";
+	args.nargs = 1;
+	args.nreturns = 1;
+
+	args.node = node;
+	ofw_real_start();
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	return (args.parent);
+}
+
+/* Return the package handle that corresponds to an instance handle. */
+static phandle_t
+ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t instance;
+		cell_t package;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"instance-to-package";
+	args.nargs = 1;
+	args.nreturns = 1;
+
+	args.instance = instance;
+	ofw_real_start();
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	return (args.package);
+}
+
+/* Get the length of a property of a package. */
+static ssize_t
+ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t package;
+		cell_t propname;
+		int32_t proplen;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"getproplen";
+	args.nargs = 2;
+	args.nreturns = 1;
+
+	ofw_real_start();
+
+	args.package = package;
+	args.propname = ofw_real_map(propname, strlen(propname) + 1);
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.propname == 0 || openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	return (args.proplen);
+}
+
+/* Get the value of a property of a package. */
+static ssize_t
+ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, 
+    size_t buflen)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t package;
+		cell_t propname;
+		cell_t buf;
+		cell_t buflen;
+		int32_t size;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"getprop";
+	args.nargs = 4;
+	args.nreturns = 1;
+
+	ofw_real_start();
+
+	args.package = package;
+	args.propname = ofw_real_map(propname, strlen(propname) + 1);
+	args.buf = ofw_real_map(buf, buflen);
+	args.buflen = buflen;
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.propname == 0 || args.buf == 0 ||
+	    openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_unmap(args.buf, buf, buflen);
+
+	ofw_real_stop();
+	return (args.size);
+}
+
+/* Get the next property of a package. */
+static int
+ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous, 
+    char *buf, size_t size)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t package;
+		cell_t previous;
+		cell_t buf;
+		cell_t flag;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"nextprop";
+	args.nargs = 3;
+	args.nreturns = 1;
+
+	ofw_real_start();
+
+	args.package = package;
+	args.previous = ofw_real_map(previous, (previous != NULL) ? (strlen(previous) + 1) : 0);
+	args.buf = ofw_real_map(buf, size);
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.buf == 0 || openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_unmap(args.buf, buf, size);
+
+	ofw_real_stop();
+	return (args.flag);
+}
+
+/* Set the value of a property of a package. */
+/* XXX Has a bug on FirePower */
+static int
+ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
+    const void *buf, size_t len)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t package;
+		cell_t propname;
+		cell_t buf;
+		cell_t len;
+		cell_t size;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"setprop";
+	args.nargs = 4;
+	args.nreturns = 1;
+
+	ofw_real_start();
+
+	args.package = package;
+	args.propname = ofw_real_map(propname, strlen(propname) + 1);
+	args.buf = ofw_real_map(buf, len);
+	args.len = len;
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.propname == 0 || args.buf == 0 ||
+	    openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	return (args.size);
+}
+
+/* Convert a device specifier to a fully qualified pathname. */
+static ssize_t
+ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t device;
+		cell_t buf;
+		cell_t len;
+		int32_t size;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"canon";
+	args.nargs = 3;
+	args.nreturns = 1;
+
+	ofw_real_start();
+
+	args.device = ofw_real_map(device, strlen(device) + 1);
+	args.buf = ofw_real_map(buf, len);
+	args.len = len;
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.device == 0 || args.buf == 0 ||
+	    openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_unmap(args.buf, buf, len);
+
+	ofw_real_stop();
+	return (args.size);
+}
+
+/* Return a package handle for the specified device. */
+static phandle_t
+ofw_real_finddevice(ofw_t ofw, const char *device)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t device;
+		cell_t package;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"finddevice";
+	args.nargs = 1;
+	args.nreturns = 1;
+
+	ofw_real_start();
+
+	args.device = ofw_real_map(device, strlen(device) + 1);
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.device == 0 ||
+	    openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	return (args.package);
+}
+
+/* Return the fully qualified pathname corresponding to an instance. */
+static ssize_t
+ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t instance;
+		cell_t buf;
+		cell_t len;
+		int32_t size;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"instance-to-path";
+	args.nargs = 3;
+	args.nreturns = 1;
+
+	ofw_real_start();
+
+	args.instance = instance;
+	args.buf = ofw_real_map(buf, len);
+	args.len = len;
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.buf == 0 ||
+	    openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_unmap(args.buf, buf, len);
+
+	ofw_real_stop();
+	return (args.size);
+}
+
+/* Return the fully qualified pathname corresponding to a package. */
+static ssize_t
+ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t package;
+		cell_t buf;
+		cell_t len;
+		int32_t size;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"package-to-path";
+	args.nargs = 3;
+	args.nreturns = 1;
+
+	ofw_real_start();
+
+	args.package = package;
+	args.buf = ofw_real_map(buf, len);
+	args.len = len;
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.buf == 0 ||
+	    openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_unmap(args.buf, buf, len);
+
+	ofw_real_stop();
+	return (args.size);
+}
+
+/*  Call the method in the scope of a given instance. */
+static int
+ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, 
+    int nargs, int nreturns, cell_t *args_and_returns)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t method;
+		cell_t instance;
+		cell_t args_n_results[12];
+	} args;
+	cell_t *ap, *cp;
+	int n;
+
+	args.name = (cell_t)(uintptr_t)"call-method";
+	args.nargs = 2;
+	args.nreturns = 1;
+
+	if (nargs > 6)
+		return (-1);
+
+	ofw_real_start();
+	args.nargs = nargs + 2;
+	args.nreturns = nreturns + 1;
+	args.method = ofw_real_map(method, strlen(method) + 1);
+	args.instance = instance;
+
+	ap = args_and_returns;
+	for (cp = args.args_n_results + (n = nargs); --n >= 0;)
+		*--cp = *(ap++);
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.method == 0 ||
+	    openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	if (args.args_n_results[nargs])
+		return (args.args_n_results[nargs]);
+	for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
+		*(ap++) = *--cp;
+	return (0);
+}
+
+static int
+ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t slot[16];
+	} args;
+	cell_t status;
+	int i = 0, j = 0;
+
+	args.name = (cell_t)(uintptr_t)"interpret";
+	args.nargs = 1;
+
+	ofw_real_start();
+	args.nreturns = ++nreturns;
+	args.slot[i++] = ofw_real_map(cmd, strlen(cmd) + 1);
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	status = args.slot[i++];
+	while (i < 1 + nreturns)
+		returns[j++] = args.slot[i++];
+	return (status);
+}
+
+/*
+ * Device I/O functions
+ */
+
+/* Open an instance for a device. */
+static ihandle_t
+ofw_real_open(ofw_t ofw, const char *device)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t device;
+		cell_t instance;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"open";
+	args.nargs = 1;
+	args.nreturns = 1;
+
+	ofw_real_start();
+
+	args.device = ofw_real_map(device, strlen(device) + 1);
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.device == 0 || openfirmware((void *)argsptr) == -1 
+	    || args.instance == 0) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	return (args.instance);
+}
+
+/* Close an instance. */
+static void
+ofw_real_close(ofw_t ofw, ihandle_t instance)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t instance;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"close";
+	args.nargs = 1;
+	args.nreturns = 0;
+	args.instance = instance;
+	ofw_real_start();
+	argsptr = ofw_real_map(&args, sizeof(args));
+	openfirmware((void *)argsptr);
+	ofw_real_stop();
+}
+
+/* Read from an instance. */
+static ssize_t
+ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t instance;
+		cell_t addr;
+		cell_t len;
+		int32_t actual;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"read";
+	args.nargs = 3;
+	args.nreturns = 1;
+
+	ofw_real_start();
+
+	args.instance = instance;
+	args.addr = ofw_real_map(addr, len);
+	args.len = len;
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_unmap(args.addr, addr, len);
+
+	ofw_real_stop();
+	return (args.actual);
+}
+
+/* Write to an instance. */
+static ssize_t
+ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t instance;
+		cell_t addr;
+		cell_t len;
+		int32_t actual;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"write";
+	args.nargs = 3;
+	args.nreturns = 1;
+
+	ofw_real_start();
+
+	args.instance = instance;
+	args.addr = ofw_real_map(addr, len);
+	args.len = len;
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	return (args.actual);
+}
+
+/* Seek to a position. */
+static int
+ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t instance;
+		cell_t poshi;
+		cell_t poslo;
+		cell_t status;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"seek";
+	args.nargs = 3;
+	args.nreturns = 1;
+
+	args.instance = instance;
+	args.poshi = pos >> 32;
+	args.poslo = pos;
+	ofw_real_start();
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return (-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	return (args.status);
+}
+
+/*
+ * Memory functions
+ */
+
+/* Claim an area of memory. */
+static caddr_t
+ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t virt;
+		cell_t size;
+		cell_t align;
+		cell_t baseaddr;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"claim";
+	args.nargs = 3;
+	args.nreturns = 1;
+
+	args.virt = (cell_t)(uintptr_t)virt;
+	args.size = size;
+	args.align = align;
+	ofw_real_start();
+	argsptr = ofw_real_map(&args, sizeof(args));
+	if (openfirmware((void *)argsptr) == -1) {
+		ofw_real_stop();
+		return ((void *)-1);
+	}
+	ofw_real_unmap(argsptr, &args, sizeof(args));
+	ofw_real_stop();
+	return ((void *)(uintptr_t)args.baseaddr);
+}
+
+/* Release an area of memory. */
+static void
+ofw_real_release(ofw_t ofw, void *virt, size_t size)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t virt;
+		cell_t size;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"release";
+	args.nargs = 2;
+	args.nreturns = 0;
+
+	args.virt = (cell_t)(uintptr_t)virt;
+	args.size = size;
+	ofw_real_start();
+	argsptr = ofw_real_map(&args, sizeof(args));
+	openfirmware((void *)argsptr);
+	ofw_real_stop();
+}
+
+/*
+ * Control transfer functions
+ */
+
+/* Suspend and drop back to the Open Firmware interface. */
+static void
+ofw_real_enter(ofw_t ofw)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"enter";
+	args.nargs = 0;
+	args.nreturns = 0;
+
+	ofw_real_start();
+	argsptr = ofw_real_map(&args, sizeof(args));
+	openfirmware((void *)argsptr);
+	/* We may come back. */
+	ofw_real_stop();
+}
+
+/* Shut down and drop back to the Open Firmware interface. */
+static void
+ofw_real_exit(ofw_t ofw)
+{
+	vm_offset_t argsptr;
+	struct {
+		cell_t name;
+		cell_t nargs;
+		cell_t nreturns;
+	} args;
+
+	args.name = (cell_t)(uintptr_t)"exit";
+	args.nargs = 0;
+	args.nreturns = 0;
+
+	ofw_real_start();
+	argsptr = ofw_real_map(&args, sizeof(args));
+	openfirmware((void *)argsptr);
+	for (;;)			/* just in case */
+		;
+	ofw_real_stop();
+}
+


Property changes on: trunk/sys/powerpc/ofw/ofw_real.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/ofw_syscons.c
===================================================================
--- trunk/sys/powerpc/ofw/ofw_syscons.c	                        (rev 0)
+++ trunk/sys/powerpc/ofw/ofw_syscons.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,1109 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Peter Grehan
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ofw/ofw_syscons.c 266019 2014-05-14 14:08:45Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/limits.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/fbio.h>
+#include <sys/consio.h>
+
+#include <machine/bus.h>
+#include <machine/sc_machdep.h>
+#include <machine/vm.h>
+
+#include <sys/rman.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/syscons/syscons.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_pci.h>
+#include <powerpc/ofw/ofw_syscons.h>
+
+static int ofwfb_ignore_mmap_checks = 1;
+static int ofwfb_reset_on_switch = 1;
+static SYSCTL_NODE(_hw, OID_AUTO, ofwfb, CTLFLAG_RD, 0, "ofwfb");
+SYSCTL_INT(_hw_ofwfb, OID_AUTO, relax_mmap, CTLFLAG_RW,
+    &ofwfb_ignore_mmap_checks, 0, "relaxed mmap bounds checking");
+SYSCTL_INT(_hw_ofwfb, OID_AUTO, reset_on_mode_switch, CTLFLAG_RW,
+    &ofwfb_reset_on_switch, 0, "reset the framebuffer driver on mode switch");
+
+extern u_char dflt_font_16[];
+extern u_char dflt_font_14[];
+extern u_char dflt_font_8[];
+
+static int ofwfb_configure(int flags);
+
+static vi_probe_t ofwfb_probe;
+static vi_init_t ofwfb_init;
+static vi_get_info_t ofwfb_get_info;
+static vi_query_mode_t ofwfb_query_mode;
+static vi_set_mode_t ofwfb_set_mode;
+static vi_save_font_t ofwfb_save_font;
+static vi_load_font_t ofwfb_load_font;
+static vi_show_font_t ofwfb_show_font;
+static vi_save_palette_t ofwfb_save_palette;
+static vi_load_palette_t ofwfb_load_palette;
+static vi_set_border_t ofwfb_set_border;
+static vi_save_state_t ofwfb_save_state;
+static vi_load_state_t ofwfb_load_state;
+static vi_set_win_org_t ofwfb_set_win_org;
+static vi_read_hw_cursor_t ofwfb_read_hw_cursor;
+static vi_set_hw_cursor_t ofwfb_set_hw_cursor;
+static vi_set_hw_cursor_shape_t ofwfb_set_hw_cursor_shape;
+static vi_blank_display_t ofwfb_blank_display;
+static vi_mmap_t ofwfb_mmap;
+static vi_ioctl_t ofwfb_ioctl;
+static vi_clear_t ofwfb_clear;
+static vi_fill_rect_t ofwfb_fill_rect;
+static vi_bitblt_t ofwfb_bitblt;
+static vi_diag_t ofwfb_diag;
+static vi_save_cursor_palette_t ofwfb_save_cursor_palette;
+static vi_load_cursor_palette_t ofwfb_load_cursor_palette;
+static vi_copy_t ofwfb_copy;
+static vi_putp_t ofwfb_putp;
+static vi_putc_t ofwfb_putc;
+static vi_puts_t ofwfb_puts;
+static vi_putm_t ofwfb_putm;
+
+static video_switch_t ofwfbvidsw = {
+	.probe			= ofwfb_probe,
+	.init			= ofwfb_init,
+	.get_info		= ofwfb_get_info,
+	.query_mode		= ofwfb_query_mode,
+	.set_mode		= ofwfb_set_mode,
+	.save_font		= ofwfb_save_font,
+	.load_font		= ofwfb_load_font,
+	.show_font		= ofwfb_show_font,
+	.save_palette		= ofwfb_save_palette,
+	.load_palette		= ofwfb_load_palette,
+	.set_border		= ofwfb_set_border,
+	.save_state		= ofwfb_save_state,
+	.load_state		= ofwfb_load_state,
+	.set_win_org		= ofwfb_set_win_org,
+	.read_hw_cursor		= ofwfb_read_hw_cursor,
+	.set_hw_cursor		= ofwfb_set_hw_cursor,
+	.set_hw_cursor_shape	= ofwfb_set_hw_cursor_shape,
+	.blank_display		= ofwfb_blank_display,
+	.mmap			= ofwfb_mmap,
+	.ioctl			= ofwfb_ioctl,
+	.clear			= ofwfb_clear,
+	.fill_rect		= ofwfb_fill_rect,
+	.bitblt			= ofwfb_bitblt,
+	.diag			= ofwfb_diag,
+	.save_cursor_palette	= ofwfb_save_cursor_palette,
+	.load_cursor_palette	= ofwfb_load_cursor_palette,
+	.copy			= ofwfb_copy,
+	.putp			= ofwfb_putp,
+	.putc			= ofwfb_putc,
+	.puts			= ofwfb_puts,
+	.putm			= ofwfb_putm,
+};
+
+/*
+ * bitmap depth-specific routines
+ */
+static vi_blank_display_t ofwfb_blank_display8;
+static vi_putc_t ofwfb_putc8;
+static vi_putm_t ofwfb_putm8;
+static vi_set_border_t ofwfb_set_border8;
+
+static vi_blank_display_t ofwfb_blank_display32;
+static vi_putc_t ofwfb_putc32;
+static vi_putm_t ofwfb_putm32;
+static vi_set_border_t ofwfb_set_border32;
+
+VIDEO_DRIVER(ofwfb, ofwfbvidsw, ofwfb_configure);
+
+extern sc_rndr_sw_t txtrndrsw;
+RENDERER(ofwfb, 0, txtrndrsw, gfb_set);
+
+RENDERER_MODULE(ofwfb, gfb_set);
+
+/*
+ * Define the iso6429-1983 colormap
+ */
+static struct {
+	uint8_t	red;
+	uint8_t	green;
+	uint8_t	blue;
+} ofwfb_cmap[16] = {		/*  #     R    G    B   Color */
+				/*  -     -    -    -   ----- */
+	{ 0x00, 0x00, 0x00 },	/*  0     0    0    0   Black */
+	{ 0x00, 0x00, 0xaa },	/*  1     0    0  2/3   Blue  */
+	{ 0x00, 0xaa, 0x00 },	/*  2     0  2/3    0   Green */
+	{ 0x00, 0xaa, 0xaa },	/*  3     0  2/3  2/3   Cyan  */
+	{ 0xaa, 0x00, 0x00 },	/*  4   2/3    0    0   Red   */
+	{ 0xaa, 0x00, 0xaa },	/*  5   2/3    0  2/3   Magenta */
+	{ 0xaa, 0x55, 0x00 },	/*  6   2/3  1/3    0   Brown */
+	{ 0xaa, 0xaa, 0xaa },	/*  7   2/3  2/3  2/3   White */
+        { 0x55, 0x55, 0x55 },	/*  8   1/3  1/3  1/3   Gray  */
+	{ 0x55, 0x55, 0xff },	/*  9   1/3  1/3    1   Bright Blue  */
+	{ 0x55, 0xff, 0x55 },	/* 10   1/3    1  1/3   Bright Green */
+	{ 0x55, 0xff, 0xff },	/* 11   1/3    1    1   Bright Cyan  */
+	{ 0xff, 0x55, 0x55 },	/* 12     1  1/3  1/3   Bright Red   */
+	{ 0xff, 0x55, 0xff },	/* 13     1  1/3    1   Bright Magenta */
+	{ 0xff, 0xff, 0x80 },	/* 14     1    1  1/3   Bright Yellow */
+	{ 0xff, 0xff, 0xff }	/* 15     1    1    1   Bright White */
+};
+
+#define	TODO	printf("%s: unimplemented\n", __func__)
+
+static u_int16_t ofwfb_static_window[ROW*COL];
+
+static struct ofwfb_softc ofwfb_softc;
+
+static __inline int
+ofwfb_background(uint8_t attr)
+{
+	return (attr >> 4);
+}
+
+static __inline int
+ofwfb_foreground(uint8_t attr)
+{
+	return (attr & 0x0f);
+}
+
+static u_int
+ofwfb_pix32(struct ofwfb_softc *sc, int attr)
+{
+	u_int retval;
+
+	if (sc->sc_tag == &bs_le_tag)
+		retval = (ofwfb_cmap[attr].red << 16) |
+			(ofwfb_cmap[attr].green << 8) |
+			ofwfb_cmap[attr].blue;
+	else
+		retval = (ofwfb_cmap[attr].blue  << 16) |
+			(ofwfb_cmap[attr].green << 8) |
+			ofwfb_cmap[attr].red;
+
+	return (retval);
+}
+
+static int
+ofwfb_configure(int flags)
+{
+	struct ofwfb_softc *sc;
+        phandle_t chosen;
+        ihandle_t stdout;
+	phandle_t node;
+	uint32_t fb_phys;
+	int depth;
+	int disable;
+	int len;
+	int i;
+	char type[16];
+	static int done = 0;
+
+	disable = 0;
+	TUNABLE_INT_FETCH("hw.syscons.disable", &disable);
+	if (disable != 0)
+		return (0);
+
+	if (done != 0)
+		return (0);
+	done = 1;
+
+	sc = &ofwfb_softc;
+
+	chosen = OF_finddevice("/chosen");
+	OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
+        node = OF_instance_to_package(stdout);
+	if (node == -1) {
+		/*
+		 * The "/chosen/stdout" does not exist try
+		 * using "screen" directly.
+		 */
+		node = OF_finddevice("screen");
+	}
+	OF_getprop(node, "device_type", type, sizeof(type));
+	if (strcmp(type, "display") != 0)
+		return (0);
+
+	/* Only support 8 and 32-bit framebuffers */
+	OF_getprop(node, "depth", &depth, sizeof(depth));
+	if (depth == 8) {
+		sc->sc_blank = ofwfb_blank_display8;
+		sc->sc_putc = ofwfb_putc8;
+		sc->sc_putm = ofwfb_putm8;
+		sc->sc_set_border = ofwfb_set_border8;
+	} else if (depth == 32) {
+		sc->sc_blank = ofwfb_blank_display32;
+		sc->sc_putc = ofwfb_putc32;
+		sc->sc_putm = ofwfb_putm32;
+		sc->sc_set_border = ofwfb_set_border32;
+	} else
+		return (0);
+
+	if (OF_getproplen(node, "height") != sizeof(sc->sc_height) ||
+	    OF_getproplen(node, "width") != sizeof(sc->sc_width) ||
+	    OF_getproplen(node, "linebytes") != sizeof(sc->sc_stride))
+		return (0);
+
+	sc->sc_depth = depth;
+	sc->sc_node = node;
+	sc->sc_console = 1;
+	OF_getprop(node, "height", &sc->sc_height, sizeof(sc->sc_height));
+	OF_getprop(node, "width", &sc->sc_width, sizeof(sc->sc_width));
+	OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride));
+
+	/*
+	 * Get the PCI addresses of the adapter. The node may be the
+	 * child of the PCI device: in that case, try the parent for
+	 * the assigned-addresses property.
+	 */
+	len = OF_getprop(node, "assigned-addresses", sc->sc_pciaddrs,
+	          sizeof(sc->sc_pciaddrs));
+	if (len == -1) {
+		len = OF_getprop(OF_parent(node), "assigned-addresses",
+		    sc->sc_pciaddrs, sizeof(sc->sc_pciaddrs));
+	}
+	if (len == -1)
+		len = 0;
+	sc->sc_num_pciaddrs = len / sizeof(struct ofw_pci_register);
+
+	/*
+	 * Grab the physical address of the framebuffer, and then map it
+	 * into our memory space. If the MMU is not yet up, it will be
+	 * remapped for us when relocation turns on.
+	 *
+	 * XXX We assume #address-cells is 1 at this point.
+	 */
+	if (OF_getproplen(node, "address") == sizeof(fb_phys)) {
+		OF_getprop(node, "address", &fb_phys, sizeof(fb_phys));
+		sc->sc_tag = &bs_be_tag;
+		bus_space_map(sc->sc_tag, fb_phys, sc->sc_height *
+		    sc->sc_stride, BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_addr);
+	} else {
+		/*
+		 * Some IBM systems don't have an address property. Try to
+		 * guess the framebuffer region from the assigned addresses.
+		 * This is ugly, but there doesn't seem to be an alternative.
+		 * Linux does the same thing.
+		 */
+
+		fb_phys = sc->sc_num_pciaddrs;
+		for (i = 0; i < sc->sc_num_pciaddrs; i++) {
+			/* If it is too small, not the framebuffer */
+			if (sc->sc_pciaddrs[i].size_lo <
+			    sc->sc_stride*sc->sc_height)
+				continue;
+			/* If it is not memory, it isn't either */
+			if (!(sc->sc_pciaddrs[i].phys_hi &
+			    OFW_PCI_PHYS_HI_SPACE_MEM32))
+				continue;
+
+			/* This could be the framebuffer */
+			fb_phys = i;
+
+			/* If it is prefetchable, it certainly is */
+			if (sc->sc_pciaddrs[i].phys_hi &
+			    OFW_PCI_PHYS_HI_PREFETCHABLE)
+				break;
+		}
+		if (fb_phys == sc->sc_num_pciaddrs)
+			return (0);
+
+		OF_decode_addr(node, fb_phys, &sc->sc_tag, &sc->sc_addr);
+	}
+
+	ofwfb_init(0, &sc->sc_va, 0);
+
+	return (0);
+}
+
+static int
+ofwfb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_init(int unit, video_adapter_t *adp, int flags)
+{
+	struct ofwfb_softc *sc;
+	video_info_t *vi;
+	int cborder;
+	int font_height;
+
+	sc = (struct ofwfb_softc *)adp;
+	vi = &adp->va_info;
+
+	vid_init_struct(adp, "ofwfb", -1, unit);
+
+	/* The default font size can be overridden by loader */
+	font_height = 16;
+	TUNABLE_INT_FETCH("hw.syscons.fsize", &font_height);
+	if (font_height == 8) {
+		sc->sc_font = dflt_font_8;
+		sc->sc_font_height = 8;
+	} else if (font_height == 14) {
+		sc->sc_font = dflt_font_14;
+		sc->sc_font_height = 14;
+	} else {
+		/* default is 8x16 */
+		sc->sc_font = dflt_font_16;
+		sc->sc_font_height = 16;
+	}
+
+	/* The user can set a border in chars - default is 1 char width */
+	cborder = 1;
+	TUNABLE_INT_FETCH("hw.syscons.border", &cborder);
+
+	vi->vi_cheight = sc->sc_font_height;
+	vi->vi_width = sc->sc_width/8 - 2*cborder;
+	vi->vi_height = sc->sc_height/sc->sc_font_height - 2*cborder;
+	vi->vi_cwidth = 8;
+
+	/*
+	 * Clamp width/height to syscons maximums
+	 */
+	if (vi->vi_width > COL)
+		vi->vi_width = COL;
+	if (vi->vi_height > ROW)
+		vi->vi_height = ROW;
+
+	sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2;
+	sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight))/2;
+
+	/*
+	 * Avoid huge amounts of conditional code in syscons by
+	 * defining a dummy h/w text display buffer.
+	 */
+	adp->va_window = (vm_offset_t) ofwfb_static_window;
+
+	/*
+	 * Enable future font-loading and flag color support, as well as 
+	 * adding V_ADP_MODECHANGE so that we ofwfb_set_mode() gets called
+	 * when the X server shuts down. This enables us to get the console
+	 * back when X disappears.
+	 */
+	adp->va_flags |= V_ADP_FONT | V_ADP_COLOR | V_ADP_MODECHANGE;
+
+	ofwfb_set_mode(&sc->sc_va, 0);
+
+	vid_register(&sc->sc_va);
+
+	return (0);
+}
+
+static int
+ofwfb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
+{
+	bcopy(&adp->va_info, info, sizeof(*info));
+	return (0);
+}
+
+static int
+ofwfb_query_mode(video_adapter_t *adp, video_info_t *info)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_set_mode(video_adapter_t *adp, int mode)
+{
+	struct ofwfb_softc *sc;
+	char name[64];
+	ihandle_t ih;
+	int i, retval;
+
+	sc = (struct ofwfb_softc *)adp;
+
+	if (ofwfb_reset_on_switch) {
+		/*
+		 * Open the display device, which will initialize it.
+		 */
+
+		memset(name, 0, sizeof(name));
+		OF_package_to_path(sc->sc_node, name, sizeof(name));
+		ih = OF_open(name);
+
+		if (sc->sc_depth == 8) {
+			/*
+			 * Install the ISO6429 colormap - older OFW systems
+			 * don't do this by default
+			 */
+			for (i = 0; i < 16; i++) {
+				OF_call_method("color!", ih, 4, 1,
+						   ofwfb_cmap[i].red,
+						   ofwfb_cmap[i].green,
+						   ofwfb_cmap[i].blue,
+						   i,
+						   &retval);
+			}
+		}
+	}
+
+	ofwfb_blank_display(&sc->sc_va, V_DISPLAY_ON);
+
+	return (0);
+}
+
+static int
+ofwfb_save_font(video_adapter_t *adp, int page, int size, int width,
+    u_char *data, int c, int count)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_load_font(video_adapter_t *adp, int page, int size, int width,
+    u_char *data, int c, int count)
+{
+	struct ofwfb_softc *sc;
+
+	sc = (struct ofwfb_softc *)adp;
+
+	/*
+	 * syscons code has already determined that current width/height
+	 * are unchanged for this new font
+	 */
+	sc->sc_font = data;
+	return (0);
+}
+
+static int
+ofwfb_show_font(video_adapter_t *adp, int page)
+{
+
+	return (0);
+}
+
+static int
+ofwfb_save_palette(video_adapter_t *adp, u_char *palette)
+{
+	/* TODO; */
+	return (0);
+}
+
+static int
+ofwfb_load_palette(video_adapter_t *adp, u_char *palette)
+{
+	/* TODO; */
+	return (0);
+}
+
+static int
+ofwfb_set_border8(video_adapter_t *adp, int border)
+{
+	struct ofwfb_softc *sc;
+	int i, j;
+	uint8_t *addr;
+	uint8_t bground;
+
+	sc = (struct ofwfb_softc *)adp;
+
+	bground = ofwfb_background(border);
+
+	/* Set top margin */
+	addr = (uint8_t *) sc->sc_addr;
+	for (i = 0; i < sc->sc_ymargin; i++) {
+		for (j = 0; j < sc->sc_width; j++) {
+			*(addr + j) = bground;
+		}
+		addr += sc->sc_stride;
+	}
+
+	/* bottom margin */
+	addr = (uint8_t *) sc->sc_addr + (sc->sc_height - sc->sc_ymargin)*sc->sc_stride;
+	for (i = 0; i < sc->sc_ymargin; i++) {
+		for (j = 0; j < sc->sc_width; j++) {
+			*(addr + j) = bground;
+		}
+		addr += sc->sc_stride;
+	}
+
+	/* remaining left and right borders */
+	addr = (uint8_t *) sc->sc_addr + sc->sc_ymargin*sc->sc_stride;
+	for (i = 0; i < sc->sc_height - 2*sc->sc_xmargin; i++) {
+		for (j = 0; j < sc->sc_xmargin; j++) {
+			*(addr + j) = bground;
+			*(addr + j + sc->sc_width - sc->sc_xmargin) = bground;
+		}
+		addr += sc->sc_stride;
+	}
+
+	return (0);
+}
+
+static int
+ofwfb_set_border32(video_adapter_t *adp, int border)
+{
+	/* XXX Be lazy for now and blank entire screen */
+	return (ofwfb_blank_display32(adp, border));
+}
+
+static int
+ofwfb_set_border(video_adapter_t *adp, int border)
+{
+	struct ofwfb_softc *sc;
+
+	sc = (struct ofwfb_softc *)adp;
+
+	return ((*sc->sc_set_border)(adp, border));
+}
+
+static int
+ofwfb_save_state(video_adapter_t *adp, void *p, size_t size)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_load_state(video_adapter_t *adp, void *p)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_set_win_org(video_adapter_t *adp, off_t offset)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
+{
+	*col = 0;
+	*row = 0;
+
+	return (0);
+}
+
+static int
+ofwfb_set_hw_cursor(video_adapter_t *adp, int col, int row)
+{
+
+	return (0);
+}
+
+static int
+ofwfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
+    int celsize, int blink)
+{
+	return (0);
+}
+
+static int
+ofwfb_blank_display8(video_adapter_t *adp, int mode)
+{
+	struct ofwfb_softc *sc;
+	int i;
+	uint32_t *addr;
+	uint32_t color;
+	uint32_t end;
+
+	sc = (struct ofwfb_softc *)adp;
+	addr = (uint32_t *) sc->sc_addr;
+	end = (sc->sc_stride/4) * sc->sc_height;
+
+	/* Splat 4 pixels at once. */
+	color = (ofwfb_background(SC_NORM_ATTR) << 24) |
+	    (ofwfb_background(SC_NORM_ATTR) << 16) |
+	    (ofwfb_background(SC_NORM_ATTR) << 8) |
+	    (ofwfb_background(SC_NORM_ATTR));
+
+	for (i = 0; i < end; i++)
+		*(addr + i) = color;
+
+	return (0);
+}
+
+static int
+ofwfb_blank_display32(video_adapter_t *adp, int mode)
+{
+	struct ofwfb_softc *sc;
+	int i;
+	uint32_t *addr, blank;
+
+	sc = (struct ofwfb_softc *)adp;
+	addr = (uint32_t *) sc->sc_addr;
+	blank = ofwfb_pix32(sc, ofwfb_background(SC_NORM_ATTR));
+
+	for (i = 0; i < (sc->sc_stride/4)*sc->sc_height; i++)
+		*(addr + i) = blank;
+
+	return (0);
+}
+
+static int
+ofwfb_blank_display(video_adapter_t *adp, int mode)
+{
+	struct ofwfb_softc *sc;
+
+	sc = (struct ofwfb_softc *)adp;
+
+	return ((*sc->sc_blank)(adp, mode));
+}
+
+static int
+ofwfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
+    int prot, vm_memattr_t *memattr)
+{
+	struct ofwfb_softc *sc;
+	int i;
+
+	sc = (struct ofwfb_softc *)adp;
+
+	/*
+	 * Make sure the requested address lies within the PCI device's
+	 * assigned addrs
+	 */
+	for (i = 0; i < sc->sc_num_pciaddrs; i++)
+	  if (offset >= sc->sc_pciaddrs[i].phys_lo &&
+	    offset < (sc->sc_pciaddrs[i].phys_lo + sc->sc_pciaddrs[i].size_lo))
+		{
+			/*
+			 * If this is a prefetchable BAR, we can (and should)
+			 * enable write-combining.
+			 */
+			if (sc->sc_pciaddrs[i].phys_hi &
+			    OFW_PCI_PHYS_HI_PREFETCHABLE)
+				*memattr = VM_MEMATTR_WRITE_COMBINING;
+
+			*paddr = offset;
+			return (0);
+		}
+
+	/*
+	 * Hack for Radeon...
+	 */
+	if (ofwfb_ignore_mmap_checks) {
+		*paddr = offset;
+		return (0);
+	}
+
+	/*
+	 * This might be a legacy VGA mem request: if so, just point it at the
+	 * framebuffer, since it shouldn't be touched
+	 */
+	if (offset < sc->sc_stride*sc->sc_height) {
+		*paddr = sc->sc_addr + offset;
+		return (0);
+	}
+
+	/*
+	 * Error if we didn't have a better idea.
+	 */
+	if (sc->sc_num_pciaddrs == 0)
+		return (ENOMEM);
+
+	return (EINVAL);
+}
+
+static int
+ofwfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
+{
+
+	return (0);
+}
+
+static int
+ofwfb_clear(video_adapter_t *adp)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_bitblt(video_adapter_t *adp, ...)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_diag(video_adapter_t *adp, int level)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
+    int size, int bpp, int bit_ltor, int byte_ltor)
+{
+	TODO;
+	return (0);
+}
+
+static int
+ofwfb_putc8(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
+{
+	struct ofwfb_softc *sc;
+	int row;
+	int col;
+	int i;
+	uint32_t *addr;
+	u_char *p, fg, bg;
+	union {
+		uint32_t l;
+		uint8_t  c[4];
+	} ch1, ch2;
+
+
+	sc = (struct ofwfb_softc *)adp;
+        row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
+        col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
+	p = sc->sc_font + c*sc->sc_font_height;
+	addr = (u_int32_t *)((uintptr_t)sc->sc_addr
+		+ (row + sc->sc_ymargin)*sc->sc_stride
+		+ col + sc->sc_xmargin);
+
+	fg = ofwfb_foreground(a);
+	bg = ofwfb_background(a);
+
+	for (i = 0; i < sc->sc_font_height; i++) {
+		u_char fline = p[i];
+
+		/*
+		 * Assume that there is more background than foreground
+		 * in characters and init accordingly
+		 */
+		ch1.l = ch2.l = (bg << 24) | (bg << 16) | (bg << 8) | bg;
+
+		/*
+		 * Calculate 2 x 4-chars at a time, and then
+		 * write these out.
+		 */
+		if (fline & 0x80) ch1.c[0] = fg;
+		if (fline & 0x40) ch1.c[1] = fg;
+		if (fline & 0x20) ch1.c[2] = fg;
+		if (fline & 0x10) ch1.c[3] = fg;
+
+		if (fline & 0x08) ch2.c[0] = fg;
+		if (fline & 0x04) ch2.c[1] = fg;
+		if (fline & 0x02) ch2.c[2] = fg;
+		if (fline & 0x01) ch2.c[3] = fg;
+
+		addr[0] = ch1.l;
+		addr[1] = ch2.l;
+		addr += (sc->sc_stride / sizeof(u_int32_t));
+	}
+
+	return (0);
+}
+
+static int
+ofwfb_putc32(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
+{
+	struct ofwfb_softc *sc;
+	int row;
+	int col;
+	int i, j, k;
+	uint32_t *addr, fg, bg;
+	u_char *p;
+
+	sc = (struct ofwfb_softc *)adp;
+        row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
+        col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
+	p = sc->sc_font + c*sc->sc_font_height;
+	addr = (uint32_t *)sc->sc_addr
+		+ (row + sc->sc_ymargin)*(sc->sc_stride/4)
+		+ col + sc->sc_xmargin;
+	
+	fg = ofwfb_pix32(sc, ofwfb_foreground(a));
+	bg = ofwfb_pix32(sc, ofwfb_background(a));
+
+	for (i = 0; i < sc->sc_font_height; i++) {
+		for (j = 0, k = 7; j < 8; j++, k--) {
+			if ((p[i] & (1 << k)) == 0)
+				*(addr + j) = bg;
+			else
+				*(addr + j) = fg;
+		}
+		addr += (sc->sc_stride/4);
+	}
+
+	return (0);
+}
+
+static int
+ofwfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
+{
+	struct ofwfb_softc *sc;
+
+	sc = (struct ofwfb_softc *)adp;
+
+	return ((*sc->sc_putc)(adp, off, c, a));
+}
+
+static int
+ofwfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++) {
+		ofwfb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
+	}
+	return (0);
+}
+
+static int
+ofwfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
+    uint32_t pixel_mask, int size, int width)
+{
+	struct ofwfb_softc *sc;
+
+	sc = (struct ofwfb_softc *)adp;
+
+	return ((*sc->sc_putm)(adp, x, y, pixel_image, pixel_mask, size,
+	    width));
+}
+
+static int
+ofwfb_putm8(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
+    uint32_t pixel_mask, int size, int width)
+{
+	struct ofwfb_softc *sc;
+	int i, j, k;
+	uint8_t *addr;
+	u_char fg, bg;
+
+	sc = (struct ofwfb_softc *)adp;
+	addr = (u_int8_t *)((uintptr_t)sc->sc_addr
+		+ (y + sc->sc_ymargin)*sc->sc_stride
+		+ x + sc->sc_xmargin);
+
+	fg = ofwfb_foreground(SC_NORM_ATTR);
+	bg = ofwfb_background(SC_NORM_ATTR);
+
+	for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) {
+		/*
+		 * Calculate 2 x 4-chars at a time, and then
+		 * write these out.
+		 */
+		for (j = 0, k = width; j < 8; j++, k--) {
+			if (x + j >= sc->sc_width - 2*sc->sc_xmargin)
+				continue;
+
+			if (pixel_image[i] & (1 << k))
+				addr[j] = (addr[j] == fg) ? bg : fg;
+		}
+
+		addr += (sc->sc_stride / sizeof(u_int8_t));
+	}
+
+	return (0);
+}
+
+static int
+ofwfb_putm32(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
+    uint32_t pixel_mask, int size, int width)
+{
+	struct ofwfb_softc *sc;
+	int i, j, k;
+	uint32_t fg, bg;
+	uint32_t *addr;
+
+	sc = (struct ofwfb_softc *)adp;
+	addr = (uint32_t *)sc->sc_addr
+		+ (y + sc->sc_ymargin)*(sc->sc_stride/4)
+		+ x + sc->sc_xmargin;
+
+	fg = ofwfb_pix32(sc, ofwfb_foreground(SC_NORM_ATTR));
+	bg = ofwfb_pix32(sc, ofwfb_background(SC_NORM_ATTR));
+
+	for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) {
+		for (j = 0, k = width; j < 8; j++, k--) {
+			if (x + j >= sc->sc_width - 2*sc->sc_xmargin)
+				continue;
+
+			if (pixel_image[i] & (1 << k))
+				*(addr + j) = (*(addr + j) == fg) ? bg : fg;
+		}
+		addr += (sc->sc_stride/4);
+	}
+
+	return (0);
+}
+
+/*
+ * Define the syscons nexus device attachment
+ */
+static void
+ofwfb_scidentify(driver_t *driver, device_t parent)
+{
+	device_t child;
+
+	/*
+	 * The Nintendo Wii doesn't have open firmware, so don't probe ofwfb
+	 * because otherwise we will crash.
+	 */
+	if (strcmp(installed_platform(), "wii") == 0)
+		return;
+	/*
+	 * Add with a priority guaranteed to make it last on
+	 * the device list
+	 */
+	child = BUS_ADD_CHILD(parent, INT_MAX, SC_DRIVER_NAME, 0);
+}
+
+static int
+ofwfb_scprobe(device_t dev)
+{
+	int error;
+
+	device_set_desc(dev, "System console");
+
+	error = sc_probe_unit(device_get_unit(dev), 
+	    device_get_flags(dev) | SC_AUTODETECT_KBD);
+	if (error != 0)
+		return (error);
+
+	/* This is a fake device, so make sure we added it ourselves */
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+ofwfb_scattach(device_t dev)
+{
+	return (sc_attach_unit(device_get_unit(dev),
+	    device_get_flags(dev) | SC_AUTODETECT_KBD));
+}
+
+static device_method_t ofwfb_sc_methods[] = {
+  	DEVMETHOD(device_identify,	ofwfb_scidentify),
+	DEVMETHOD(device_probe,		ofwfb_scprobe),
+	DEVMETHOD(device_attach,	ofwfb_scattach),
+	{ 0, 0 }
+};
+
+static driver_t ofwfb_sc_driver = {
+	SC_DRIVER_NAME,
+	ofwfb_sc_methods,
+	sizeof(sc_softc_t),
+};
+
+static devclass_t	sc_devclass;
+
+DRIVER_MODULE(ofwfb, nexus, ofwfb_sc_driver, sc_devclass, 0, 0);
+
+/*
+ * Define a stub keyboard driver in case one hasn't been
+ * compiled into the kernel
+ */
+#include <sys/kbio.h>
+#include <dev/kbd/kbdreg.h>
+
+static int dummy_kbd_configure(int flags);
+
+keyboard_switch_t dummysw;
+
+static int
+dummy_kbd_configure(int flags)
+{
+
+	return (0);
+}
+KEYBOARD_DRIVER(dummy, dummysw, dummy_kbd_configure);
+
+/*
+ * Utility routines from <dev/fb/fbreg.h>
+ */
+void
+ofwfb_bcopy(const void *s, void *d, size_t c)
+{
+	bcopy(s, d, c);
+}
+
+void
+ofwfb_bzero(void *d, size_t c)
+{
+	bzero(d, c);
+}
+
+void
+ofwfb_fillw(int pat, void *base, size_t cnt)
+{
+	u_int16_t *bptr = base;
+
+	while (cnt--)
+		*bptr++ = pat;
+}
+
+u_int16_t
+ofwfb_readw(u_int16_t *addr)
+{
+	return (*addr);
+}
+
+void
+ofwfb_writew(u_int16_t *addr, u_int16_t val)
+{
+	*addr = val;
+}


Property changes on: trunk/sys/powerpc/ofw/ofw_syscons.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/ofw_syscons.h
===================================================================
--- trunk/sys/powerpc/ofw/ofw_syscons.h	                        (rev 0)
+++ trunk/sys/powerpc/ofw/ofw_syscons.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,64 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Peter Grehan
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ofw/ofw_syscons.h 255904 2013-09-26 22:47:02Z nwhitehorn $
+ */
+
+#ifndef _OFW_SYSCONS_H_
+#define _OFW_SYSCONS_H_
+
+struct ofwfb_softc {
+	video_adapter_t	sc_va;
+	struct cdev *sc_si;
+	bus_space_tag_t sc_tag;
+	phandle_t	sc_node;
+	int	       	sc_console;
+
+	intptr_t	sc_addr;
+	int		sc_depth;
+        int	       	sc_height;
+        int	       	sc_width;
+	int	       	sc_stride;
+        int	       	sc_ncol;
+        int	       	sc_nrow;
+
+	int	       	sc_xmargin;
+	int	       	sc_ymargin;
+
+	u_char	       *sc_font;
+	int		sc_font_height;
+
+	vi_blank_display_t *sc_blank;
+	vi_putc_t	*sc_putc;
+	vi_putm_t	*sc_putm;
+	vi_set_border_t	*sc_set_border;
+
+#define OFWSC_MAXADDR	8
+	int		sc_num_pciaddrs;
+	struct ofw_pci_register sc_pciaddrs[OFWSC_MAXADDR];
+};
+
+#endif


Property changes on: trunk/sys/powerpc/ofw/ofw_syscons.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/ofwcall32.S
===================================================================
--- trunk/sys/powerpc/ofw/ofwcall32.S	                        (rev 0)
+++ trunk/sys/powerpc/ofw/ofwcall32.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,157 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2009-2011 Nathan Whitehorn
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ofw/ofwcall32.S 223485 2011-06-23 22:21:28Z nwhitehorn $
+ */
+
+#include <sys/syscall.h>
+
+#include <machine/trap.h>
+#include <machine/param.h>
+#include <machine/spr.h>
+#include <machine/asm.h>
+
+#define	OFWSTKSZ	4096		/* 4K Open Firmware stack */
+
+/*
+ * Globals
+ */
+	.data
+GLOBAL(ofmsr)
+	.long	0, 0, 0, 0, 0		/* msr/sprg0-3 used in Open Firmware */
+GLOBAL(rtasmsr)
+	.long	0
+GLOBAL(openfirmware_entry)
+	.long	0			/* Open Firmware entry point */
+GLOBAL(rtas_entry)
+	.long	0			/* RTAS entry point */
+
+	.align	4
+ofwstk:
+	.space	OFWSTKSZ
+rtas_regsave:
+	.space	4
+
+/*
+ * Open Firmware Entry Point. May need to enter real mode.
+ *
+ * C prototype: int ofwcall(void *callbuffer);
+ */
+
+ASENTRY(ofwcall)
+	mflr	%r0
+	stw	%r0,4(%r1)
+
+	/* Record the old MSR */
+	mfmsr	%r6
+
+	/* read client interface handler */
+	lis	%r4,openfirmware_entry at ha
+	lwz	%r4,openfirmware_entry at l(%r4)
+
+	/*
+	 * Set the MSR to the OF value. This has the side effect of disabling
+	 * exceptions, which prevents preemption later.
+	 */
+
+	lis	%r5,ofmsr at ha
+	lwz	%r5,ofmsr at l(%r5)
+	mtmsr	%r5
+	isync
+
+	/*
+	 * Set up OF stack. This needs to be potentially accessible in real mode
+	 * The pointer to the current kernel stack is placed at the very
+	 * top of the stack along with the old MSR so we can get them back
+	 * later.
+	 */
+	mr	%r5,%r1
+	lis	%r1,(ofwstk+OFWSTKSZ-32)@ha
+	addi	%r1,%r1,(ofwstk+OFWSTKSZ-32)@l
+	stw	%r5,20(%r1)	/* Save real stack pointer */
+	stw	%r2,24(%r1)	/* Save curthread */
+	stw	%r6,28(%r1)	/* Save old MSR */
+	li	%r5,0
+	stw	%r5,4(%r1)
+	stw	%r5,0(%r1)
+
+	/* Finally, branch to OF */
+	mtctr	%r4
+	bctrl
+
+	/* Reload stack pointer and MSR from the OFW stack */
+	lwz	%r6,28(%r1)
+	lwz	%r2,24(%r1)
+	lwz	%r1,20(%r1)
+
+	/* Now set the real MSR */
+	mtmsr	%r6
+	isync
+
+	/* Return */
+	lwz	%r0,4(%r1)
+	mtlr 	%r0
+	blr
+
+/*
+ * RTAS Entry Point. Similar to the OF one, but simpler (no separate stack)
+ *
+ * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
+ */
+
+ASENTRY(rtascall)
+	mflr	%r0
+	stw	%r0,4(%r1)
+
+	/* Record the old MSR to real-mode-accessible area */
+	mfmsr	%r0
+	lis	%r5,rtas_regsave at ha
+	stw	%r0,rtas_regsave at l(%r5)
+
+	/* read client interface handler */
+	lis	%r5,rtas_entry at ha
+	lwz	%r5,rtas_entry at l(%r5)
+
+	/* Set the MSR to the RTAS value */
+	lis	%r6,rtasmsr at ha
+	lwz	%r6,rtasmsr at l(%r6)
+	mtmsr	%r6
+	isync
+
+	/* Branch to RTAS */
+	mtctr	%r5
+	bctrl
+
+	/* Now set the MSR back */
+	lis	%r6,rtas_regsave at ha
+	lwz	%r6,rtas_regsave at l(%r6)
+	mtmsr	%r6
+	isync
+
+	/* And return */
+	lwz	%r0,4(%r1)
+	mtlr 	%r0
+	blr
+


Property changes on: trunk/sys/powerpc/ofw/ofwcall32.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/ofwcall64.S
===================================================================
--- trunk/sys/powerpc/ofw/ofwcall64.S	                        (rev 0)
+++ trunk/sys/powerpc/ofw/ofwcall64.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,291 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2009-2011 Nathan Whitehorn
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ofw/ofwcall64.S 230400 2012-01-20 22:34:19Z andreast $
+ */
+
+#include <sys/syscall.h>
+
+#include <machine/trap.h>
+#include <machine/param.h>
+#include <machine/spr.h>
+#include <machine/asm.h>
+
+#define	OFWSTKSZ	4096		/* 4K Open Firmware stack */
+
+/*
+ * Globals
+ */
+	.data
+	.align	4
+ofwstk:
+	.space	OFWSTKSZ
+rtas_regsave:
+	.space	24 /* 3 * sizeof(register_t) */
+GLOBAL(ofmsr)
+	.llong  0, 0, 0, 0, 0		/* msr/sprg0-3 used in Open Firmware */
+GLOBAL(rtasmsr)
+	.llong	0
+GLOBAL(openfirmware_entry)
+	.llong	0			/* Open Firmware entry point */
+GLOBAL(rtas_entry)
+	.llong	0			/* RTAS entry point */
+
+/*
+ * Open Firmware Real-mode Entry Point. This is a huge pain.
+ */
+
+ASENTRY_NOPROF(ofwcall)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-208(%r1)
+
+	/*
+	 * We need to save the following, because OF's register save/
+	 * restore code assumes that the contents of registers are
+	 * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
+	 * get placed in that order in the stack.
+	 */
+
+	mfcr	%r4
+	std	%r4,48(%r1)
+	std	%r13,56(%r1)
+	std	%r14,64(%r1)
+	std	%r15,72(%r1)
+	std	%r16,80(%r1)
+	std	%r17,88(%r1)
+	std	%r18,96(%r1)
+	std	%r19,104(%r1)
+	std	%r20,112(%r1)
+	std	%r21,120(%r1)
+	std	%r22,128(%r1)
+	std	%r23,136(%r1)
+	std	%r24,144(%r1)
+	std	%r25,152(%r1)
+	std	%r26,160(%r1)
+	std	%r27,168(%r1)
+	std	%r28,176(%r1)
+	std	%r29,184(%r1)
+	std	%r30,192(%r1)
+	std	%r31,200(%r1)
+
+	/* Record the old MSR */
+	mfmsr	%r6
+
+	/* read client interface handler */
+	lis	%r4,openfirmware_entry at ha
+	ld	%r4,openfirmware_entry at l(%r4)
+
+	/*
+	 * Set the MSR to the OF value. This has the side effect of disabling
+	 * exceptions, which is important for the next few steps.
+	 */
+
+	lis	%r5,ofmsr at ha
+	ld	%r5,ofmsr at l(%r5)
+	mtmsrd	%r5
+	isync
+
+	/*
+	 * Set up OF stack. This needs to be accessible in real mode and
+	 * use the 32-bit ABI stack frame format. The pointer to the current
+	 * kernel stack is placed at the very top of the stack along with
+	 * the old MSR so we can get them back later.
+	 */
+	mr	%r5,%r1
+	lis	%r1,(ofwstk+OFWSTKSZ-32)@ha
+	addi	%r1,%r1,(ofwstk+OFWSTKSZ-32)@l
+	std	%r5,8(%r1)	/* Save real stack pointer */
+	std	%r2,16(%r1)	/* Save old TOC */
+	std	%r6,24(%r1)	/* Save old MSR */
+	li	%r5,0
+	stw	%r5,4(%r1)
+	stw	%r5,0(%r1)
+
+	/* Finally, branch to OF */
+	mtctr	%r4
+	bctrl
+
+	/* Reload stack pointer and MSR from the OFW stack */
+	ld	%r6,24(%r1)
+	ld	%r2,16(%r1)
+	ld	%r1,8(%r1)
+
+	/* Now set the real MSR */
+	mtmsrd	%r6
+	isync
+
+	/* Sign-extend the return value from OF */
+	extsw	%r3,%r3
+
+	/* Restore all the non-volatile registers */
+	ld	%r5,48(%r1)
+	mtcr	%r5
+	ld	%r13,56(%r1)
+	ld	%r14,64(%r1)
+	ld	%r15,72(%r1)
+	ld	%r16,80(%r1)
+	ld	%r17,88(%r1)
+	ld	%r18,96(%r1)
+	ld	%r19,104(%r1)
+	ld	%r20,112(%r1)
+	ld	%r21,120(%r1)
+	ld	%r22,128(%r1)
+	ld	%r23,136(%r1)
+	ld	%r24,144(%r1)
+	ld	%r25,152(%r1)
+	ld	%r26,160(%r1)
+	ld	%r27,168(%r1)
+	ld	%r28,176(%r1)
+	ld	%r29,184(%r1)
+	ld	%r30,192(%r1)
+	ld	%r31,200(%r1)
+
+	/* Restore the stack and link register */
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr 	%r0
+	blr
+
+/*
+ * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
+ * stack)
+ *
+ * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
+ */
+
+ASENTRY_NOPROF(rtascall)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-208(%r1)
+
+	/*
+	 * We need to save the following, because RTAS's register save/
+	 * restore code assumes that the contents of registers are
+	 * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
+	 * get placed in that order in the stack.
+	 */
+
+	mfcr	%r5
+	std	%r5,48(%r1)
+	std	%r13,56(%r1)
+	std	%r14,64(%r1)
+	std	%r15,72(%r1)
+	std	%r16,80(%r1)
+	std	%r17,88(%r1)
+	std	%r18,96(%r1)
+	std	%r19,104(%r1)
+	std	%r20,112(%r1)
+	std	%r21,120(%r1)
+	std	%r22,128(%r1)
+	std	%r23,136(%r1)
+	std	%r24,144(%r1)
+	std	%r25,152(%r1)
+	std	%r26,160(%r1)
+	std	%r27,168(%r1)
+	std	%r28,176(%r1)
+	std	%r29,184(%r1)
+	std	%r30,192(%r1)
+	std	%r31,200(%r1)
+
+	/* Record the old MSR */
+	mfmsr	%r6
+
+	/* read client interface handler */
+	lis	%r5,rtas_entry at ha
+	ld	%r5,rtas_entry at l(%r5)
+
+	/*
+	 * Set the MSR to the RTAS value. This has the side effect of disabling
+	 * exceptions, which is important for the next few steps.
+	 */
+
+	lis	%r7,rtasmsr at ha
+	ld	%r7,rtasmsr at l(%r7)
+	mtmsrd	%r7
+	isync
+
+	/*
+	 * Set up RTAS register save area, so that we can get back all of
+	 * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
+	 * Put this in r1, since RTAS is obliged to save it. Kernel globals
+	 * are below 4 GB, so this is safe.
+	 */
+	mr	%r7,%r1
+	lis	%r1,rtas_regsave at ha
+	addi	%r1,%r1,rtas_regsave at l
+	std	%r7,0(%r1)	/* Save 64-bit stack pointer */
+	std	%r2,8(%r1)	/* Save TOC */
+	std	%r6,16(%r1)	/* Save MSR */
+
+	/* Finally, branch to RTAS */
+	mtctr	%r5
+	bctrl
+
+	/* 
+	 * Reload stack pointer and MSR from the reg save area in r1. We are
+	 * running in 32-bit mode at this point, so it doesn't matter if r1
+	 * has become sign-extended.
+	 */
+	ld	%r6,16(%r1)
+	ld	%r2,8(%r1)
+	ld	%r1,0(%r1)
+
+	/* Now set the real MSR */
+	mtmsrd	%r6
+	isync
+
+	/* Sign-extend the return value from RTAS */
+	extsw	%r3,%r3
+
+	/* Restore all the non-volatile registers */
+	ld	%r5,48(%r1)
+	mtcr	%r5
+	ld	%r13,56(%r1)
+	ld	%r14,64(%r1)
+	ld	%r15,72(%r1)
+	ld	%r16,80(%r1)
+	ld	%r17,88(%r1)
+	ld	%r18,96(%r1)
+	ld	%r19,104(%r1)
+	ld	%r20,112(%r1)
+	ld	%r21,120(%r1)
+	ld	%r22,128(%r1)
+	ld	%r23,136(%r1)
+	ld	%r24,144(%r1)
+	ld	%r25,152(%r1)
+	ld	%r26,160(%r1)
+	ld	%r27,168(%r1)
+	ld	%r28,176(%r1)
+	ld	%r29,184(%r1)
+	ld	%r30,192(%r1)
+	ld	%r31,200(%r1)
+
+	/* Restore the stack and link register */
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr 	%r0
+	blr
+


Property changes on: trunk/sys/powerpc/ofw/ofwcall64.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/ofwmagic.S
===================================================================
--- trunk/sys/powerpc/ofw/ofwmagic.S	                        (rev 0)
+++ trunk/sys/powerpc/ofw/ofwmagic.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,69 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/ofw/ofwmagic.S 222613 2011-06-02 14:12:37Z nwhitehorn $ */
+/* $NetBSD: ofwmagic.S,v 1.2 1997/10/09 08:38:18 jtc Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * Magic note section used by Open Firmware.
+ */
+
+	.section ".note"
+
+	/*# note header */
+
+	/*# length of name */
+	.long	8
+
+	/*# note descriptor size */
+	.long	20
+
+	/*# note type (IEEE 1275) */
+	.long	0x1275
+
+	/*# name of owner */
+	.asciz	"PowerPC"
+	.balign	4
+
+
+	/*# note descriptor */
+
+	/*# real mode (-1) or virtual mode (0) */
+	.long	0
+
+	/*# real-base */
+	.long	-1
+	/*# real-size */
+	.long	-1
+
+	/*# virt-base */
+	.long	-1
+	/*# virt-size */
+	.long	-1


Property changes on: trunk/sys/powerpc/ofw/ofwmagic.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/openpic_ofw.c
===================================================================
--- trunk/sys/powerpc/ofw/openpic_ofw.c	                        (rev 0)
+++ trunk/sys/powerpc/ofw/openpic_ofw.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,166 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2003 by Peter Grehan. 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. 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ofw/openpic_ofw.c 266160 2014-05-15 17:30:16Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <sys/rman.h>
+
+#include <machine/openpicvar.h>
+
+#include "pic_if.h"
+
+/*
+ * OFW interface
+ */
+static int	openpic_ofw_probe(device_t);
+static int	openpic_ofw_attach(device_t);
+
+static void	openpic_ofw_translate_code(device_t, u_int irq, int code,
+		    enum intr_trigger *trig, enum intr_polarity *pol);
+
+static device_method_t  openpic_ofw_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		openpic_ofw_probe),
+	DEVMETHOD(device_attach,	openpic_ofw_attach),
+
+	/* PIC interface */
+	DEVMETHOD(pic_bind,		openpic_bind),
+	DEVMETHOD(pic_config,		openpic_config),
+	DEVMETHOD(pic_dispatch,		openpic_dispatch),
+	DEVMETHOD(pic_enable,		openpic_enable),
+	DEVMETHOD(pic_eoi,		openpic_eoi),
+	DEVMETHOD(pic_ipi,		openpic_ipi),
+	DEVMETHOD(pic_mask,		openpic_mask),
+	DEVMETHOD(pic_unmask,		openpic_unmask),
+
+	DEVMETHOD(pic_translate_code,	openpic_ofw_translate_code),
+
+	DEVMETHOD_END
+};
+
+static driver_t openpic_ofw_driver = {
+	"openpic",
+	openpic_ofw_methods,
+	sizeof(struct openpic_softc),
+};
+
+DRIVER_MODULE(openpic, ofwbus, openpic_ofw_driver, openpic_devclass, 0, 0);
+DRIVER_MODULE(openpic, simplebus, openpic_ofw_driver, openpic_devclass, 0, 0);
+DRIVER_MODULE(openpic, macio, openpic_ofw_driver, openpic_devclass, 0, 0);
+
+static int
+openpic_ofw_probe(device_t dev)
+{
+	const char *type = ofw_bus_get_type(dev);
+
+	if (type == NULL)
+                return (ENXIO);
+
+	if (!ofw_bus_is_compatible(dev, "chrp,open-pic") &&
+	    strcmp(type, "open-pic") != 0)
+                return (ENXIO);
+
+	/*
+	 * On some U4 systems, there is a phantom MPIC in the mac-io cell.
+	 * The uninorth driver will pick up the real PIC, so ignore it here.
+	 */
+	if (OF_finddevice("/u4") != (phandle_t)-1)
+		return (ENXIO);
+
+	device_set_desc(dev, OPENPIC_DEVSTR);
+	return (0);
+}
+
+static int
+openpic_ofw_attach(device_t dev)
+{
+	phandle_t xref, node;
+
+	node = ofw_bus_get_node(dev);
+
+	if (OF_getprop(node, "phandle", &xref, sizeof(xref)) == -1 &&
+	    OF_getprop(node, "ibm,phandle", &xref, sizeof(xref)) == -1 &&
+	    OF_getprop(node, "linux,phandle", &xref, sizeof(xref)) == -1)
+		xref = node;
+
+	return (openpic_common_attach(dev, xref));
+}
+
+static void
+openpic_ofw_translate_code(device_t dev, u_int irq, int code,
+    enum intr_trigger *trig, enum intr_polarity *pol)
+{
+	switch (code) {
+	case 0:
+		/* L to H edge */
+		*trig = INTR_TRIGGER_EDGE;
+		*pol = INTR_POLARITY_HIGH;
+		break;
+	case 1:
+		/* Active L level */
+		*trig = INTR_TRIGGER_LEVEL;
+		*pol = INTR_POLARITY_LOW;
+		break;
+	case 2:
+		/* Active H level */
+		*trig = INTR_TRIGGER_LEVEL;
+		*pol = INTR_POLARITY_HIGH;
+		break;
+	case 3:
+		/* H to L edge */
+		*trig = INTR_TRIGGER_EDGE;
+		*pol = INTR_POLARITY_LOW;
+		break;
+	default:
+		*trig = INTR_TRIGGER_CONFORM;
+		*pol = INTR_POLARITY_CONFORM;
+	}
+}
+


Property changes on: trunk/sys/powerpc/ofw/openpic_ofw.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ofw/rtas.c
===================================================================
--- trunk/sys/powerpc/ofw/rtas.c	                        (rev 0)
+++ trunk/sys/powerpc/ofw/rtas.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,262 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ofw/rtas.c 259258 2013-12-12 13:00:07Z andreast $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+#include <machine/pmap.h>
+#include <machine/rtas.h>
+#include <machine/stdarg.h>
+
+#include <dev/ofw/openfirm.h>
+
+static MALLOC_DEFINE(M_RTAS, "rtas", "Run Time Abstraction Service");
+
+static vm_offset_t	rtas_bounce_phys;
+static caddr_t		rtas_bounce_virt;
+static off_t		rtas_bounce_offset;
+static size_t		rtas_bounce_size;
+static uintptr_t	rtas_private_data;
+static struct mtx	rtas_mtx;
+static phandle_t	rtas;
+
+/* From ofwcall.S */
+int rtascall(vm_offset_t callbuffer, uintptr_t rtas_privdat);
+extern uintptr_t	rtas_entry;
+extern register_t	rtasmsr;
+
+int setfault(faultbuf);             /* defined in locore.S */
+
+/*
+ * After the VM is up, allocate RTAS memory and instantiate it
+ */
+
+static void rtas_setup(void *);
+
+SYSINIT(rtas_setup, SI_SUB_KMEM, SI_ORDER_ANY, rtas_setup, NULL);
+
+static void
+rtas_setup(void *junk)
+{
+	ihandle_t rtasi;
+	cell_t rtas_size = 0, rtas_ptr;
+	char path[31];
+	int result;
+
+	rtas = OF_finddevice("/rtas");
+	if (rtas == -1) {
+		rtas = 0;
+		return;
+	}
+	OF_package_to_path(rtas, path, sizeof(path));
+	rtasi = OF_open(path);
+	if (rtasi == 0) {
+		rtas = 0;
+		printf("Error initializing RTAS: could not open node\n");
+		return;
+	}
+
+	mtx_init(&rtas_mtx, "RTAS", NULL, MTX_SPIN);
+
+	/* RTAS must be called with everything turned off in MSR */
+	rtasmsr = mfmsr();
+	rtasmsr &= ~(PSL_IR | PSL_DR | PSL_EE | PSL_SE);
+	#ifdef __powerpc64__
+	rtasmsr &= ~PSL_SF;
+	#endif
+
+	/*
+	 * Allocate rtas_size + one page of contiguous, wired physical memory
+	 * that can fit into a 32-bit address space and accessed from real mode.
+	 * This is used both to bounce arguments and for RTAS private data.
+	 *
+	 * It must be 4KB-aligned and not cross a 256 MB boundary.
+	 */
+
+	OF_getprop(rtas, "rtas-size", &rtas_size, sizeof(rtas_size));
+	rtas_size = round_page(rtas_size);
+	rtas_bounce_virt = contigmalloc(rtas_size + PAGE_SIZE, M_RTAS, 0, 0,
+	    ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT),
+	    4096, 256*1024*1024);
+
+	rtas_private_data = vtophys(rtas_bounce_virt);
+	rtas_bounce_virt += rtas_size;	/* Actual bounce area */
+	rtas_bounce_phys = vtophys(rtas_bounce_virt);
+	rtas_bounce_size = PAGE_SIZE;
+
+	/*
+	 * Instantiate RTAS. We always use the 32-bit version.
+	 */
+
+	result = OF_call_method("instantiate-rtas", rtasi, 1, 1,
+	    (cell_t)rtas_private_data, &rtas_ptr);
+	OF_close(rtasi);
+
+	if (result != 0) {
+		rtas = 0;
+		rtas_ptr = 0;
+		printf("Error initializing RTAS (%d)\n", result);
+		return;
+	}
+
+	rtas_entry = (uintptr_t)(rtas_ptr);
+}
+
+static cell_t
+rtas_real_map(const void *buf, size_t len)
+{
+	cell_t phys;
+
+	mtx_assert(&rtas_mtx, MA_OWNED);
+
+	/*
+	 * Make sure the bounce page offset satisfies any reasonable
+	 * alignment constraint.
+	 */
+	rtas_bounce_offset += sizeof(register_t) -
+	    (rtas_bounce_offset % sizeof(register_t));
+
+	if (rtas_bounce_offset + len > rtas_bounce_size) {
+		panic("Oversize RTAS call!");
+		return 0;
+	}
+
+	if (buf != NULL)
+		memcpy(rtas_bounce_virt + rtas_bounce_offset, buf, len);
+	else
+		return (0);
+
+	phys = rtas_bounce_phys + rtas_bounce_offset;
+	rtas_bounce_offset += len;
+
+	return (phys);
+}
+
+static void
+rtas_real_unmap(cell_t physaddr, void *buf, size_t len)
+{
+	mtx_assert(&rtas_mtx, MA_OWNED);
+
+	if (physaddr == 0)
+		return;
+
+	memcpy(buf, rtas_bounce_virt + (physaddr - rtas_bounce_phys), len);
+}
+
+/* Check if we have RTAS */
+int
+rtas_exists(void)
+{
+	return (rtas != 0);
+}
+
+/* Call an RTAS method by token */
+int
+rtas_call_method(cell_t token, int nargs, int nreturns, ...)
+{
+	vm_offset_t argsptr;
+	faultbuf env, *oldfaultbuf;
+	va_list ap;
+	struct {
+		cell_t token;
+		cell_t nargs;
+		cell_t nreturns;
+		cell_t args_n_results[12];
+	} args;
+	int n, result;
+
+	if (!rtas_exists() || nargs + nreturns > 12)
+		return (-1);
+
+	args.token = token;
+	va_start(ap, nreturns);
+
+	mtx_lock_spin(&rtas_mtx);
+	rtas_bounce_offset = 0;
+
+	args.nargs = nargs;
+	args.nreturns = nreturns;
+
+	for (n = 0; n < nargs; n++)
+		args.args_n_results[n] = va_arg(ap, cell_t);
+
+	argsptr = rtas_real_map(&args, sizeof(args));
+
+	/* Get rid of any stale machine checks that have been waiting.  */
+	__asm __volatile ("sync; isync");
+	oldfaultbuf = curthread->td_pcb->pcb_onfault;
+        if (!setfault(env)) {
+		__asm __volatile ("sync");
+		result = rtascall(argsptr, rtas_private_data);
+		__asm __volatile ("sync; isync");
+	} else {
+		result = RTAS_HW_ERROR;
+	}
+	curthread->td_pcb->pcb_onfault = oldfaultbuf;
+	__asm __volatile ("sync");
+
+	rtas_real_unmap(argsptr, &args, sizeof(args));
+	mtx_unlock_spin(&rtas_mtx);
+
+	if (result < 0)
+		return (result);
+
+	for (n = nargs; n < nargs + nreturns; n++)
+		*va_arg(ap, cell_t *) = args.args_n_results[n];
+	return (result);
+}
+
+/* Look up an RTAS token */
+cell_t
+rtas_token_lookup(const char *method)
+{
+	cell_t token;
+	
+	if (!rtas_exists())
+		return (-1);
+
+	if (OF_getprop(rtas, method, &token, sizeof(token)) == -1)
+		return (-1);
+
+	return (token);
+}
+
+


Property changes on: trunk/sys/powerpc/ofw/rtas.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/ata_dbdma.c
===================================================================
--- trunk/sys/powerpc/powermac/ata_dbdma.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/ata_dbdma.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,287 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2008 by Nathan Whitehorn. 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. 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/cdefs.h>
+__FBSDID("* $FreeBSD: stable/10/sys/powerpc/powermac/ata_dbdma.c 249213 2013-04-06 19:12:49Z marius $");
+
+/*
+ * Common routines for the DMA engine on both the Apple Kauai and MacIO
+ * ATA controllers.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/sema.h>
+#include <sys/taskqueue.h>
+#include <vm/uma.h>
+#include <machine/stdarg.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/ata.h>
+#include <dev/ata/ata-all.h>
+#include <dev/ata/ata-pci.h>
+#include <ata_if.h>
+
+#include "ata_dbdma.h"
+
+struct ata_dbdma_dmaload_args {
+	struct ata_dbdma_channel *sc;
+
+	int write;
+	int nsegs;
+};
+
+static void
+ata_dbdma_setprd(void *xarg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+	struct ata_dbdma_dmaload_args *arg = xarg;
+	struct ata_dbdma_channel *sc = arg->sc;
+	int branch_type, command;
+	int prev_stop;
+	int i;
+
+	mtx_lock(&sc->dbdma_mtx);
+
+	prev_stop = sc->next_dma_slot-1;
+	if (prev_stop < 0)
+		prev_stop = 0xff;
+
+	for (i = 0; i < nsegs; i++) {
+		/* Loop back to the beginning if this is our last slot */
+		if (sc->next_dma_slot == 0xff)
+			branch_type = DBDMA_ALWAYS;
+		else
+			branch_type = DBDMA_NEVER;
+
+		if (arg->write) {
+			command = (i + 1 < nsegs) ? DBDMA_OUTPUT_MORE : 
+			    DBDMA_OUTPUT_LAST;
+		} else {
+			command = (i + 1 < nsegs) ? DBDMA_INPUT_MORE : 
+			    DBDMA_INPUT_LAST;
+		}
+
+		dbdma_insert_command(sc->dbdma, sc->next_dma_slot++,
+		    command, 0, segs[i].ds_addr, segs[i].ds_len,
+		    DBDMA_NEVER, branch_type, DBDMA_NEVER, 0);
+
+		if (branch_type == DBDMA_ALWAYS)
+			sc->next_dma_slot = 0;
+	}
+
+	/* We have a corner case where the STOP command is the last slot,
+	 * but you can't branch in STOP commands. So add a NOP branch here
+	 * and the STOP in slot 0. */
+
+	if (sc->next_dma_slot == 0xff) {
+		dbdma_insert_branch(sc->dbdma, sc->next_dma_slot, 0);
+		sc->next_dma_slot = 0;
+	}
+
+#if 0
+	dbdma_insert_command(sc->dbdma, sc->next_dma_slot++,
+	    DBDMA_NOP, 0, 0, 0, DBDMA_ALWAYS, DBDMA_NEVER, DBDMA_NEVER, 0);
+#endif
+	dbdma_insert_stop(sc->dbdma, sc->next_dma_slot++);
+	dbdma_insert_nop(sc->dbdma, prev_stop);
+
+	dbdma_sync_commands(sc->dbdma, BUS_DMASYNC_PREWRITE);
+
+	mtx_unlock(&sc->dbdma_mtx);
+
+	arg->nsegs = nsegs;
+}
+
+static int
+ata_dbdma_status(device_t dev)
+{
+	struct ata_dbdma_channel *sc = device_get_softc(dev);
+	struct ata_channel *ch = device_get_softc(dev);
+
+	if (sc->sc_ch.dma.flags & ATA_DMA_ACTIVE) {
+		return (!(dbdma_get_chan_status(sc->dbdma) & 
+		    DBDMA_STATUS_ACTIVE));
+	}
+
+	if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) {
+		DELAY(100);
+		if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY)
+			return 0;
+	}
+	return 1;
+}
+
+static int
+ata_dbdma_start(struct ata_request *request)
+{
+	struct ata_dbdma_channel *sc = device_get_softc(request->parent);
+
+	sc->sc_ch.dma.flags |= ATA_DMA_ACTIVE;
+	dbdma_wake(sc->dbdma);
+	return 0;
+}
+
+static void
+ata_dbdma_reset(device_t dev)
+{
+	struct ata_dbdma_channel *sc = device_get_softc(dev);
+
+	mtx_lock(&sc->dbdma_mtx);
+
+	dbdma_stop(sc->dbdma);
+	dbdma_insert_stop(sc->dbdma, 0);
+	sc->next_dma_slot=1;
+	dbdma_set_current_cmd(sc->dbdma, 0);
+
+	sc->sc_ch.dma.flags &= ~ATA_DMA_ACTIVE;
+
+	mtx_unlock(&sc->dbdma_mtx);
+}
+
+static int
+ata_dbdma_stop(struct ata_request *request)
+{
+	struct ata_dbdma_channel *sc = device_get_softc(request->parent);
+
+	uint16_t status;
+	
+	status = dbdma_get_chan_status(sc->dbdma);
+
+	dbdma_pause(sc->dbdma);
+	sc->sc_ch.dma.flags &= ~ATA_DMA_ACTIVE;
+
+	if (status & DBDMA_STATUS_DEAD) {
+		device_printf(request->parent,"DBDMA dead, resetting "
+		    "channel...\n");
+		ata_dbdma_reset(request->parent);
+		return ATA_S_ERROR;
+	}
+
+	if (!(status & DBDMA_STATUS_RUN)) {
+		device_printf(request->parent,"DBDMA confused, stop called "
+		    "when channel is not running!\n");
+		return ATA_S_ERROR;
+	}
+
+	if (status & DBDMA_STATUS_ACTIVE) {
+		device_printf(request->parent,"DBDMA channel stopped "
+		    "prematurely\n");
+		return ATA_S_ERROR;
+	}
+	return 0;
+}
+
+static int
+ata_dbdma_load(struct ata_request *request, void *addr, int *entries)
+{
+	struct ata_channel *ch = device_get_softc(request->parent);
+	struct ata_dbdma_dmaload_args args;
+
+	int error;
+
+	args.sc = device_get_softc(request->parent);
+	args.write = !(request->flags & ATA_R_READ);
+
+	if (!request->bytecount) {
+		device_printf(request->dev,
+		    "FAILURE - zero length DMA transfer attempted\n");
+		return EIO;
+	}
+	if (((uintptr_t)(request->data) & (ch->dma.alignment - 1)) ||
+	    (request->bytecount & (ch->dma.alignment - 1))) {
+		device_printf(request->dev,
+		    "FAILURE - non aligned DMA transfer attempted\n");
+		return EIO;
+	}
+	if (request->bytecount > ch->dma.max_iosize) {
+		device_printf(request->dev,
+		    "FAILURE - oversized DMA transfer attempt %d > %d\n",
+		    request->bytecount, ch->dma.max_iosize);
+		return EIO;
+	}
+
+	request->dma = &ch->dma.slot[0];
+
+	if ((error = bus_dmamap_load(request->dma->data_tag, 
+	    request->dma->data_map, request->data, request->bytecount,
+	    &ata_dbdma_setprd, &args, BUS_DMA_NOWAIT))) {
+		device_printf(request->dev, "FAILURE - load data\n");
+		goto error;
+	}
+
+	if (entries)
+		*entries = args.nsegs;
+
+	bus_dmamap_sync(request->dma->sg_tag, request->dma->sg_map,
+	    BUS_DMASYNC_PREWRITE);
+	bus_dmamap_sync(request->dma->data_tag, request->dma->data_map,
+	    (request->flags & ATA_R_READ) ?
+	    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
+
+	return 0;
+
+error:
+	ch->dma.unload(request);
+	return EIO;
+}
+
+void
+ata_dbdma_dmainit(device_t dev)
+{
+	struct ata_dbdma_channel *sc = device_get_softc(dev);
+	int error;
+
+	error = dbdma_allocate_channel(sc->dbdma_regs, sc->dbdma_offset,
+	    bus_get_dma_tag(dev), 256, &sc->dbdma);
+
+	dbdma_set_wait_selector(sc->dbdma,1 << 7, 1 << 7);
+
+	dbdma_insert_stop(sc->dbdma,0);
+	sc->next_dma_slot=1;
+
+	sc->sc_ch.dma.start = ata_dbdma_start;
+	sc->sc_ch.dma.stop = ata_dbdma_stop;
+	sc->sc_ch.dma.load = ata_dbdma_load;
+	sc->sc_ch.dma.reset = ata_dbdma_reset;
+
+	/*
+	 * DBDMA's field for transfer size is 16 bits. This will overflow
+	 * if we try to do a 64K transfer, so stop short of 64K.
+	 */
+	sc->sc_ch.dma.segsize = 126 * DEV_BSIZE;
+	ata_dmainit(dev);
+
+	sc->sc_ch.hw.status = ata_dbdma_status;
+
+	mtx_init(&sc->dbdma_mtx, "ATA DBDMA", NULL, MTX_DEF);
+}


Property changes on: trunk/sys/powerpc/powermac/ata_dbdma.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/ata_dbdma.h
===================================================================
--- trunk/sys/powerpc/powermac/ata_dbdma.h	                        (rev 0)
+++ trunk/sys/powerpc/powermac/ata_dbdma.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,56 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2008 by Nathan Whitehorn. 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/ata_dbdma.h 183409 2008-09-27 15:13:44Z nwhitehorn $
+ */
+
+#ifndef ATA_DBDMA_H
+#define ATA_DBDMA_H
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/dbdma.h>
+
+struct ata_dbdma_channel {
+	struct ata_channel	sc_ch;
+
+	int			dbdma_rid;
+	struct resource		*dbdma_regs;
+	u_int			dbdma_offset;
+
+	dbdma_channel_t		*dbdma;
+	int			next_dma_slot;
+
+	struct mtx		dbdma_mtx;
+};
+
+void ata_dbdma_dmainit(device_t dev);
+
+#endif /* ATA_DBDMA_H */
+


Property changes on: trunk/sys/powerpc/powermac/ata_dbdma.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/ata_kauai.c
===================================================================
--- trunk/sys/powerpc/powermac/ata_kauai.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/ata_kauai.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,375 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2004 by Peter Grehan. 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. 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/ata_kauai.c 256857 2013-10-21 19:11:15Z andreast $");
+
+/*
+ * Mac 'Kauai' PCI ATA controller
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/sema.h>
+#include <sys/taskqueue.h>
+#include <vm/uma.h>
+#include <machine/stdarg.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/ata.h>
+#include <dev/ata/ata-all.h>
+#include <ata_if.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <machine/intr_machdep.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include "ata_dbdma.h"
+
+#define  ATA_KAUAI_REGOFFSET	0x2000
+#define  ATA_KAUAI_DBDMAOFFSET	0x1000
+
+/*
+ * Offset to alt-control register from base
+ */
+#define  ATA_KAUAI_ALTOFFSET    (ATA_KAUAI_REGOFFSET + 0x160)
+
+/*
+ * Define the gap between registers
+ */
+#define ATA_KAUAI_REGGAP        16
+
+/*
+ * PIO and DMA access registers
+ */
+#define PIO_CONFIG_REG	(ATA_KAUAI_REGOFFSET + 0x200)
+#define UDMA_CONFIG_REG	(ATA_KAUAI_REGOFFSET + 0x210)
+#define DMA_IRQ_REG	(ATA_KAUAI_REGOFFSET + 0x300)
+
+#define USE_DBDMA_IRQ	0
+
+/*
+ * Define the kauai pci bus attachment.
+ */
+static  int  ata_kauai_probe(device_t dev);
+static  int  ata_kauai_attach(device_t dev);
+static  int  ata_kauai_setmode(device_t dev, int target, int mode);
+static  int  ata_kauai_begin_transaction(struct ata_request *request);
+
+static device_method_t ata_kauai_methods[] = {
+        /* Device interface */
+	DEVMETHOD(device_probe,		ata_kauai_probe),
+	DEVMETHOD(device_attach,	ata_kauai_attach),
+	DEVMETHOD(device_detach,	bus_generic_detach),
+	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
+	DEVMETHOD(device_suspend,	bus_generic_suspend),
+	DEVMETHOD(device_resume,	bus_generic_resume),
+
+	/* ATA interface */
+	DEVMETHOD(ata_setmode,		ata_kauai_setmode),
+	DEVMETHOD_END
+};
+
+struct ata_kauai_softc {
+	struct ata_dbdma_channel sc_ch;
+
+	struct resource *sc_memr;
+
+	int shasta;
+
+	uint32_t udmaconf[2];
+	uint32_t wdmaconf[2];
+	uint32_t pioconf[2];
+};
+
+static driver_t ata_kauai_driver = {
+	"ata",
+	ata_kauai_methods,
+	sizeof(struct ata_kauai_softc),
+};
+
+DRIVER_MODULE(ata, pci, ata_kauai_driver, ata_devclass, NULL, NULL);
+MODULE_DEPEND(ata, ata, 1, 1, 1);
+
+/*
+ * PCI ID search table
+ */
+static const struct kauai_pci_dev {
+        u_int32_t	kpd_devid;
+        const char	*kpd_desc;
+} kauai_pci_devlist[] = {
+        { 0x0033106b, "Uninorth2 Kauai ATA Controller" },
+        { 0x003b106b, "Intrepid Kauai ATA Controller" },
+        { 0x0043106b, "K2 Kauai ATA Controller" },
+        { 0x0050106b, "Shasta Kauai ATA Controller" },
+        { 0x0069106b, "Intrepid-2 Kauai ATA Controller" },
+        { 0, NULL }
+};
+
+/*
+ * IDE transfer timings
+ */
+#define KAUAI_PIO_MASK	0xff000fff
+#define KAUAI_DMA_MASK	0x00fff000
+#define KAUAI_UDMA_MASK	0x0000ffff
+
+static const u_int pio_timing_kauai[] = {
+	0x08000a92,	/* PIO0 */
+	0x0800060f,	/* PIO1 */
+	0x0800038b,	/* PIO2 */
+	0x05000249,	/* PIO3 */
+	0x04000148	/* PIO4 */
+};
+
+static const u_int pio_timing_shasta[] = {
+	0x0a000c97,	/* PIO0 */
+	0x07000712,	/* PIO1 */
+	0x040003cd,	/* PIO2 */
+	0x0400028b,	/* PIO3 */
+	0x0400010a	/* PIO4 */
+};
+
+static const u_int dma_timing_kauai[] = {
+        0x00618000,	/* WDMA0 */
+        0x00209000,	/* WDMA1 */
+        0x00148000	/* WDMA2 */
+};
+
+static const u_int dma_timing_shasta[] = {
+        0x00820800,	/* WDMA0 */
+        0x0028b000,	/* WDMA1 */
+        0x001ca000	/* WDMA2 */
+};
+
+static const u_int udma_timing_kauai[] = {
+        0x000070c1,	/* UDMA0 */
+        0x00005d81,	/* UDMA1 */
+        0x00004a61,	/* UDMA2 */
+        0x00003a51,	/* UDMA3 */
+        0x00002a31,	/* UDMA4 */
+        0x00002921	/* UDMA5 */
+};
+
+static const u_int udma_timing_shasta[] = {
+        0x00035901,	/* UDMA0 */
+        0x000348b1,	/* UDMA1 */
+        0x00033881,	/* UDMA2 */
+        0x00033861,	/* UDMA3 */
+        0x00033841,	/* UDMA4 */
+        0x00033031,	/* UDMA5 */
+        0x00033021	/* UDMA6 */
+};
+
+static int
+ata_kauai_probe(device_t dev)
+{
+	struct ata_kauai_softc *sc;
+	u_int32_t devid;
+	phandle_t node;
+	const char *compatstring = NULL;
+	int i, found;
+
+	found = 0;
+	devid = pci_get_devid(dev);
+        for (i = 0; kauai_pci_devlist[i].kpd_desc != NULL; i++) {
+                if (devid == kauai_pci_devlist[i].kpd_devid) {
+			found = 1;
+                        device_set_desc(dev, kauai_pci_devlist[i].kpd_desc);
+		}
+	}
+
+	if (!found)
+		return (ENXIO);
+
+	node = ofw_bus_get_node(dev);
+	sc = device_get_softc(dev);
+	bzero(sc, sizeof(struct ata_kauai_softc));
+
+	compatstring = ofw_bus_get_compat(dev);
+	if (compatstring != NULL && strcmp(compatstring,"shasta-ata") == 0)
+		sc->shasta = 1;
+
+	/* Pre-K2 controllers apparently need this hack */
+	if (!sc->shasta &&
+	    (compatstring == NULL || strcmp(compatstring, "K2-UATA") != 0))
+		bus_set_resource(dev, SYS_RES_IRQ, 0, 39, 1);
+
+        return (ata_probe(dev));
+}
+
+#if USE_DBDMA_IRQ
+static int
+ata_kauai_dma_interrupt(struct ata_kauai_softc *sc)
+{
+	/* Clear the DMA interrupt bits */
+
+	bus_write_4(sc->sc_memr, DMA_IRQ_REG, 0x80000000);
+
+	return ata_interrupt(sc);
+}
+#endif
+
+static int
+ata_kauai_attach(device_t dev)
+{
+	struct ata_kauai_softc *sc = device_get_softc(dev);
+	struct ata_channel *ch;
+	int i, rid;
+#if USE_DBDMA_IRQ
+	int dbdma_irq_rid = 1;
+	struct resource *dbdma_irq;
+	void *cookie;
+#endif
+
+	ch = &sc->sc_ch.sc_ch;
+
+        rid = PCIR_BARS;
+	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 
+	    RF_ACTIVE);
+        if (sc->sc_memr == NULL) {
+                device_printf(dev, "could not allocate memory\n");
+                return (ENXIO);
+        }
+
+	/*
+	 * Set up the resource vectors
+	 */
+        for (i = ATA_DATA; i <= ATA_COMMAND; i++) {
+                ch->r_io[i].res = sc->sc_memr;
+                ch->r_io[i].offset = i*ATA_KAUAI_REGGAP + ATA_KAUAI_REGOFFSET;
+        }
+        ch->r_io[ATA_CONTROL].res = sc->sc_memr;
+        ch->r_io[ATA_CONTROL].offset = ATA_KAUAI_ALTOFFSET;
+	ata_default_registers(dev);
+
+	ch->unit = 0;
+	ch->flags |= ATA_USE_16BIT;
+
+	/* XXX: ATAPI DMA is unreliable. We should find out why. */
+	ch->flags |= ATA_NO_ATAPI_DMA;
+	ata_generic_hw(dev);
+
+	pci_enable_busmaster(dev);
+
+	/* Init DMA engine */
+
+	sc->sc_ch.dbdma_rid = 1;
+	sc->sc_ch.dbdma_regs = sc->sc_memr;
+	sc->sc_ch.dbdma_offset = ATA_KAUAI_DBDMAOFFSET;
+
+	ata_dbdma_dmainit(dev);
+
+#if USE_DBDMA_IRQ
+	/* Bind to DBDMA interrupt as well */
+	if ((dbdma_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+	    &dbdma_irq_rid, RF_SHAREABLE | RF_ACTIVE)) != NULL) {
+		bus_setup_intr(dev, dbdma_irq, ATA_INTR_FLAGS, NULL,
+		    (driver_intr_t *)ata_kauai_dma_interrupt, sc,&cookie);
+	}
+#endif
+
+	/* Set up initial mode */
+	sc->pioconf[0] = sc->pioconf[1] = 
+	    bus_read_4(sc->sc_memr, PIO_CONFIG_REG) & 0x0f000fff;
+
+	sc->udmaconf[0] = sc->udmaconf[1] = 0;
+	sc->wdmaconf[0] = sc->wdmaconf[1] = 0;
+
+	/* Magic FCR value from Apple */
+	bus_write_4(sc->sc_memr, 0, 0x00000007);
+
+	/* Set begin_transaction */
+	sc->sc_ch.sc_ch.hw.begin_transaction = ata_kauai_begin_transaction;
+
+	return ata_attach(dev);
+}
+
+static int
+ata_kauai_setmode(device_t dev, int target, int mode)
+{
+	struct ata_kauai_softc *sc = device_get_softc(dev);
+
+	mode = min(mode,sc->shasta ? ATA_UDMA6 : ATA_UDMA5);
+
+	if (sc->shasta) {
+		switch (mode & ATA_DMA_MASK) {
+		    case ATA_UDMA0:
+			sc->udmaconf[target] 
+			    = udma_timing_shasta[mode & ATA_MODE_MASK];
+			break;
+		    case ATA_WDMA0:
+			sc->udmaconf[target] = 0;
+			sc->wdmaconf[target] 
+			    = dma_timing_shasta[mode & ATA_MODE_MASK];
+			break;
+		    default:
+			sc->pioconf[target] 
+			    = pio_timing_shasta[(mode & ATA_MODE_MASK) - 
+			    ATA_PIO0];
+			break;
+		}
+	} else {
+		switch (mode & ATA_DMA_MASK) {
+		    case ATA_UDMA0:
+			sc->udmaconf[target] 
+			    = udma_timing_kauai[mode & ATA_MODE_MASK];
+			break;
+		    case ATA_WDMA0:
+			sc->udmaconf[target] = 0;
+			sc->wdmaconf[target]
+			    = dma_timing_kauai[mode & ATA_MODE_MASK];
+			break;
+		    default:
+			sc->pioconf[target] 
+			    = pio_timing_kauai[(mode & ATA_MODE_MASK)
+			    - ATA_PIO0];
+			break;
+		}
+	}
+
+	return (mode);
+}
+
+static int
+ata_kauai_begin_transaction(struct ata_request *request)
+{
+	struct ata_kauai_softc *sc = device_get_softc(request->parent);
+
+	bus_write_4(sc->sc_memr, UDMA_CONFIG_REG, sc->udmaconf[request->unit]);
+	bus_write_4(sc->sc_memr, PIO_CONFIG_REG, 
+	    sc->wdmaconf[request->unit] | sc->pioconf[request->unit]);
+
+	return ata_begin_transaction(request);
+}


Property changes on: trunk/sys/powerpc/powermac/ata_kauai.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/ata_macio.c
===================================================================
--- trunk/sys/powerpc/powermac/ata_macio.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/ata_macio.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,339 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2002 by Peter Grehan. 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. 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/ata_macio.c 256857 2013-10-21 19:11:15Z andreast $");
+
+/*
+ * Mac-io ATA controller
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/sema.h>
+#include <sys/taskqueue.h>
+#include <vm/uma.h>
+#include <machine/stdarg.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/ata.h>
+#include <dev/ata/ata-all.h>
+#include <ata_if.h>
+
+#include <dev/ofw/ofw_bus.h>
+
+#include "ata_dbdma.h"
+
+/*
+ * Offset to control registers from base
+ */
+#define ATA_MACIO_ALTOFFSET	0x160
+
+/*
+ * Define the gap between registers
+ */
+#define ATA_MACIO_REGGAP	16
+
+/*
+ * Whether or not to bind to the DBDMA IRQ
+ */
+#define USE_DBDMA_IRQ		0
+
+/*
+ * Timing register
+ */
+#define ATA_MACIO_TIMINGREG	0x200
+
+#define ATA_TIME_TO_TICK(rev,time) howmany(time, (rev == 4) ? 15 : 30)
+#define PIO_REC_OFFSET 4
+#define PIO_REC_MIN 1
+#define PIO_ACT_MIN 1
+#define DMA_REC_OFFSET 1
+#define DMA_REC_MIN 1
+#define DMA_ACT_MIN 1
+
+struct ide_timings {
+	int cycle;      /* minimum cycle time [ns] */
+	int active;     /* minimum command active time [ns] */
+};
+
+static const struct ide_timings pio_timings[5] = {
+	{ 600, 180 },	/* PIO 0 */
+	{ 390, 150 },	/* PIO 1 */
+	{ 240, 105 },	/* PIO 2 */
+	{ 180,  90 },	/* PIO 3 */
+	{ 120,  75 }	/* PIO 4 */
+};
+
+static const struct ide_timings dma_timings[3] = {
+	{ 480, 240 },	/* WDMA 0 */
+	{ 165,  90 },	/* WDMA 1 */
+	{ 120,  75 }	/* WDMA 2 */
+};
+
+static const struct ide_timings udma_timings[5] = {
+        { 120, 180 },	/* UDMA 0 */
+        {  90, 150 },	/* UDMA 1 */
+        {  60, 120 },	/* UDMA 2 */
+        {  45,  90 },	/* UDMA 3 */
+        {  30,  90 }	/* UDMA 4 */
+};
+
+/*
+ * Define the macio ata bus attachment.
+ */
+static  int  ata_macio_probe(device_t dev);
+static  int  ata_macio_setmode(device_t dev, int target, int mode);
+static  int  ata_macio_attach(device_t dev);
+static  int  ata_macio_begin_transaction(struct ata_request *request);
+
+static device_method_t ata_macio_methods[] = {
+        /* Device interface */
+	DEVMETHOD(device_probe,		ata_macio_probe),
+	DEVMETHOD(device_attach,        ata_macio_attach),
+
+	/* ATA interface */
+	DEVMETHOD(ata_setmode,		ata_macio_setmode),
+	DEVMETHOD_END
+};
+
+struct ata_macio_softc {
+	struct ata_dbdma_channel sc_ch;
+
+	int rev;
+	int max_mode;
+	struct resource *sc_mem;
+
+	uint32_t udmaconf[2];
+	uint32_t wdmaconf[2];
+	uint32_t pioconf[2];
+};
+
+static driver_t ata_macio_driver = {
+	"ata",
+	ata_macio_methods,
+	sizeof(struct ata_macio_softc),
+};
+
+DRIVER_MODULE(ata, macio, ata_macio_driver, ata_devclass, NULL, NULL);
+MODULE_DEPEND(ata, ata, 1, 1, 1);
+
+static int
+ata_macio_probe(device_t dev)
+{
+	const char *type = ofw_bus_get_type(dev);
+	const char *name = ofw_bus_get_name(dev);
+	struct ata_macio_softc *sc;
+
+	if (strcmp(type, "ata") != 0 &&
+	    strcmp(type, "ide") != 0)
+		return (ENXIO);
+
+	sc = device_get_softc(dev);
+	bzero(sc, sizeof(struct ata_macio_softc));
+
+	if (strcmp(name,"ata-4") == 0) {
+		device_set_desc(dev,"Apple MacIO Ultra ATA Controller");
+		sc->rev = 4;
+		sc->max_mode = ATA_UDMA4;
+	} else {
+		device_set_desc(dev,"Apple MacIO ATA Controller");
+		sc->rev = 3;
+		sc->max_mode = ATA_WDMA2;
+	}
+
+	return (ata_probe(dev));
+}
+
+static int
+ata_macio_attach(device_t dev)
+{
+	struct ata_macio_softc *sc = device_get_softc(dev);
+	uint32_t timingreg;
+	struct ata_channel *ch;
+	int rid, i;
+
+	/*
+	 * Allocate resources
+	 */
+
+	rid = 0;
+	ch = &sc->sc_ch.sc_ch;
+	sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 
+	    RF_ACTIVE);
+	if (sc->sc_mem == NULL) {
+		device_printf(dev, "could not allocate memory\n");
+		return (ENXIO);
+	}
+
+	/*
+	 * Set up the resource vectors
+	 */
+	for (i = ATA_DATA; i <= ATA_COMMAND; i++) {
+		ch->r_io[i].res = sc->sc_mem;
+		ch->r_io[i].offset = i * ATA_MACIO_REGGAP;
+	}
+	ch->r_io[ATA_CONTROL].res = sc->sc_mem;
+	ch->r_io[ATA_CONTROL].offset = ATA_MACIO_ALTOFFSET;
+	ata_default_registers(dev);
+
+	ch->unit = 0;
+	ch->flags |= ATA_USE_16BIT | ATA_NO_ATAPI_DMA;
+	ata_generic_hw(dev);
+
+#if USE_DBDMA_IRQ
+	int dbdma_irq_rid = 1;
+	struct resource *dbdma_irq;
+	void *cookie;
+#endif
+
+	/* Init DMA engine */
+
+	sc->sc_ch.dbdma_rid = 1;
+	sc->sc_ch.dbdma_regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 
+	    &sc->sc_ch.dbdma_rid, RF_ACTIVE); 
+
+	ata_dbdma_dmainit(dev);
+
+	/* Configure initial timings */
+	timingreg = bus_read_4(sc->sc_mem, ATA_MACIO_TIMINGREG);
+	if (sc->rev == 4) {
+		sc->udmaconf[0] = sc->udmaconf[1] = timingreg & 0x1ff00000;
+		sc->wdmaconf[0] = sc->wdmaconf[1] = timingreg & 0x001ffc00;
+		sc->pioconf[0]  = sc->pioconf[1]  = timingreg & 0x000003ff;
+	} else {
+		sc->udmaconf[0] = sc->udmaconf[1] = 0;
+		sc->wdmaconf[0] = sc->wdmaconf[1] = timingreg & 0xfffff800;
+		sc->pioconf[0]  = sc->pioconf[1]  = timingreg & 0x000007ff;
+	}
+
+#if USE_DBDMA_IRQ
+	/* Bind to DBDMA interrupt as well */
+
+	if ((dbdma_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+	    &dbdma_irq_rid, RF_SHAREABLE | RF_ACTIVE)) != NULL) {
+		bus_setup_intr(dev, dbdma_irq, ATA_INTR_FLAGS, NULL,
+			(driver_intr_t *)ata_interrupt, sc,&cookie);
+	} 
+#endif
+
+	/* Set begin_transaction */
+	sc->sc_ch.sc_ch.hw.begin_transaction = ata_macio_begin_transaction;
+
+	return ata_attach(dev);
+}
+
+static int
+ata_macio_setmode(device_t dev, int target, int mode)
+{
+	struct ata_macio_softc *sc = device_get_softc(dev);
+
+	int min_cycle = 0, min_active = 0;
+        int cycle_tick = 0, act_tick = 0, inact_tick = 0, half_tick;
+
+	mode = min(mode, sc->max_mode);
+
+	if ((mode & ATA_DMA_MASK) == ATA_UDMA0) {
+		min_cycle = udma_timings[mode & ATA_MODE_MASK].cycle;
+		min_active = udma_timings[mode & ATA_MODE_MASK].active;
+	
+		cycle_tick = ATA_TIME_TO_TICK(sc->rev,min_cycle);
+		act_tick = ATA_TIME_TO_TICK(sc->rev,min_active);
+
+		/* mask: 0x1ff00000 */
+		sc->udmaconf[target] =
+		    (cycle_tick << 21) | (act_tick << 25) | 0x100000;
+	} else if ((mode & ATA_DMA_MASK) == ATA_WDMA0) {
+		min_cycle = dma_timings[mode & ATA_MODE_MASK].cycle;
+		min_active = dma_timings[mode & ATA_MODE_MASK].active;
+	
+		cycle_tick = ATA_TIME_TO_TICK(sc->rev,min_cycle);
+		act_tick = ATA_TIME_TO_TICK(sc->rev,min_active);
+
+		if (sc->rev == 4) {
+			inact_tick = cycle_tick - act_tick;
+			/* mask: 0x001ffc00 */
+			sc->wdmaconf[target] = 
+			    (act_tick << 10) | (inact_tick << 15);
+		} else {
+			inact_tick = cycle_tick - act_tick - DMA_REC_OFFSET;
+			if (inact_tick < DMA_REC_MIN)
+				inact_tick = DMA_REC_MIN;
+			half_tick = 0;  /* XXX */
+
+			/* mask: 0xfffff800 */
+			sc->wdmaconf[target] = (half_tick << 21) 
+			    | (inact_tick << 16) | (act_tick << 11);
+		}
+	} else {
+		min_cycle = 
+		    pio_timings[(mode & ATA_MODE_MASK) - ATA_PIO0].cycle;
+		min_active = 
+		    pio_timings[(mode & ATA_MODE_MASK) - ATA_PIO0].active;
+	
+		cycle_tick = ATA_TIME_TO_TICK(sc->rev,min_cycle);
+		act_tick = ATA_TIME_TO_TICK(sc->rev,min_active);
+
+		if (sc->rev == 4) {
+			inact_tick = cycle_tick - act_tick;
+
+			/* mask: 0x000003ff */
+			sc->pioconf[target] =
+			    (inact_tick << 5) | act_tick;
+		} else {
+			if (act_tick < PIO_ACT_MIN)
+				act_tick = PIO_ACT_MIN;
+
+			inact_tick = cycle_tick - act_tick - PIO_REC_OFFSET;
+			if (inact_tick < PIO_REC_MIN)
+				inact_tick = PIO_REC_MIN;
+
+			/* mask: 0x000007ff */
+			sc->pioconf[target] = 
+			    (inact_tick << 5) | act_tick;
+		}
+	}
+
+	return (mode);
+}
+
+static int
+ata_macio_begin_transaction(struct ata_request *request)
+{
+	struct ata_macio_softc *sc = device_get_softc(request->parent);
+
+	bus_write_4(sc->sc_mem, ATA_MACIO_TIMINGREG, 
+	    sc->udmaconf[request->unit] | sc->wdmaconf[request->unit] 
+	    | sc->pioconf[request->unit]); 
+
+	return ata_begin_transaction(request);
+}


Property changes on: trunk/sys/powerpc/powermac/ata_macio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/atibl.c
===================================================================
--- trunk/sys/powerpc/powermac/atibl.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/atibl.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,316 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Justin Hibbits
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/atibl.c 271205 2014-09-06 19:38:40Z jhibbits $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+
+#include <dev/ofw/openfirm.h>
+
+/* From the xf86-video-ati driver's radeon_reg.h */
+#define RADEON_LVDS_GEN_CNTL         0x02d0
+#define  RADEON_LVDS_ON               (1   <<  0)
+#define  RADEON_LVDS_DISPLAY_DIS      (1   <<  1)
+#define  RADEON_LVDS_PANEL_TYPE       (1   <<  2)
+#define  RADEON_LVDS_PANEL_FORMAT     (1   <<  3)
+#define  RADEON_LVDS_RST_FM           (1   <<  6)
+#define  RADEON_LVDS_EN               (1   <<  7)
+#define  RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8
+#define  RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8)
+#define  RADEON_LVDS_BL_MOD_EN        (1   << 16)
+#define  RADEON_LVDS_DIGON            (1   << 18)
+#define  RADEON_LVDS_BLON             (1   << 19)
+#define RADEON_LVDS_PLL_CNTL         0x02d4
+#define  RADEON_LVDS_PLL_EN           (1   << 16)
+#define  RADEON_LVDS_PLL_RESET        (1   << 17)
+#define RADEON_PIXCLKS_CNTL          0x002d
+#define  RADEON_PIXCLK_LVDS_ALWAYS_ONb (1   << 14)
+#define RADEON_DISP_PWR_MAN          0x0d08
+#define  RADEON_AUTO_PWRUP_EN          (1 << 26)
+#define RADEON_CLOCK_CNTL_DATA       0x000c
+#define RADEON_CLOCK_CNTL_INDEX      0x0008
+#define  RADEON_PLL_WR_EN              (1 << 7)
+#define RADEON_CRTC_GEN_CNTL         0x0050
+
+struct atibl_softc {
+	struct resource *sc_memr;
+	int		 sc_level;
+};
+
+static void atibl_identify(driver_t *driver, device_t parent);
+static int atibl_probe(device_t dev);
+static int atibl_attach(device_t dev);
+static int atibl_setlevel(struct atibl_softc *sc, int newlevel);
+static int atibl_getlevel(struct atibl_softc *sc);
+static int atibl_resume(device_t dev);
+static int atibl_suspend(device_t dev);
+static int atibl_sysctl(SYSCTL_HANDLER_ARGS);
+
+static device_method_t atibl_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_identify,	atibl_identify),
+	DEVMETHOD(device_probe,		atibl_probe),
+	DEVMETHOD(device_attach,	atibl_attach),
+	DEVMETHOD(device_suspend,	atibl_suspend),
+	DEVMETHOD(device_resume,	atibl_resume),
+	{0, 0},
+};
+
+static driver_t	atibl_driver = {
+	"backlight",
+	atibl_methods,
+	sizeof(struct atibl_softc)
+};
+
+static devclass_t atibl_devclass;
+
+DRIVER_MODULE(atibl, vgapci, atibl_driver, atibl_devclass, 0, 0);
+
+static void
+atibl_identify(driver_t *driver, device_t parent)
+{
+	if (OF_finddevice("mac-io/backlight") == -1)
+		return;
+	if (device_find_child(parent, "backlight", -1) == NULL)
+		device_add_child(parent, "backlight", -1);
+}
+
+static int
+atibl_probe(device_t dev)
+{
+	char		control[8];
+	phandle_t	handle;
+
+	handle = OF_finddevice("mac-io/backlight");
+
+	if (handle == -1)
+		return (ENXIO);
+
+	if (OF_getprop(handle, "backlight-control", &control, sizeof(control)) < 0)
+		return (ENXIO);
+
+	if (strcmp(control, "ati") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "PowerBook backlight for ATI graphics");
+
+	return (0);
+}
+
+static int
+atibl_attach(device_t dev)
+{
+	struct atibl_softc	*sc;
+	struct sysctl_ctx_list *ctx;
+	struct sysctl_oid *tree;
+	int			 rid;
+
+	sc = device_get_softc(dev);
+
+	rid = 0x18;	/* BAR[2], for the MMIO register */
+	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+			RF_ACTIVE | RF_SHAREABLE);
+	if (sc->sc_memr == NULL) {
+		device_printf(dev, "Could not alloc mem resource!\n");
+		return (ENXIO);
+	}
+
+	ctx = device_get_sysctl_ctx(dev);
+	tree = device_get_sysctl_tree(dev);
+
+	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+	    "level", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+	    atibl_sysctl, "I", "Backlight level (0-100)");
+
+	return (0);
+}
+
+static uint32_t __inline
+atibl_pll_rreg(struct atibl_softc *sc, uint32_t reg)
+{
+	uint32_t data, save, tmp;
+
+	bus_write_1(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX,
+	    ((reg & 0x3f) | RADEON_PLL_WR_EN));
+	(void)bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA);
+	(void)bus_read_4(sc->sc_memr, RADEON_CRTC_GEN_CNTL);
+
+	data = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA);
+
+	/* Only necessary on R300, bt won't hurt others. */
+	save = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX);
+	tmp = save & (~0x3f | RADEON_PLL_WR_EN);
+	bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, tmp);
+	tmp = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA);
+	bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, save);
+
+	return data;
+}
+
+static void __inline
+atibl_pll_wreg(struct atibl_softc *sc, uint32_t reg, uint32_t val)
+{
+	uint32_t save, tmp;
+
+	bus_write_1(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX,
+	    ((reg & 0x3f) | RADEON_PLL_WR_EN));
+	(void)bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA);
+	(void)bus_read_4(sc->sc_memr, RADEON_CRTC_GEN_CNTL);
+
+	bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA, val);
+	DELAY(5000);
+
+	/* Only necessary on R300, bt won't hurt others. */
+	save = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX);
+	tmp = save & (~0x3f | RADEON_PLL_WR_EN);
+	bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, tmp);
+	tmp = bus_read_4(sc->sc_memr, RADEON_CLOCK_CNTL_DATA);
+	bus_write_4(sc->sc_memr, RADEON_CLOCK_CNTL_INDEX, save);
+}
+
+static int
+atibl_setlevel(struct atibl_softc *sc, int newlevel)
+{
+	uint32_t lvds_gen_cntl;
+	uint32_t lvds_pll_cntl;
+	uint32_t pixclks_cntl;
+	uint32_t disp_pwr_reg;
+
+	if (newlevel > 100)
+		newlevel = 100;
+
+	if (newlevel < 0)
+		newlevel = 0;
+
+	lvds_gen_cntl = bus_read_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL);
+
+	if (newlevel > 0) {
+		newlevel = (newlevel * 5) / 2 + 5;
+		disp_pwr_reg = bus_read_4(sc->sc_memr, RADEON_DISP_PWR_MAN);
+		disp_pwr_reg |= RADEON_AUTO_PWRUP_EN;
+		bus_write_4(sc->sc_memr, RADEON_DISP_PWR_MAN, disp_pwr_reg);
+		lvds_pll_cntl = bus_read_4(sc->sc_memr, RADEON_LVDS_PLL_CNTL);
+		lvds_pll_cntl |= RADEON_LVDS_PLL_EN;
+		bus_write_4(sc->sc_memr, RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
+		lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
+		bus_write_4(sc->sc_memr, RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
+		DELAY(1000);
+
+		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS | 
+		    RADEON_LVDS_BL_MOD_LEVEL_MASK);
+		lvds_gen_cntl |= RADEON_LVDS_ON | RADEON_LVDS_EN |
+		    RADEON_LVDS_DIGON | RADEON_LVDS_BLON;
+		lvds_gen_cntl |= (newlevel << RADEON_LVDS_BL_MOD_LEVEL_SHIFT) &
+		    RADEON_LVDS_BL_MOD_LEVEL_MASK;
+		lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
+		DELAY(200000);
+		bus_write_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
+	} else {
+		pixclks_cntl = atibl_pll_rreg(sc, RADEON_PIXCLKS_CNTL);
+		atibl_pll_wreg(sc, RADEON_PIXCLKS_CNTL,
+		    pixclks_cntl & ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
+		lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
+		lvds_gen_cntl &= ~(RADEON_LVDS_BL_MOD_EN | RADEON_LVDS_BL_MOD_LEVEL_MASK);
+		bus_write_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
+		lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN);
+		DELAY(200000);
+		bus_write_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
+
+		atibl_pll_wreg(sc, RADEON_PIXCLKS_CNTL, pixclks_cntl);
+		DELAY(200000);
+	}
+
+	return (0);
+}
+
+static int
+atibl_getlevel(struct atibl_softc *sc)
+{
+	uint32_t	lvds_gen_cntl;
+	int			level;
+
+	lvds_gen_cntl = bus_read_4(sc->sc_memr, RADEON_LVDS_GEN_CNTL);
+
+	level = ((lvds_gen_cntl & RADEON_LVDS_BL_MOD_LEVEL_MASK) >>
+	    RADEON_LVDS_BL_MOD_LEVEL_SHIFT);
+	if (level != 0)
+		level = ((level - 5) * 2) / 5;
+
+	return (level);
+}
+
+static int
+atibl_suspend(device_t dev)
+{
+	struct atibl_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	sc->sc_level = atibl_getlevel(sc);
+	atibl_setlevel(sc, 0);
+
+	return (0);
+}
+
+static int
+atibl_resume(device_t dev)
+{
+	struct atibl_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	atibl_setlevel(sc, sc->sc_level);
+
+	return (0);
+}
+
+static int
+atibl_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	struct atibl_softc *sc;
+	int newlevel, error;
+
+	sc = arg1;
+
+	newlevel = atibl_getlevel(sc);
+
+	error = sysctl_handle_int(oidp, &newlevel, 0, req);
+
+	if (error || !req->newptr)
+		return (error);
+
+	return (atibl_setlevel(sc, newlevel));
+}


Property changes on: trunk/sys/powerpc/powermac/atibl.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/cpcht.c
===================================================================
--- trunk/sys/powerpc/powermac/cpcht.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/cpcht.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,735 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008-2010 Nathan Whitehorn
+ * 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.
+ *
+ * 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 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/cpcht.c 266160 2014-05-15 17:30:16Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/pciio.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/openpicvar.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <powerpc/ofw/ofw_pci.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include "pcib_if.h"
+#include "pic_if.h"
+
+/*
+ * IBM CPC9X5 Hypertransport Device interface.
+ */
+static int		cpcht_probe(device_t);
+static int		cpcht_attach(device_t);
+
+static void		cpcht_configure_htbridge(device_t, phandle_t);
+
+/*
+ * pcib interface.
+ */
+static u_int32_t	cpcht_read_config(device_t, u_int, u_int, u_int,
+			    u_int, int);
+static void		cpcht_write_config(device_t, u_int, u_int, u_int,
+			    u_int, u_int32_t, int);
+static int		cpcht_route_interrupt(device_t, device_t, int);
+static int		cpcht_alloc_msi(device_t dev, device_t child,
+			    int count, int maxcount, int *irqs);
+static int		cpcht_release_msi(device_t dev, device_t child,
+			    int count, int *irqs);
+static int		cpcht_alloc_msix(device_t dev, device_t child,
+			    int *irq);
+static int		cpcht_release_msix(device_t dev, device_t child,
+			    int irq);
+static int		cpcht_map_msi(device_t dev, device_t child,
+			    int irq, uint64_t *addr, uint32_t *data);
+
+/*
+ * Driver methods.
+ */
+static device_method_t	cpcht_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		cpcht_probe),
+	DEVMETHOD(device_attach,	cpcht_attach),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_read_config,	cpcht_read_config),
+	DEVMETHOD(pcib_write_config,	cpcht_write_config),
+	DEVMETHOD(pcib_route_interrupt,	cpcht_route_interrupt),
+	DEVMETHOD(pcib_alloc_msi,	cpcht_alloc_msi),
+	DEVMETHOD(pcib_release_msi,	cpcht_release_msi),
+	DEVMETHOD(pcib_alloc_msix,	cpcht_alloc_msix),
+	DEVMETHOD(pcib_release_msix,	cpcht_release_msix),
+	DEVMETHOD(pcib_map_msi,		cpcht_map_msi),
+
+	DEVMETHOD_END
+};
+
+struct cpcht_irq {
+	enum {
+	    IRQ_NONE, IRQ_HT, IRQ_MSI, IRQ_INTERNAL
+	}		irq_type; 
+
+	int		ht_source;
+
+	vm_offset_t	ht_base;
+	vm_offset_t	apple_eoi;
+	uint32_t	eoi_data;
+	int		edge;
+};
+
+static struct cpcht_irq *cpcht_irqmap = NULL;
+uint32_t cpcht_msipic = 0;
+
+struct cpcht_softc {
+	struct ofw_pci_softc	pci_sc;
+	vm_offset_t		sc_data;
+	uint64_t		sc_populated_slots;
+
+	struct cpcht_irq	htirq_map[128];
+	struct mtx		htirq_mtx;
+};
+
+static devclass_t	cpcht_devclass;
+DEFINE_CLASS_1(pcib, cpcht_driver, cpcht_methods, sizeof(struct cpcht_softc),
+    ofw_pci_driver);
+DRIVER_MODULE(cpcht, ofwbus, cpcht_driver, cpcht_devclass, 0, 0);
+
+#define CPCHT_IOPORT_BASE	0xf4000000UL /* Hardwired */
+#define CPCHT_IOPORT_SIZE	0x00400000UL
+
+#define HTAPIC_REQUEST_EOI	0x20
+#define HTAPIC_TRIGGER_LEVEL	0x02
+#define HTAPIC_MASK		0x01
+
+static int
+cpcht_probe(device_t dev)
+{
+	const char	*type, *compatible;
+
+	type = ofw_bus_get_type(dev);
+	compatible = ofw_bus_get_compat(dev);
+
+	if (type == NULL || compatible == NULL)
+		return (ENXIO);
+
+	if (strcmp(type, "ht") != 0)
+		return (ENXIO);
+
+	if (strcmp(compatible, "u3-ht") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "IBM CPC9X5 HyperTransport Tunnel");
+	return (0);
+}
+
+static int
+cpcht_attach(device_t dev)
+{
+	struct		cpcht_softc *sc;
+	phandle_t	node, child;
+	u_int32_t	reg[3];
+	int		i;
+
+	node = ofw_bus_get_node(dev);
+	sc = device_get_softc(dev);
+
+	if (OF_getprop(node, "reg", reg, sizeof(reg)) < 12)
+		return (ENXIO);
+
+	if (OF_getproplen(node, "ranges") <= 0)
+		sc->pci_sc.sc_quirks = OFW_PCI_QUIRK_RANGES_ON_CHILDREN;
+	sc->sc_populated_slots = 0;
+	sc->sc_data = (vm_offset_t)pmap_mapdev(reg[1], reg[2]);
+
+	/*
+	 * Set up the resource manager and the HT->MPIC mapping. For cpcht,
+	 * the ranges are properties of the child bridges, and this is also
+	 * where we get the HT interrupts properties.
+	 */
+
+#if 0
+	/* I/O port mappings are usually not in the device tree */
+	rman_manage_region(&sc->pci_sc.sc_io_rman, 0, CPCHT_IOPORT_SIZE - 1);
+#endif
+
+	bzero(sc->htirq_map, sizeof(sc->htirq_map));
+	mtx_init(&sc->htirq_mtx, "cpcht irq", NULL, MTX_DEF);
+	for (i = 0; i < 8; i++)
+		sc->htirq_map[i].irq_type = IRQ_INTERNAL;
+	for (child = OF_child(node); child != 0; child = OF_peer(child))
+		cpcht_configure_htbridge(dev, child);
+
+	/* Now make the mapping table available to the MPIC */
+	cpcht_irqmap = sc->htirq_map;
+
+	return (ofw_pci_attach(dev));
+}
+
+static void
+cpcht_configure_htbridge(device_t dev, phandle_t child)
+{
+	struct cpcht_softc *sc;
+	struct ofw_pci_register pcir;
+	int ptr, nextptr;
+	uint32_t vend, val;
+	int i, nirq, irq;
+	u_int b, f, s;
+
+	sc = device_get_softc(dev);
+	if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1)
+		return;
+
+	b = OFW_PCI_PHYS_HI_BUS(pcir.phys_hi);
+	s = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi);
+	f = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi);
+
+	/*
+	 * Mark this slot is populated. The remote south bridge does
+	 * not like us talking to unpopulated slots on the root bus.
+	 */
+	sc->sc_populated_slots |= (1 << s);
+
+	/*
+	 * Next build up any HT->MPIC mappings for this sub-bus. One would
+	 * naively hope that enabling, disabling, and EOIing interrupts would
+	 * cause the appropriate HT bus transactions to that effect. This is
+	 * not the case.
+	 *
+	 * Instead, we have to muck about on the HT peer's root PCI bridges,
+	 * figure out what interrupts they send, enable them, and cache
+	 * the location of their WaitForEOI registers so that we can
+	 * send EOIs later.
+	 */
+
+	/* All the devices we are interested in have caps */
+	if (!(PCIB_READ_CONFIG(dev, b, s, f, PCIR_STATUS, 2)
+	    & PCIM_STATUS_CAPPRESENT))
+		return;
+
+	nextptr = PCIB_READ_CONFIG(dev, b, s, f, PCIR_CAP_PTR, 1);
+	while (nextptr != 0) {
+		ptr = nextptr;
+		nextptr = PCIB_READ_CONFIG(dev, b, s, f,
+		    ptr + PCICAP_NEXTPTR, 1);
+
+		/* Find the HT IRQ capabilities */
+		if (PCIB_READ_CONFIG(dev, b, s, f,
+		    ptr + PCICAP_ID, 1) != PCIY_HT)
+			continue;
+
+		val = PCIB_READ_CONFIG(dev, b, s, f, ptr + PCIR_HT_COMMAND, 2);
+		if ((val & PCIM_HTCMD_CAP_MASK) != PCIM_HTCAP_INTERRUPT)
+			continue;
+
+		/* Ask for the IRQ count */
+		PCIB_WRITE_CONFIG(dev, b, s, f, ptr + PCIR_HT_COMMAND, 0x1, 1);
+		nirq = PCIB_READ_CONFIG(dev, b, s, f, ptr + 4, 4);
+		nirq = ((nirq >> 16) & 0xff) + 1;
+
+		device_printf(dev, "%d HT IRQs on device %d.%d\n", nirq, s, f);
+
+		for (i = 0; i < nirq; i++) {
+			PCIB_WRITE_CONFIG(dev, b, s, f,
+			     ptr + PCIR_HT_COMMAND, 0x10 + (i << 1), 1);
+			irq = PCIB_READ_CONFIG(dev, b, s, f, ptr + 4, 4);
+
+			/*
+			 * Mask this interrupt for now.
+			 */
+			PCIB_WRITE_CONFIG(dev, b, s, f, ptr + 4,
+			    irq | HTAPIC_MASK, 4);
+			irq = (irq >> 16) & 0xff;
+
+			sc->htirq_map[irq].irq_type = IRQ_HT;
+			sc->htirq_map[irq].ht_source = i;
+			sc->htirq_map[irq].ht_base = sc->sc_data + 
+			    (((((s & 0x1f) << 3) | (f & 0x07)) << 8) | (ptr));
+
+			PCIB_WRITE_CONFIG(dev, b, s, f,
+			     ptr + PCIR_HT_COMMAND, 0x11 + (i << 1), 1);
+			sc->htirq_map[irq].eoi_data =
+			    PCIB_READ_CONFIG(dev, b, s, f, ptr + 4, 4) |
+			    0x80000000;
+
+			/*
+			 * Apple uses a non-compliant IO/APIC that differs
+			 * in how we signal EOIs. Check if this device was 
+			 * made by Apple, and act accordingly.
+			 */
+			vend = PCIB_READ_CONFIG(dev, b, s, f,
+			    PCIR_DEVVENDOR, 4);
+			if ((vend & 0xffff) == 0x106b)
+				sc->htirq_map[irq].apple_eoi = 
+				 (sc->htirq_map[irq].ht_base - ptr) + 0x60;
+		}
+	}
+}
+
+static u_int32_t
+cpcht_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
+    int width)
+{
+	struct		cpcht_softc *sc;
+	vm_offset_t	caoff;
+
+	sc = device_get_softc(dev);
+	caoff = sc->sc_data + 
+		(((((slot & 0x1f) << 3) | (func & 0x07)) << 8) | reg);
+
+	if (bus == 0 && (!(sc->sc_populated_slots & (1 << slot)) || func > 0))
+		return (0xffffffff);
+
+	if (bus > 0)
+		caoff += 0x01000000UL + (bus << 16);
+
+	switch (width) {
+	case 1:
+		return (in8rb(caoff));
+		break;
+	case 2:
+		return (in16rb(caoff));
+		break;
+	case 4:
+		return (in32rb(caoff));
+		break;
+	}
+
+	return (0xffffffff);
+}
+
+static void
+cpcht_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+    u_int reg, u_int32_t val, int width)
+{
+	struct		cpcht_softc *sc;
+	vm_offset_t	caoff;
+
+	sc = device_get_softc(dev);
+	caoff = sc->sc_data + 
+		(((((slot & 0x1f) << 3) | (func & 0x07)) << 8) | reg);
+
+	if (bus == 0 && (!(sc->sc_populated_slots & (1 << slot)) || func > 0))
+		return;
+
+	if (bus > 0)
+		caoff += 0x01000000UL + (bus << 16);
+
+	switch (width) {
+	case 1:
+		out8rb(caoff, val);
+		break;
+	case 2:
+		out16rb(caoff, val);
+		break;
+	case 4:
+		out32rb(caoff, val);
+		break;
+	}
+}
+
+static int
+cpcht_route_interrupt(device_t bus, device_t dev, int pin)
+{
+	return (pin);
+}
+
+static int
+cpcht_alloc_msi(device_t dev, device_t child, int count, int maxcount,
+    int *irqs)
+{
+	struct cpcht_softc *sc;
+	int i, j;
+
+	sc = device_get_softc(dev);
+	j = 0;
+
+	/* Bail if no MSI PIC yet */
+	if (cpcht_msipic == 0)
+		return (ENXIO);
+
+	mtx_lock(&sc->htirq_mtx);
+	for (i = 8; i < 124 - count; i++) {
+		for (j = 0; j < count; j++) {
+			if (sc->htirq_map[i+j].irq_type != IRQ_NONE)
+				break;
+		}
+		if (j == count)
+			break;
+
+		i += j; /* We know there isn't a large enough run */
+	}
+
+	if (j != count) {
+		mtx_unlock(&sc->htirq_mtx);
+		return (ENXIO);
+	}
+
+	for (j = 0; j < count; j++) {
+		irqs[j] = MAP_IRQ(cpcht_msipic, i+j);
+		sc->htirq_map[i+j].irq_type = IRQ_MSI;
+	}
+	mtx_unlock(&sc->htirq_mtx);
+
+	return (0);
+}
+
+static int
+cpcht_release_msi(device_t dev, device_t child, int count, int *irqs)
+{
+	struct cpcht_softc *sc;
+	int i;
+
+	sc = device_get_softc(dev);
+
+	mtx_lock(&sc->htirq_mtx);
+	for (i = 0; i < count; i++)
+		sc->htirq_map[irqs[i] & 0xff].irq_type = IRQ_NONE;
+	mtx_unlock(&sc->htirq_mtx);
+
+	return (0);
+}
+
+static int
+cpcht_alloc_msix(device_t dev, device_t child, int *irq)
+{
+	struct cpcht_softc *sc;
+	int i;
+
+	sc = device_get_softc(dev);
+
+	/* Bail if no MSI PIC yet */
+	if (cpcht_msipic == 0)
+		return (ENXIO);
+
+	mtx_lock(&sc->htirq_mtx);
+	for (i = 8; i < 124; i++) {
+		if (sc->htirq_map[i].irq_type == IRQ_NONE) {
+			sc->htirq_map[i].irq_type = IRQ_MSI;
+			*irq = MAP_IRQ(cpcht_msipic, i);
+
+			mtx_unlock(&sc->htirq_mtx);
+			return (0);
+		}
+	}
+	mtx_unlock(&sc->htirq_mtx);
+
+	return (ENXIO);
+}
+	
+static int
+cpcht_release_msix(device_t dev, device_t child, int irq)
+{
+	struct cpcht_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	mtx_lock(&sc->htirq_mtx);
+	sc->htirq_map[irq & 0xff].irq_type = IRQ_NONE;
+	mtx_unlock(&sc->htirq_mtx);
+
+	return (0);
+}
+
+static int
+cpcht_map_msi(device_t dev, device_t child, int irq, uint64_t *addr,
+    uint32_t *data)
+{
+	device_t pcib;
+	struct pci_devinfo *dinfo;
+	struct pcicfg_ht *ht = NULL;
+
+	for (pcib = child; pcib != dev; pcib =
+	    device_get_parent(device_get_parent(pcib))) {
+		dinfo = device_get_ivars(pcib);
+		ht = &dinfo->cfg.ht;
+
+		if (ht == NULL)
+			continue;
+	}
+
+	if (ht == NULL)
+		return (ENXIO);
+
+	*addr = ht->ht_msiaddr;
+	*data = irq & 0xff;
+
+	return (0);
+}
+
+/*
+ * Driver for the integrated MPIC on U3/U4 (CPC925/CPC945)
+ */
+
+static int	openpic_cpcht_probe(device_t);
+static int	openpic_cpcht_attach(device_t);
+static void	openpic_cpcht_config(device_t, u_int irq,
+		    enum intr_trigger trig, enum intr_polarity pol);
+static void	openpic_cpcht_enable(device_t, u_int irq, u_int vector);
+static void	openpic_cpcht_unmask(device_t, u_int irq);
+static void	openpic_cpcht_eoi(device_t, u_int irq);
+
+static device_method_t  openpic_cpcht_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		openpic_cpcht_probe),
+	DEVMETHOD(device_attach,	openpic_cpcht_attach),
+
+	/* PIC interface */
+	DEVMETHOD(pic_bind,		openpic_bind),
+	DEVMETHOD(pic_config,		openpic_cpcht_config),
+	DEVMETHOD(pic_dispatch,		openpic_dispatch),
+	DEVMETHOD(pic_enable,		openpic_cpcht_enable),
+	DEVMETHOD(pic_eoi,		openpic_cpcht_eoi),
+	DEVMETHOD(pic_ipi,		openpic_ipi),
+	DEVMETHOD(pic_mask,		openpic_mask),
+	DEVMETHOD(pic_unmask,		openpic_cpcht_unmask),
+
+	{ 0, 0 },
+};
+
+struct openpic_cpcht_softc {
+	struct openpic_softc sc_openpic;
+
+	struct mtx sc_ht_mtx;
+};
+
+static driver_t openpic_cpcht_driver = {
+	"htpic",
+	openpic_cpcht_methods,
+	sizeof(struct openpic_cpcht_softc),
+};
+
+DRIVER_MODULE(openpic, unin, openpic_cpcht_driver, openpic_devclass, 0, 0);
+
+static int
+openpic_cpcht_probe(device_t dev)
+{
+	const char *type = ofw_bus_get_type(dev);
+
+	if (strcmp(type, "open-pic") != 0)
+                return (ENXIO);
+
+	device_set_desc(dev, OPENPIC_DEVSTR);
+	return (0);
+}
+
+static int
+openpic_cpcht_attach(device_t dev)
+{
+	struct openpic_cpcht_softc *sc;
+	phandle_t node;
+	int err, irq;
+
+	node = ofw_bus_get_node(dev);
+	err = openpic_common_attach(dev, node);
+	if (err != 0)
+		return (err);
+
+	/*
+	 * The HT APIC stuff is not thread-safe, so we need a mutex to
+	 * protect it.
+	 */
+	sc = device_get_softc(dev);
+	mtx_init(&sc->sc_ht_mtx, "htpic", NULL, MTX_SPIN);
+
+	/*
+	 * Interrupts 0-3 are internally sourced and are level triggered
+	 * active low. Interrupts 4-123 are connected to a pulse generator
+	 * and should be programmed as edge triggered low-to-high.
+	 * 
+	 * IBM CPC945 Manual, Section 9.3.
+	 */
+
+	for (irq = 0; irq < 4; irq++)
+		openpic_config(dev, irq, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
+	for (irq = 4; irq < 124; irq++)
+		openpic_config(dev, irq, INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);
+
+	/*
+	 * Use this PIC for MSI only if it is the root PIC. This may not
+	 * be necessary, but Linux does it, and I cannot find any U3 machines
+	 * with MSI devices to test.
+	 */
+	if (dev == root_pic)
+		cpcht_msipic = node;
+
+	return (0);
+}
+
+static void
+openpic_cpcht_config(device_t dev, u_int irq, enum intr_trigger trig,
+    enum intr_polarity pol)
+{
+	struct openpic_cpcht_softc *sc;
+	uint32_t ht_irq;
+
+	/*
+	 * The interrupt settings for the MPIC are completely determined
+	 * by the internal wiring in the northbridge. Real changes to these
+	 * settings need to be negotiated with the remote IO-APIC on the HT
+	 * link.
+	 */
+
+	sc = device_get_softc(dev);
+
+	if (cpcht_irqmap != NULL && irq < 128 &&
+	    cpcht_irqmap[irq].ht_base > 0 && !cpcht_irqmap[irq].edge) {
+		mtx_lock_spin(&sc->sc_ht_mtx);
+
+		/* Program the data port */
+		out8rb(cpcht_irqmap[irq].ht_base + PCIR_HT_COMMAND,
+		    0x10 + (cpcht_irqmap[irq].ht_source << 1));
+
+		/* Grab the IRQ config register */
+		ht_irq = in32rb(cpcht_irqmap[irq].ht_base + 4);
+
+		/* Mask the IRQ while we fiddle settings */
+		out32rb(cpcht_irqmap[irq].ht_base + 4, ht_irq | HTAPIC_MASK);
+		
+		/* Program the interrupt sense */
+		ht_irq &= ~(HTAPIC_TRIGGER_LEVEL | HTAPIC_REQUEST_EOI);
+		if (trig == INTR_TRIGGER_EDGE) {
+			cpcht_irqmap[irq].edge = 1;
+		} else {
+			cpcht_irqmap[irq].edge = 0;
+			ht_irq |= HTAPIC_TRIGGER_LEVEL | HTAPIC_REQUEST_EOI;
+		}
+		out32rb(cpcht_irqmap[irq].ht_base + 4, ht_irq);
+
+		mtx_unlock_spin(&sc->sc_ht_mtx);
+	}
+}
+
+static void
+openpic_cpcht_enable(device_t dev, u_int irq, u_int vec)
+{
+	struct openpic_cpcht_softc *sc;
+	uint32_t ht_irq;
+
+	openpic_enable(dev, irq, vec);
+
+	sc = device_get_softc(dev);
+
+	if (cpcht_irqmap != NULL && irq < 128 &&
+	    cpcht_irqmap[irq].ht_base > 0) {
+		mtx_lock_spin(&sc->sc_ht_mtx);
+
+		/* Program the data port */
+		out8rb(cpcht_irqmap[irq].ht_base + PCIR_HT_COMMAND,
+		    0x10 + (cpcht_irqmap[irq].ht_source << 1));
+
+		/* Unmask the interrupt */
+		ht_irq = in32rb(cpcht_irqmap[irq].ht_base + 4);
+		ht_irq &= ~HTAPIC_MASK;
+		out32rb(cpcht_irqmap[irq].ht_base + 4, ht_irq);
+
+		mtx_unlock_spin(&sc->sc_ht_mtx);
+	}
+		
+	openpic_cpcht_eoi(dev, irq);
+}
+
+static void
+openpic_cpcht_unmask(device_t dev, u_int irq)
+{
+	struct openpic_cpcht_softc *sc;
+	uint32_t ht_irq;
+
+	openpic_unmask(dev, irq);
+
+	sc = device_get_softc(dev);
+
+	if (cpcht_irqmap != NULL && irq < 128 &&
+	    cpcht_irqmap[irq].ht_base > 0) {
+		mtx_lock_spin(&sc->sc_ht_mtx);
+
+		/* Program the data port */
+		out8rb(cpcht_irqmap[irq].ht_base + PCIR_HT_COMMAND,
+		    0x10 + (cpcht_irqmap[irq].ht_source << 1));
+
+		/* Unmask the interrupt */
+		ht_irq = in32rb(cpcht_irqmap[irq].ht_base + 4);
+		ht_irq &= ~HTAPIC_MASK;
+		out32rb(cpcht_irqmap[irq].ht_base + 4, ht_irq);
+
+		mtx_unlock_spin(&sc->sc_ht_mtx);
+	}
+
+	openpic_cpcht_eoi(dev, irq);
+}
+
+static void
+openpic_cpcht_eoi(device_t dev, u_int irq)
+{
+	struct openpic_cpcht_softc *sc;
+	uint32_t off, mask;
+
+	if (irq == 255)
+		return;
+
+	sc = device_get_softc(dev);
+
+	if (cpcht_irqmap != NULL && irq < 128 &&
+	    cpcht_irqmap[irq].ht_base > 0 && !cpcht_irqmap[irq].edge) {
+		/* If this is an HT IRQ, acknowledge it at the remote APIC */
+
+		if (cpcht_irqmap[irq].apple_eoi) {
+			off = (cpcht_irqmap[irq].ht_source >> 3) & ~3;
+			mask = 1 << (cpcht_irqmap[irq].ht_source & 0x1f);
+			out32rb(cpcht_irqmap[irq].apple_eoi + off, mask);
+		} else {
+			mtx_lock_spin(&sc->sc_ht_mtx);
+
+			out8rb(cpcht_irqmap[irq].ht_base + PCIR_HT_COMMAND,
+			    0x11 + (cpcht_irqmap[irq].ht_source << 1));
+			out32rb(cpcht_irqmap[irq].ht_base + 4,
+			    cpcht_irqmap[irq].eoi_data);
+
+			mtx_unlock_spin(&sc->sc_ht_mtx);
+		}
+	}
+
+	openpic_eoi(dev, irq);
+}


Property changes on: trunk/sys/powerpc/powermac/cpcht.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/cuda.c
===================================================================
--- trunk/sys/powerpc/powermac/cuda.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/cuda.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,794 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Michael Lorenz
+ * Copyright 2008 by Nathan Whitehorn
+ * 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. 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/cuda.c 227843 2011-11-22 21:28:20Z marius $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/clock.h>
+#include <sys/reboot.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <sys/rman.h>
+
+#include <dev/adb/adb.h>
+
+#include "clock_if.h"
+#include "cudavar.h"
+#include "viareg.h"
+
+/*
+ * MacIO interface
+ */
+static int	cuda_probe(device_t);
+static int	cuda_attach(device_t);
+static int	cuda_detach(device_t);
+
+static u_int	cuda_adb_send(device_t dev, u_char command_byte, int len, 
+    u_char *data, u_char poll);
+static u_int	cuda_adb_autopoll(device_t dev, uint16_t mask);
+static u_int	cuda_poll(device_t dev);
+static void	cuda_send_inbound(struct cuda_softc *sc);
+static void	cuda_send_outbound(struct cuda_softc *sc);
+static void	cuda_shutdown(void *xsc, int howto);
+
+/*
+ * Clock interface
+ */
+static int cuda_gettime(device_t dev, struct timespec *ts);
+static int cuda_settime(device_t dev, struct timespec *ts);
+
+static device_method_t  cuda_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		cuda_probe),
+	DEVMETHOD(device_attach,	cuda_attach),
+        DEVMETHOD(device_detach,        cuda_detach),
+        DEVMETHOD(device_shutdown,      bus_generic_shutdown),
+        DEVMETHOD(device_suspend,       bus_generic_suspend),
+        DEVMETHOD(device_resume,        bus_generic_resume),
+
+	/* ADB bus interface */
+	DEVMETHOD(adb_hb_send_raw_packet,	cuda_adb_send),
+	DEVMETHOD(adb_hb_controller_poll,	cuda_poll),
+	DEVMETHOD(adb_hb_set_autopoll_mask,	cuda_adb_autopoll),
+
+	/* Clock interface */
+	DEVMETHOD(clock_gettime,	cuda_gettime),
+	DEVMETHOD(clock_settime,	cuda_settime),
+
+	DEVMETHOD_END
+};
+
+static driver_t cuda_driver = {
+	"cuda",
+	cuda_methods,
+	sizeof(struct cuda_softc),
+};
+
+static devclass_t cuda_devclass;
+
+DRIVER_MODULE(cuda, macio, cuda_driver, cuda_devclass, 0, 0);
+DRIVER_MODULE(adb, cuda, adb_driver, adb_devclass, 0, 0);
+
+static void cuda_intr(void *arg);
+static uint8_t cuda_read_reg(struct cuda_softc *sc, u_int offset);
+static void cuda_write_reg(struct cuda_softc *sc, u_int offset, uint8_t value);
+static void cuda_idle(struct cuda_softc *);
+static void cuda_tip(struct cuda_softc *);
+static void cuda_clear_tip(struct cuda_softc *);
+static void cuda_in(struct cuda_softc *);
+static void cuda_out(struct cuda_softc *);
+static void cuda_toggle_ack(struct cuda_softc *);
+static void cuda_ack_off(struct cuda_softc *);
+static int cuda_intr_state(struct cuda_softc *);
+
+static int
+cuda_probe(device_t dev)
+{
+	const char *type = ofw_bus_get_type(dev);
+
+	if (strcmp(type, "via-cuda") != 0)
+                return (ENXIO);
+
+	device_set_desc(dev, CUDA_DEVSTR);
+	return (0);
+}
+
+static int
+cuda_attach(device_t dev)
+{
+	struct cuda_softc *sc;
+
+	volatile int i;
+	uint8_t reg;
+	phandle_t node,child;
+	
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+	
+	sc->sc_memrid = 0;
+	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 
+	    &sc->sc_memrid, RF_ACTIVE);
+
+	if (sc->sc_memr == NULL) {
+		device_printf(dev, "Could not alloc mem resource!\n");
+		return (ENXIO);
+	}
+
+	sc->sc_irqrid = 0;
+	sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqrid,
+            	RF_ACTIVE);
+        if (sc->sc_irq == NULL) {
+                device_printf(dev, "could not allocate interrupt\n");
+                return (ENXIO);
+        }
+
+	if (bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE 
+	    | INTR_ENTROPY, NULL, cuda_intr, dev, &sc->sc_ih) != 0) {
+                device_printf(dev, "could not setup interrupt\n");
+                bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid,
+                    sc->sc_irq);
+                return (ENXIO);
+        }
+
+	mtx_init(&sc->sc_mutex,"cuda",NULL,MTX_DEF | MTX_RECURSE);
+
+	sc->sc_sent = 0;
+	sc->sc_received = 0;
+	sc->sc_waiting = 0;
+	sc->sc_polling = 0;
+	sc->sc_state = CUDA_NOTREADY;
+	sc->sc_autopoll = 0;
+	sc->sc_rtc = -1;
+
+	STAILQ_INIT(&sc->sc_inq);
+	STAILQ_INIT(&sc->sc_outq);
+	STAILQ_INIT(&sc->sc_freeq);
+
+	for (i = 0; i < CUDA_MAXPACKETS; i++)
+		STAILQ_INSERT_TAIL(&sc->sc_freeq, &sc->sc_pkts[i], pkt_q);
+
+	/* Init CUDA */
+
+	reg = cuda_read_reg(sc, vDirB);
+	reg |= 0x30;	/* register B bits 4 and 5: outputs */
+	cuda_write_reg(sc, vDirB, reg);
+
+	reg = cuda_read_reg(sc, vDirB);
+	reg &= 0xf7;	/* register B bit 3: input */
+	cuda_write_reg(sc, vDirB, reg);
+
+	reg = cuda_read_reg(sc, vACR);
+	reg &= ~vSR_OUT;	/* make sure SR is set to IN */
+	cuda_write_reg(sc, vACR, reg);
+
+	cuda_write_reg(sc, vACR, (cuda_read_reg(sc, vACR) | 0x0c) & ~0x10);
+
+	sc->sc_state = CUDA_IDLE;	/* used by all types of hardware */
+
+	cuda_write_reg(sc, vIER, 0x84); /* make sure VIA interrupts are on */
+
+	cuda_idle(sc);	/* reset ADB */
+
+	/* Reset CUDA */
+
+	i = cuda_read_reg(sc, vSR);	/* clear interrupt */
+	cuda_write_reg(sc, vIER, 0x04); /* no interrupts while clearing */
+	cuda_idle(sc);	/* reset state to idle */
+	DELAY(150);
+	cuda_tip(sc);	/* signal start of frame */
+	DELAY(150);
+	cuda_toggle_ack(sc);
+	DELAY(150);
+	cuda_clear_tip(sc);
+	DELAY(150);
+	cuda_idle(sc);	/* back to idle state */
+	i = cuda_read_reg(sc, vSR);	/* clear interrupt */
+	cuda_write_reg(sc, vIER, 0x84);	/* ints ok now */
+
+	/* Initialize child buses (ADB) */
+	node = ofw_bus_get_node(dev);
+
+	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
+		char name[32];
+
+		memset(name, 0, sizeof(name));
+		OF_getprop(child, "name", name, sizeof(name));
+
+		if (bootverbose)
+			device_printf(dev, "CUDA child <%s>\n",name);
+
+		if (strncmp(name, "adb", 4) == 0) {
+			sc->adb_bus = device_add_child(dev,"adb",-1);
+		}
+	}
+
+	clock_register(dev, 1000);
+	EVENTHANDLER_REGISTER(shutdown_final, cuda_shutdown, sc,
+	    SHUTDOWN_PRI_LAST);
+
+	return (bus_generic_attach(dev));
+}
+
+static int cuda_detach(device_t dev) {
+	struct cuda_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih);
+	bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid, sc->sc_irq);
+	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_memrid, sc->sc_memr);
+	mtx_destroy(&sc->sc_mutex);
+
+	return (bus_generic_detach(dev));
+}
+
+static uint8_t
+cuda_read_reg(struct cuda_softc *sc, u_int offset) {
+	return (bus_read_1(sc->sc_memr, offset));
+}
+
+static void
+cuda_write_reg(struct cuda_softc *sc, u_int offset, uint8_t value) {
+	bus_write_1(sc->sc_memr, offset, value);
+}
+
+static void
+cuda_idle(struct cuda_softc *sc)
+{
+	uint8_t reg;
+
+	reg = cuda_read_reg(sc, vBufB);
+	reg |= (vPB4 | vPB5);
+	cuda_write_reg(sc, vBufB, reg);
+}
+
+static void
+cuda_tip(struct cuda_softc *sc)
+{
+	uint8_t reg;
+
+	reg = cuda_read_reg(sc, vBufB);
+	reg &= ~vPB5;
+	cuda_write_reg(sc, vBufB, reg);
+}
+
+static void
+cuda_clear_tip(struct cuda_softc *sc)
+{
+	uint8_t reg;
+
+	reg = cuda_read_reg(sc, vBufB);
+	reg |= vPB5;
+	cuda_write_reg(sc, vBufB, reg);
+}
+
+static void
+cuda_in(struct cuda_softc *sc)
+{
+	uint8_t reg;
+
+	reg = cuda_read_reg(sc, vACR);
+	reg &= ~vSR_OUT;
+	cuda_write_reg(sc, vACR, reg);
+}
+
+static void
+cuda_out(struct cuda_softc *sc)
+{
+	uint8_t reg;
+
+	reg = cuda_read_reg(sc, vACR);
+	reg |= vSR_OUT;
+	cuda_write_reg(sc, vACR, reg);
+}
+
+static void
+cuda_toggle_ack(struct cuda_softc *sc)
+{
+	uint8_t reg;
+
+	reg = cuda_read_reg(sc, vBufB);
+	reg ^= vPB4;
+	cuda_write_reg(sc, vBufB, reg);
+}
+
+static void
+cuda_ack_off(struct cuda_softc *sc)
+{
+	uint8_t reg;
+
+	reg = cuda_read_reg(sc, vBufB);
+	reg |= vPB4;
+	cuda_write_reg(sc, vBufB, reg);
+}
+
+static int
+cuda_intr_state(struct cuda_softc *sc)
+{
+	return ((cuda_read_reg(sc, vBufB) & vPB3) == 0);
+}
+
+static int
+cuda_send(void *cookie, int poll, int length, uint8_t *msg)
+{
+	struct cuda_softc *sc = cookie;
+	device_t dev = sc->sc_dev;
+	struct cuda_packet *pkt;
+
+	if (sc->sc_state == CUDA_NOTREADY)
+		return (-1);
+
+	mtx_lock(&sc->sc_mutex);
+
+	pkt = STAILQ_FIRST(&sc->sc_freeq);
+	if (pkt == NULL) {
+		mtx_unlock(&sc->sc_mutex);
+		return (-1);
+	}
+
+	pkt->len = length - 1;
+	pkt->type = msg[0];
+	memcpy(pkt->data, &msg[1], pkt->len);
+
+	STAILQ_REMOVE_HEAD(&sc->sc_freeq, pkt_q);
+	STAILQ_INSERT_TAIL(&sc->sc_outq, pkt, pkt_q);
+
+	/*
+	 * If we already are sending a packet, we should bail now that this
+	 * one has been added to the queue.
+	 */
+
+	if (sc->sc_waiting) {
+		mtx_unlock(&sc->sc_mutex);
+		return (0);
+	}
+
+	cuda_send_outbound(sc);
+	mtx_unlock(&sc->sc_mutex);
+
+	if (sc->sc_polling || poll || cold)
+		cuda_poll(dev);
+
+	return (0);
+}
+
+static void
+cuda_send_outbound(struct cuda_softc *sc)
+{
+	struct cuda_packet *pkt;
+
+	mtx_assert(&sc->sc_mutex, MA_OWNED);
+
+	pkt = STAILQ_FIRST(&sc->sc_outq);
+	if (pkt == NULL)
+		return;
+
+	sc->sc_out_length = pkt->len + 1;
+	memcpy(sc->sc_out, &pkt->type, pkt->len + 1);
+	sc->sc_sent = 0;
+
+	STAILQ_REMOVE_HEAD(&sc->sc_outq, pkt_q);
+	STAILQ_INSERT_TAIL(&sc->sc_freeq, pkt, pkt_q);
+
+	sc->sc_waiting = 1;
+
+	cuda_poll(sc->sc_dev);
+
+	DELAY(150);
+
+	if (sc->sc_state == CUDA_IDLE && !cuda_intr_state(sc)) {
+		sc->sc_state = CUDA_OUT;
+		cuda_out(sc);
+		cuda_write_reg(sc, vSR, sc->sc_out[0]);
+		cuda_ack_off(sc);
+		cuda_tip(sc);
+	}
+}
+
+static void
+cuda_send_inbound(struct cuda_softc *sc)
+{
+	device_t dev;
+	struct cuda_packet *pkt;
+
+	dev = sc->sc_dev;
+	
+	mtx_lock(&sc->sc_mutex);
+
+	while ((pkt = STAILQ_FIRST(&sc->sc_inq)) != NULL) {
+		STAILQ_REMOVE_HEAD(&sc->sc_inq, pkt_q);
+
+		mtx_unlock(&sc->sc_mutex);
+
+		/* check if we have a handler for this message */
+		switch (pkt->type) {
+		   case CUDA_ADB:
+			if (pkt->len > 2) {
+				adb_receive_raw_packet(sc->adb_bus,
+				    pkt->data[0],pkt->data[1],
+				    pkt->len - 2,&pkt->data[2]);
+			} else {
+				adb_receive_raw_packet(sc->adb_bus,
+				    pkt->data[0],pkt->data[1],0,NULL);
+			}
+			break;
+		   case CUDA_PSEUDO:
+			mtx_lock(&sc->sc_mutex);
+			switch (pkt->data[1]) {
+			case CMD_AUTOPOLL:
+				sc->sc_autopoll = 1;
+				break;
+			case CMD_READ_RTC:
+				memcpy(&sc->sc_rtc, &pkt->data[2],
+				    sizeof(sc->sc_rtc));
+				wakeup(&sc->sc_rtc);
+				break;
+			case CMD_WRITE_RTC:
+				break;
+			}
+			mtx_unlock(&sc->sc_mutex);
+			break;
+		   case CUDA_ERROR:
+			/*
+			 * CUDA will throw errors if we miss a race between
+			 * sending and receiving packets. This is already
+			 * handled when we abort packet output to handle
+			 * this packet in cuda_intr(). Thus, we ignore
+			 * these messages.
+			 */
+			break;
+		   default:
+			device_printf(dev,"unknown CUDA command %d\n",
+			    pkt->type);
+			break;
+		}
+
+		mtx_lock(&sc->sc_mutex);
+
+		STAILQ_INSERT_TAIL(&sc->sc_freeq, pkt, pkt_q);
+	}
+
+	mtx_unlock(&sc->sc_mutex);
+}
+
+static u_int
+cuda_poll(device_t dev)
+{
+	struct cuda_softc *sc = device_get_softc(dev);
+
+	if (sc->sc_state == CUDA_IDLE && !cuda_intr_state(sc) && 
+	    !sc->sc_waiting)
+		return (0);
+
+	cuda_intr(dev);
+	return (0);
+}
+
+static void
+cuda_intr(void *arg)
+{
+	device_t        dev;
+	struct cuda_softc *sc;
+
+	int i, ending, restart_send, process_inbound;
+	uint8_t reg;
+
+        dev = (device_t)arg;
+	sc = device_get_softc(dev);
+
+	mtx_lock(&sc->sc_mutex);
+
+	restart_send = 0;
+	process_inbound = 0;
+	reg = cuda_read_reg(sc, vIFR);
+	if ((reg & vSR_INT) != vSR_INT) {
+		mtx_unlock(&sc->sc_mutex);
+		return;
+	}
+
+	cuda_write_reg(sc, vIFR, 0x7f);	/* Clear interrupt */
+
+switch_start:
+	switch (sc->sc_state) {
+	case CUDA_IDLE:
+		/*
+		 * This is an unexpected packet, so grab the first (dummy)
+		 * byte, set up the proper vars, and tell the chip we are
+		 * starting to receive the packet by setting the TIP bit.
+		 */
+		sc->sc_in[1] = cuda_read_reg(sc, vSR);
+
+		if (cuda_intr_state(sc) == 0) {
+			/* must have been a fake start */
+
+			if (sc->sc_waiting) {
+				/* start over */
+				DELAY(150);
+				sc->sc_state = CUDA_OUT;
+				sc->sc_sent = 0;
+				cuda_out(sc);
+				cuda_write_reg(sc, vSR, sc->sc_out[1]);
+				cuda_ack_off(sc);
+				cuda_tip(sc);
+			}
+			break;
+		}
+
+		cuda_in(sc);
+		cuda_tip(sc);
+
+		sc->sc_received = 1;
+		sc->sc_state = CUDA_IN;
+		break;
+
+	case CUDA_IN:
+		sc->sc_in[sc->sc_received] = cuda_read_reg(sc, vSR);
+		ending = 0;
+
+		if (sc->sc_received > 255) {
+			/* bitch only once */
+			if (sc->sc_received == 256) {
+				device_printf(dev,"input overflow\n");
+				ending = 1;
+			}
+		} else
+			sc->sc_received++;
+
+		/* intr off means this is the last byte (end of frame) */
+		if (cuda_intr_state(sc) == 0) {
+			ending = 1;
+		} else {
+			cuda_toggle_ack(sc);			
+		}
+		
+		if (ending == 1) {	/* end of message? */
+			struct cuda_packet *pkt;
+
+			/* reset vars and signal the end of this frame */
+			cuda_idle(sc);
+
+			/* Queue up the packet */
+			pkt = STAILQ_FIRST(&sc->sc_freeq);
+			if (pkt != NULL) {
+				/* If we have a free packet, process it */
+
+				pkt->len = sc->sc_received - 2;
+				pkt->type = sc->sc_in[1];
+				memcpy(pkt->data, &sc->sc_in[2], pkt->len);
+
+				STAILQ_REMOVE_HEAD(&sc->sc_freeq, pkt_q);
+				STAILQ_INSERT_TAIL(&sc->sc_inq, pkt, pkt_q);
+
+				process_inbound = 1;
+			}
+
+			sc->sc_state = CUDA_IDLE;
+			sc->sc_received = 0;
+
+			/*
+			 * If there is something waiting to be sent out,
+			 * set everything up and send the first byte.
+			 */
+			if (sc->sc_waiting == 1) {
+				DELAY(1500);	/* required */
+				sc->sc_sent = 0;
+				sc->sc_state = CUDA_OUT;
+
+				/*
+				 * If the interrupt is on, we were too slow
+				 * and the chip has already started to send
+				 * something to us, so back out of the write
+				 * and start a read cycle.
+				 */
+				if (cuda_intr_state(sc)) {
+					cuda_in(sc);
+					cuda_idle(sc);
+					sc->sc_sent = 0;
+					sc->sc_state = CUDA_IDLE;
+					sc->sc_received = 0;
+					DELAY(150);
+					goto switch_start;
+				}
+
+				/*
+				 * If we got here, it's ok to start sending
+				 * so load the first byte and tell the chip
+				 * we want to send.
+				 */
+				cuda_out(sc);
+				cuda_write_reg(sc, vSR,
+				    sc->sc_out[sc->sc_sent]);
+				cuda_ack_off(sc);
+				cuda_tip(sc);
+			}
+		}
+		break;
+
+	case CUDA_OUT:
+		i = cuda_read_reg(sc, vSR);	/* reset SR-intr in IFR */
+
+		sc->sc_sent++;
+		if (cuda_intr_state(sc)) {	/* ADB intr low during write */
+			cuda_in(sc);	/* make sure SR is set to IN */
+			cuda_idle(sc);
+			sc->sc_sent = 0;	/* must start all over */
+			sc->sc_state = CUDA_IDLE;	/* new state */
+			sc->sc_received = 0;
+			sc->sc_waiting = 1;	/* must retry when done with
+						 * read */
+			DELAY(150);
+			goto switch_start;	/* process next state right
+						 * now */
+			break;
+		}
+		if (sc->sc_out_length == sc->sc_sent) {	/* check for done */
+			sc->sc_waiting = 0;	/* done writing */
+			sc->sc_state = CUDA_IDLE;	/* signal bus is idle */
+			cuda_in(sc);
+			cuda_idle(sc);
+		} else {
+			/* send next byte */
+			cuda_write_reg(sc, vSR, sc->sc_out[sc->sc_sent]);
+			cuda_toggle_ack(sc);	/* signal byte ready to
+							 * shift */
+		}
+		break;
+
+	case CUDA_NOTREADY:
+		break;
+
+	default:
+		break;
+	}
+
+	mtx_unlock(&sc->sc_mutex);
+
+	if (process_inbound)
+		cuda_send_inbound(sc);
+
+	mtx_lock(&sc->sc_mutex);
+	/* If we have another packet waiting, set it up */
+	if (!sc->sc_waiting && sc->sc_state == CUDA_IDLE)
+		cuda_send_outbound(sc);
+
+	mtx_unlock(&sc->sc_mutex);
+
+}
+
+static u_int
+cuda_adb_send(device_t dev, u_char command_byte, int len, u_char *data, 
+    u_char poll)
+{
+	struct cuda_softc *sc = device_get_softc(dev);
+	uint8_t packet[16];
+	int i;
+
+	/* construct an ADB command packet and send it */
+	packet[0] = CUDA_ADB;
+	packet[1] = command_byte;
+	for (i = 0; i < len; i++)
+		packet[i + 2] = data[i];
+
+	cuda_send(sc, poll, len + 2, packet);
+
+	return (0);
+}
+
+static u_int 
+cuda_adb_autopoll(device_t dev, uint16_t mask) {
+	struct cuda_softc *sc = device_get_softc(dev);
+
+	uint8_t cmd[] = {CUDA_PSEUDO, CMD_AUTOPOLL, mask != 0};
+
+	mtx_lock(&sc->sc_mutex);
+
+	if (cmd[2] == sc->sc_autopoll) {
+		mtx_unlock(&sc->sc_mutex);
+		return (0);
+	}
+
+	sc->sc_autopoll = -1;
+	cuda_send(sc, 1, 3, cmd);
+
+	mtx_unlock(&sc->sc_mutex);
+
+	return (0);
+}
+
+static void
+cuda_shutdown(void *xsc, int howto)
+{
+	struct cuda_softc *sc = xsc;
+	uint8_t cmd[] = {CUDA_PSEUDO, 0};
+
+	cmd[1] = (howto & RB_HALT) ? CMD_POWEROFF : CMD_RESET;
+	cuda_poll(sc->sc_dev);
+	cuda_send(sc, 1, 2, cmd);
+
+	while (1)
+		cuda_poll(sc->sc_dev);
+}
+
+#define DIFF19041970	2082844800
+
+static int
+cuda_gettime(device_t dev, struct timespec *ts)
+{
+	struct cuda_softc *sc = device_get_softc(dev);
+	uint8_t cmd[] = {CUDA_PSEUDO, CMD_READ_RTC};
+
+	mtx_lock(&sc->sc_mutex);
+	sc->sc_rtc = -1;
+	cuda_send(sc, 1, 2, cmd);
+	if (sc->sc_rtc == -1)
+		mtx_sleep(&sc->sc_rtc, &sc->sc_mutex, 0, "rtc", 100);
+
+	ts->tv_sec = sc->sc_rtc - DIFF19041970;
+	ts->tv_nsec = 0;
+	mtx_unlock(&sc->sc_mutex);
+
+	return (0);
+}
+
+static int
+cuda_settime(device_t dev, struct timespec *ts)
+{
+	struct cuda_softc *sc = device_get_softc(dev);
+	uint8_t cmd[] = {CUDA_PSEUDO, CMD_WRITE_RTC, 0, 0, 0, 0};
+	uint32_t sec;
+
+	sec = ts->tv_sec + DIFF19041970;
+	memcpy(&cmd[2], &sec, sizeof(sec));
+
+	mtx_lock(&sc->sc_mutex);
+	cuda_send(sc, 0, 6, cmd);
+	mtx_unlock(&sc->sc_mutex);
+
+	return (0);
+}
+


Property changes on: trunk/sys/powerpc/powermac/cuda.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/cudavar.h
===================================================================
--- trunk/sys/powerpc/powermac/cudavar.h	                        (rev 0)
+++ trunk/sys/powerpc/powermac/cudavar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,111 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Michael Lorenz
+ * Copyright (c) 2008 Nathan Whitehorn
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/cudavar.h 205506 2010-03-23 03:14:44Z nwhitehorn $
+ *
+ */
+
+#ifndef	_POWERPC_CUDAVAR_H_
+#define	_POWERPC_CUDAVAR_H_
+
+#define CUDA_DEVSTR	"Apple CUDA I/O Controller"
+#define	CUDA_MAXPACKETS	10
+
+/* Cuda addresses */
+#define CUDA_ADB	0
+#define CUDA_PSEUDO	1
+#define CUDA_ERROR	2	/* error codes? */
+#define CUDA_TIMER	3
+#define CUDA_POWER	4
+#define CUDA_IIC	5	/* XXX ??? */
+#define CUDA_PMU	6
+#define CUDA_ADB_QUERY	7
+
+/* Cuda commands */
+#define CMD_AUTOPOLL	1
+#define CMD_READ_RTC	3
+#define CMD_WRITE_RTC	9
+#define CMD_POWEROFF	10
+#define CMD_RESET	17
+#define CMD_IIC		34
+
+/* Cuda state codes */
+#define CUDA_NOTREADY	0x1	/* has not been initialized yet */
+#define CUDA_IDLE	0x2	/* the bus is currently idle */
+#define CUDA_OUT	0x3	/* sending out a command */
+#define CUDA_IN		0x4	/* receiving data */
+#define CUDA_POLLING	0x5	/* polling - II only */
+
+struct cuda_packet {
+	uint8_t len;
+	uint8_t type;
+
+	uint8_t data[253];
+	STAILQ_ENTRY(cuda_packet) pkt_q;
+};
+
+STAILQ_HEAD(cuda_pktq, cuda_packet);
+
+struct cuda_softc {
+	device_t	sc_dev;
+	int		sc_memrid;
+	struct resource	*sc_memr;
+	int     	sc_irqrid;
+        struct resource *sc_irq;
+        void    	*sc_ih;
+
+	struct mtx	sc_mutex;
+
+	device_t	adb_bus;
+
+	int		sc_node;
+	volatile int	sc_state;
+	int		sc_waiting;
+	int		sc_polling;
+	int		sc_iic_done;
+	volatile int	sc_autopoll;
+	uint32_t	sc_rtc;
+
+	int sc_i2c_read_len;
+
+	/* internal buffers */
+	uint8_t		sc_in[256];
+	uint8_t		sc_out[256];
+	int		sc_sent;
+	int		sc_out_length;
+	int		sc_received;
+
+	struct cuda_packet sc_pkts[CUDA_MAXPACKETS];
+	struct cuda_pktq sc_inq;
+	struct cuda_pktq sc_outq;
+	struct cuda_pktq sc_freeq;
+};
+
+#endif /* _POWERPC_CUDAVAR_H_ */


Property changes on: trunk/sys/powerpc/powermac/cudavar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/dbdma.c
===================================================================
--- trunk/sys/powerpc/powermac/dbdma.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/dbdma.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,359 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/dbdma.c 227293 2011-11-07 06:44:47Z ed $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/endian.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <machine/dbdma.h>
+#include <sys/rman.h>
+
+#include "dbdmavar.h"
+
+static MALLOC_DEFINE(M_DBDMA, "dbdma", "DBDMA Command List");
+
+static uint32_t dbdma_read_reg(dbdma_channel_t *, u_int);
+static void dbdma_write_reg(dbdma_channel_t *, u_int, uint32_t);
+static void dbdma_phys_callback(void *, bus_dma_segment_t *, int, int);
+
+static void
+dbdma_phys_callback(void *chan, bus_dma_segment_t *segs, int nsegs, int error)
+{
+	dbdma_channel_t *channel = (dbdma_channel_t *)(chan);
+
+	channel->sc_slots_pa = segs[0].ds_addr;
+	dbdma_write_reg(channel, CHAN_CMDPTR, channel->sc_slots_pa);
+}
+
+int
+dbdma_allocate_channel(struct resource *dbdma_regs, u_int offset,
+    bus_dma_tag_t parent_dma, int slots, dbdma_channel_t **chan)
+{
+	int error = 0;
+	dbdma_channel_t *channel;
+
+	channel = *chan = malloc(sizeof(struct dbdma_channel), M_DBDMA, 
+	    M_WAITOK | M_ZERO);
+
+	channel->sc_regs = dbdma_regs;
+	channel->sc_off = offset;
+	dbdma_stop(channel);
+
+	channel->sc_slots_pa = 0;
+
+	error = bus_dma_tag_create(parent_dma, 16, 0, BUS_SPACE_MAXADDR_32BIT,
+	    BUS_SPACE_MAXADDR, NULL, NULL, PAGE_SIZE, 1, PAGE_SIZE, 0, NULL,
+	    NULL, &(channel->sc_dmatag));
+
+	error = bus_dmamem_alloc(channel->sc_dmatag,
+	    (void **)&channel->sc_slots, BUS_DMA_WAITOK | BUS_DMA_ZERO,
+	    &channel->sc_dmamap);
+
+	error = bus_dmamap_load(channel->sc_dmatag, channel->sc_dmamap,
+	    channel->sc_slots, PAGE_SIZE, dbdma_phys_callback, channel, 0);
+
+	dbdma_write_reg(channel, CHAN_CMDPTR_HI, 0);
+
+	channel->sc_nslots = slots;
+
+	return (error);
+}
+
+int
+dbdma_resize_channel(dbdma_channel_t *chan, int newslots)
+{
+
+	if (newslots > (PAGE_SIZE / sizeof(struct dbdma_command)))
+		return (-1);
+	
+	chan->sc_nslots = newslots;
+	return (0);
+}
+
+int
+dbdma_free_channel(dbdma_channel_t *chan)
+{
+
+	dbdma_stop(chan);
+
+	bus_dmamem_free(chan->sc_dmatag, chan->sc_slots, chan->sc_dmamap);
+	bus_dma_tag_destroy(chan->sc_dmatag);
+
+	free(chan, M_DBDMA);
+
+	return (0);
+}
+
+uint16_t
+dbdma_get_cmd_status(dbdma_channel_t *chan, int slot)
+{
+
+	bus_dmamap_sync(chan->sc_dmatag, chan->sc_dmamap, BUS_DMASYNC_POSTREAD);
+
+	/*
+	 * I really did mean to swap resCount and xferStatus here, to
+	 * account for the quad-word little endian fields.
+	 */
+	return (le16toh(chan->sc_slots[slot].resCount));
+}
+
+void
+dbdma_clear_cmd_status(dbdma_channel_t *chan, int slot)
+{
+	/* See endian note above */
+	chan->sc_slots[slot].resCount = 0;
+}
+
+uint16_t
+dbdma_get_residuals(dbdma_channel_t *chan, int slot)
+{
+
+	bus_dmamap_sync(chan->sc_dmatag, chan->sc_dmamap, BUS_DMASYNC_POSTREAD);
+
+	return (le16toh(chan->sc_slots[slot].xferStatus));
+}
+
+void
+dbdma_reset(dbdma_channel_t *chan)
+{
+
+	dbdma_stop(chan);
+	dbdma_set_current_cmd(chan, 0);
+	dbdma_run(chan);
+}
+
+void
+dbdma_run(dbdma_channel_t *chan)
+{
+	uint32_t control_reg;
+
+	control_reg = DBDMA_STATUS_RUN | DBDMA_STATUS_PAUSE |
+	    DBDMA_STATUS_WAKE | DBDMA_STATUS_DEAD;
+	control_reg <<= DBDMA_REG_MASK_SHIFT;
+
+	control_reg |= DBDMA_STATUS_RUN;
+	dbdma_write_reg(chan, CHAN_CONTROL_REG, control_reg);
+}
+
+void
+dbdma_pause(dbdma_channel_t *chan)
+{
+	uint32_t control_reg;
+
+	control_reg = DBDMA_STATUS_PAUSE;
+	control_reg <<= DBDMA_REG_MASK_SHIFT;
+
+	control_reg |= DBDMA_STATUS_PAUSE;
+	dbdma_write_reg(chan, CHAN_CONTROL_REG, control_reg);
+}
+
+void
+dbdma_wake(dbdma_channel_t *chan)
+{
+	uint32_t control_reg;
+
+	control_reg = DBDMA_STATUS_WAKE | DBDMA_STATUS_PAUSE |
+	    DBDMA_STATUS_RUN | DBDMA_STATUS_DEAD;
+	control_reg <<= DBDMA_REG_MASK_SHIFT;
+
+	control_reg |= DBDMA_STATUS_WAKE | DBDMA_STATUS_RUN;
+	dbdma_write_reg(chan, CHAN_CONTROL_REG, control_reg);
+}
+
+void
+dbdma_stop(dbdma_channel_t *chan)
+{
+	uint32_t control_reg;
+
+	control_reg = DBDMA_STATUS_RUN;
+	control_reg <<= DBDMA_REG_MASK_SHIFT;
+
+	dbdma_write_reg(chan, CHAN_CONTROL_REG, control_reg);
+
+	while (dbdma_read_reg(chan, CHAN_STATUS_REG) & DBDMA_STATUS_ACTIVE)
+		DELAY(5);
+}
+
+void
+dbdma_set_current_cmd(dbdma_channel_t *chan, int slot)
+{
+	uint32_t cmd;
+
+	cmd = chan->sc_slots_pa + slot * sizeof(struct dbdma_command);
+	dbdma_write_reg(chan, CHAN_CMDPTR, cmd);
+}
+
+uint16_t
+dbdma_get_chan_status(dbdma_channel_t *chan)
+{
+	uint32_t status_reg;
+
+	status_reg = dbdma_read_reg(chan, CHAN_STATUS_REG);
+	return (status_reg & 0x0000ffff);
+}
+
+uint8_t
+dbdma_get_device_status(dbdma_channel_t *chan)
+{
+	return (dbdma_get_chan_status(chan) & 0x00ff);
+}
+
+void
+dbdma_set_device_status(dbdma_channel_t *chan, uint8_t mask, uint8_t value)
+{
+	uint32_t control_reg;
+	
+	control_reg = mask;
+	control_reg <<= DBDMA_REG_MASK_SHIFT;
+	control_reg |= value;
+
+	dbdma_write_reg(chan, CHAN_CONTROL_REG, control_reg);
+}
+
+void
+dbdma_set_interrupt_selector(dbdma_channel_t *chan, uint8_t mask, uint8_t val)
+{
+	uint32_t intr_select;
+
+	intr_select = mask;
+	intr_select <<= DBDMA_REG_MASK_SHIFT;
+
+	intr_select |= val;
+	dbdma_write_reg(chan, CHAN_INTR_SELECT, intr_select);
+}
+
+void
+dbdma_set_branch_selector(dbdma_channel_t *chan, uint8_t mask, uint8_t val)
+{
+	uint32_t br_select;
+
+	br_select = mask;
+	br_select <<= DBDMA_REG_MASK_SHIFT;
+
+	br_select |= val;
+	dbdma_write_reg(chan, CHAN_BRANCH_SELECT, br_select);
+}
+
+void
+dbdma_set_wait_selector(dbdma_channel_t *chan, uint8_t mask, uint8_t val)
+{
+	uint32_t wait_select;
+
+	wait_select = mask;
+	wait_select <<= DBDMA_REG_MASK_SHIFT;
+	wait_select |= val;
+	dbdma_write_reg(chan, CHAN_WAIT_SELECT, wait_select);
+}
+
+void
+dbdma_insert_command(dbdma_channel_t *chan, int slot, int command, int stream,
+    bus_addr_t data, size_t count, uint8_t interrupt, uint8_t branch,
+    uint8_t wait, uint32_t branch_slot)
+{
+	struct dbdma_command cmd;
+	uint32_t *flip;
+
+	cmd.cmd = command;
+	cmd.key = stream;
+	cmd.intr = interrupt;
+	cmd.branch = branch;
+	cmd.wait = wait;
+
+	cmd.reqCount = count;
+	cmd.address = (uint32_t)(data);
+	if (command != DBDMA_STORE_QUAD && command != DBDMA_LOAD_QUAD)
+		cmd.cmdDep = chan->sc_slots_pa + 
+		    branch_slot * sizeof(struct dbdma_command);
+	else
+		cmd.cmdDep = branch_slot;
+
+	cmd.resCount = 0;
+	cmd.xferStatus = 0;
+
+	/*
+	 * Move quadwords to little-endian. God only knows why
+	 * Apple thought this was a good idea.
+	 */
+	flip = (uint32_t *)(&cmd);
+	flip[0] = htole32(flip[0]);
+	flip[1] = htole32(flip[1]);
+	flip[2] = htole32(flip[2]);
+
+	chan->sc_slots[slot] = cmd;
+}
+
+void
+dbdma_insert_stop(dbdma_channel_t *chan, int slot)
+{
+
+	dbdma_insert_command(chan, slot, DBDMA_STOP, 0, 0, 0, DBDMA_NEVER,
+	    DBDMA_NEVER, DBDMA_NEVER, 0);
+}
+
+void
+dbdma_insert_nop(dbdma_channel_t *chan, int slot)
+{
+
+	dbdma_insert_command(chan, slot, DBDMA_NOP, 0, 0, 0, DBDMA_NEVER,
+	    DBDMA_NEVER, DBDMA_NEVER, 0);
+}
+
+void
+dbdma_insert_branch(dbdma_channel_t *chan, int slot, int to_slot)
+{
+
+	dbdma_insert_command(chan, slot, DBDMA_NOP, 0, 0, 0, DBDMA_NEVER,
+	    DBDMA_ALWAYS, DBDMA_NEVER, to_slot);
+}
+
+void
+dbdma_sync_commands(dbdma_channel_t *chan, bus_dmasync_op_t op)
+{
+
+	bus_dmamap_sync(chan->sc_dmatag, chan->sc_dmamap, op);
+}
+
+static uint32_t
+dbdma_read_reg(dbdma_channel_t *chan, u_int offset)
+{
+
+	return (bus_read_4(chan->sc_regs, chan->sc_off + offset));
+}
+
+static void
+dbdma_write_reg(dbdma_channel_t *chan, u_int offset, uint32_t val)
+{
+
+	bus_write_4(chan->sc_regs, chan->sc_off + offset, val);
+}


Property changes on: trunk/sys/powerpc/powermac/dbdma.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/dbdmavar.h
===================================================================
--- trunk/sys/powerpc/powermac/dbdmavar.h	                        (rev 0)
+++ trunk/sys/powerpc/powermac/dbdmavar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,106 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/dbdmavar.h 184382 2008-10-27 23:11:14Z nwhitehorn $
+ */
+
+#ifndef _POWERPC_POWERMAC_DBDMAVAR_H_
+#define _POWERPC_POWERMAC_DBDMAVAR_H_
+
+struct dbdma_command {
+	uint8_t cmd:4; /* DBDMA command */
+
+	uint8_t _resd1:1;
+	uint8_t key:3; /* Stream number, or 6 for KEY_SYSTEM */
+	uint8_t _resd2:2;
+
+	/* Interrupt, branch, and wait flags */
+	uint8_t intr:2;
+	uint8_t branch:2;
+	uint8_t wait:2;
+
+	uint16_t reqCount; /* Bytes to transfer */
+
+	uint32_t address; /* 32-bit system physical address */
+	uint32_t cmdDep; /* Branch address or quad word to load/store */
+
+	uint16_t xferStatus; /* Contents of channel status after completion */
+	uint16_t resCount; /* Number of residual bytes outstanding */
+};
+
+struct dbdma_channel {
+	struct resource 	*sc_regs;
+	u_int			sc_off;
+
+	struct dbdma_command	*sc_slots;
+	int			sc_nslots;
+	bus_addr_t		sc_slots_pa;
+
+	bus_dma_tag_t		sc_dmatag;
+	bus_dmamap_t		sc_dmamap;
+};
+	
+
+/*
+   DBDMA registers are found at 0x8000 + n*0x100 in the macio register space,
+   and are laid out as follows within each block: 
+	
+   Address:			Description:		Length (bytes):
+   0x000 			Channel Control 	4
+   0x004 			Channel Status		4
+   0x00C			Command Phys Addr	4
+   0x010			Interrupt Select	4
+   0x014			Branch Select		4
+   0x018			Wait Select		4
+*/
+
+#define CHAN_CONTROL_REG	0x00
+#define	CHAN_STATUS_REG		0x04
+#define CHAN_CMDPTR_HI		0x08
+#define CHAN_CMDPTR		0x0C
+#define	CHAN_INTR_SELECT	0x10
+#define CHAN_BRANCH_SELECT	0x14
+#define CHAN_WAIT_SELECT	0x18
+
+/* Channel control is the write channel to channel status, the upper 16 bits
+   are a mask of which bytes to change */
+
+#define	DBDMA_REG_MASK_SHIFT	16
+
+/* Status bits 0-7 are device dependent status bits */
+
+/*
+   The Interrupt/Branch/Wait Select triggers the corresponding condition bits
+   in the event that (select.mask & device dependent status) == select.value
+
+   They are defined a follows:
+	Byte 1: Reserved
+	Byte 2: Mask
+	Byte 3: Reserved
+	Byte 4: Value
+*/
+
+#endif /* _POWERPC_POWERMAC_DBDMAVAR_H_ */


Property changes on: trunk/sys/powerpc/powermac/dbdmavar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/fcu.c
===================================================================
--- trunk/sys/powerpc/powermac/fcu.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/fcu.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,678 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 Andreas Tobler
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/fcu.c 273736 2014-10-27 14:38:00Z hselasky $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/callout.h>
+#include <sys/conf.h>
+#include <sys/cpu.h>
+#include <sys/ctype.h>
+#include <sys/kernel.h>
+#include <sys/reboot.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/limits.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <powerpc/powermac/powermac_thermal.h>
+
+/* FCU registers
+ * /u3 at 0,f8000000/i2c at f8001000/fan at 15e
+ */
+#define FCU_RPM_FAIL      0x0b      /* fans states in bits 0<1-6>7 */
+#define FCU_RPM_AVAILABLE 0x0c
+#define FCU_RPM_ACTIVE    0x0d
+#define FCU_RPM_READ(x)   0x11 + (x) * 2
+#define FCU_RPM_SET(x)    0x10 + (x) * 2
+
+#define FCU_PWM_FAIL      0x2b
+#define FCU_PWM_AVAILABLE 0x2c
+#define FCU_PWM_ACTIVE    0x2d
+#define FCU_PWM_RPM(x)    0x31 + (x) * 2 /* Get RPM. */
+#define FCU_PWM_SGET(x)   0x30 + (x) * 2 /* Set or get PWM. */
+
+struct fcu_fan {
+	struct	pmac_fan fan;
+	device_t dev;
+
+	int     id;
+	enum {
+		FCU_FAN_RPM,
+		FCU_FAN_PWM
+	} type;
+	int     setpoint;
+	int     rpm;
+};
+
+struct fcu_softc {
+	device_t		sc_dev;
+	struct intr_config_hook enum_hook;
+	uint32_t                sc_addr;
+	struct fcu_fan		*sc_fans;
+	int			sc_nfans;
+};
+
+/* We can read the PWM and the RPM from a PWM controlled fan.
+ * Offer both values via sysctl.
+ */
+enum {
+	FCU_PWM_SYSCTL_PWM   = 1 << 8,
+	FCU_PWM_SYSCTL_RPM   = 2 << 8
+};
+
+static int fcu_rpm_shift;
+
+/* Regular bus attachment functions */
+static int  fcu_probe(device_t);
+static int  fcu_attach(device_t);
+
+/* Utility functions */
+static void fcu_attach_fans(device_t dev);
+static int  fcu_fill_fan_prop(device_t dev);
+static int  fcu_fan_set_rpm(struct fcu_fan *fan, int rpm);
+static int  fcu_fan_get_rpm(struct fcu_fan *fan);
+static int  fcu_fan_set_pwm(struct fcu_fan *fan, int pwm);
+static int  fcu_fan_get_pwm(device_t dev, struct fcu_fan *fan, int *pwm,
+			    int *rpm);
+static int  fcu_fanrpm_sysctl(SYSCTL_HANDLER_ARGS);
+static void fcu_start(void *xdev);
+static int  fcu_write(device_t dev, uint32_t addr, uint8_t reg, uint8_t *buf,
+		      int len);
+static int  fcu_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data);
+
+static device_method_t  fcu_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		fcu_probe),
+	DEVMETHOD(device_attach,	fcu_attach),
+	{ 0, 0 },
+};
+
+static driver_t fcu_driver = {
+	"fcu",
+	fcu_methods,
+	sizeof(struct fcu_softc)
+};
+
+static devclass_t fcu_devclass;
+
+DRIVER_MODULE(fcu, iicbus, fcu_driver, fcu_devclass, 0, 0);
+static MALLOC_DEFINE(M_FCU, "fcu", "FCU Sensor Information");
+
+static int
+fcu_write(device_t dev, uint32_t addr, uint8_t reg, uint8_t *buff,
+	  int len)
+{
+	unsigned char buf[4];
+	int try = 0;
+
+	struct iic_msg msg[] = {
+		{ addr, IIC_M_WR, 0, buf }
+	};
+
+	msg[0].len = len + 1;
+	buf[0] = reg;
+	memcpy(buf + 1, buff, len);
+
+	for (;;)
+	{
+		if (iicbus_transfer(dev, msg, 1) == 0)
+			return (0);
+
+		if (++try > 5) {
+			device_printf(dev, "iicbus write failed\n");
+			return (-1);
+		}
+		pause("fcu_write", hz);
+	}
+}
+
+static int
+fcu_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data)
+{
+	uint8_t buf[4];
+	int err, try = 0;
+
+	struct iic_msg msg[2] = {
+	    { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
+	    { addr, IIC_M_RD, 1, buf },
+	};
+
+	for (;;)
+	{
+		  err = iicbus_transfer(dev, msg, 2);
+		  if (err != 0)
+			  goto retry;
+
+		  *data = *((uint8_t*)buf);
+		  return (0);
+	retry:
+		  if (++try > 5) {
+			  device_printf(dev, "iicbus read failed\n");
+			  return (-1);
+		  }
+		  pause("fcu_read_1", hz);
+	}
+}
+
+static int
+fcu_probe(device_t dev)
+{
+	const char  *name, *compatible;
+	struct fcu_softc *sc;
+
+	name = ofw_bus_get_name(dev);
+	compatible = ofw_bus_get_compat(dev);
+
+	if (!name)
+		return (ENXIO);
+
+	if (strcmp(name, "fan") != 0 || strcmp(compatible, "fcu") != 0)
+		return (ENXIO);
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+	sc->sc_addr = iicbus_get_addr(dev);
+
+	device_set_desc(dev, "Apple Fan Control Unit");
+
+	return (0);
+}
+
+static int
+fcu_attach(device_t dev)
+{
+	struct fcu_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	sc->enum_hook.ich_func = fcu_start;
+	sc->enum_hook.ich_arg = dev;
+
+	/* We have to wait until interrupts are enabled. I2C read and write
+	 * only works if the interrupts are available.
+	 * The unin/i2c is controlled by the htpic on unin. But this is not
+	 * the master. The openpic on mac-io is controlling the htpic.
+	 * This one gets attached after the mac-io probing and then the
+	 * interrupts will be available.
+	 */
+
+	if (config_intrhook_establish(&sc->enum_hook) != 0)
+		return (ENOMEM);
+
+	return (0);
+}
+
+static void
+fcu_start(void *xdev)
+{
+	unsigned char buf[1] = { 0xff };
+	struct fcu_softc *sc;
+
+	device_t dev = (device_t)xdev;
+
+	sc = device_get_softc(dev);
+
+	/* Start the fcu device. */
+	fcu_write(sc->sc_dev, sc->sc_addr, 0xe, buf, 1);
+	fcu_write(sc->sc_dev, sc->sc_addr, 0x2e, buf, 1);
+	fcu_read_1(sc->sc_dev, sc->sc_addr, 0, buf);
+	fcu_rpm_shift = (buf[0] == 1) ? 2 : 3;
+
+	device_printf(dev, "FCU initialized, RPM shift: %d\n",
+		      fcu_rpm_shift);
+
+	/* Detect and attach child devices. */
+
+	fcu_attach_fans(dev);
+
+	config_intrhook_disestablish(&sc->enum_hook);
+
+}
+
+static int
+fcu_fan_set_rpm(struct fcu_fan *fan, int rpm)
+{
+	uint8_t reg;
+	struct fcu_softc *sc;
+	unsigned char buf[2];
+
+	sc = device_get_softc(fan->dev);
+
+	/* Clamp to allowed range */
+	rpm = max(fan->fan.min_rpm, rpm);
+	rpm = min(fan->fan.max_rpm, rpm);
+
+	if (fan->type == FCU_FAN_RPM) {
+		reg = FCU_RPM_SET(fan->id);
+		fan->setpoint = rpm;
+	} else {
+		device_printf(fan->dev, "Unknown fan type: %d\n", fan->type);
+		return (ENXIO);
+	}
+
+	buf[0] = rpm >> (8 - fcu_rpm_shift);
+	buf[1] = rpm << fcu_rpm_shift;
+
+	if (fcu_write(sc->sc_dev, sc->sc_addr, reg, buf, 2) < 0)
+		return (EIO);
+
+	return (0);
+}
+
+static int
+fcu_fan_get_rpm(struct fcu_fan *fan)
+{
+	uint8_t reg;
+	struct fcu_softc *sc;
+	uint8_t buff[2] = { 0, 0 };
+	uint8_t active = 0, avail = 0, fail = 0;
+	int rpm;
+
+	sc = device_get_softc(fan->dev);
+
+	if (fan->type == FCU_FAN_RPM) {
+		/* Check if the fan is available. */
+		reg = FCU_RPM_AVAILABLE;
+		if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &avail) < 0)
+			return (-1);
+		if ((avail & (1 << fan->id)) == 0) {
+			device_printf(fan->dev,
+			    "RPM Fan not available ID: %d\n", fan->id);
+			return (-1);
+		}
+		/* Check if we have a failed fan. */
+		reg = FCU_RPM_FAIL;
+		if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &fail) < 0)
+			return (-1);
+		if ((fail & (1 << fan->id)) != 0) {
+			device_printf(fan->dev,
+			    "RPM Fan failed ID: %d\n", fan->id);
+			return (-1);
+		}
+		/* Check if fan is active. */
+		reg = FCU_RPM_ACTIVE;
+		if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &active) < 0)
+			return (-1);
+		if ((active & (1 << fan->id)) == 0) {
+			device_printf(fan->dev, "RPM Fan not active ID: %d\n",
+				      fan->id);
+			return (-1);
+		}
+		reg = FCU_RPM_READ(fan->id);
+
+	} else {
+		device_printf(fan->dev, "Unknown fan type: %d\n", fan->type);
+		return (-1);
+	}
+
+	/* It seems that we can read the fans rpm. */
+	if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buff) < 0)
+		return (-1);
+
+	rpm = (buff[0] << (8 - fcu_rpm_shift)) | buff[1] >> fcu_rpm_shift;
+
+	return (rpm);
+}
+
+static int
+fcu_fan_set_pwm(struct fcu_fan *fan, int pwm)
+{
+	uint8_t reg;
+	struct fcu_softc *sc;
+	uint8_t buf[2];
+
+	sc = device_get_softc(fan->dev);
+
+	/* Clamp to allowed range */
+	pwm = max(fan->fan.min_rpm, pwm);
+	pwm = min(fan->fan.max_rpm, pwm);
+
+	if (fan->type == FCU_FAN_PWM) {
+		reg = FCU_PWM_SGET(fan->id);
+		if (pwm > 100)
+			pwm = 100;
+		if (pwm < 30)
+			pwm = 30;
+		fan->setpoint = pwm;
+	} else {
+		device_printf(fan->dev, "Unknown fan type: %d\n", fan->type);
+		return (EIO);
+	}
+
+	buf[0] = (pwm * 2550) / 1000;
+
+	if (fcu_write(sc->sc_dev, sc->sc_addr, reg, buf, 1) < 0)
+		return (EIO);
+	return (0);
+}
+
+static int
+fcu_fan_get_pwm(device_t dev, struct fcu_fan *fan, int *pwm, int *rpm)
+{
+	uint8_t reg;
+	struct fcu_softc *sc;
+	uint8_t buf[2];
+	uint8_t active = 0, avail = 0, fail = 0;
+
+	sc = device_get_softc(dev);
+
+	if (fan->type == FCU_FAN_PWM) {
+		/* Check if the fan is available. */
+		reg = FCU_PWM_AVAILABLE;
+		if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &avail) < 0)
+			return (-1);
+		if ((avail & (1 << fan->id)) == 0) {
+			device_printf(dev, "PWM Fan not available ID: %d\n",
+				      fan->id);
+			return (-1);
+		}
+		/* Check if we have a failed fan. */
+		reg = FCU_PWM_FAIL;
+		if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &fail) < 0)
+			return (-1);
+		if ((fail & (1 << fan->id)) != 0) {
+			device_printf(dev, "PWM Fan failed ID: %d\n", fan->id);
+			return (-1);
+		}
+		/* Check if fan is active. */
+		reg = FCU_PWM_ACTIVE;
+		if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &active) < 0)
+			return (-1);
+		if ((active & (1 << fan->id)) == 0) {
+			device_printf(dev, "PWM Fan not active ID: %d\n",
+				      fan->id);
+			return (-1);
+		}
+		reg = FCU_PWM_SGET(fan->id);
+	} else {
+		device_printf(dev, "Unknown fan type: %d\n", fan->type);
+		return (EIO);
+	}
+
+	/* It seems that we can read the fans pwm. */
+	if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buf) < 0)
+		return (-1);
+
+	*pwm = (buf[0] * 1000) / 2550;
+
+	/* Now read the rpm. */
+	reg = FCU_PWM_RPM(fan->id);
+	if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buf) < 0)
+		return (-1);
+
+	*rpm = (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift;
+
+	return (0);
+}
+
+/*
+ * This function returns the number of fans. If we call it the second time
+ * and we have allocated memory for sc->sc_fans, we fill in the properties.
+ */
+static int
+fcu_fill_fan_prop(device_t dev)
+{
+	phandle_t child;
+	struct fcu_softc *sc;
+	u_int id[8];
+	char location[96];
+	char type[64];
+	int i = 0, j, len = 0, prop_len, prev_len = 0;
+
+	sc = device_get_softc(dev);
+
+	child = ofw_bus_get_node(dev);
+
+	/* Fill the fan location property. */
+	prop_len = OF_getprop(child, "hwctrl-location", location,
+			      sizeof(location));
+	while (len < prop_len) {
+		if (sc->sc_fans != NULL) {
+			strcpy(sc->sc_fans[i].fan.name, location + len);
+		}
+		prev_len = strlen(location + len) + 1;
+		len += prev_len;
+		i++;
+	}
+	if (sc->sc_fans == NULL)
+		return (i);
+
+	/* Fill the fan type property. */
+	len = 0;
+	i = 0;
+	prev_len = 0;
+	prop_len = OF_getprop(child, "hwctrl-type", type, sizeof(type));
+	while (len < prop_len) {
+		if (strcmp(type + len, "fan-rpm") == 0)
+			sc->sc_fans[i].type = FCU_FAN_RPM;
+		else
+			sc->sc_fans[i].type = FCU_FAN_PWM;
+		prev_len = strlen(type + len) + 1;
+		len += prev_len;
+		i++;
+	}
+
+	/* Fill the fan ID property. */
+	prop_len = OF_getprop(child, "hwctrl-id", id, sizeof(id));
+	for (j = 0; j < i; j++)
+		sc->sc_fans[j].id = ((id[j] >> 8) & 0x0f) % 8;
+
+	/* Fill the fan zone property. */
+	prop_len = OF_getprop(child, "hwctrl-zone", id, sizeof(id));
+	for (j = 0; j < i; j++)
+		sc->sc_fans[j].fan.zone = id[j];
+
+	/* Finish setting up fan properties */
+	for (j = 0; j < i; j++) {
+		sc->sc_fans[j].dev = sc->sc_dev;
+		if (sc->sc_fans[j].type == FCU_FAN_RPM) {
+			sc->sc_fans[j].fan.min_rpm = 4800 >> fcu_rpm_shift;
+			sc->sc_fans[j].fan.max_rpm = 56000 >> fcu_rpm_shift;
+			sc->sc_fans[j].setpoint =
+			    fcu_fan_get_rpm(&sc->sc_fans[j]);
+			sc->sc_fans[j].fan.read = 
+			    (int (*)(struct pmac_fan *))(fcu_fan_get_rpm);
+			sc->sc_fans[j].fan.set =
+			    (int (*)(struct pmac_fan *, int))(fcu_fan_set_rpm);
+		} else {
+			sc->sc_fans[j].fan.min_rpm = 30;	/* Percent */
+			sc->sc_fans[j].fan.max_rpm = 100;
+			sc->sc_fans[j].fan.read = NULL;
+			sc->sc_fans[j].fan.set =
+			    (int (*)(struct pmac_fan *, int))(fcu_fan_set_pwm);
+		}
+		sc->sc_fans[j].fan.default_rpm = sc->sc_fans[j].fan.max_rpm;
+	}
+
+	return (i);
+}
+
+static int
+fcu_fanrpm_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	device_t fcu;
+	struct fcu_softc *sc;
+	struct fcu_fan *fan;
+	int rpm = 0, pwm = 0, error = 0;
+
+	fcu = arg1;
+	sc = device_get_softc(fcu);
+	fan = &sc->sc_fans[arg2 & 0x00ff];
+	if (fan->type == FCU_FAN_RPM) {
+		rpm = fcu_fan_get_rpm(fan);
+		if (rpm < 0)
+			return (EIO);
+		error = sysctl_handle_int(oidp, &rpm, 0, req);
+	} else {
+		error = fcu_fan_get_pwm(fcu, fan, &pwm, &rpm);
+		if (error < 0)
+			return (EIO);
+
+		switch (arg2 & 0xff00) {
+		case FCU_PWM_SYSCTL_PWM:
+			error = sysctl_handle_int(oidp, &pwm, 0, req);
+			break;
+		case FCU_PWM_SYSCTL_RPM:
+			error = sysctl_handle_int(oidp, &rpm, 0, req);
+			break;
+		default:
+			/* This should never happen */
+			return (EINVAL);
+		};
+	}
+
+	/* We can only read the RPM from a PWM controlled fan, so return. */
+	if ((arg2 & 0xff00) == FCU_PWM_SYSCTL_RPM)
+		return (0);
+
+	if (error || !req->newptr)
+		return (error);
+
+	if (fan->type == FCU_FAN_RPM)
+		return (fcu_fan_set_rpm(fan, rpm));
+	else
+		return (fcu_fan_set_pwm(fan, pwm));
+}
+
+static void
+fcu_attach_fans(device_t dev)
+{
+	struct fcu_softc *sc;
+	struct sysctl_oid *oid, *fanroot_oid;
+	struct sysctl_ctx_list *ctx;
+	char sysctl_name[32];
+	int i, j;
+
+	sc = device_get_softc(dev);
+
+	sc->sc_nfans = 0;
+
+	/* Count the actual number of fans. */
+	sc->sc_nfans = fcu_fill_fan_prop(dev);
+
+	device_printf(dev, "%d fans detected!\n", sc->sc_nfans);
+
+	if (sc->sc_nfans == 0) {
+		device_printf(dev, "WARNING: No fans detected!\n");
+		return;
+	}
+
+	sc->sc_fans = malloc(sc->sc_nfans * sizeof(struct fcu_fan), M_FCU,
+			     M_WAITOK | M_ZERO);
+
+	ctx = device_get_sysctl_ctx(dev);
+	fanroot_oid = SYSCTL_ADD_NODE(ctx,
+	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "fans",
+	    CTLFLAG_RD, 0, "FCU Fan Information");
+
+	/* Now we can fill the properties into the allocated struct. */
+	sc->sc_nfans = fcu_fill_fan_prop(dev);
+
+	/* Register fans with pmac_thermal */
+	for (i = 0; i < sc->sc_nfans; i++)
+		pmac_thermal_fan_register(&sc->sc_fans[i].fan);
+
+	/* Add sysctls for the fans. */
+	for (i = 0; i < sc->sc_nfans; i++) {
+		for (j = 0; j < strlen(sc->sc_fans[i].fan.name); j++) {
+			sysctl_name[j] = tolower(sc->sc_fans[i].fan.name[j]);
+			if (isspace(sysctl_name[j]))
+				sysctl_name[j] = '_';
+		}
+		sysctl_name[j] = 0;
+
+		if (sc->sc_fans[i].type == FCU_FAN_RPM) {
+			oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(fanroot_oid),
+					      OID_AUTO, sysctl_name,
+					      CTLFLAG_RD, 0, "Fan Information");
+			SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+				       "minrpm", CTLFLAG_RD,
+				       &(sc->sc_fans[i].fan.min_rpm), 0,
+				       "Minimum allowed RPM");
+			SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+				       "maxrpm", CTLFLAG_RD,
+				       &(sc->sc_fans[i].fan.max_rpm), 0,
+				       "Maximum allowed RPM");
+			/* I use i to pass the fan id. */
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+					"rpm", CTLTYPE_INT | CTLFLAG_RW, dev, i,
+					fcu_fanrpm_sysctl, "I", "Fan RPM");
+		} else {
+			fcu_fan_get_pwm(dev, &sc->sc_fans[i],
+					&sc->sc_fans[i].setpoint,
+					&sc->sc_fans[i].rpm);
+
+			oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(fanroot_oid),
+					      OID_AUTO, sysctl_name,
+					      CTLFLAG_RD, 0, "Fan Information");
+			SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+				       "minpwm", CTLFLAG_RD,
+				       &(sc->sc_fans[i].fan.min_rpm), 0,
+				       "Minimum allowed PWM in %");
+			SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+				       "maxpwm", CTLFLAG_RD,
+				       &(sc->sc_fans[i].fan.max_rpm), 0,
+				       "Maximum allowed PWM in %");
+			/* I use i to pass the fan id or'ed with the type
+			 * of info I want to display/modify.
+			 */
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+					"pwm", CTLTYPE_INT | CTLFLAG_RW, dev,
+					FCU_PWM_SYSCTL_PWM | i,
+					fcu_fanrpm_sysctl, "I", "Fan PWM in %");
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+					"rpm", CTLTYPE_INT | CTLFLAG_RD, dev,
+					FCU_PWM_SYSCTL_RPM | i,
+					fcu_fanrpm_sysctl, "I", "Fan RPM");
+		}
+	}
+
+	/* Dump fan location, type & RPM. */
+	if (bootverbose) {
+		device_printf(dev, "Fans\n");
+		for (i = 0; i < sc->sc_nfans; i++) {
+			device_printf(dev, "Location: %s type: %d ID: %d "
+				      "RPM: %d\n", sc->sc_fans[i].fan.name,
+				      sc->sc_fans[i].type, sc->sc_fans[i].id,
+				      (sc->sc_fans[i].type == FCU_FAN_RPM) ?
+				      sc->sc_fans[i].setpoint :
+				      sc->sc_fans[i].rpm );
+	    }
+	}
+}


Property changes on: trunk/sys/powerpc/powermac/fcu.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/grackle.c
===================================================================
--- trunk/sys/powerpc/powermac/grackle.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/grackle.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,326 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2003 by Peter Grehan. 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. 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/grackle.c 266160 2014-05-15 17:30:16Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <sys/rman.h>
+
+#include <powerpc/ofw/ofw_pci.h>
+#include <powerpc/powermac/gracklevar.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include "pcib_if.h"
+
+/*
+ * Device interface.
+ */
+static int		grackle_probe(device_t);
+static int		grackle_attach(device_t);
+
+/*
+ * pcib interface.
+ */
+static u_int32_t	grackle_read_config(device_t, u_int, u_int, u_int,
+			    u_int, int);
+static void		grackle_write_config(device_t, u_int, u_int, u_int,
+			    u_int, u_int32_t, int);
+
+/*
+ * Local routines.
+ */
+static int		grackle_enable_config(struct grackle_softc *, u_int,
+			    u_int, u_int, u_int);
+static void		grackle_disable_config(struct grackle_softc *);
+static int		badaddr(void *, size_t);
+
+int			setfault(faultbuf);	/* defined in locore.S */
+
+/*
+ * Driver methods.
+ */
+static device_method_t	grackle_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		grackle_probe),
+	DEVMETHOD(device_attach,	grackle_attach),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_read_config,	grackle_read_config),
+	DEVMETHOD(pcib_write_config,	grackle_write_config),
+
+	DEVMETHOD_END
+};
+
+static devclass_t	grackle_devclass;
+DEFINE_CLASS_1(pcib, grackle_driver, grackle_methods,
+    sizeof(struct grackle_softc), ofw_pci_driver);
+DRIVER_MODULE(grackle, ofwbus, grackle_driver, grackle_devclass, 0, 0);
+
+static int
+grackle_probe(device_t dev)
+{
+	const char	*type, *compatible;
+
+	type = ofw_bus_get_type(dev);
+	compatible = ofw_bus_get_compat(dev);
+
+	if (type == NULL || compatible == NULL)
+		return (ENXIO);
+
+	if (strcmp(type, "pci") != 0 || strcmp(compatible, "grackle") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "MPC106 (Grackle) Host-PCI bridge");
+	return (0);
+}
+
+static int
+grackle_attach(device_t dev)
+{
+	struct		grackle_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	/*
+	 * The Grackle PCI config addr/data registers are actually in
+	 * PCI space, but since they are needed to actually probe the
+	 * PCI bus, use the fact that they are also available directly
+	 * on the processor bus and map them
+	 */
+	sc->sc_addr = (vm_offset_t)pmap_mapdev(GRACKLE_ADDR, PAGE_SIZE);
+	sc->sc_data = (vm_offset_t)pmap_mapdev(GRACKLE_DATA, PAGE_SIZE);
+
+	return (ofw_pci_attach(dev));
+}
+
+static u_int32_t
+grackle_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
+    int width)
+{
+	struct		grackle_softc *sc;
+	vm_offset_t	caoff;
+	u_int32_t	retval = 0xffffffff;
+
+	sc = device_get_softc(dev);
+	caoff = sc->sc_data + (reg & 0x03);
+
+	if (grackle_enable_config(sc, bus, slot, func, reg) != 0) {
+
+		/*
+		 * Config probes to non-existent devices on the
+		 * secondary bus generates machine checks. Be sure
+		 * to catch these.
+		 */
+		if (bus > 0) {
+		  if (badaddr((void *)sc->sc_data, 4)) {
+			  return (retval);
+		  }
+		}
+
+		switch (width) {
+		case 1:
+			retval = (in8rb(caoff));
+			break;
+		case 2:
+			retval = (in16rb(caoff));
+			break;
+		case 4:
+			retval = (in32rb(caoff));
+			break;
+		}
+	}
+	grackle_disable_config(sc);
+
+	return (retval);
+}
+
+static void
+grackle_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+    u_int reg, u_int32_t val, int width)
+{
+	struct		grackle_softc *sc;
+	vm_offset_t	caoff;
+
+	sc = device_get_softc(dev);
+	caoff = sc->sc_data + (reg & 0x03);
+
+	if (grackle_enable_config(sc, bus, slot, func, reg)) {
+		switch (width) {
+		case 1:
+			out8rb(caoff, val);
+			(void)in8rb(caoff);
+			break;
+		case 2:
+			out16rb(caoff, val);
+			(void)in16rb(caoff);
+			break;
+		case 4:
+			out32rb(caoff, val);
+			(void)in32rb(caoff);
+			break;
+		}
+	}
+	grackle_disable_config(sc);
+}
+
+static int
+grackle_enable_config(struct grackle_softc *sc, u_int bus, u_int slot,
+    u_int func, u_int reg)
+{
+	u_int32_t	cfgval;
+
+	/*
+	 * Unlike UniNorth, the format of the config word is the same
+	 * for local (0) and remote busses.
+	 */
+	cfgval = (bus << 16) | (slot << 11) | (func << 8) | (reg & 0xFC)
+	    | GRACKLE_CFG_ENABLE;
+
+	out32rb(sc->sc_addr, cfgval);
+	(void) in32rb(sc->sc_addr);
+
+	return (1);
+}
+
+static void
+grackle_disable_config(struct grackle_softc *sc)
+{
+	/*
+	 * Clear the GRACKLE_CFG_ENABLE bit to prevent stray
+	 * accesses from causing config cycles
+	 */
+	out32rb(sc->sc_addr, 0);
+}
+
+static int
+badaddr(void *addr, size_t size)
+{
+	struct thread	*td;
+	faultbuf	env, *oldfaultbuf;
+	int		x;
+
+	/* Get rid of any stale machine checks that have been waiting.  */
+	__asm __volatile ("sync; isync");
+
+	td = curthread;
+
+	oldfaultbuf = td->td_pcb->pcb_onfault;
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = oldfaultbuf;
+		__asm __volatile ("sync");
+		return 1;
+	}
+
+	__asm __volatile ("sync");
+
+	switch (size) {
+	case 1:
+		x = *(volatile int8_t *)addr;
+		break;
+	case 2:
+		x = *(volatile int16_t *)addr;
+		break;
+	case 4:
+		x = *(volatile int32_t *)addr;
+		break;
+	default:
+		panic("badaddr: invalid size (%zd)", size);
+	}
+
+	/* Make sure we took the machine check, if we caused one. */
+	__asm __volatile ("sync; isync");
+
+	td->td_pcb->pcb_onfault = oldfaultbuf;
+	__asm __volatile ("sync");	/* To be sure. */
+
+	return (0);
+}
+
+/*
+ * Driver to swallow Grackle host bridges from the PCI bus side.
+ */
+static int
+grackle_hb_probe(device_t dev)
+{
+
+	if (pci_get_devid(dev) == 0x00021057) {
+		device_set_desc(dev, "Grackle Host to PCI bridge");
+		device_quiet(dev);
+		return (0);
+	}
+
+	return (ENXIO);
+}
+
+static int
+grackle_hb_attach(device_t dev)
+{
+
+	return (0);
+}
+
+static device_method_t grackle_hb_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,         grackle_hb_probe),
+	DEVMETHOD(device_attach,        grackle_hb_attach),
+
+	{ 0, 0 }
+};
+
+static driver_t grackle_hb_driver = {
+	"grackle_hb",
+	grackle_hb_methods,
+	1,
+};
+static devclass_t grackle_hb_devclass;
+
+DRIVER_MODULE(grackle_hb, pci, grackle_hb_driver, grackle_hb_devclass, 0, 0);


Property changes on: trunk/sys/powerpc/powermac/grackle.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/gracklevar.h
===================================================================
--- trunk/sys/powerpc/powermac/gracklevar.h	                        (rev 0)
+++ trunk/sys/powerpc/powermac/gracklevar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,52 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2003 by Peter Grehan. 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/gracklevar.h 230993 2012-02-04 19:54:13Z nwhitehorn $
+ */
+
+#ifndef	_POWERPC_POWERMAC_GRACKLEVAR_H_
+#define	_POWERPC_POWERMAC_GRACKLEVAR_H_
+
+struct grackle_softc {
+	struct ofw_pci_softc	pci_sc;
+	vm_offset_t		sc_addr;
+	vm_offset_t		sc_data;
+};
+
+/*
+ * Apple uses address map B for the MPC106
+ */
+#define GRACKLE_ADDR	0xFEC00000
+#define GRACKLE_DATA	0xFEE00000
+
+/*
+ * The high bit of the config word is 'Enable'. This should always be
+ * set.
+ */
+#define GRACKLE_CFG_ENABLE	0x80000000
+
+#endif  /* _POWERPC_POWERMAC_GRACKLEVAR_H_ */


Property changes on: trunk/sys/powerpc/powermac/gracklevar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/hrowpic.c
===================================================================
--- trunk/sys/powerpc/powermac/hrowpic.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/hrowpic.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,281 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2003 by Peter Grehan. 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/hrowpic.c 237936 2012-07-01 19:07:45Z rpaulo $
+ */
+
+/*
+ * A driver for the PIC found in the Heathrow/Paddington MacIO chips.
+ * This was superseded by an OpenPIC in the Keylargo and beyond 
+ * MacIO versions.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <powerpc/powermac/hrowpicvar.h>
+
+#include "pic_if.h"
+
+/*
+ * MacIO interface
+ */
+static int	hrowpic_probe(device_t);
+static int	hrowpic_attach(device_t);
+
+static void	hrowpic_dispatch(device_t, struct trapframe *);
+static void	hrowpic_enable(device_t, u_int, u_int);
+static void	hrowpic_eoi(device_t, u_int);
+static void	hrowpic_ipi(device_t, u_int);
+static void	hrowpic_mask(device_t, u_int);
+static void	hrowpic_unmask(device_t, u_int);
+
+static device_method_t  hrowpic_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,         hrowpic_probe),
+	DEVMETHOD(device_attach,        hrowpic_attach),
+
+	/* PIC interface */
+	DEVMETHOD(pic_dispatch,		hrowpic_dispatch),
+	DEVMETHOD(pic_enable,		hrowpic_enable),
+	DEVMETHOD(pic_eoi,		hrowpic_eoi),
+	DEVMETHOD(pic_ipi,		hrowpic_ipi),
+	DEVMETHOD(pic_mask,		hrowpic_mask),
+	DEVMETHOD(pic_unmask,		hrowpic_unmask),
+
+	{ 0, 0 },
+};
+
+static driver_t hrowpic_driver = {
+	"hrowpic",
+	hrowpic_methods,
+	sizeof(struct hrowpic_softc)
+};
+
+static devclass_t hrowpic_devclass;
+
+DRIVER_MODULE(hrowpic, macio, hrowpic_driver, hrowpic_devclass, 0, 0);
+
+static uint32_t
+hrowpic_read_reg(struct hrowpic_softc *sc, u_int reg, u_int bank)
+{
+	if (bank == HPIC_PRIMARY)
+		reg += HPIC_1ST_OFFSET;
+
+	return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg));
+}
+
+static void
+hrowpic_write_reg(struct hrowpic_softc *sc, u_int reg, u_int bank,
+    uint32_t val)
+{
+
+	if (bank == HPIC_PRIMARY)
+		reg += HPIC_1ST_OFFSET;
+
+	bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val);
+
+	/* XXX Issue a read to force the write to complete. */
+	bus_space_read_4(sc->sc_bt, sc->sc_bh, reg);
+}
+
+static int
+hrowpic_probe(device_t dev)
+{
+	const char *type = ofw_bus_get_type(dev);
+
+	/*
+	 * OpenPIC cells have a type of "open-pic", so this
+	 * is sufficient to identify a Heathrow cell
+	 */
+	if (strcmp(type, "interrupt-controller") != 0)
+		return (ENXIO);
+
+	/*
+	 * The description was already printed out in the nexus
+	 * probe, so don't do it again here
+	 */
+	device_set_desc(dev, "Heathrow MacIO interrupt controller");
+	return (0);
+}
+
+static int
+hrowpic_attach(device_t dev)
+{
+	struct hrowpic_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+
+	sc->sc_rrid = 0;
+	sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid,
+	    RF_ACTIVE);
+
+	if (sc->sc_rres == NULL) {
+		device_printf(dev, "Could not alloc mem resource!\n");
+		return (ENXIO);
+	}
+
+	sc->sc_bt = rman_get_bustag(sc->sc_rres);
+	sc->sc_bh = rman_get_bushandle(sc->sc_rres);
+
+	/*
+	 * Disable all interrupt sources and clear outstanding interrupts
+	 */
+	hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_PRIMARY, 0);
+	hrowpic_write_reg(sc, HPIC_CLEAR,  HPIC_PRIMARY, 0xffffffff);
+	hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_SECONDARY, 0);
+	hrowpic_write_reg(sc, HPIC_CLEAR,  HPIC_SECONDARY, 0xffffffff);
+
+	powerpc_register_pic(dev, ofw_bus_get_node(dev), 64, 0, FALSE);
+	return (0);
+}
+
+/*
+ * Local routines
+ */
+
+static void
+hrowpic_toggle_irq(struct hrowpic_softc *sc, int irq, int enable)
+{
+	u_int roffset;
+	u_int rbit;
+
+	KASSERT((irq > 0) && (irq <= HROWPIC_IRQMAX), ("en irq out of range"));
+
+	/*
+	 * Humor the SMP layer if it wants to set up an IPI handler.
+	 */
+	if (irq == HROWPIC_IRQMAX)
+		return;
+
+	/*
+	 * Calculate prim/sec register bank for the IRQ, update soft copy,
+	 * and enable the IRQ as an interrupt source
+	 */
+	roffset = HPIC_INT_TO_BANK(irq);
+	rbit = HPIC_INT_TO_REGBIT(irq);
+
+	if (enable)
+		sc->sc_softreg[roffset] |= (1 << rbit);
+	else
+		sc->sc_softreg[roffset] &= ~(1 << rbit);
+		
+	hrowpic_write_reg(sc, HPIC_ENABLE, roffset, sc->sc_softreg[roffset]);
+}
+
+/*
+ * PIC I/F methods.
+ */
+
+static void
+hrowpic_dispatch(device_t dev, struct trapframe *tf)
+{
+	struct hrowpic_softc *sc;
+	uint64_t mask;
+	uint32_t reg;
+	u_int irq;
+
+	sc = device_get_softc(dev);
+	while (1) {
+		mask = hrowpic_read_reg(sc, HPIC_STATUS, HPIC_SECONDARY);
+		reg = hrowpic_read_reg(sc, HPIC_STATUS, HPIC_PRIMARY);
+		mask = (mask << 32) | reg;
+		if (mask == 0)
+			break;
+
+		irq = 0;
+		while (irq < HROWPIC_IRQMAX) {
+			if (mask & 1)
+				powerpc_dispatch_intr(sc->sc_vector[irq], tf);
+			mask >>= 1;
+			irq++;
+		}
+	}
+}
+
+static void
+hrowpic_enable(device_t dev, u_int irq, u_int vector)
+{
+	struct hrowpic_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->sc_vector[irq] = vector;
+	hrowpic_toggle_irq(sc, irq, 1);
+}
+
+static void
+hrowpic_eoi(device_t dev, u_int irq)
+{
+	struct hrowpic_softc *sc;
+	int bank;
+
+	sc = device_get_softc(dev);
+	bank = (irq >= 32) ? HPIC_SECONDARY : HPIC_PRIMARY ;
+	hrowpic_write_reg(sc, HPIC_CLEAR, bank, 1U << (irq & 0x1f));
+}
+
+static void
+hrowpic_ipi(device_t dev, u_int irq)
+{
+	/* No SMP support. */
+}
+
+static void
+hrowpic_mask(device_t dev, u_int irq)
+{
+	struct hrowpic_softc *sc;
+
+	sc = device_get_softc(dev);
+	hrowpic_toggle_irq(sc, irq, 0);
+}
+
+static void
+hrowpic_unmask(device_t dev, u_int irq)
+{
+	struct hrowpic_softc *sc;
+
+	sc = device_get_softc(dev);
+	hrowpic_toggle_irq(sc, irq, 1);
+}


Property changes on: trunk/sys/powerpc/powermac/hrowpic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/hrowpicvar.h
===================================================================
--- trunk/sys/powerpc/powermac/hrowpicvar.h	                        (rev 0)
+++ trunk/sys/powerpc/powermac/hrowpicvar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,76 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2003 by Peter Grehan. 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/hrowpicvar.h 171805 2007-08-11 19:25:32Z marcel $
+ */
+
+#ifndef  _POWERPC_POWERMAC_HROWPICVAR_H_
+#define  _POWERPC_POWERMAC_HROWPICVAR_H_
+
+#define HROWPIC_IRQMAX	64
+#define HROWPIC_IRQ_REGNUM	32	/* irqs per register */
+#define HROWPIC_IRQ_SHIFT	5	/* high or low irq word */
+#define HROWPIC_IRQ_MASK ((HROWPIC_IRQMAX-1) >> 1)  /* irq bit pos in word */
+
+/*
+ * Register offsets within bank. There are two identical banks,
+ * separated by 16 bytes. Interrupts 0->31 are processed in the
+ * second bank, and 32->63 in the first bank.
+ */
+#define  HPIC_STATUS	0x00		/* active interrupt sources */
+#define  HPIC_ENABLE	0x04		/* interrupt asserts ppc EXTINT */
+#define  HPIC_CLEAR	0x08		/* clear int source */
+#define  HPIC_TRIGGER	0x0c		/* edge/level int trigger */
+
+#define HPIC_PRIMARY	1	/* primary register bank */
+#define HPIC_SECONDARY  0       /* secondary register bank */
+
+/*
+ * Convert an interrupt into a prim/sec bank number
+ */
+#define HPIC_INT_TO_BANK(x) \
+	(((x) >> HROWPIC_IRQ_SHIFT) ^ 1)
+
+/*
+ * Convert an interrupt into the bit number within a bank register
+ */
+#define HPIC_INT_TO_REGBIT(x) \
+	((x) & HROWPIC_IRQ_MASK)
+
+#define  HPIC_1ST_OFFSET  0x10		/* offset to primary reg bank */
+
+struct hrowpic_softc {
+	device_t	sc_dev;			/* macio device */
+	struct resource *sc_rres;		/* macio bus resource */
+	bus_space_tag_t sc_bt;			/* macio bus tag/handle */
+	bus_space_handle_t sc_bh;
+	int		sc_rrid;
+	uint32_t	sc_softreg[2];		/* ENABLE reg copy */
+	u_int		sc_vector[HROWPIC_IRQMAX];
+};
+
+#endif  /* _POWERPC_POWERMAC_HROWPICVAR_H_ */


Property changes on: trunk/sys/powerpc/powermac/hrowpicvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/kiic.c
===================================================================
--- trunk/sys/powerpc/powermac/kiic.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/kiic.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,445 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 Tsubai Masanari.  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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/kiic.c 254737 2013-08-23 20:39:41Z andreast $
+ *	NetBSD: ki2c.c,v 1.11 2007/12/06 17:00:33 ad Exp
+ *	Id: ki2c.c,v 1.7 2002/10/05 09:56:05 tsubai Exp
+ */
+
+/*
+ * 	Support routines for the Keywest I2C controller.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+#include <dev/ofw/ofw_bus.h>
+#include "iicbus_if.h"
+
+/* Keywest I2C Register offsets */
+#define MODE	0
+#define CONTROL	1
+#define STATUS	2
+#define ISR	3
+#define IER	4
+#define ADDR	5
+#define SUBADDR	6
+#define DATA	7
+#define REV	8
+
+/* MODE */
+#define I2C_SPEED	0x03	/* Speed mask */
+#define  I2C_100kHz	0x00
+#define  I2C_50kHz	0x01
+#define  I2C_25kHz	0x02
+#define I2C_MODE	0x0c	/* Mode mask */
+#define  I2C_DUMBMODE	0x00	/*  Dumb mode */
+#define  I2C_STDMODE	0x04	/*  Standard mode */
+#define  I2C_STDSUBMODE	0x08	/*  Standard mode + sub address */
+#define  I2C_COMBMODE	0x0c	/*  Combined mode */
+#define I2C_PORT	0xf0	/* Port mask */
+
+/* CONTROL */
+#define I2C_CT_AAK	0x01	/* Send AAK */
+#define I2C_CT_ADDR	0x02	/* Send address(es) */
+#define I2C_CT_STOP	0x04	/* Send STOP */
+#define I2C_CT_START	0x08	/* Send START */
+
+/* STATUS */
+#define I2C_ST_BUSY	0x01	/* Busy */
+#define I2C_ST_LASTAAK	0x02	/* Last AAK */
+#define I2C_ST_LASTRW	0x04	/* Last R/W */
+#define I2C_ST_SDA	0x08	/* SDA */
+#define I2C_ST_SCL	0x10	/* SCL */
+
+/* ISR/IER */
+#define I2C_INT_DATA	0x01	/* Data byte sent/received */
+#define I2C_INT_ADDR	0x02	/* Address sent */
+#define I2C_INT_STOP	0x04	/* STOP condition sent */
+#define I2C_INT_START	0x08	/* START condition sent */
+
+/* I2C flags */
+#define I2C_BUSY	0x01
+#define I2C_READING	0x02
+#define I2C_ERROR	0x04
+#define I2C_SELECTED	0x08
+
+struct kiic_softc {
+	device_t 		 sc_dev;
+	phandle_t		 sc_node;
+	struct mtx 		 sc_mutex;
+	struct resource		*sc_reg;
+	int			 sc_irqrid;
+	struct resource		*sc_irq;
+	void			*sc_ih;
+	u_int 			 sc_regstep;
+	u_int 			 sc_flags;
+	u_char			*sc_data;
+	int 			 sc_resid;
+	uint16_t		 sc_i2c_base;
+	device_t 		 sc_iicbus;
+};
+
+static int 	kiic_probe(device_t dev);
+static int 	kiic_attach(device_t dev);
+static void 	kiic_writereg(struct kiic_softc *sc, u_int, u_int);
+static u_int 	kiic_readreg(struct kiic_softc *, u_int);
+static void 	kiic_setport(struct kiic_softc *, u_int);
+static void 	kiic_setmode(struct kiic_softc *, u_int);
+static void 	kiic_setspeed(struct kiic_softc *, u_int);
+static void 	kiic_intr(void *xsc);
+static int	kiic_transfer(device_t dev, struct iic_msg *msgs,
+		    uint32_t nmsgs);
+static phandle_t kiic_get_node(device_t bus, device_t dev);
+
+static device_method_t kiic_methods[] = {
+	/* device interface */
+	DEVMETHOD(device_probe, 	kiic_probe),
+	DEVMETHOD(device_attach, 	kiic_attach),
+
+	/* iicbus interface */
+	DEVMETHOD(iicbus_callback,	iicbus_null_callback),
+	DEVMETHOD(iicbus_transfer,	kiic_transfer),
+
+	/* ofw_bus interface */
+	DEVMETHOD(ofw_bus_get_node,	kiic_get_node),
+
+	{ 0, 0 }
+};
+
+static driver_t kiic_driver = {
+	"iichb",
+	kiic_methods,
+	sizeof(struct kiic_softc)
+};
+static devclass_t kiic_devclass;
+
+DRIVER_MODULE(kiic, macio, kiic_driver, kiic_devclass, 0, 0);
+DRIVER_MODULE(kiic, unin, kiic_driver, kiic_devclass, 0, 0);
+
+static int
+kiic_probe(device_t self)
+{
+	const char *name;
+
+	name = ofw_bus_get_name(self);
+	if (name && strcmp(name, "i2c") == 0) {
+		device_set_desc(self, "Keywest I2C controller");
+		return (0);
+	}
+
+	return (ENXIO);
+}
+
+static int
+kiic_attach(device_t self)
+{
+	struct kiic_softc *sc = device_get_softc(self);
+	int rid, rate;
+	phandle_t node;
+	char name[64];
+
+	bzero(sc, sizeof(*sc));
+	sc->sc_dev = self;
+	
+	node = ofw_bus_get_node(self);
+	if (node == 0 || node == -1) {
+		return (EINVAL);
+	}
+
+	rid = 0;
+	sc->sc_reg = bus_alloc_resource_any(self, SYS_RES_MEMORY,
+			&rid, RF_ACTIVE);
+	if (sc->sc_reg == NULL) {
+		return (ENOMEM);
+	}
+
+	if (OF_getprop(node, "AAPL,i2c-rate", &rate, 4) != 4) {
+		device_printf(self, "cannot get i2c-rate\n");
+		return (ENXIO);
+	}
+	if (OF_getprop(node, "AAPL,address-step", &sc->sc_regstep, 4) != 4) {
+		device_printf(self, "unable to find i2c address step\n");
+		return (ENXIO);
+	}
+
+	/*
+	 * Some Keywest I2C devices have their children attached directly
+	 * underneath them.  Some have a single 'iicbus' child with the
+	 * devices underneath that.  Sort this out, and make sure that the
+	 * OFW I2C layer has the correct node.
+	 *
+	 * Note: the I2C children of the Uninorth bridges have two ports.
+	 *  In general, the port is designated in the 9th bit of the I2C
+	 *  address. However, for kiic devices with children attached below
+	 *  an i2c-bus node, the port is indicated in the 'reg' property
+	 *  of the i2c-bus node.
+	 */
+
+	sc->sc_node = node;
+
+	node = OF_child(node);
+	if (OF_getprop(node, "name", name, sizeof(name)) > 0) {
+		if (strcmp(name,"i2c-bus") == 0) {
+			phandle_t reg;
+			if (OF_getprop(node, "reg", &reg, sizeof(reg)) > 0)
+				sc->sc_i2c_base = reg << 8;
+
+			sc->sc_node = node;
+		}
+	}
+
+	mtx_init(&sc->sc_mutex, "kiic", NULL, MTX_DEF);
+
+	sc->sc_irq = bus_alloc_resource_any(self, SYS_RES_IRQ, &sc->sc_irqrid, 
+	    RF_ACTIVE);
+	bus_setup_intr(self, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE, NULL,
+	    kiic_intr, sc, &sc->sc_ih);
+
+	kiic_writereg(sc, ISR, kiic_readreg(sc, ISR));
+	kiic_writereg(sc, STATUS, 0);
+	kiic_writereg(sc, IER, 0);
+
+	kiic_setmode(sc, I2C_STDMODE);
+	kiic_setspeed(sc, I2C_100kHz);		/* XXX rate */
+	
+	kiic_writereg(sc, IER, I2C_INT_DATA | I2C_INT_ADDR | I2C_INT_STOP);
+
+	if (bootverbose)
+		device_printf(self, "Revision: %02X\n", kiic_readreg(sc, REV));
+
+	/* Add the IIC bus layer */
+	sc->sc_iicbus = device_add_child(self, "iicbus", -1);
+
+	return (bus_generic_attach(self));
+}
+
+static void
+kiic_writereg(struct kiic_softc *sc, u_int reg, u_int val)
+{
+	bus_write_4(sc->sc_reg, sc->sc_regstep * reg, val);
+	DELAY(100); /* register access delay */
+}
+
+static u_int
+kiic_readreg(struct kiic_softc *sc, u_int reg)
+{
+	return bus_read_4(sc->sc_reg, sc->sc_regstep * reg) & 0xff;
+}
+
+static void
+kiic_setmode(struct kiic_softc *sc, u_int mode)
+{
+	u_int x;
+
+	KASSERT((mode & ~I2C_MODE) == 0, ("bad mode"));
+	x = kiic_readreg(sc, MODE);
+	x &= ~I2C_MODE;
+	x |= mode;
+	kiic_writereg(sc, MODE, x);
+}
+
+static void
+kiic_setport(struct kiic_softc *sc, u_int port)
+{
+	u_int x;
+
+	KASSERT(port == 1 || port == 0, ("bad port"));
+	x = kiic_readreg(sc, MODE);
+	x &= ~I2C_PORT;
+	x |= (port << 4);
+	kiic_writereg(sc, MODE, x);
+}
+
+static void
+kiic_setspeed(struct kiic_softc *sc, u_int speed)
+{
+	u_int x;
+
+	KASSERT((speed & ~I2C_SPEED) == 0, ("bad speed"));
+	x = kiic_readreg(sc, MODE);
+	x &= ~I2C_SPEED;
+	x |= speed;
+	kiic_writereg(sc, MODE, x);
+}
+
+static void
+kiic_intr(void *xsc)
+{
+	struct kiic_softc *sc = xsc;
+	u_int isr;
+	uint32_t x;
+
+	mtx_lock(&sc->sc_mutex);
+	isr = kiic_readreg(sc, ISR);
+
+	if (isr & I2C_INT_ADDR) {
+		sc->sc_flags |= I2C_SELECTED;
+
+		if (sc->sc_flags & I2C_READING) {
+			if (sc->sc_resid > 1) {
+				x = kiic_readreg(sc, CONTROL);
+				x |= I2C_CT_AAK;
+				kiic_writereg(sc, CONTROL, x);
+			}
+		} else {
+			kiic_writereg(sc, DATA, *sc->sc_data++);
+			sc->sc_resid--;
+		}
+	}
+
+	if (isr & I2C_INT_DATA) {
+		if (sc->sc_flags & I2C_READING) {
+			if (sc->sc_resid > 0) {
+				*sc->sc_data++ = kiic_readreg(sc, DATA);
+				sc->sc_resid--;
+			}
+			if (sc->sc_resid == 0)  /* done */
+				kiic_writereg(sc, CONTROL, 0);
+		} else {
+			if (sc->sc_resid == 0) {
+				x = kiic_readreg(sc, CONTROL);
+				x |= I2C_CT_STOP;
+				kiic_writereg(sc, CONTROL, x);
+			} else {
+				kiic_writereg(sc, DATA, *sc->sc_data++);
+				sc->sc_resid--;
+			}
+		}
+	}
+
+	if (isr & I2C_INT_STOP) {
+		kiic_writereg(sc, CONTROL, 0);
+		sc->sc_flags &= ~I2C_SELECTED;
+		wakeup(sc->sc_dev);
+	}
+
+	kiic_writereg(sc, ISR, isr);
+	mtx_unlock(&sc->sc_mutex);
+}
+
+static int
+kiic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
+{
+	struct kiic_softc *sc;
+	int i, x, timo, err;
+	uint16_t addr;
+	uint8_t subaddr;
+
+	sc = device_get_softc(dev);
+	timo = 100;
+	subaddr = 0;
+
+	mtx_lock(&sc->sc_mutex);
+
+	if (sc->sc_flags & I2C_BUSY)
+		mtx_sleep(dev, &sc->sc_mutex, 0, "kiic", timo);
+
+	if (sc->sc_flags & I2C_BUSY) {
+		mtx_unlock(&sc->sc_mutex);
+		return (ETIMEDOUT);
+	}
+		
+	sc->sc_flags = I2C_BUSY;
+
+	/* Clear pending interrupts, and reset controller */
+	kiic_writereg(sc, ISR, kiic_readreg(sc, ISR));
+	kiic_writereg(sc, STATUS, 0);
+
+	for (i = 0; i < nmsgs; i++) {
+		if (msgs[i].flags & IIC_M_NOSTOP) {
+			if (msgs[i+1].flags & IIC_M_RD)
+				kiic_setmode(sc, I2C_COMBMODE);
+			else
+				kiic_setmode(sc, I2C_STDSUBMODE);
+			KASSERT(msgs[i].len == 1, ("oversize I2C message"));
+			subaddr = msgs[i].buf[0];
+			i++;
+		} else {
+			kiic_setmode(sc, I2C_STDMODE);
+		}
+
+		sc->sc_data = msgs[i].buf;
+		sc->sc_resid = msgs[i].len;
+		sc->sc_flags = I2C_BUSY;
+		addr = msgs[i].slave;
+		timo = 1000 + sc->sc_resid * 200;
+		timo += 100000;
+
+		if (msgs[i].flags & IIC_M_RD) {
+			sc->sc_flags |= I2C_READING;
+			addr |= 1;
+		}
+
+		addr |= sc->sc_i2c_base;
+
+		kiic_setport(sc, (addr & 0x100) >> 8);
+		kiic_writereg(sc, ADDR, addr & 0xff);
+		kiic_writereg(sc, SUBADDR, subaddr);
+
+		x = kiic_readreg(sc, CONTROL) | I2C_CT_ADDR;
+		kiic_writereg(sc, CONTROL, x);
+
+		err = mtx_sleep(dev, &sc->sc_mutex, 0, "kiic", timo);
+		
+		msgs[i].len -= sc->sc_resid;
+
+		if ((sc->sc_flags & I2C_ERROR) || err == EWOULDBLOCK) {
+			device_printf(sc->sc_dev, "I2C error\n");
+			sc->sc_flags = 0;
+			mtx_unlock(&sc->sc_mutex);
+			return (EIO);
+		}
+	}
+
+	sc->sc_flags = 0;
+
+	mtx_unlock(&sc->sc_mutex);
+
+	return (0);
+}
+
+static phandle_t
+kiic_get_node(device_t bus, device_t dev)
+{
+	struct kiic_softc *sc;
+
+	sc = device_get_softc(bus);
+	/* We only have one child, the I2C bus, which needs our own node. */
+		
+	return sc->sc_node;
+}
+


Property changes on: trunk/sys/powerpc/powermac/kiic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/macgpio.c
===================================================================
--- trunk/sys/powerpc/powermac/macgpio.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/macgpio.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,364 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2008 by Nathan Whitehorn. 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/macgpio.c 218184 2011-02-02 05:58:51Z marcel $
+ */
+
+/*
+ * Driver for MacIO GPIO controller
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/pmap.h>
+#include <machine/resource.h>
+#include <machine/vmparam.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include <powerpc/powermac/macgpiovar.h>
+
+/*
+ * Macgpio softc
+ */
+struct macgpio_softc {
+	phandle_t	sc_node;
+	struct resource	*sc_gpios;
+	int		sc_gpios_rid;
+};
+
+static MALLOC_DEFINE(M_MACGPIO, "macgpio", "macgpio device information");
+
+static int	macgpio_probe(device_t);
+static int	macgpio_attach(device_t);
+static int	macgpio_print_child(device_t dev, device_t child);
+static void	macgpio_probe_nomatch(device_t, device_t);
+static struct resource *macgpio_alloc_resource(device_t, device_t, int, int *,
+		    u_long, u_long, u_long, u_int);
+static int	macgpio_activate_resource(device_t, device_t, int, int,
+		    struct resource *);
+static int	macgpio_deactivate_resource(device_t, device_t, int, int,
+		    struct resource *);
+static ofw_bus_get_devinfo_t macgpio_get_devinfo;
+
+/*
+ * Bus interface definition
+ */
+static device_method_t macgpio_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,         macgpio_probe),
+	DEVMETHOD(device_attach,        macgpio_attach),
+	DEVMETHOD(device_detach,        bus_generic_detach),
+	DEVMETHOD(device_shutdown,      bus_generic_shutdown),
+	DEVMETHOD(device_suspend,       bus_generic_suspend),
+	DEVMETHOD(device_resume,        bus_generic_resume),
+	
+	/* Bus interface */
+	DEVMETHOD(bus_print_child,      macgpio_print_child),
+	DEVMETHOD(bus_probe_nomatch,    macgpio_probe_nomatch),
+	DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),	
+
+        DEVMETHOD(bus_alloc_resource,   macgpio_alloc_resource),
+        DEVMETHOD(bus_activate_resource, macgpio_activate_resource),
+        DEVMETHOD(bus_deactivate_resource, macgpio_deactivate_resource),
+        DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+
+	DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
+
+	/* ofw_bus interface */
+	DEVMETHOD(ofw_bus_get_devinfo,	macgpio_get_devinfo),
+	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
+	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
+	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
+	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
+	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
+
+	{ 0, 0 }
+};
+
+static driver_t macgpio_pci_driver = {
+        "macgpio",
+        macgpio_methods,
+	sizeof(struct macgpio_softc)
+};
+
+devclass_t macgpio_devclass;
+
+DRIVER_MODULE(macgpio, macio, macgpio_pci_driver, macgpio_devclass, 0, 0);
+
+struct macgpio_devinfo {
+	struct ofw_bus_devinfo mdi_obdinfo;
+	struct resource_list mdi_resources;
+
+	int gpio_num;
+};
+
+static int
+macgpio_probe(device_t dev)
+{
+	const char *name;
+
+	name = ofw_bus_get_name(dev);
+	if (name && strcmp(name, "gpio") == 0) {
+		device_set_desc(dev, "MacIO GPIO Controller");
+		return (0);
+	}
+	
+        return (ENXIO);	
+}
+
+/*
+ * Scan Open Firmware child nodes, and attach these as children
+ * of the macgpio bus
+ */
+static int 
+macgpio_attach(device_t dev)
+{
+	struct macgpio_softc *sc;
+        struct macgpio_devinfo *dinfo;
+        phandle_t root, child, iparent;
+        device_t cdev;
+	uint32_t irq;
+
+	sc = device_get_softc(dev);
+	root = sc->sc_node = ofw_bus_get_node(dev);
+	
+	sc->sc_gpios = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->sc_gpios_rid, RF_ACTIVE);
+
+	/*
+	 * Iterate through the sub-devices
+	 */
+	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
+		dinfo = malloc(sizeof(*dinfo), M_MACGPIO, M_WAITOK | M_ZERO);
+		if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo, child) !=
+		    0) {
+			free(dinfo, M_MACGPIO);
+			continue;
+		}
+
+		if (OF_getprop(child,"reg",&dinfo->gpio_num,
+		    sizeof(dinfo->gpio_num)) != sizeof(dinfo->gpio_num)) {
+			/*
+			 * Some early GPIO controllers don't provide GPIO
+			 * numbers for GPIOs designed only to provide
+			 * interrupt resources.  We should still allow these
+			 * to attach, but with caution.
+			 */
+
+			dinfo->gpio_num = -1;
+		}
+
+		resource_list_init(&dinfo->mdi_resources);
+
+		if (OF_getprop(child, "interrupts", &irq, sizeof(irq)) == 
+		    sizeof(irq)) {
+			OF_searchprop(child, "interrupt-parent", &iparent,
+			    sizeof(iparent));
+			resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ,
+			    0, MAP_IRQ(iparent, irq), MAP_IRQ(iparent, irq),
+			    1);
+		}
+
+		/* Fix messed-up offsets */
+		if (dinfo->gpio_num > 0x50)
+			dinfo->gpio_num -= 0x50;
+
+		cdev = device_add_child(dev, NULL, -1);
+		if (cdev == NULL) {
+			device_printf(dev, "<%s>: device_add_child failed\n",
+			    dinfo->mdi_obdinfo.obd_name);
+			ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
+			free(dinfo, M_MACGPIO);
+			continue;
+		}
+		device_set_ivars(cdev, dinfo);
+	}
+
+	return (bus_generic_attach(dev));
+}
+
+
+static int
+macgpio_print_child(device_t dev, device_t child)
+{
+        struct macgpio_devinfo *dinfo;
+        int retval = 0;
+
+        dinfo = device_get_ivars(child);
+
+        retval += bus_print_child_header(dev, child);
+	
+	if (dinfo->gpio_num >= GPIO_BASE)
+		printf(" gpio %d", dinfo->gpio_num - GPIO_BASE);
+	else if (dinfo->gpio_num >= GPIO_EXTINT_BASE)
+		printf(" extint-gpio %d", dinfo->gpio_num - GPIO_EXTINT_BASE);
+	else if (dinfo->gpio_num >= 0)
+		printf(" addr 0x%02x", dinfo->gpio_num); /* should not happen */
+
+	resource_list_print_type(&dinfo->mdi_resources, "irq", SYS_RES_IRQ, 
+	    "%ld");
+        retval += bus_print_child_footer(dev, child);
+
+        return (retval);
+}
+
+
+static void
+macgpio_probe_nomatch(device_t dev, device_t child)
+{
+        struct macgpio_devinfo *dinfo;
+	const char *type;
+
+	if (bootverbose) {
+		dinfo = device_get_ivars(child);
+
+		if ((type = ofw_bus_get_type(child)) == NULL)
+			type = "(unknown)";
+		device_printf(dev, "<%s, %s>", type, ofw_bus_get_name(child));
+		if (dinfo->gpio_num >= 0)
+			printf(" gpio %d",dinfo->gpio_num);
+		resource_list_print_type(&dinfo->mdi_resources, "irq", 
+		    SYS_RES_IRQ, "%ld");
+		printf(" (no driver attached)\n");
+	}
+}
+
+
+static struct resource *
+macgpio_alloc_resource(device_t bus, device_t child, int type, int *rid,
+		     u_long start, u_long end, u_long count, u_int flags)
+{
+	struct macgpio_devinfo *dinfo;
+
+	dinfo = device_get_ivars(child);
+
+	if (type != SYS_RES_IRQ)
+		return (NULL);
+
+	return (resource_list_alloc(&dinfo->mdi_resources, bus, child, type, 
+	    rid, start, end, count, flags));
+}
+
+static int
+macgpio_activate_resource(device_t bus, device_t child, int type, int rid,
+			   struct resource *res)
+{
+	struct macgpio_softc *sc;
+	struct macgpio_devinfo *dinfo;
+	u_char val;
+
+	sc = device_get_softc(bus);
+	dinfo = device_get_ivars(child);
+
+	if (type != SYS_RES_IRQ)
+		return ENXIO;
+
+	if (dinfo->gpio_num >= 0) {
+		val = bus_read_1(sc->sc_gpios,dinfo->gpio_num);
+		val |= 0x80;
+		bus_write_1(sc->sc_gpios,dinfo->gpio_num,val);
+	}
+
+	return (bus_activate_resource(bus, type, rid, res));
+}
+
+
+static int
+macgpio_deactivate_resource(device_t bus, device_t child, int type, int rid,
+			  struct resource *res)
+{
+	struct macgpio_softc *sc;
+	struct macgpio_devinfo *dinfo;
+	u_char val;
+
+	sc = device_get_softc(bus);
+	dinfo = device_get_ivars(child);
+
+	if (type != SYS_RES_IRQ)
+		return ENXIO;
+
+	if (dinfo->gpio_num >= 0) {
+		val = bus_read_1(sc->sc_gpios,dinfo->gpio_num);
+		val &= ~0x80;
+		bus_write_1(sc->sc_gpios,dinfo->gpio_num,val);
+	}
+
+	return (bus_deactivate_resource(bus, type, rid, res));
+}
+
+uint8_t
+macgpio_read(device_t dev)
+{
+	struct macgpio_softc *sc;
+	struct macgpio_devinfo *dinfo;
+
+	sc = device_get_softc(device_get_parent(dev));
+	dinfo = device_get_ivars(dev);
+
+	if (dinfo->gpio_num < 0)
+		return (0);
+
+	return (bus_read_1(sc->sc_gpios,dinfo->gpio_num));
+}
+
+void
+macgpio_write(device_t dev, uint8_t val)
+{
+	struct macgpio_softc *sc;
+	struct macgpio_devinfo *dinfo;
+
+	sc = device_get_softc(device_get_parent(dev));
+	dinfo = device_get_ivars(dev);
+
+	if (dinfo->gpio_num < 0)
+		return;
+
+	bus_write_1(sc->sc_gpios,dinfo->gpio_num,val);
+}
+
+static const struct ofw_bus_devinfo *
+macgpio_get_devinfo(device_t dev, device_t child)
+{
+	struct macgpio_devinfo *dinfo;
+
+	dinfo = device_get_ivars(child);
+	return (&dinfo->mdi_obdinfo);
+}
+


Property changes on: trunk/sys/powerpc/powermac/macgpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/macgpiovar.h
===================================================================
--- trunk/sys/powerpc/powermac/macgpiovar.h	                        (rev 0)
+++ trunk/sys/powerpc/powermac/macgpiovar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,45 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2008 by Nathan Whitehorn. 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/macgpiovar.h 185757 2008-12-08 03:00:45Z nwhitehorn $
+ */
+
+#ifndef _MACIO_MACGPIOVAR_H_
+#define _MACIO_MACGPIOVAR_H_
+
+/* relative offsets into gpio space */
+#define GPIO_EXTINT_BASE	0x08
+#define GPIO_BASE		0x1a
+
+/* gpio bit definitions */
+#define GPIO_DATA		0x01 /* GPIO data */
+#define GPIO_LEVEL_RO		0x02 /* read-only level on pin */
+#define GPIO_DDR_INPUT		0x00 /* use for input */
+#define GPIO_DDR_OUTPUT		0x04 /* use for output */
+
+uint8_t	macgpio_read(device_t dev);
+void	macgpio_write(device_t dev,uint8_t);
+
+#endif /* _MACIO_MACGPIOVAR_H_ */


Property changes on: trunk/sys/powerpc/powermac/macgpiovar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/macio.c
===================================================================
--- trunk/sys/powerpc/powermac/macio.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/macio.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,703 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2002 by Peter Grehan. 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/macio.c 273652 2014-10-26 01:30:46Z ian $
+ */
+
+/*
+ * Driver for KeyLargo/Pangea, the MacPPC south bridge ASIC.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/pmap.h>
+#include <machine/resource.h>
+#include <machine/vmparam.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include <powerpc/powermac/maciovar.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+/*
+ * Macio softc
+ */
+struct macio_softc {
+	phandle_t    sc_node;
+	vm_offset_t  sc_base;
+	vm_offset_t  sc_size;
+	struct rman  sc_mem_rman;
+
+	/* FCR registers */
+	int          sc_memrid;
+	struct resource	*sc_memr;
+};
+
+static MALLOC_DEFINE(M_MACIO, "macio", "macio device information");
+
+static int  macio_probe(device_t);
+static int  macio_attach(device_t);
+static int  macio_print_child(device_t dev, device_t child);
+static void macio_probe_nomatch(device_t, device_t);
+static struct   resource *macio_alloc_resource(device_t, device_t, int, int *,
+					       u_long, u_long, u_long, u_int);
+static int  macio_activate_resource(device_t, device_t, int, int,
+				    struct resource *);
+static int  macio_deactivate_resource(device_t, device_t, int, int,
+				      struct resource *);
+static int  macio_release_resource(device_t, device_t, int, int,
+				   struct resource *);
+static struct resource_list *macio_get_resource_list (device_t, device_t);
+static ofw_bus_get_devinfo_t macio_get_devinfo;
+
+/*
+ * Bus interface definition
+ */
+static device_method_t macio_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,         macio_probe),
+	DEVMETHOD(device_attach,        macio_attach),
+	DEVMETHOD(device_detach,        bus_generic_detach),
+	DEVMETHOD(device_shutdown,      bus_generic_shutdown),
+	DEVMETHOD(device_suspend,       bus_generic_suspend),
+	DEVMETHOD(device_resume,        bus_generic_resume),
+	
+	/* Bus interface */
+	DEVMETHOD(bus_print_child,      macio_print_child),
+	DEVMETHOD(bus_probe_nomatch,    macio_probe_nomatch),
+	DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),	
+
+        DEVMETHOD(bus_alloc_resource,   macio_alloc_resource),
+        DEVMETHOD(bus_release_resource, macio_release_resource),
+        DEVMETHOD(bus_activate_resource, macio_activate_resource),
+        DEVMETHOD(bus_deactivate_resource, macio_deactivate_resource),
+        DEVMETHOD(bus_get_resource_list, macio_get_resource_list),	
+
+	DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
+
+	/* ofw_bus interface */
+	DEVMETHOD(ofw_bus_get_devinfo,	macio_get_devinfo),
+	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
+	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
+	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
+	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
+	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
+
+	{ 0, 0 }
+};
+
+static driver_t macio_pci_driver = {
+        "macio",
+        macio_methods,
+	sizeof(struct macio_softc)
+};
+
+devclass_t macio_devclass;
+
+DRIVER_MODULE(macio, pci, macio_pci_driver, macio_devclass, 0, 0);
+
+/*
+ * PCI ID search table
+ */
+static struct macio_pci_dev {
+        u_int32_t  mpd_devid;
+	char    *mpd_desc;
+} macio_pci_devlist[] = {
+	{ 0x0017106b, "Paddington I/O Controller" },
+	{ 0x0022106b, "KeyLargo I/O Controller" },
+	{ 0x0025106b, "Pangea I/O Controller" },
+	{ 0x003e106b, "Intrepid I/O Controller" },
+	{ 0x0041106b, "K2 KeyLargo I/O Controller" },
+	{ 0x004f106b, "Shasta I/O Controller" },
+	{ 0, NULL }
+};
+
+/*
+ * Devices to exclude from the probe
+ * XXX some of these may be required in the future...
+ */
+#define	MACIO_QUIRK_IGNORE		0x00000001
+#define	MACIO_QUIRK_CHILD_HAS_INTR	0x00000002
+#define	MACIO_QUIRK_USE_CHILD_REG	0x00000004
+
+struct macio_quirk_entry {
+	const char	*mq_name;
+	int		mq_quirks;
+};
+
+static struct macio_quirk_entry macio_quirks[] = {
+	{ "escc-legacy",		MACIO_QUIRK_IGNORE },
+	{ "timer",			MACIO_QUIRK_IGNORE },
+	{ "escc",			MACIO_QUIRK_CHILD_HAS_INTR },
+        { "i2s", 			MACIO_QUIRK_CHILD_HAS_INTR | 
+					MACIO_QUIRK_USE_CHILD_REG },
+	{ NULL,				0 }
+};
+
+static int
+macio_get_quirks(const char *name)
+{
+        struct	macio_quirk_entry *mqe;
+
+        for (mqe = macio_quirks; mqe->mq_name != NULL; mqe++)
+                if (strcmp(name, mqe->mq_name) == 0)
+                        return (mqe->mq_quirks);
+        return (0);
+}
+
+
+/*
+ * Add an interrupt to the dev's resource list if present
+ */
+static void
+macio_add_intr(phandle_t devnode, struct macio_devinfo *dinfo)
+{
+	phandle_t iparent;
+	int	*intr;
+	int	i, nintr;
+	int 	icells;
+
+	if (dinfo->mdi_ninterrupts >= 6) {
+		printf("macio: device has more than 6 interrupts\n");
+		return;
+	}
+
+	nintr = OF_getprop_alloc(devnode, "interrupts", sizeof(*intr), 
+		(void **)&intr);
+	if (nintr == -1) {
+		nintr = OF_getprop_alloc(devnode, "AAPL,interrupts", 
+			sizeof(*intr), (void **)&intr);
+		if (nintr == -1)
+			return;
+	}
+
+	if (intr[0] == -1)
+		return;
+
+	if (OF_getprop(devnode, "interrupt-parent", &iparent, sizeof(iparent))
+	    <= 0)
+		panic("Interrupt but no interrupt parent!\n");
+
+	if (OF_getprop(OF_node_from_xref(iparent), "#interrupt-cells", &icells,
+	    sizeof(icells)) <= 0)
+		icells = 1;
+
+	for (i = 0; i < nintr; i+=icells) {
+		u_int irq = MAP_IRQ(iparent, intr[i]);
+
+		resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ,
+		    dinfo->mdi_ninterrupts, irq, irq, 1);
+
+		dinfo->mdi_interrupts[dinfo->mdi_ninterrupts] = irq;
+		dinfo->mdi_ninterrupts++;
+	}
+}
+
+
+static void
+macio_add_reg(phandle_t devnode, struct macio_devinfo *dinfo)
+{
+	struct		macio_reg *reg, *regp;
+	phandle_t 	child;
+	char		buf[8];
+	int		i, layout_id = 0, nreg, res;
+
+	nreg = OF_getprop_alloc(devnode, "reg", sizeof(*reg), (void **)&reg);
+	if (nreg == -1)
+		return;
+
+        /*
+         *  Some G5's have broken properties in the i2s-a area. If so we try
+         *  to fix it. Right now we know of two different cases, one for
+         *  sound layout-id 36 and the other one for sound layout-id 76.
+         *  What is missing is the base address for the memory addresses.
+         *  We take them from the parent node (i2s) and use the size
+         *  information from the child. 
+         */
+
+        if (reg[0].mr_base == 0) {
+		child = OF_child(devnode);
+		while (child != 0) {
+			res = OF_getprop(child, "name", buf, sizeof(buf));
+			if (res > 0 && strcmp(buf, "sound") == 0)
+				break;
+			child = OF_peer(child);
+		}
+
+                res = OF_getprop(child, "layout-id", &layout_id,
+				sizeof(layout_id));
+
+                if (res > 0 && (layout_id == 36 || layout_id == 76)) {
+                        res = OF_getprop_alloc(OF_parent(devnode), "reg",
+						sizeof(*regp), (void **)&regp);
+                        reg[0] = regp[0];
+                        reg[1].mr_base = regp[1].mr_base;
+                        reg[2].mr_base = regp[1].mr_base + reg[1].mr_size;
+                }
+        } 
+
+	for (i = 0; i < nreg; i++) {
+		resource_list_add(&dinfo->mdi_resources, SYS_RES_MEMORY, i,
+		    reg[i].mr_base, reg[i].mr_base + reg[i].mr_size,
+		    reg[i].mr_size);
+	}
+}
+
+/*
+ * PCI probe
+ */
+static int
+macio_probe(device_t dev)
+{
+        int i;
+        u_int32_t devid;
+	
+        devid = pci_get_devid(dev);
+        for (i = 0; macio_pci_devlist[i].mpd_desc != NULL; i++) {
+                if (devid == macio_pci_devlist[i].mpd_devid) {
+                        device_set_desc(dev, macio_pci_devlist[i].mpd_desc);
+                        return (0);
+                }
+        }
+	
+        return (ENXIO);	
+}
+
+/*
+ * PCI attach: scan Open Firmware child nodes, and attach these as children
+ * of the macio bus
+ */
+static int 
+macio_attach(device_t dev)
+{
+	struct macio_softc *sc;
+        struct macio_devinfo *dinfo;
+        phandle_t  root;
+	phandle_t  child;
+	phandle_t  subchild;
+        device_t cdev;
+        u_int reg[3];
+	char compat[32];
+	int error, quirks;
+
+	sc = device_get_softc(dev);
+	root = sc->sc_node = ofw_bus_get_node(dev);
+	
+	/*
+	 * Locate the device node and it's base address
+	 */
+	if (OF_getprop(root, "assigned-addresses", 
+		       reg, sizeof(reg)) < (ssize_t)sizeof(reg)) {
+		return (ENXIO);
+	}
+
+	/* Used later to see if we have to enable the I2S part. */
+	OF_getprop(root, "compatible", compat, sizeof(compat));
+
+	sc->sc_base = reg[2];
+	sc->sc_size = MACIO_REG_SIZE;
+
+	sc->sc_memrid = PCIR_BAR(0);
+	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->sc_memrid, RF_ACTIVE);
+
+	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+	sc->sc_mem_rman.rm_descr = "MacIO Device Memory";
+	error = rman_init(&sc->sc_mem_rman);
+	if (error) {
+		device_printf(dev, "rman_init() failed. error = %d\n", error);
+		return (error);
+	}
+	error = rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size);	
+	if (error) {
+		device_printf(dev,
+		    "rman_manage_region() failed. error = %d\n", error);
+		return (error);
+	}
+
+	/*
+	 * Iterate through the sub-devices
+	 */
+	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
+		dinfo = malloc(sizeof(*dinfo), M_MACIO, M_WAITOK | M_ZERO);
+		if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo, child) !=
+		    0) {
+			free(dinfo, M_MACIO);
+			continue;
+		}
+		quirks = macio_get_quirks(dinfo->mdi_obdinfo.obd_name);
+		if ((quirks & MACIO_QUIRK_IGNORE) != 0) {
+			ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
+			free(dinfo, M_MACIO);
+			continue;
+		}
+		resource_list_init(&dinfo->mdi_resources);
+		dinfo->mdi_ninterrupts = 0;
+		macio_add_intr(child, dinfo);
+		if ((quirks & MACIO_QUIRK_USE_CHILD_REG) != 0)
+			macio_add_reg(OF_child(child), dinfo);
+		else
+			macio_add_reg(child, dinfo);
+		if ((quirks & MACIO_QUIRK_CHILD_HAS_INTR) != 0)
+			for (subchild = OF_child(child); subchild != 0;
+			    subchild = OF_peer(subchild))
+				macio_add_intr(subchild, dinfo);
+		cdev = device_add_child(dev, NULL, -1);
+		if (cdev == NULL) {
+			device_printf(dev, "<%s>: device_add_child failed\n",
+			    dinfo->mdi_obdinfo.obd_name);
+			resource_list_free(&dinfo->mdi_resources);
+			ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
+			free(dinfo, M_MACIO);
+			continue;
+		}
+		device_set_ivars(cdev, dinfo);
+
+		/* Set FCRs to enable some devices */
+		if (sc->sc_memr == NULL)
+			continue;
+
+		if (strcmp(ofw_bus_get_name(cdev), "bmac") == 0 ||
+		    strcmp(ofw_bus_get_compat(cdev), "bmac+") == 0) {
+			uint32_t fcr;
+
+			fcr = bus_read_4(sc->sc_memr, HEATHROW_FCR);
+
+			fcr |= FCR_ENET_ENABLE & ~FCR_ENET_RESET;
+			bus_write_4(sc->sc_memr, HEATHROW_FCR, fcr);
+			DELAY(50000);
+			fcr |= FCR_ENET_RESET;
+			bus_write_4(sc->sc_memr, HEATHROW_FCR, fcr);
+			DELAY(50000);
+			fcr &= ~FCR_ENET_RESET;
+			bus_write_4(sc->sc_memr, HEATHROW_FCR, fcr);
+			DELAY(50000);
+			
+			bus_write_4(sc->sc_memr, HEATHROW_FCR, fcr);
+		}
+
+		/*
+		 * Make sure the I2S0 and the I2S0_CLK are enabled.
+		 * On certain G5's they are not.
+		 */
+		if ((strcmp(ofw_bus_get_name(cdev), "i2s") == 0) &&
+		    (strcmp(compat, "K2-Keylargo") == 0)) {
+
+			uint32_t fcr1;
+
+			fcr1 = bus_read_4(sc->sc_memr, KEYLARGO_FCR1);
+			fcr1 |= FCR1_I2S0_CLK_ENABLE | FCR1_I2S0_ENABLE;
+			bus_write_4(sc->sc_memr, KEYLARGO_FCR1, fcr1);
+		}
+
+	}
+
+	return (bus_generic_attach(dev));
+}
+
+
+static int
+macio_print_child(device_t dev, device_t child)
+{
+        struct macio_devinfo *dinfo;
+        struct resource_list *rl;
+        int retval = 0;
+
+        dinfo = device_get_ivars(child);
+        rl = &dinfo->mdi_resources;
+
+        retval += bus_print_child_header(dev, child);
+
+        retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
+        retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+
+        retval += bus_print_child_footer(dev, child);
+
+        return (retval);
+}
+
+
+static void
+macio_probe_nomatch(device_t dev, device_t child)
+{
+        struct macio_devinfo *dinfo;
+        struct resource_list *rl;
+	const char *type;
+
+	if (bootverbose) {
+		dinfo = device_get_ivars(child);
+		rl = &dinfo->mdi_resources;
+
+		if ((type = ofw_bus_get_type(child)) == NULL)
+			type = "(unknown)";
+		device_printf(dev, "<%s, %s>", type, ofw_bus_get_name(child));
+		resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
+		resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+		printf(" (no driver attached)\n");
+	}
+}
+
+
+static struct resource *
+macio_alloc_resource(device_t bus, device_t child, int type, int *rid,
+		     u_long start, u_long end, u_long count, u_int flags)
+{
+	struct		macio_softc *sc;
+	int		needactivate;
+	struct		resource *rv;
+	struct		rman *rm;
+	u_long		adjstart, adjend, adjcount;
+	struct		macio_devinfo *dinfo;
+	struct		resource_list_entry *rle;
+
+	sc = device_get_softc(bus);
+	dinfo = device_get_ivars(child);
+
+	needactivate = flags & RF_ACTIVE;
+	flags &= ~RF_ACTIVE;
+
+	switch (type) {
+	case SYS_RES_MEMORY:
+	case SYS_RES_IOPORT:
+		rle = resource_list_find(&dinfo->mdi_resources, SYS_RES_MEMORY,
+		    *rid);
+		if (rle == NULL) {
+			device_printf(bus, "no rle for %s memory %d\n",
+			    device_get_nameunit(child), *rid);
+			return (NULL);
+		}
+
+		if (start < rle->start)
+			adjstart = rle->start;
+		else if (start > rle->end)
+			adjstart = rle->end;
+		else
+			adjstart = start;
+
+		if (end < rle->start)
+			adjend = rle->start;
+		else if (end > rle->end)
+			adjend = rle->end;
+		else
+			adjend = end;
+
+		adjcount = adjend - adjstart;
+
+		rm = &sc->sc_mem_rman;
+		break;
+
+	case SYS_RES_IRQ:
+		/* Check for passthrough from subattachments like macgpio */
+		if (device_get_parent(child) != bus)
+			return BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
+			    type, rid, start, end, count, flags);
+
+		rle = resource_list_find(&dinfo->mdi_resources, SYS_RES_IRQ,
+		    *rid);
+		if (rle == NULL) {
+			if (dinfo->mdi_ninterrupts >= 6) {
+				device_printf(bus,
+				    "%s has more than 6 interrupts\n",
+				    device_get_nameunit(child));
+				return (NULL);
+			}
+			resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ,
+			    dinfo->mdi_ninterrupts, start, start, 1);
+
+			dinfo->mdi_interrupts[dinfo->mdi_ninterrupts] = start;
+			dinfo->mdi_ninterrupts++;
+		}
+
+		return (resource_list_alloc(&dinfo->mdi_resources, bus, child,
+		    type, rid, start, end, count, flags));
+
+	default:
+		device_printf(bus, "unknown resource request from %s\n",
+			      device_get_nameunit(child));
+		return (NULL);
+	}
+
+	rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags,
+	    child);
+	if (rv == NULL) {
+		device_printf(bus,
+		    "failed to reserve resource %#lx - %#lx (%#lx) for %s\n",
+		    adjstart, adjend, adjcount, device_get_nameunit(child));
+		return (NULL);
+	}
+
+	rman_set_rid(rv, *rid);
+
+	if (needactivate) {
+		if (bus_activate_resource(child, type, *rid, rv) != 0) {
+                        device_printf(bus,
+				      "failed to activate resource for %s\n",
+				      device_get_nameunit(child));
+			rman_release_resource(rv);
+			return (NULL);
+                }
+        }
+
+	return (rv);
+}
+
+
+static int
+macio_release_resource(device_t bus, device_t child, int type, int rid,
+		       struct resource *res)
+{
+	if (rman_get_flags(res) & RF_ACTIVE) {
+		int error = bus_deactivate_resource(child, type, rid, res);
+		if (error)
+			return error;
+	}
+
+	return (rman_release_resource(res));
+}
+
+
+static int
+macio_activate_resource(device_t bus, device_t child, int type, int rid,
+			   struct resource *res)
+{
+	struct macio_softc *sc;
+	void    *p;
+
+	sc = device_get_softc(bus);
+
+	if (type == SYS_RES_IRQ)
+                return (bus_activate_resource(bus, type, rid, res));
+
+	if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
+		p = pmap_mapdev((vm_offset_t)rman_get_start(res) + sc->sc_base,
+				(vm_size_t)rman_get_size(res));
+		if (p == NULL)
+			return (ENOMEM);
+		rman_set_virtual(res, p);
+		rman_set_bustag(res, &bs_le_tag);
+		rman_set_bushandle(res, (u_long)p);
+	}
+
+	return (rman_activate_resource(res));
+}
+
+
+static int
+macio_deactivate_resource(device_t bus, device_t child, int type, int rid,
+			  struct resource *res)
+{
+        /*
+         * If this is a memory resource, unmap it.
+         */
+        if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
+		u_int32_t psize;
+
+		psize = rman_get_size(res);
+		pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize);
+	}
+
+	return (rman_deactivate_resource(res));
+}
+
+
+static struct resource_list *
+macio_get_resource_list (device_t dev, device_t child)
+{
+	struct macio_devinfo *dinfo;
+
+	dinfo = device_get_ivars(child);
+	return (&dinfo->mdi_resources);
+}
+
+static const struct ofw_bus_devinfo *
+macio_get_devinfo(device_t dev, device_t child)
+{
+	struct macio_devinfo *dinfo;
+
+	dinfo = device_get_ivars(child);
+	return (&dinfo->mdi_obdinfo);
+}
+
+int
+macio_enable_wireless(device_t dev, bool enable)
+{
+	struct macio_softc *sc = device_get_softc(dev);
+	uint32_t x;
+
+	if (enable) {
+		x = bus_read_4(sc->sc_memr, KEYLARGO_FCR2);
+		x |= 0x4;
+		bus_write_4(sc->sc_memr, KEYLARGO_FCR2, x);
+
+		/* Enable card slot. */
+		bus_write_1(sc->sc_memr, KEYLARGO_GPIO_BASE + 0x0f, 5);
+		DELAY(1000);
+		bus_write_1(sc->sc_memr, KEYLARGO_GPIO_BASE + 0x0f, 4);
+		DELAY(1000);
+		x = bus_read_4(sc->sc_memr, KEYLARGO_FCR2);
+		x &= ~0x80000000;
+
+		bus_write_4(sc->sc_memr, KEYLARGO_FCR2, x);
+		/* out8(gpio + 0x10, 4); */
+
+		bus_write_1(sc->sc_memr, KEYLARGO_EXTINT_GPIO_REG_BASE + 0x0b, 0);
+		bus_write_1(sc->sc_memr, KEYLARGO_EXTINT_GPIO_REG_BASE + 0x0a, 0x28);
+		bus_write_1(sc->sc_memr, KEYLARGO_EXTINT_GPIO_REG_BASE + 0x0d, 0x28);
+		bus_write_1(sc->sc_memr, KEYLARGO_GPIO_BASE + 0x0d, 0x28);
+		bus_write_1(sc->sc_memr, KEYLARGO_GPIO_BASE + 0x0e, 0x28);
+		bus_write_4(sc->sc_memr, 0x1c000, 0);
+
+		/* Initialize the card. */
+		bus_write_4(sc->sc_memr, 0x1a3e0, 0x41);
+		x = bus_read_4(sc->sc_memr, KEYLARGO_FCR2);
+		x |= 0x80000000;
+		bus_write_4(sc->sc_memr, KEYLARGO_FCR2, x);
+	} else {
+		x = bus_read_4(sc->sc_memr, KEYLARGO_FCR2);
+		x &= ~0x4;
+		bus_write_4(sc->sc_memr, KEYLARGO_FCR2, x);
+		/* out8(gpio + 0x10, 0); */
+	}
+
+	return (0);
+}


Property changes on: trunk/sys/powerpc/powermac/macio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/maciovar.h
===================================================================
--- trunk/sys/powerpc/powermac/maciovar.h	                        (rev 0)
+++ trunk/sys/powerpc/powermac/maciovar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,80 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2002 by Peter Grehan. 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/maciovar.h 264375 2014-04-12 19:57:15Z andreast $
+ */
+
+#ifndef _MACIO_MACIOVAR_H_
+#define _MACIO_MACIOVAR_H_
+
+/*
+ * The addr space size
+ * XXX it would be better if this could be determined by querying the
+ *     PCI device, but there isn't an access method for this
+ */
+#define MACIO_REG_SIZE  0x7ffff
+
+/*
+ * Feature Control Registers (FCR)
+ */
+#define HEATHROW_FCR	0x38
+#define KEYLARGO_FCR0	0x38
+#define KEYLARGO_FCR1	0x3c
+#define KEYLARGO_FCR2	0x40
+
+#define FCR_ENET_ENABLE	0x60000000
+#define FCR_ENET_RESET	0x80000000
+
+#define FCR1_I2S0_CLK_ENABLE	0x00001000
+#define FCR1_I2S0_ENABLE	0x00002000
+
+/* Used only by macio_enable_wireless() for now. */
+#define KEYLARGO_GPIO_BASE	0x6a
+#define KEYLARGO_EXTINT_GPIO_REG_BASE	0x58
+
+/*
+ * Format of a macio reg property entry.
+ */
+struct macio_reg {
+	u_int32_t	mr_base;
+	u_int32_t	mr_size;
+};
+
+/*
+ * Per macio device structure.
+ */
+struct macio_devinfo {
+	int        mdi_interrupts[6];
+	int	   mdi_ninterrupts;
+	int        mdi_base;
+	struct ofw_bus_devinfo mdi_obdinfo;
+	struct resource_list mdi_resources;
+};
+
+extern int macio_enable_wireless(device_t dev, bool enable);
+
+#endif /* _MACIO_MACIOVAR_H_ */


Property changes on: trunk/sys/powerpc/powermac/maciovar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/nvbl.c
===================================================================
--- trunk/sys/powerpc/powermac/nvbl.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/nvbl.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,200 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Justin Hibbits
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/nvbl.c 261455 2014-02-04 03:36:42Z eadler $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+
+#include <dev/ofw/openfirm.h>
+
+#define NVIDIA_BRIGHT_MIN     (0x0ec)
+#define NVIDIA_BRIGHT_MAX     (0x538)
+#define NVIDIA_BRIGHT_SCALE   ((NVIDIA_BRIGHT_MAX - NVIDIA_BRIGHT_MIN)/100)
+/* nVidia's MMIO registers are at PCI BAR[0] */
+#define NVIDIA_MMIO_PMC       (0x0)
+#define  NVIDIA_PMC_OFF         (NVIDIA_MMIO_PMC + 0x10f0)
+#define   NVIDIA_PMC_BL_SHIFT    (16)
+#define   NVIDIA_PMC_BL_EN       (1U << 31)
+
+
+struct nvbl_softc {
+	device_t	 dev;
+	struct resource *sc_memr;
+};
+
+static void nvbl_identify(driver_t *driver, device_t parent);
+static int nvbl_probe(device_t dev);
+static int nvbl_attach(device_t dev);
+static int nvbl_setlevel(struct nvbl_softc *sc, int newlevel);
+static int nvbl_getlevel(struct nvbl_softc *sc);
+static int nvbl_sysctl(SYSCTL_HANDLER_ARGS);
+
+static device_method_t nvbl_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_identify, nvbl_identify),
+	DEVMETHOD(device_probe, nvbl_probe),
+	DEVMETHOD(device_attach, nvbl_attach),
+	{0, 0},
+};
+
+static driver_t	nvbl_driver = {
+	"backlight",
+	nvbl_methods,
+	sizeof(struct nvbl_softc)
+};
+
+static devclass_t nvbl_devclass;
+
+DRIVER_MODULE(nvbl, vgapci, nvbl_driver, nvbl_devclass, 0, 0);
+
+static void
+nvbl_identify(driver_t *driver, device_t parent)
+{
+	if (OF_finddevice("mac-io/backlight") == -1)
+		return;
+	if (device_find_child(parent, "backlight", -1) == NULL)
+		device_add_child(parent, "backlight", -1);
+}
+
+static int
+nvbl_probe(device_t dev)
+{
+	char		control[8];
+	phandle_t	handle;
+
+	handle = OF_finddevice("mac-io/backlight");
+
+	if (handle == -1)
+		return (ENXIO);
+
+	if (OF_getprop(handle, "backlight-control", &control, sizeof(control)) < 0)
+		return (ENXIO);
+
+	if (strcmp(control, "mnca") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "PowerBook backlight for nVidia graphics");
+
+	return (0);
+}
+
+static int
+nvbl_attach(device_t dev)
+{
+	struct nvbl_softc	*sc;
+	struct sysctl_ctx_list *ctx;
+	struct sysctl_oid *tree;
+	int			 rid;
+
+	sc = device_get_softc(dev);
+
+	rid = 0x10;	/* BAR[0], for the MMIO register */
+	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+			RF_ACTIVE | RF_SHAREABLE);
+	if (sc->sc_memr == NULL) {
+		device_printf(dev, "Could not alloc mem resource!\n");
+		return (ENXIO);
+	}
+
+	/* Turn on big-endian mode */
+	if (!(bus_read_stream_4(sc->sc_memr, NVIDIA_MMIO_PMC + 4) & 0x01000001)) {
+		bus_write_stream_4(sc->sc_memr, NVIDIA_MMIO_PMC + 4, 0x01000001);
+		mb();
+	}
+
+	ctx = device_get_sysctl_ctx(dev);
+	tree = device_get_sysctl_tree(dev);
+
+	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+			"level", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+			nvbl_sysctl, "I", "Backlight level (0-100)");
+
+	return (0);
+}
+
+static int
+nvbl_setlevel(struct nvbl_softc *sc, int newlevel)
+{
+	uint32_t pmc_reg;
+
+	if (newlevel > 100)
+		newlevel = 100;
+
+	if (newlevel < 0)
+		newlevel = 0;
+
+	if (newlevel > 0)
+		newlevel = (newlevel * NVIDIA_BRIGHT_SCALE) + NVIDIA_BRIGHT_MIN;
+
+	pmc_reg = bus_read_stream_4(sc->sc_memr, NVIDIA_PMC_OFF) & 0xffff;
+	pmc_reg |= NVIDIA_PMC_BL_EN | (newlevel << NVIDIA_PMC_BL_SHIFT);
+	bus_write_stream_4(sc->sc_memr, NVIDIA_PMC_OFF, pmc_reg);
+
+	return (0);
+}
+
+static int
+nvbl_getlevel(struct nvbl_softc *sc)
+{
+	uint16_t level;
+
+	level = bus_read_stream_2(sc->sc_memr, NVIDIA_PMC_OFF) & 0x7fff;
+
+	if (level  < NVIDIA_BRIGHT_MIN)
+		return 0;
+
+	level = (level - NVIDIA_BRIGHT_MIN) / NVIDIA_BRIGHT_SCALE;
+
+	return (level);
+}
+
+static int
+nvbl_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	struct nvbl_softc *sc;
+	int newlevel, error;
+
+	sc = arg1;
+
+	newlevel = nvbl_getlevel(sc);
+
+	error = sysctl_handle_int(oidp, &newlevel, 0, req);
+
+	if (error || !req->newptr)
+		return (error);
+
+	return (nvbl_setlevel(sc, newlevel));
+}


Property changes on: trunk/sys/powerpc/powermac/nvbl.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/platform_powermac.c
===================================================================
--- trunk/sys/powerpc/powermac/platform_powermac.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/platform_powermac.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,396 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Marcel Moolenaar
+ * Copyright (c) 2009 Nathan Whitehorn
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/platform_powermac.c 266020 2014-05-14 14:17:51Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/altivec.h>	/* For save_vec() */
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/fpu.h>	/* For save_fpu() */
+#include <machine/hid.h>
+#include <machine/platformvar.h>
+#include <machine/pmap.h>
+#include <machine/setjmp.h>
+#include <machine/smp.h>
+#include <machine/spr.h>
+
+#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
+
+#include "platform_if.h"
+
+extern void *ap_pcpu;
+
+static int powermac_probe(platform_t);
+static int powermac_attach(platform_t);
+void powermac_mem_regions(platform_t, struct mem_region *phys, int *physsz,
+    struct mem_region *avail, int *availsz);
+static u_long powermac_timebase_freq(platform_t, struct cpuref *cpuref);
+static int powermac_smp_first_cpu(platform_t, struct cpuref *cpuref);
+static int powermac_smp_next_cpu(platform_t, struct cpuref *cpuref);
+static int powermac_smp_get_bsp(platform_t, struct cpuref *cpuref);
+static int powermac_smp_start_cpu(platform_t, struct pcpu *cpu);
+static void powermac_reset(platform_t);
+static void powermac_sleep(platform_t);
+
+static platform_method_t powermac_methods[] = {
+	PLATFORMMETHOD(platform_probe, 		powermac_probe),
+	PLATFORMMETHOD(platform_attach,		powermac_attach),
+	PLATFORMMETHOD(platform_mem_regions,	powermac_mem_regions),
+	PLATFORMMETHOD(platform_timebase_freq,	powermac_timebase_freq),
+	
+	PLATFORMMETHOD(platform_smp_first_cpu,	powermac_smp_first_cpu),
+	PLATFORMMETHOD(platform_smp_next_cpu,	powermac_smp_next_cpu),
+	PLATFORMMETHOD(platform_smp_get_bsp,	powermac_smp_get_bsp),
+	PLATFORMMETHOD(platform_smp_start_cpu,	powermac_smp_start_cpu),
+
+	PLATFORMMETHOD(platform_reset,		powermac_reset),
+	PLATFORMMETHOD(platform_sleep,		powermac_sleep),
+
+	PLATFORMMETHOD_END
+};
+
+static platform_def_t powermac_platform = {
+	"powermac",
+	powermac_methods,
+	0
+};
+
+PLATFORM_DEF(powermac_platform);
+
+static int
+powermac_probe(platform_t plat)
+{
+	char compat[255];
+	ssize_t compatlen;
+	char *curstr;
+	phandle_t root;
+
+	root = OF_peer(0);
+	if (root == 0)
+		return (ENXIO);
+
+	compatlen = OF_getprop(root, "compatible", compat, sizeof(compat));
+	
+	for (curstr = compat; curstr < compat + compatlen;
+	    curstr += strlen(curstr) + 1) {
+		if (strncmp(curstr, "MacRISC", 7) == 0)
+			return (BUS_PROBE_SPECIFIC);
+	}
+
+	return (ENXIO);
+}
+
+void
+powermac_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
+    struct mem_region *avail, int *availsz)
+{
+	phandle_t memory;
+	cell_t memoryprop[PHYS_AVAIL_SZ * 2];
+	ssize_t propsize, i, j;
+	int physacells = 1;
+
+	memory = OF_finddevice("/memory");
+
+	/* "reg" has variable #address-cells, but #size-cells is always 1 */
+	OF_getprop(OF_parent(memory), "#address-cells", &physacells,
+	    sizeof(physacells));
+
+	propsize = OF_getprop(memory, "reg", memoryprop, sizeof(memoryprop));
+	propsize /= sizeof(cell_t);
+	for (i = 0, j = 0; i < propsize; i += physacells+1, j++) {
+		phys[j].mr_start = memoryprop[i];
+		if (physacells == 2) {
+#ifndef __powerpc64__
+			/* On 32-bit PPC, ignore regions starting above 4 GB */
+			if (memoryprop[i] != 0) {
+				j--;
+				continue;
+			}
+#else
+			phys[j].mr_start <<= 32;
+#endif
+			phys[j].mr_start |= memoryprop[i+1];
+		}
+		phys[j].mr_size = memoryprop[i + physacells];
+	}
+	*physsz = j;
+
+	/* "available" always has #address-cells = 1 */
+	propsize = OF_getprop(memory, "available", memoryprop,
+	    sizeof(memoryprop));
+	propsize /= sizeof(cell_t);
+	for (i = 0, j = 0; i < propsize; i += 2, j++) {
+		avail[j].mr_start = memoryprop[i];
+		avail[j].mr_size = memoryprop[i + 1];
+	}
+
+#ifdef __powerpc64__
+	/* Add in regions above 4 GB to the available list */
+	for (i = 0; i < *physsz; i++) {
+		if (phys[i].mr_start > BUS_SPACE_MAXADDR_32BIT) {
+			avail[j].mr_start = phys[i].mr_start;
+			avail[j].mr_size = phys[i].mr_size;
+			j++;
+		}
+	}
+#endif
+	*availsz = j;
+}
+
+static int
+powermac_attach(platform_t plat)
+{
+	phandle_t rootnode;
+	char model[32];
+
+
+	/*
+	 * Quiesce Open Firmware on PowerMac11,2 and 12,1. It is
+	 * necessary there to shut down a background thread doing fan
+	 * management, and is harmful on other machines (it will make OF
+	 * shut off power to various system components it had turned on).
+	 *
+	 * Note: we don't need to worry about which OF module we are
+	 * using since this is called only from very early boot, within
+	 * OF's boot context.
+	 */
+
+	rootnode = OF_finddevice("/");
+	if (OF_getprop(rootnode, "model", model, sizeof(model)) > 0) {
+		if (strcmp(model, "PowerMac11,2") == 0 ||
+		    strcmp(model, "PowerMac12,1") == 0) {
+			ofw_quiesce();
+		}
+	}
+
+	return (0);
+}
+
+static u_long
+powermac_timebase_freq(platform_t plat, struct cpuref *cpuref)
+{
+	phandle_t phandle;
+	int32_t ticks = -1;
+
+	phandle = cpuref->cr_hwref;
+
+	OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks));
+
+	if (ticks <= 0)
+		panic("Unable to determine timebase frequency!");
+
+	return (ticks);
+}
+
+
+static int
+powermac_smp_fill_cpuref(struct cpuref *cpuref, phandle_t cpu)
+{
+	cell_t cpuid;
+	int res;
+
+	cpuref->cr_hwref = cpu;
+	res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid));
+
+	/*
+	 * psim doesn't have a reg property, so assume 0 as for the
+	 * uniprocessor case in the CHRP spec. 
+	 */
+	if (res < 0) {
+		cpuid = 0;
+	}
+
+	cpuref->cr_cpuid = cpuid & 0xff;
+	return (0);
+}
+
+static int
+powermac_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
+{
+	char buf[8];
+	phandle_t cpu, dev, root;
+	int res;
+
+	root = OF_peer(0);
+
+	dev = OF_child(root);
+	while (dev != 0) {
+		res = OF_getprop(dev, "name", buf, sizeof(buf));
+		if (res > 0 && strcmp(buf, "cpus") == 0)
+			break;
+		dev = OF_peer(dev);
+	}
+	if (dev == 0) {
+		/*
+		 * psim doesn't have a name property on the /cpus node,
+		 * but it can be found directly
+		 */
+		dev = OF_finddevice("/cpus");
+		if (dev == -1)
+			return (ENOENT);
+	}
+
+	cpu = OF_child(dev);
+
+	while (cpu != 0) {
+		res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
+		if (res > 0 && strcmp(buf, "cpu") == 0)
+			break;
+		cpu = OF_peer(cpu);
+	}
+	if (cpu == 0)
+		return (ENOENT);
+
+	return (powermac_smp_fill_cpuref(cpuref, cpu));
+}
+
+static int
+powermac_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
+{
+	char buf[8];
+	phandle_t cpu;
+	int res;
+
+	cpu = OF_peer(cpuref->cr_hwref);
+	while (cpu != 0) {
+		res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
+		if (res > 0 && strcmp(buf, "cpu") == 0)
+			break;
+		cpu = OF_peer(cpu);
+	}
+	if (cpu == 0)
+		return (ENOENT);
+
+	return (powermac_smp_fill_cpuref(cpuref, cpu));
+}
+
+static int
+powermac_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
+{
+	ihandle_t inst;
+	phandle_t bsp, chosen;
+	int res;
+
+	chosen = OF_finddevice("/chosen");
+	if (chosen == -1)
+		return (ENXIO);
+
+	res = OF_getprop(chosen, "cpu", &inst, sizeof(inst));
+	if (res < 0)
+		return (ENXIO);
+
+	bsp = OF_instance_to_package(inst);
+	return (powermac_smp_fill_cpuref(cpuref, bsp));
+}
+
+static int
+powermac_smp_start_cpu(platform_t plat, struct pcpu *pc)
+{
+#ifdef SMP
+	phandle_t cpu;
+	volatile uint8_t *rstvec;
+	static volatile uint8_t *rstvec_virtbase = NULL;
+	int res, reset, timeout;
+
+	cpu = pc->pc_hwref;
+	res = OF_getprop(cpu, "soft-reset", &reset, sizeof(reset));
+	if (res < 0) {
+		reset = 0x58;
+
+		switch (pc->pc_cpuid) {
+		case 0:
+			reset += 0x03;
+			break;
+		case 1:
+			reset += 0x04;
+			break;
+		case 2:
+			reset += 0x0f;
+			break;
+		case 3:
+			reset += 0x10;
+			break;
+		default:
+			return (ENXIO);
+		}
+	}
+
+	ap_pcpu = pc;
+
+	if (rstvec_virtbase == NULL)
+		rstvec_virtbase = pmap_mapdev(0x80000000, PAGE_SIZE);
+
+	rstvec = rstvec_virtbase + reset;
+
+	*rstvec = 4;
+	powerpc_sync();
+	(void)(*rstvec);
+	powerpc_sync();
+	DELAY(1);
+	*rstvec = 0;
+	powerpc_sync();
+	(void)(*rstvec);
+	powerpc_sync();
+
+	timeout = 10000;
+	while (!pc->pc_awake && timeout--)
+		DELAY(100);
+
+	return ((pc->pc_awake) ? 0 : EBUSY);
+#else
+	/* No SMP support */
+	return (ENXIO);
+#endif
+}
+
+static void
+powermac_reset(platform_t platform)
+{
+	OF_reboot();
+}
+
+void
+powermac_sleep(platform_t platform)
+{
+
+	*(unsigned long *)0x80 = 0x100;
+	cpu_sleep();
+}
+


Property changes on: trunk/sys/powerpc/powermac/platform_powermac.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/pmu.c
===================================================================
--- trunk/sys/powerpc/powermac/pmu.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/pmu.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,1056 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Michael Lorenz
+ * Copyright 2008 by Nathan Whitehorn
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/pmu.c 262675 2014-03-02 02:35:46Z jhibbits $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/clock.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/sysctl.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/led/led.h>
+
+#include <machine/_inttypes.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/hid.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <sys/rman.h>
+
+#include <dev/adb/adb.h>
+
+#include "clock_if.h"
+#include "pmuvar.h"
+#include "viareg.h"
+#include "uninorthvar.h"	/* For unin_chip_sleep()/unin_chip_wake() */
+
+#define PMU_DEFAULTS	PMU_INT_TICK | PMU_INT_ADB | \
+	PMU_INT_PCEJECT | PMU_INT_SNDBRT | \
+	PMU_INT_BATTERY | PMU_INT_ENVIRONMENT
+
+/*
+ * Bus interface
+ */
+static int	pmu_probe(device_t);
+static int	pmu_attach(device_t);
+static int	pmu_detach(device_t);
+
+/*
+ * Clock interface
+ */
+static int	pmu_gettime(device_t dev, struct timespec *ts);
+static int	pmu_settime(device_t dev, struct timespec *ts);
+
+/*
+ * ADB Interface
+ */
+
+static u_int	pmu_adb_send(device_t dev, u_char command_byte, int len, 
+		    u_char *data, u_char poll);
+static u_int	pmu_adb_autopoll(device_t dev, uint16_t mask);
+static u_int	pmu_poll(device_t dev);
+
+/*
+ * Power interface
+ */
+
+static void	pmu_shutdown(void *xsc, int howto);
+static void	pmu_set_sleepled(void *xsc, int onoff);
+static int	pmu_server_mode(SYSCTL_HANDLER_ARGS);
+static int	pmu_acline_state(SYSCTL_HANDLER_ARGS);
+static int	pmu_query_battery(struct pmu_softc *sc, int batt, 
+		    struct pmu_battstate *info);
+static int	pmu_battquery_sysctl(SYSCTL_HANDLER_ARGS);
+
+/*
+ * List of battery-related sysctls we might ask for
+ */
+
+enum {
+	PMU_BATSYSCTL_PRESENT	= 1 << 8,
+	PMU_BATSYSCTL_CHARGING	= 2 << 8,
+	PMU_BATSYSCTL_CHARGE	= 3 << 8,
+	PMU_BATSYSCTL_MAXCHARGE = 4 << 8,
+	PMU_BATSYSCTL_CURRENT	= 5 << 8,
+	PMU_BATSYSCTL_VOLTAGE	= 6 << 8,
+	PMU_BATSYSCTL_TIME	= 7 << 8,
+	PMU_BATSYSCTL_LIFE	= 8 << 8
+};
+
+static device_method_t  pmu_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		pmu_probe),
+	DEVMETHOD(device_attach,	pmu_attach),
+        DEVMETHOD(device_detach,        pmu_detach),
+        DEVMETHOD(device_shutdown,      bus_generic_shutdown),
+
+	/* ADB bus interface */
+	DEVMETHOD(adb_hb_send_raw_packet,   pmu_adb_send),
+	DEVMETHOD(adb_hb_controller_poll,   pmu_poll),
+	DEVMETHOD(adb_hb_set_autopoll_mask, pmu_adb_autopoll),
+
+	/* Clock interface */
+	DEVMETHOD(clock_gettime,	pmu_gettime),
+	DEVMETHOD(clock_settime,	pmu_settime),
+
+	DEVMETHOD_END
+};
+
+static driver_t pmu_driver = {
+	"pmu",
+	pmu_methods,
+	sizeof(struct pmu_softc),
+};
+
+static devclass_t pmu_devclass;
+
+DRIVER_MODULE(pmu, macio, pmu_driver, pmu_devclass, 0, 0);
+DRIVER_MODULE(adb, pmu, adb_driver, adb_devclass, 0, 0);
+
+static int	pmuextint_probe(device_t);
+static int	pmuextint_attach(device_t);
+
+static device_method_t  pmuextint_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		pmuextint_probe),
+	DEVMETHOD(device_attach,	pmuextint_attach),
+	
+	{0,0}
+};
+
+static driver_t pmuextint_driver = {
+	"pmuextint",
+	pmuextint_methods,
+	0
+};
+
+static devclass_t pmuextint_devclass;
+
+DRIVER_MODULE(pmuextint, macgpio, pmuextint_driver, pmuextint_devclass, 0, 0);
+
+/* Make sure uhid is loaded, as it turns off some of the ADB emulation */
+MODULE_DEPEND(pmu, usb, 1, 1, 1);
+
+static void pmu_intr(void *arg);
+static void pmu_in(struct pmu_softc *sc);
+static void pmu_out(struct pmu_softc *sc);
+static void pmu_ack_on(struct pmu_softc *sc);
+static void pmu_ack_off(struct pmu_softc *sc);
+static int pmu_send(void *cookie, int cmd, int length, uint8_t *in_msg,
+	int rlen, uint8_t *out_msg);
+static uint8_t pmu_read_reg(struct pmu_softc *sc, u_int offset);
+static void pmu_write_reg(struct pmu_softc *sc, u_int offset, uint8_t value);
+static int pmu_intr_state(struct pmu_softc *);
+
+/* these values shows that number of data returned after 'send' cmd is sent */
+static signed char pm_send_cmd_type[] = {
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x01, 0x01,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x00, 0x00,   -1,   -1,   -1,   -1,   -1, 0x00,
+	  -1, 0x00, 0x02, 0x01, 0x01,   -1,   -1,   -1,
+	0x00,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x04, 0x14,   -1, 0x03,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x02, 0x02,   -1,   -1,   -1,   -1,
+	0x01, 0x01,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x00, 0x00,   -1,   -1, 0x01,   -1,   -1,   -1,
+	0x01, 0x00, 0x02, 0x02,   -1, 0x01, 0x03, 0x01,
+	0x00, 0x01, 0x00, 0x00, 0x00,   -1,   -1,   -1,
+	0x02,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   -1,   -1,
+	0x01, 0x01, 0x01,   -1,   -1,   -1,   -1,   -1,
+	0x00, 0x00,   -1,   -1,   -1, 0x05, 0x04, 0x04,
+	0x04,   -1, 0x00,   -1,   -1,   -1,   -1,   -1,
+	0x00,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x01, 0x02,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x00, 0x00,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x02, 0x02, 0x02, 0x04,   -1, 0x00,   -1,   -1,
+	0x01, 0x01, 0x03, 0x02,   -1,   -1,   -1,   -1,
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x00,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x01, 0x01,   -1,   -1, 0x00, 0x00,   -1,   -1,
+	  -1, 0x04, 0x00,   -1,   -1,   -1,   -1,   -1,
+	0x03,   -1, 0x00,   -1, 0x00,   -1,   -1, 0x00,
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1
+};
+
+/* these values shows that number of data returned after 'receive' cmd is sent */
+static signed char pm_receive_cmd_type[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02,   -1,   -1,   -1,   -1,   -1, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x05, 0x15,   -1, 0x02,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x03, 0x03,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x04, 0x04, 0x03, 0x09,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  -1,   -1,   -1,   -1,   -1, 0x01, 0x01, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x06,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x02,   -1,   -1, 0x02,   -1,   -1,   -1,
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  -1,   -1, 0x02,   -1,   -1,   -1,   -1, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+};
+
+/* We only have one of each device, so globals are safe */
+static device_t pmu = NULL;
+static device_t pmu_extint = NULL;
+
+static int
+pmuextint_probe(device_t dev)
+{
+	const char *type = ofw_bus_get_type(dev);
+
+	if (strcmp(type, "extint-gpio1") != 0)
+                return (ENXIO);
+
+	device_set_desc(dev, "Apple PMU99 External Interrupt");
+	return (0);
+}
+
+static int
+pmu_probe(device_t dev)
+{
+	const char *type = ofw_bus_get_type(dev);
+
+	if (strcmp(type, "via-pmu") != 0)
+                return (ENXIO);
+
+	device_set_desc(dev, "Apple PMU99 Controller");
+	return (0);
+}
+
+
+static int
+setup_pmu_intr(device_t dev, device_t extint)
+{
+	struct pmu_softc *sc;
+	sc = device_get_softc(dev);
+
+	sc->sc_irqrid = 0;
+	sc->sc_irq = bus_alloc_resource_any(extint, SYS_RES_IRQ, &sc->sc_irqrid,
+           	RF_ACTIVE);
+        if (sc->sc_irq == NULL) {
+                device_printf(dev, "could not allocate interrupt\n");
+                return (ENXIO);
+        }
+
+	if (bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE 
+	    | INTR_ENTROPY, NULL, pmu_intr, dev, &sc->sc_ih) != 0) {
+                device_printf(dev, "could not setup interrupt\n");
+                bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid,
+                    sc->sc_irq);
+                return (ENXIO);
+        }
+
+	return (0);
+}
+
+static int
+pmuextint_attach(device_t dev)
+{
+	pmu_extint = dev;
+	if (pmu)
+		return (setup_pmu_intr(pmu,dev));
+
+	return (0);
+}
+
+static int
+pmu_attach(device_t dev)
+{
+	struct pmu_softc *sc;
+
+	int i;
+	uint8_t reg;
+	uint8_t cmd[2] = {2, 0};
+	uint8_t resp[16];
+	phandle_t node,child;
+	struct sysctl_ctx_list *ctx;
+	struct sysctl_oid *tree;
+	
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+	
+	sc->sc_memrid = 0;
+	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 
+		          &sc->sc_memrid, RF_ACTIVE);
+
+	mtx_init(&sc->sc_mutex,"pmu",NULL,MTX_DEF | MTX_RECURSE);
+
+	if (sc->sc_memr == NULL) {
+		device_printf(dev, "Could not alloc mem resource!\n");
+		return (ENXIO);
+	}
+
+	/*
+	 * Our interrupt is attached to a GPIO pin. Depending on probe order,
+	 * we may not have found it yet. If we haven't, it will find us, and
+	 * attach our interrupt then.
+	 */
+	pmu = dev;
+	if (pmu_extint != NULL) {
+		if (setup_pmu_intr(dev,pmu_extint) != 0)
+			return (ENXIO);
+	}
+
+	sc->sc_autopoll = 0;
+	sc->sc_batteries = 0;
+	sc->adb_bus = NULL;
+	sc->sc_leddev = NULL;
+
+	/* Init PMU */
+
+	pmu_write_reg(sc, vBufB, pmu_read_reg(sc, vBufB) | vPB4);
+	pmu_write_reg(sc, vDirB, (pmu_read_reg(sc, vDirB) | vPB4) & ~vPB3);
+
+	reg = PMU_DEFAULTS;
+	pmu_send(sc, PMU_SET_IMASK, 1, &reg, 16, resp);
+
+	pmu_write_reg(sc, vIER, 0x94); /* make sure VIA interrupts are on */
+
+	pmu_send(sc, PMU_SYSTEM_READY, 1, cmd, 16, resp);
+	pmu_send(sc, PMU_GET_VERSION, 0, cmd, 16, resp);
+
+	/* Initialize child buses (ADB) */
+	node = ofw_bus_get_node(dev);
+
+	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
+		char name[32];
+
+		memset(name, 0, sizeof(name));
+		OF_getprop(child, "name", name, sizeof(name));
+
+		if (bootverbose)
+			device_printf(dev, "PMU child <%s>\n",name);
+
+		if (strncmp(name, "adb", 4) == 0) {
+			sc->adb_bus = device_add_child(dev,"adb",-1);
+		}
+
+		if (strncmp(name, "power-mgt", 9) == 0) {
+			uint32_t prim_info[9];
+
+			if (OF_getprop(child, "prim-info", prim_info, 
+			    sizeof(prim_info)) >= 7) 
+				sc->sc_batteries = (prim_info[6] >> 16) & 0xff;
+
+			if (bootverbose && sc->sc_batteries > 0)
+				device_printf(dev, "%d batteries detected\n",
+				    sc->sc_batteries);
+		}
+	}
+
+	/*
+	 * Set up sysctls
+	 */
+
+	ctx = device_get_sysctl_ctx(dev);
+	tree = device_get_sysctl_tree(dev);
+
+	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+	    "server_mode", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+	    pmu_server_mode, "I", "Enable reboot after power failure");
+
+	if (sc->sc_batteries > 0) {
+		struct sysctl_oid *oid, *battroot;
+		char battnum[2];
+
+		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+		    "acline", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
+		    pmu_acline_state, "I", "AC Line Status");
+
+		battroot = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+		    "batteries", CTLFLAG_RD, 0, "Battery Information");
+
+		for (i = 0; i < sc->sc_batteries; i++) {
+			battnum[0] = i + '0';
+			battnum[1] = '\0';
+
+			oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(battroot),
+			    OID_AUTO, battnum, CTLFLAG_RD, 0, 
+			    "Battery Information");
+		
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+			    "present", CTLTYPE_INT | CTLFLAG_RD, sc, 
+			    PMU_BATSYSCTL_PRESENT | i, pmu_battquery_sysctl, 
+			    "I", "Battery present");
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+			    "charging", CTLTYPE_INT | CTLFLAG_RD, sc,
+			    PMU_BATSYSCTL_CHARGING | i, pmu_battquery_sysctl, 
+			    "I", "Battery charging");
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+			    "charge", CTLTYPE_INT | CTLFLAG_RD, sc,
+			    PMU_BATSYSCTL_CHARGE | i, pmu_battquery_sysctl, 
+			    "I", "Battery charge (mAh)");
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+			    "maxcharge", CTLTYPE_INT | CTLFLAG_RD, sc,
+			    PMU_BATSYSCTL_MAXCHARGE | i, pmu_battquery_sysctl, 
+			    "I", "Maximum battery capacity (mAh)");
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+			    "rate", CTLTYPE_INT | CTLFLAG_RD, sc,
+			    PMU_BATSYSCTL_CURRENT | i, pmu_battquery_sysctl, 
+			    "I", "Battery discharge rate (mA)");
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+			    "voltage", CTLTYPE_INT | CTLFLAG_RD, sc,
+			    PMU_BATSYSCTL_VOLTAGE | i, pmu_battquery_sysctl, 
+			    "I", "Battery voltage (mV)");
+
+			/* Knobs for mental compatibility with ACPI */
+
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+			    "time", CTLTYPE_INT | CTLFLAG_RD, sc,
+			    PMU_BATSYSCTL_TIME | i, pmu_battquery_sysctl, 
+			    "I", "Time Remaining (minutes)");
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+			    "life", CTLTYPE_INT | CTLFLAG_RD, sc,
+			    PMU_BATSYSCTL_LIFE | i, pmu_battquery_sysctl, 
+			    "I", "Capacity remaining (percent)");
+		}
+	}
+
+	/*
+	 * Set up LED interface
+	 */
+
+	sc->sc_leddev = led_create(pmu_set_sleepled, sc, "sleepled");
+
+	/*
+	 * Register RTC
+	 */
+
+	clock_register(dev, 1000);
+
+	/*
+	 * Register power control handler
+	 */
+	EVENTHANDLER_REGISTER(shutdown_final, pmu_shutdown, sc,
+	    SHUTDOWN_PRI_LAST);
+
+	return (bus_generic_attach(dev));
+}
+
+static int 
+pmu_detach(device_t dev) 
+{
+	struct pmu_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	if (sc->sc_leddev != NULL)
+		led_destroy(sc->sc_leddev);
+
+	bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih);
+	bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid, sc->sc_irq);
+	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_memrid, sc->sc_memr);
+	mtx_destroy(&sc->sc_mutex);
+
+	return (bus_generic_detach(dev));
+}
+
+static uint8_t
+pmu_read_reg(struct pmu_softc *sc, u_int offset) 
+{
+	return (bus_read_1(sc->sc_memr, offset));
+}
+
+static void
+pmu_write_reg(struct pmu_softc *sc, u_int offset, uint8_t value) 
+{
+	bus_write_1(sc->sc_memr, offset, value);
+}
+
+static int
+pmu_send_byte(struct pmu_softc *sc, uint8_t data)
+{
+
+	pmu_out(sc);
+	pmu_write_reg(sc, vSR, data);
+	pmu_ack_off(sc);
+	/* wait for intr to come up */
+	/* XXX should add a timeout and bail if it expires */
+	do {} while (pmu_intr_state(sc) == 0);
+	pmu_ack_on(sc);
+	do {} while (pmu_intr_state(sc));
+	pmu_ack_on(sc);
+	return 0;
+}
+
+static inline int
+pmu_read_byte(struct pmu_softc *sc, uint8_t *data)
+{
+	volatile uint8_t scratch;
+	pmu_in(sc);
+	scratch = pmu_read_reg(sc, vSR);
+	pmu_ack_off(sc);
+	/* wait for intr to come up */
+	do {} while (pmu_intr_state(sc) == 0);
+	pmu_ack_on(sc);
+	do {} while (pmu_intr_state(sc));
+	*data = pmu_read_reg(sc, vSR);
+	return 0;
+}
+
+static int
+pmu_intr_state(struct pmu_softc *sc)
+{
+	return ((pmu_read_reg(sc, vBufB) & vPB3) == 0);
+}
+
+static int
+pmu_send(void *cookie, int cmd, int length, uint8_t *in_msg, int rlen,
+    uint8_t *out_msg)
+{
+	struct pmu_softc *sc = cookie;
+	int i, rcv_len = -1;
+	uint8_t out_len, intreg;
+
+	intreg = pmu_read_reg(sc, vIER);
+	intreg &= 0x10;
+	pmu_write_reg(sc, vIER, intreg);
+
+	/* wait idle */
+	do {} while (pmu_intr_state(sc));
+
+	/* send command */
+	pmu_send_byte(sc, cmd);
+
+	/* send length if necessary */
+	if (pm_send_cmd_type[cmd] < 0) {
+		pmu_send_byte(sc, length);
+	}
+
+	for (i = 0; i < length; i++) {
+		pmu_send_byte(sc, in_msg[i]);
+	}
+
+	/* see if there's data to read */
+	rcv_len = pm_receive_cmd_type[cmd];
+	if (rcv_len == 0) 
+		goto done;
+
+	/* read command */
+	if (rcv_len == 1) {
+		pmu_read_byte(sc, out_msg);
+		goto done;
+	} else
+		out_msg[0] = cmd;
+	if (rcv_len < 0) {
+		pmu_read_byte(sc, &out_len);
+		rcv_len = out_len + 1;
+	}
+	for (i = 1; i < min(rcv_len, rlen); i++)
+		pmu_read_byte(sc, &out_msg[i]);
+
+done:
+	pmu_write_reg(sc, vIER, (intreg == 0) ? 0 : 0x90);
+
+	return rcv_len;
+}
+
+
+static u_int
+pmu_poll(device_t dev)
+{
+	pmu_intr(dev);
+	return (0);
+}
+
+static void
+pmu_in(struct pmu_softc *sc)
+{
+	uint8_t reg;
+
+	reg = pmu_read_reg(sc, vACR);
+	reg &= ~vSR_OUT;
+	reg |= 0x0c;
+	pmu_write_reg(sc, vACR, reg);
+}
+
+static void
+pmu_out(struct pmu_softc *sc)
+{
+	uint8_t reg;
+
+	reg = pmu_read_reg(sc, vACR);
+	reg |= vSR_OUT;
+	reg |= 0x0c;
+	pmu_write_reg(sc, vACR, reg);
+}
+
+static void
+pmu_ack_off(struct pmu_softc *sc)
+{
+	uint8_t reg;
+
+	reg = pmu_read_reg(sc, vBufB);
+	reg &= ~vPB4;
+	pmu_write_reg(sc, vBufB, reg);
+}
+
+static void
+pmu_ack_on(struct pmu_softc *sc)
+{
+	uint8_t reg;
+
+	reg = pmu_read_reg(sc, vBufB);
+	reg |= vPB4;
+	pmu_write_reg(sc, vBufB, reg);
+}
+
+static void
+pmu_intr(void *arg)
+{
+	device_t        dev;
+	struct pmu_softc *sc;
+
+	unsigned int len;
+	uint8_t resp[16];
+	uint8_t junk[16];
+
+        dev = (device_t)arg;
+	sc = device_get_softc(dev);
+
+	mtx_lock(&sc->sc_mutex);
+
+	pmu_write_reg(sc, vIFR, 0x90);	/* Clear 'em */
+	len = pmu_send(sc, PMU_INT_ACK, 0, NULL, 16, resp);
+
+	mtx_unlock(&sc->sc_mutex);
+
+	if ((len < 1) || (resp[1] == 0)) {
+		return;
+	}
+
+	if (resp[1] & PMU_INT_ADB) {
+		/*
+		 * the PMU will turn off autopolling after each command that
+		 * it did not issue, so we assume any but TALK R0 is ours and
+		 * re-enable autopoll here whenever we receive an ACK for a
+		 * non TR0 command.
+		 */
+		mtx_lock(&sc->sc_mutex);
+
+		if ((resp[2] & 0x0f) != (ADB_COMMAND_TALK << 2)) {
+			if (sc->sc_autopoll) {
+				uint8_t cmd[] = {0, PMU_SET_POLL_MASK, 
+				    (sc->sc_autopoll >> 8) & 0xff, 
+				    sc->sc_autopoll & 0xff};
+
+				pmu_send(sc, PMU_ADB_CMD, 4, cmd, 16, junk);
+			}
+		}	
+
+		mtx_unlock(&sc->sc_mutex);
+
+		adb_receive_raw_packet(sc->adb_bus,resp[1],resp[2],
+			len - 3,&resp[3]);
+	}
+	if (resp[1] & PMU_INT_ENVIRONMENT) {
+		/* if the lid was just closed, notify devd. */
+		if ((resp[2] & PMU_ENV_LID_CLOSED) && (!sc->lid_closed)) {
+			sc->lid_closed = 1;
+			if (devctl_process_running())
+				devctl_notify("PMU", "lid", "close", NULL);
+		}
+		else if (!(resp[2] & PMU_ENV_LID_CLOSED) && (sc->lid_closed)) {
+			/* if the lid was just opened, notify devd. */
+			if (devctl_process_running())
+				devctl_notify("PMU", "lid", "open", NULL);
+			sc->lid_closed = 0;
+		}
+	}
+}
+
+static u_int
+pmu_adb_send(device_t dev, u_char command_byte, int len, u_char *data, 
+    u_char poll)
+{
+	struct pmu_softc *sc = device_get_softc(dev);
+	int i,replen;
+	uint8_t packet[16], resp[16];
+
+	/* construct an ADB command packet and send it */
+
+	packet[0] = command_byte;
+
+	packet[1] = 0;
+	packet[2] = len;
+	for (i = 0; i < len; i++)
+		packet[i + 3] = data[i];
+
+	mtx_lock(&sc->sc_mutex);
+	replen = pmu_send(sc, PMU_ADB_CMD, len + 3, packet, 16, resp);
+	mtx_unlock(&sc->sc_mutex);
+
+	if (poll)
+		pmu_poll(dev);
+
+	return 0;
+}
+
+static u_int 
+pmu_adb_autopoll(device_t dev, uint16_t mask) 
+{
+	struct pmu_softc *sc = device_get_softc(dev);
+
+	/* magical incantation to re-enable autopolling */
+	uint8_t cmd[] = {0, PMU_SET_POLL_MASK, (mask >> 8) & 0xff, mask & 0xff};
+	uint8_t resp[16];
+
+	mtx_lock(&sc->sc_mutex);
+
+	if (sc->sc_autopoll == mask) {
+		mtx_unlock(&sc->sc_mutex);
+		return 0;
+	}
+
+	sc->sc_autopoll = mask & 0xffff;
+
+	if (mask)
+		pmu_send(sc, PMU_ADB_CMD, 4, cmd, 16, resp);
+	else
+		pmu_send(sc, PMU_ADB_POLL_OFF, 0, NULL, 16, resp);
+
+	mtx_unlock(&sc->sc_mutex);
+	
+	return 0;
+}
+
+static void
+pmu_shutdown(void *xsc, int howto)
+{
+	struct pmu_softc *sc = xsc;
+	uint8_t cmd[] = {'M', 'A', 'T', 'T'};
+	
+	if (howto & RB_HALT)
+		pmu_send(sc, PMU_POWER_OFF, 4, cmd, 0, NULL);
+	else
+		pmu_send(sc, PMU_RESET_CPU, 0, NULL, 0, NULL);
+
+	for (;;);
+}
+
+static void
+pmu_set_sleepled(void *xsc, int onoff)
+{
+	struct pmu_softc *sc = xsc;
+	uint8_t cmd[] = {4, 0, 0};
+
+	cmd[2] = onoff;
+	
+	mtx_lock(&sc->sc_mutex);
+	pmu_send(sc, PMU_SET_SLEEPLED, 3, cmd, 0, NULL);
+	mtx_unlock(&sc->sc_mutex);
+}
+
+static int
+pmu_server_mode(SYSCTL_HANDLER_ARGS)
+{
+	struct pmu_softc *sc = arg1;
+	
+	u_int server_mode = 0;
+	uint8_t getcmd[] = {PMU_PWR_GET_POWERUP_EVENTS};
+	uint8_t setcmd[] = {0, 0, PMU_PWR_WAKEUP_AC_INSERT};
+	uint8_t resp[3];
+	int error, len;
+
+	mtx_lock(&sc->sc_mutex);
+	len = pmu_send(sc, PMU_POWER_EVENTS, 1, getcmd, 3, resp);
+	mtx_unlock(&sc->sc_mutex);
+
+	if (len == 3)
+		server_mode = (resp[2] & PMU_PWR_WAKEUP_AC_INSERT) ? 1 : 0;
+
+	error = sysctl_handle_int(oidp, &server_mode, 0, req);
+
+	if (len != 3)
+		return (EINVAL);
+
+	if (error || !req->newptr)
+		return (error);
+
+	if (server_mode == 1)
+		setcmd[0] = PMU_PWR_SET_POWERUP_EVENTS;
+	else if (server_mode == 0)
+		setcmd[0] = PMU_PWR_CLR_POWERUP_EVENTS;
+	else
+		return (EINVAL);
+
+	setcmd[1] = resp[1];
+
+	mtx_lock(&sc->sc_mutex);
+	pmu_send(sc, PMU_POWER_EVENTS, 3, setcmd, 2, resp);
+	mtx_unlock(&sc->sc_mutex);
+
+	return (0);
+}
+
+static int
+pmu_query_battery(struct pmu_softc *sc, int batt, struct pmu_battstate *info)
+{
+	uint8_t reg;
+	uint8_t resp[16];
+	int len;
+
+	reg = batt + 1;
+
+	mtx_lock(&sc->sc_mutex);
+	len = pmu_send(sc, PMU_SMART_BATTERY_STATE, 1, &reg, 16, resp);
+	mtx_unlock(&sc->sc_mutex);
+
+	if (len < 3)
+		return (-1);
+
+	/* All PMU battery info replies share a common header:
+	 * Byte 1	Payload Format
+	 * Byte 2	Battery Flags
+	 */
+
+	info->state = resp[2];
+
+	switch (resp[1]) {
+	case 3:
+	case 4:	
+		/*
+		 * Formats 3 and 4 appear to be the same:
+		 * Byte 3	Charge
+		 * Byte 4	Max Charge
+		 * Byte 5	Current
+		 * Byte 6	Voltage
+		 */
+
+		info->charge = resp[3];
+		info->maxcharge = resp[4];
+		/* Current can be positive or negative */
+		info->current = (int8_t)resp[5];
+		info->voltage = resp[6];
+		break;
+	case 5:
+		/*
+		 * Formats 5 is a wider version of formats 3 and 4
+		 * Byte 3-4	Charge
+		 * Byte 5-6	Max Charge
+		 * Byte 7-8	Current
+		 * Byte 9-10	Voltage
+		 */
+
+		info->charge = (resp[3] << 8) | resp[4];
+		info->maxcharge = (resp[5] << 8) | resp[6];
+		/* Current can be positive or negative */
+		info->current = (int16_t)((resp[7] << 8) | resp[8]);
+		info->voltage = (resp[9] << 8) | resp[10];
+		break;
+	default:
+		device_printf(sc->sc_dev, "Unknown battery info format (%d)!\n",
+		    resp[1]);
+		return (-1);
+	}
+
+	return (0);
+}
+
+static int
+pmu_acline_state(SYSCTL_HANDLER_ARGS)
+{
+	struct pmu_softc *sc;
+	struct pmu_battstate batt;
+	int error, result;
+
+	sc = arg1;
+
+	/* The PMU treats the AC line status as a property of the battery */
+	error = pmu_query_battery(sc, 0, &batt);
+
+	if (error != 0)
+		return (error);
+	
+	result = (batt.state & PMU_PWR_AC_PRESENT) ? 1 : 0;
+	error = sysctl_handle_int(oidp, &result, 0, req);
+
+	return (error);
+}
+
+static int
+pmu_battquery_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	struct pmu_softc *sc;
+	struct pmu_battstate batt;
+	int error, result;
+
+	sc = arg1;
+
+	error = pmu_query_battery(sc, arg2 & 0x00ff, &batt);
+
+	if (error != 0)
+		return (error);
+
+	switch (arg2 & 0xff00) {
+	case PMU_BATSYSCTL_PRESENT:
+		result = (batt.state & PMU_PWR_BATT_PRESENT) ? 1 : 0;
+		break;
+	case PMU_BATSYSCTL_CHARGING:
+		result = (batt.state & PMU_PWR_BATT_CHARGING) ? 1 : 0;
+		break;
+	case PMU_BATSYSCTL_CHARGE:
+		result = batt.charge;
+		break;
+	case PMU_BATSYSCTL_MAXCHARGE:
+		result = batt.maxcharge;
+		break;
+	case PMU_BATSYSCTL_CURRENT:
+		result = batt.current;
+		break;
+	case PMU_BATSYSCTL_VOLTAGE:
+		result = batt.voltage;
+		break;
+	case PMU_BATSYSCTL_TIME:
+		/* Time remaining until full charge/discharge, in minutes */
+
+		if (batt.current >= 0)
+			result = (batt.maxcharge - batt.charge) /* mAh */ * 60 
+			    / batt.current /* mA */;
+		else
+			result = (batt.charge /* mAh */ * 60) 
+			    / (-batt.current /* mA */);
+		break;
+	case PMU_BATSYSCTL_LIFE:
+		/* Battery charge fraction, in percent */
+		result = (batt.charge * 100) / batt.maxcharge;
+		break;
+	default:
+		/* This should never happen */
+		result = -1;
+	};
+
+	error = sysctl_handle_int(oidp, &result, 0, req);
+
+	return (error);
+}
+
+#define DIFF19041970	2082844800
+
+static int
+pmu_gettime(device_t dev, struct timespec *ts)
+{
+	struct pmu_softc *sc = device_get_softc(dev);
+	uint8_t resp[16];
+	uint32_t sec;
+
+	mtx_lock(&sc->sc_mutex);
+	pmu_send(sc, PMU_READ_RTC, 0, NULL, 16, resp);
+	mtx_unlock(&sc->sc_mutex);
+
+	memcpy(&sec, &resp[1], 4);
+	ts->tv_sec = sec - DIFF19041970;
+	ts->tv_nsec = 0;
+
+	return (0);
+}
+
+static int
+pmu_settime(device_t dev, struct timespec *ts)
+{
+	struct pmu_softc *sc = device_get_softc(dev);
+	uint32_t sec;
+
+	sec = ts->tv_sec + DIFF19041970;
+
+	mtx_lock(&sc->sc_mutex);
+	pmu_send(sc, PMU_SET_RTC, sizeof(sec), (uint8_t *)&sec, 0, NULL);
+	mtx_unlock(&sc->sc_mutex);
+
+	return (0);
+}
+
+int
+pmu_set_speed(int low_speed)
+{
+	struct pmu_softc *sc;
+	uint8_t sleepcmd[] = {'W', 'O', 'O', 'F', 0};
+	uint8_t resp[16];
+
+	sc = device_get_softc(pmu);
+	pmu_write_reg(sc, vIER, 0x10);
+	spinlock_enter();
+	mtdec(0x7fffffff);
+	mb();
+	mtdec(0x7fffffff);
+
+	sleepcmd[4] = low_speed;
+	pmu_send(sc, PMU_CPU_SPEED, 5, sleepcmd, 16, resp);
+	unin_chip_sleep(NULL, 1);
+	platform_sleep();
+	unin_chip_wake(NULL);
+
+	mtdec(1);	/* Force a decrementer exception */
+	spinlock_exit();
+	pmu_write_reg(sc, vIER, 0x90);
+
+	return (0);
+}


Property changes on: trunk/sys/powerpc/powermac/pmu.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/pmuvar.h
===================================================================
--- trunk/sys/powerpc/powermac/pmuvar.h	                        (rev 0)
+++ trunk/sys/powerpc/powermac/pmuvar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,179 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Michael Lorenz
+ * Copyright (c) 2008 Nathan Whitehorn
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/pmuvar.h 260674 2014-01-15 06:17:15Z jhibbits $
+ *
+ */
+
+#ifndef PMUVAR_H
+#define PMUVAR_H
+
+/* PMU commands */
+#define PMU_POWER_CTRL0		0x10	/* control power of some devices */
+#define PMU_POWER_CTRL		0x11	/* control power of some devices */
+
+#define PMU_POWER_OFF		0x7e	/* Turn Power off */
+#define PMU_RESET_CPU		0xd0	/* Reset CPU */
+
+#define PMU_SET_RTC		0x30	/* Set realtime clock */
+#define PMU_READ_RTC		0x38	/* Read realtime clock */
+
+#define PMU_WRITE_PRAM		0x32	/* Write PRAM */
+#define PMU_READ_PRAM		0x3a	/* Read PRAM */
+
+#define PMU_WRITE_NVRAM		0x33	/* Write NVRAM */
+#define PMU_READ_NVRAM		0x3b	/* Read NVRAM */
+
+#define PMU_EJECT_PCMCIA	0x4c	/* Eject PCMCIA slot */
+
+#define PMU_SET_BRIGHTNESS	0x41	/* Set backlight brightness */
+#define PMU_READ_BRIGHTNESS	0xd9	/* Read brightness button position */
+
+#define PMU_POWER_EVENTS        0x8f    /* Send power-event commands to PMU */
+#define PMU_SYSTEM_READY        0xdf    /* tell PMU we are awake */
+
+#define PMU_BATTERY_STATE	0x6b	/* Read old battery state */
+#define PMU_SMART_BATTERY_STATE	0x6f	/* Read battery state */
+
+#define PMU_ADB_CMD		0x20	/* Send ADB packet */
+#define PMU_ADB_POLL_OFF	0x21	/* Disable ADB auto-poll */
+#define PMU_SET_VOL		0x40	/* Set volume button position */
+#define PMU_GET_VOL		0x48	/* Get volume button position */
+#define PMU_SET_IMASK		0x70	/* Set interrupt mask */
+#define PMU_INT_ACK		0x78	/* Read interrupt bits */
+#define PMU_CPU_SPEED		0x7d	/* Control CPU speed on some models */
+#define PMU_SLEEP		0x7f	/* Put CPU to sleep */
+#define PMU_SET_POLL_MASK	0x86	/*
+					 * 16bit mask enables autopolling per
+					 * device
+					 */
+#define PMU_I2C_CMD		0x9a	/* i2c commands */
+#define PMU_GET_LID_STATE	0xdc	/* Report lid state */
+#define PMU_GET_VERSION		0xea	/* Identify thyself */
+#define	PMU_SET_SLEEPLED	0xee	/* Set sleep LED on/off */
+
+/* Bits in PMU interrupt and interrupt mask bytes */
+#define PMU_INT_ADB_AUTO	0x04	/* ADB autopoll, when PMU_INT_ADB */
+#define PMU_INT_PCEJECT		0x04	/* PC-card eject buttons */
+#define PMU_INT_SNDBRT		0x08	/* sound/brightness up/down buttons */
+#define PMU_INT_ADB		0x10	/* ADB autopoll or reply data */
+#define PMU_INT_BATTERY		0x20
+#define PMU_INT_ENVIRONMENT	0x40
+#define PMU_INT_TICK		0x80	/* 1-second tick interrupt */
+
+/* Bits to use with the PMU_POWER_CTRL0 command */
+#define PMU_POW0_ON		0x80	/* OR this to power ON the device */
+#define PMU_POW0_OFF		0x00	/* leave bit 7 to 0 to power it OFF */
+#define PMU_POW0_HARD_DRIVE	0x04	/* wallstreet/lombard? */
+
+/* Bits to use with the PMU_POWER_CTRL command */
+#define PMU_POW_ON		0x80	/* OR this to power ON the device */
+#define PMU_POW_OFF		0x00	/* leave bit 7 to 0 to power it OFF */
+#define PMU_POW_BACKLIGHT	0x01	/* backlight power */
+#define PMU_POW_CHARGER		0x02	/* battery charger power */
+#define PMU_POW_IRLED		0x04	/* IR led power (on wallstreet) */
+#define PMU_POW_MEDIABAY	0x08	/* media bay power (wallstreet/lombard ?) */
+
+/* Bits from PMU_GET_LID_STATE or PMU_INT_ENVIRONMENT on core99 */
+#define PMU_ENV_LID_CLOSED	0x01	/* The lid is closed */
+
+/* PMU PMU_POWER_EVENTS commands */
+enum {
+	PMU_PWR_GET_POWERUP_EVENTS      = 0x00,
+	PMU_PWR_SET_POWERUP_EVENTS      = 0x01,
+	PMU_PWR_CLR_POWERUP_EVENTS      = 0x02,
+	PMU_PWR_GET_WAKEUP_EVENTS       = 0x03,
+	PMU_PWR_SET_WAKEUP_EVENTS       = 0x04,
+	PMU_PWR_CLR_WAKEUP_EVENTS       = 0x05,
+};
+
+/* PMU Power Information */
+
+#define PMU_PWR_AC_PRESENT	(1 << 0)
+#define PMU_PWR_BATT_CHARGING	(1 << 1)
+#define PMU_PWR_BATT_PRESENT	(1 << 2)
+#define PMU_PWR_BATT_FULL	(1 << 5)
+#define PMU_PWR_PCHARGE_RESET	(1 << 6)
+#define PMU_PWR_BATT_EXIST	(1 << 7)
+
+
+/* I2C related definitions */
+#define PMU_I2C_MODE_SIMPLE	0
+#define PMU_I2C_MODE_STDSUB	1
+#define PMU_I2C_MODE_COMBINED	2
+
+#define PMU_I2C_BUS_STATUS	0
+#define PMU_I2C_BUS_SYSCLK	1
+#define PMU_I2C_BUS_POWER	2
+
+#define PMU_I2C_STATUS_OK	0
+#define PMU_I2C_STATUS_DATAREAD	1
+#define PMU_I2C_STATUS_BUSY	0xfe
+
+/* Power events wakeup bits */
+enum {
+	PMU_PWR_WAKEUP_KEY		= 0x01, /* Wake on key press */
+	PMU_PWR_WAKEUP_AC_INSERT	= 0x02, /* Wake on AC adapter plug */
+	PMU_PWR_WAKEUP_AC_CHANGE 	= 0x04,
+	PMU_PWR_WAKEUP_LID_OPEN		= 0x08,
+	PMU_PWR_WAKEUP_RING		= 0x10,
+};
+
+#define PMU_NOTREADY	0x1	/* has not been initialized yet */
+#define PMU_IDLE	0x2	/* the bus is currently idle */
+#define PMU_OUT		0x3	/* sending out a command */
+#define PMU_IN		0x4	/* receiving data */
+
+struct pmu_softc {
+	device_t	sc_dev;
+	int		sc_memrid;
+	struct resource	*sc_memr;
+	int     	sc_irqrid;
+        struct resource *sc_irq;
+        void    	*sc_ih;
+
+	struct mtx	sc_mutex;
+	device_t	adb_bus;
+	volatile int	sc_autopoll;
+	int		sc_batteries;
+	struct cdev	*sc_leddev;
+	int		lid_closed;
+	uint8_t		saved_regs[9];
+};
+
+struct pmu_battstate {
+	int state;
+
+	int charge;
+	int maxcharge;
+	int current;
+	int voltage;
+};
+
+int pmu_set_speed(int low_speed);
+
+#endif /* PMUVAR_H */


Property changes on: trunk/sys/powerpc/powermac/pmuvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/powermac_thermal.c
===================================================================
--- trunk/sys/powerpc/powermac/powermac_thermal.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/powermac_thermal.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,201 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009-2011 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/powermac_thermal.c 265970 2014-05-13 18:08:15Z ian $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+
+#include <sys/types.h>
+#include <sys/kthread.h>
+#include <sys/malloc.h>
+#include <sys/reboot.h>
+#include <sys/sysctl.h>
+#include <sys/queue.h>
+
+#include "powermac_thermal.h"
+
+static void fan_management_proc(void);
+static void pmac_therm_manage_fans(void);
+
+static struct proc *pmac_them_proc;
+static int enable_pmac_thermal = 1;
+
+static struct kproc_desc pmac_therm_kp = {
+	"pmac_thermal",
+	fan_management_proc,
+	&pmac_them_proc
+};
+
+SYSINIT(pmac_therm_setup, SI_SUB_KTHREAD_IDLE, SI_ORDER_ANY, kproc_start,
+    &pmac_therm_kp);
+SYSCTL_INT(_machdep, OID_AUTO, manage_fans, CTLFLAG_RW | CTLFLAG_TUN,
+    &enable_pmac_thermal, 1, "Enable automatic fan management");
+static MALLOC_DEFINE(M_PMACTHERM, "pmactherm", "Powermac Thermal Management");
+
+struct pmac_fan_le {
+	struct pmac_fan			*fan;
+	int				last_val;
+	SLIST_ENTRY(pmac_fan_le)	entries;
+};
+struct pmac_sens_le {
+	struct pmac_therm		*sensor;
+	int				last_val;
+#define MAX_CRITICAL_COUNT 6
+	int				critical_count;
+	SLIST_ENTRY(pmac_sens_le)	entries;
+};
+static SLIST_HEAD(pmac_fans, pmac_fan_le) fans = SLIST_HEAD_INITIALIZER(fans);
+static SLIST_HEAD(pmac_sensors, pmac_sens_le) sensors =
+    SLIST_HEAD_INITIALIZER(sensors);
+
+static void
+fan_management_proc(void)
+{
+	/* Nothing to manage? */
+	if (SLIST_EMPTY(&fans))
+		kproc_exit(0);
+	
+	while (1) {
+		pmac_therm_manage_fans();
+		pause("pmac_therm", hz);
+	}
+}
+
+static void
+pmac_therm_manage_fans(void)
+{
+	struct pmac_sens_le *sensor;
+	struct pmac_fan_le *fan;
+	int average_excess, max_excess_zone, frac_excess;
+	int nsens, nsens_zone;
+	int temp;
+
+	if (!enable_pmac_thermal)
+		return;
+
+	/* Read all the sensors */
+	SLIST_FOREACH(sensor, &sensors, entries) {
+		temp = sensor->sensor->read(sensor->sensor);
+		if (temp > 0) /* Use the previous temp in case of error */
+			sensor->last_val = temp;
+
+		if (sensor->last_val > sensor->sensor->max_temp) {
+			sensor->critical_count++;
+			printf("WARNING: Current temperature (%s: %d.%d C) "
+			    "exceeds critical temperature (%d.%d C); "
+			    "count=%d\n",
+			    sensor->sensor->name,
+			    (sensor->last_val - ZERO_C_TO_K) / 10,
+			    (sensor->last_val - ZERO_C_TO_K) % 10,
+			    (sensor->sensor->max_temp - ZERO_C_TO_K) / 10,
+			    (sensor->sensor->max_temp - ZERO_C_TO_K) % 10,
+			    sensor->critical_count);
+			if (sensor->critical_count >= MAX_CRITICAL_COUNT) {
+				printf("WARNING: %s temperature exceeded "
+				    "critical temperature %d times in a row; "
+				    "shutting down!\n",
+				    sensor->sensor->name,
+				    sensor->critical_count);
+				shutdown_nice(RB_POWEROFF);
+			}
+		} else {
+			if (sensor->critical_count > 0)
+				sensor->critical_count--;
+		}
+	}
+
+	/* Set all the fans */
+	SLIST_FOREACH(fan, &fans, entries) {
+		nsens = nsens_zone = 0;
+		average_excess = max_excess_zone = 0;
+		SLIST_FOREACH(sensor, &sensors, entries) {
+			frac_excess = (sensor->last_val -
+			    sensor->sensor->target_temp)*100 /
+			    (sensor->sensor->max_temp -
+			    sensor->sensor->target_temp);
+			if (frac_excess < 0)
+				frac_excess = 0;
+			if (sensor->sensor->zone == fan->fan->zone) {
+				max_excess_zone = imax(max_excess_zone,
+				    frac_excess);
+				nsens_zone++;
+			}
+			average_excess += frac_excess;
+			nsens++;
+		}
+		average_excess /= nsens;
+
+		/* If there are no sensors in this zone, use the average */
+		if (nsens_zone == 0)
+			max_excess_zone = average_excess;
+		/* No sensors at all? Use default */
+		if (nsens == 0) {
+			fan->fan->set(fan->fan, fan->fan->default_rpm);
+			continue;
+		}
+
+		/*
+		 * Scale the fan linearly in the max temperature in its
+		 * thermal zone.
+		 */
+		fan->fan->set(fan->fan, max_excess_zone *
+		    (fan->fan->max_rpm - fan->fan->min_rpm)/100 +
+		    fan->fan->min_rpm);
+	}
+}
+
+void
+pmac_thermal_fan_register(struct pmac_fan *fan)
+{
+	struct pmac_fan_le *list_entry;
+
+	list_entry = malloc(sizeof(struct pmac_fan_le), M_PMACTHERM,
+	    M_ZERO | M_WAITOK);
+	list_entry->fan = fan;
+
+	SLIST_INSERT_HEAD(&fans, list_entry, entries);
+}
+
+void
+pmac_thermal_sensor_register(struct pmac_therm *sensor)
+{
+	struct pmac_sens_le *list_entry;
+
+	list_entry = malloc(sizeof(struct pmac_sens_le), M_PMACTHERM,
+	    M_ZERO | M_WAITOK);
+	list_entry->sensor = sensor;
+	list_entry->last_val = 0;
+	list_entry->critical_count = 0;
+
+	SLIST_INSERT_HEAD(&sensors, list_entry, entries);
+}
+


Property changes on: trunk/sys/powerpc/powermac/powermac_thermal.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/powermac_thermal.h
===================================================================
--- trunk/sys/powerpc/powermac/powermac_thermal.h	                        (rev 0)
+++ trunk/sys/powerpc/powermac/powermac_thermal.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,57 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009-2011 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/powermac_thermal.h 222659 2011-06-03 20:43:12Z andreast $
+ */
+
+#ifndef _POWERPC_POWERMAC_POWERMAC_THERMAL_H
+#define _POWERPC_POWERMAC_POWERMAC_THERMAL_H
+
+#define ZERO_C_TO_K 2732
+
+struct pmac_fan {
+	int min_rpm, max_rpm, default_rpm;
+	
+	char name[32];
+	int zone;
+
+	int (*read)(struct pmac_fan *);
+	int (*set)(struct pmac_fan *, int value);
+};
+
+struct pmac_therm {
+	int target_temp, max_temp;	/* Tenths of a degree K */
+	
+	char name[32];
+	int zone;
+
+	int (*read)(struct pmac_therm *);
+};
+
+void pmac_thermal_fan_register(struct pmac_fan *);
+void pmac_thermal_sensor_register(struct pmac_therm *);
+
+#endif


Property changes on: trunk/sys/powerpc/powermac/powermac_thermal.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/pswitch.c
===================================================================
--- trunk/sys/powerpc/powermac/pswitch.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/pswitch.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,145 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2002 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/pswitch.c 174898 2007-12-25 17:52:02Z rwatson $
+ */
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+
+#include <machine/resource.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <powerpc/powermac/maciovar.h>
+
+struct pswitch_softc {
+	int	sc_irqrid;
+	struct	resource *sc_irq;
+	void	*sc_ih;
+};
+
+static int	pswitch_probe(device_t);
+static int	pswitch_attach(device_t);
+
+static int	pswitch_intr(void *);
+
+static device_method_t pswitch_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		pswitch_probe),
+	DEVMETHOD(device_attach,	pswitch_attach),
+
+	{ 0, 0 }
+};
+
+static driver_t pswitch_driver = {
+	"pswitch",
+	pswitch_methods,
+	sizeof(struct pswitch_softc)
+};
+
+static devclass_t pswitch_devclass;
+
+DRIVER_MODULE(pswitch, macio, pswitch_driver, pswitch_devclass, 0, 0);
+
+static int
+pswitch_probe(device_t dev)
+{
+	char	*type = macio_get_devtype(dev);
+
+	if (strcmp(type, "gpio") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "GPIO Programmer's Switch");
+	return (0);
+}
+
+static int
+pswitch_attach(device_t dev)
+{
+	struct		pswitch_softc *sc;
+	phandle_t	node, child;
+	char		type[32];
+	u_int		irq[2];
+
+	sc = device_get_softc(dev);
+	node = macio_get_node(dev);
+
+	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
+		if (OF_getprop(child, "device_type", type, 32) == -1)
+			continue;
+
+		if (strcmp(type, "programmer-switch") == 0)
+			break;
+	}
+
+	if (child == 0) {
+		device_printf(dev, "could not find correct node\n");
+		return (ENXIO);
+	}
+
+	if (OF_getprop(child, "interrupts", irq, sizeof(irq)) == -1) {
+		device_printf(dev, "could not get interrupt\n");
+		return (ENXIO);
+	}
+
+	sc->sc_irqrid = 0;
+	sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_irqrid,
+	    irq[0], irq[0], 1, RF_ACTIVE);
+	if (sc->sc_irq == NULL) {
+		device_printf(dev, "could not allocate interrupt\n");
+		return (ENXIO);
+	}
+
+	if (bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC,
+	    pswitch_intr, NULL, dev, &sc->sc_ih) != 0) {
+		device_printf(dev, "could not setup interrupt\n");
+		bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid,
+		    sc->sc_irq);
+		return (ENXIO);
+	}
+
+	return (0);
+}
+
+static int
+pswitch_intr(void *arg)
+{
+	device_t	dev;
+
+	dev = (device_t)arg;
+
+	kdb_enter(KDB_WHY_POWERPC, device_get_nameunit(dev));
+	return (FILTER_HANDLED);
+}


Property changes on: trunk/sys/powerpc/powermac/pswitch.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/smu.c
===================================================================
--- trunk/sys/powerpc/powermac/smu.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/smu.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,1580 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Nathan Whitehorn
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/smu.c 273736 2014-10-27 14:38:00Z hselasky $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/conf.h>
+#include <sys/cpu.h>
+#include <sys/clock.h>
+#include <sys/ctype.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/reboot.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/unistd.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+#include <dev/led/led.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <powerpc/powermac/macgpiovar.h>
+#include <powerpc/powermac/powermac_thermal.h>
+
+#include "clock_if.h"
+#include "iicbus_if.h"
+
+struct smu_cmd {
+	volatile uint8_t cmd;
+	uint8_t		len;
+	uint8_t		data[254];
+
+	STAILQ_ENTRY(smu_cmd) cmd_q;
+};
+
+STAILQ_HEAD(smu_cmdq, smu_cmd);
+
+struct smu_fan {
+	struct pmac_fan fan;
+	device_t dev;
+	cell_t	reg;
+
+	enum {
+		SMU_FAN_RPM,
+		SMU_FAN_PWM
+	} type;
+	int	setpoint;
+	int	old_style;
+	int     rpm;
+};
+
+/* We can read the PWM and the RPM from a PWM controlled fan.
+ * Offer both values via sysctl.
+ */
+enum {
+	SMU_PWM_SYSCTL_PWM   = 1 << 8,
+	SMU_PWM_SYSCTL_RPM   = 2 << 8
+};
+
+struct smu_sensor {
+	struct pmac_therm therm;
+	device_t dev;
+
+	cell_t	reg;
+	enum {
+		SMU_CURRENT_SENSOR,
+		SMU_VOLTAGE_SENSOR,
+		SMU_POWER_SENSOR,
+		SMU_TEMP_SENSOR
+	} type;
+};
+
+struct smu_softc {
+	device_t	sc_dev;
+	struct mtx	sc_mtx;
+
+	struct resource	*sc_memr;
+	int		sc_memrid;
+	int		sc_u3;
+
+	bus_dma_tag_t	sc_dmatag;
+	bus_space_tag_t	sc_bt;
+	bus_space_handle_t sc_mailbox;
+
+	struct smu_cmd	*sc_cmd, *sc_cur_cmd;
+	bus_addr_t	sc_cmd_phys;
+	bus_dmamap_t	sc_cmd_dmamap;
+	struct smu_cmdq	sc_cmdq;
+
+	struct smu_fan	*sc_fans;
+	int		sc_nfans;
+	int		old_style_fans;
+	struct smu_sensor *sc_sensors;
+	int		sc_nsensors;
+
+	int		sc_doorbellirqid;
+	struct resource	*sc_doorbellirq;
+	void		*sc_doorbellirqcookie;
+
+	struct proc	*sc_fanmgt_proc;
+	time_t		sc_lastuserchange;
+
+	/* Calibration data */
+	uint16_t	sc_cpu_diode_scale;
+	int16_t		sc_cpu_diode_offset;
+
+	uint16_t	sc_cpu_volt_scale;
+	int16_t		sc_cpu_volt_offset;
+	uint16_t	sc_cpu_curr_scale;
+	int16_t		sc_cpu_curr_offset;
+
+	uint16_t	sc_slots_pow_scale;
+	int16_t		sc_slots_pow_offset;
+
+	struct cdev 	*sc_leddev;
+};
+
+/* regular bus attachment functions */
+
+static int	smu_probe(device_t);
+static int	smu_attach(device_t);
+static const struct ofw_bus_devinfo *
+    smu_get_devinfo(device_t bus, device_t dev);
+
+/* cpufreq notification hooks */
+
+static void	smu_cpufreq_pre_change(device_t, const struct cf_level *level);
+static void	smu_cpufreq_post_change(device_t, const struct cf_level *level);
+
+/* clock interface */
+static int	smu_gettime(device_t dev, struct timespec *ts);
+static int	smu_settime(device_t dev, struct timespec *ts);
+
+/* utility functions */
+static int	smu_run_cmd(device_t dev, struct smu_cmd *cmd, int wait);
+static int	smu_get_datablock(device_t dev, int8_t id, uint8_t *buf,
+		    size_t len);
+static void	smu_attach_i2c(device_t dev, phandle_t i2croot);
+static void	smu_attach_fans(device_t dev, phandle_t fanroot);
+static void	smu_attach_sensors(device_t dev, phandle_t sensroot);
+static void	smu_set_sleepled(void *xdev, int onoff);
+static int	smu_server_mode(SYSCTL_HANDLER_ARGS);
+static void	smu_doorbell_intr(void *xdev);
+static void	smu_shutdown(void *xdev, int howto);
+
+/* where to find the doorbell GPIO */
+
+static device_t	smu_doorbell = NULL;
+
+static device_method_t  smu_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		smu_probe),
+	DEVMETHOD(device_attach,	smu_attach),
+
+	/* Clock interface */
+	DEVMETHOD(clock_gettime,	smu_gettime),
+	DEVMETHOD(clock_settime,	smu_settime),
+
+	/* ofw_bus interface */
+	DEVMETHOD(bus_child_pnpinfo_str,ofw_bus_gen_child_pnpinfo_str),
+	DEVMETHOD(ofw_bus_get_devinfo,	smu_get_devinfo),
+	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
+	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
+	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
+	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
+	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
+
+	{ 0, 0 },
+};
+
+static driver_t smu_driver = {
+	"smu",
+	smu_methods,
+	sizeof(struct smu_softc)
+};
+
+static devclass_t smu_devclass;
+
+DRIVER_MODULE(smu, ofwbus, smu_driver, smu_devclass, 0, 0);
+static MALLOC_DEFINE(M_SMU, "smu", "SMU Sensor Information");
+
+#define SMU_MAILBOX		0x8000860c
+#define SMU_FANMGT_INTERVAL	1000 /* ms */
+
+/* Command types */
+#define SMU_ADC			0xd8
+#define SMU_FAN			0x4a
+#define SMU_RPM_STATUS		0x01
+#define SMU_RPM_SETPOINT	0x02
+#define SMU_PWM_STATUS		0x11
+#define SMU_PWM_SETPOINT	0x12
+#define SMU_I2C			0x9a
+#define  SMU_I2C_SIMPLE		0x00
+#define  SMU_I2C_NORMAL		0x01
+#define  SMU_I2C_COMBINED	0x02
+#define SMU_MISC		0xee
+#define  SMU_MISC_GET_DATA	0x02
+#define  SMU_MISC_LED_CTRL	0x04
+#define SMU_POWER		0xaa
+#define SMU_POWER_EVENTS	0x8f
+#define  SMU_PWR_GET_POWERUP	0x00
+#define  SMU_PWR_SET_POWERUP	0x01
+#define  SMU_PWR_CLR_POWERUP	0x02
+#define SMU_RTC			0x8e
+#define  SMU_RTC_GET		0x81
+#define  SMU_RTC_SET		0x80
+
+/* Power event types */
+#define SMU_WAKEUP_KEYPRESS	0x01
+#define SMU_WAKEUP_AC_INSERT	0x02
+#define SMU_WAKEUP_AC_CHANGE	0x04
+#define SMU_WAKEUP_RING		0x10
+
+/* Data blocks */
+#define SMU_CPUTEMP_CAL		0x18
+#define SMU_CPUVOLT_CAL		0x21
+#define SMU_SLOTPW_CAL		0x78
+
+/* Partitions */
+#define SMU_PARTITION		0x3e
+#define SMU_PARTITION_LATEST	0x01
+#define SMU_PARTITION_BASE	0x02
+#define SMU_PARTITION_UPDATE	0x03
+
+static int
+smu_probe(device_t dev)
+{
+	const char *name = ofw_bus_get_name(dev);
+
+	if (strcmp(name, "smu") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "Apple System Management Unit");
+	return (0);
+}
+
+static void
+smu_phys_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
+{
+	struct smu_softc *sc = xsc;
+
+	sc->sc_cmd_phys = segs[0].ds_addr;
+}
+
+static int
+smu_attach(device_t dev)
+{
+	struct smu_softc *sc;
+	phandle_t	node, child;
+	uint8_t		data[12];
+
+	sc = device_get_softc(dev);
+
+	mtx_init(&sc->sc_mtx, "smu", NULL, MTX_DEF);
+	sc->sc_cur_cmd = NULL;
+	sc->sc_doorbellirqid = -1;
+
+	sc->sc_u3 = 0;
+	if (OF_finddevice("/u3") != -1)
+		sc->sc_u3 = 1;
+
+	/*
+	 * Map the mailbox area. This should be determined from firmware,
+	 * but I have not found a simple way to do that.
+	 */
+	bus_dma_tag_create(NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT,
+	    BUS_SPACE_MAXADDR, NULL, NULL, PAGE_SIZE, 1, PAGE_SIZE, 0, NULL,
+	    NULL, &(sc->sc_dmatag));
+	sc->sc_bt = &bs_le_tag;
+	bus_space_map(sc->sc_bt, SMU_MAILBOX, 4, 0, &sc->sc_mailbox);
+
+	/*
+	 * Allocate the command buffer. This can be anywhere in the low 4 GB
+	 * of memory.
+	 */
+	bus_dmamem_alloc(sc->sc_dmatag, (void **)&sc->sc_cmd, BUS_DMA_WAITOK | 
+	    BUS_DMA_ZERO, &sc->sc_cmd_dmamap);
+	bus_dmamap_load(sc->sc_dmatag, sc->sc_cmd_dmamap,
+	    sc->sc_cmd, PAGE_SIZE, smu_phys_callback, sc, 0);
+	STAILQ_INIT(&sc->sc_cmdq);
+
+	/*
+	 * Set up handlers to change CPU voltage when CPU frequency is changed.
+	 */
+	EVENTHANDLER_REGISTER(cpufreq_pre_change, smu_cpufreq_pre_change, dev,
+	    EVENTHANDLER_PRI_ANY);
+	EVENTHANDLER_REGISTER(cpufreq_post_change, smu_cpufreq_post_change, dev,
+	    EVENTHANDLER_PRI_ANY);
+
+	node = ofw_bus_get_node(dev);
+
+	/* Some SMUs have RPM and PWM controlled fans which do not sit
+	 * under the same node. So we have to attach them separately.
+	 */
+	smu_attach_fans(dev, node);
+
+	/*
+	 * Now detect and attach the other child devices.
+	 */
+	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
+		char name[32];
+		memset(name, 0, sizeof(name));
+		OF_getprop(child, "name", name, sizeof(name));
+
+		if (strncmp(name, "sensors", 8) == 0)
+			smu_attach_sensors(dev, child);
+
+		if (strncmp(name, "smu-i2c-control", 15) == 0)
+			smu_attach_i2c(dev, child);
+	}
+
+	/* Some SMUs have the I2C children directly under the bus. */
+	smu_attach_i2c(dev, node);
+
+	/*
+	 * Collect calibration constants.
+	 */
+	smu_get_datablock(dev, SMU_CPUTEMP_CAL, data, sizeof(data));
+	sc->sc_cpu_diode_scale = (data[4] << 8) + data[5];
+	sc->sc_cpu_diode_offset = (data[6] << 8) + data[7];
+
+	smu_get_datablock(dev, SMU_CPUVOLT_CAL, data, sizeof(data));
+	sc->sc_cpu_volt_scale = (data[4] << 8) + data[5];
+	sc->sc_cpu_volt_offset = (data[6] << 8) + data[7];
+	sc->sc_cpu_curr_scale = (data[8] << 8) + data[9];
+	sc->sc_cpu_curr_offset = (data[10] << 8) + data[11];
+
+	smu_get_datablock(dev, SMU_SLOTPW_CAL, data, sizeof(data));
+	sc->sc_slots_pow_scale = (data[4] << 8) + data[5];
+	sc->sc_slots_pow_offset = (data[6] << 8) + data[7];
+
+	/*
+	 * Set up LED interface
+	 */
+	sc->sc_leddev = led_create(smu_set_sleepled, dev, "sleepled");
+
+	/*
+	 * Reset on power loss behavior
+	 */
+
+	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+            SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+	    "server_mode", CTLTYPE_INT | CTLFLAG_RW, dev, 0,
+	    smu_server_mode, "I", "Enable reboot after power failure");
+
+	/*
+	 * Set up doorbell interrupt.
+	 */
+	sc->sc_doorbellirqid = 0;
+	sc->sc_doorbellirq = bus_alloc_resource_any(smu_doorbell, SYS_RES_IRQ,
+	    &sc->sc_doorbellirqid, RF_ACTIVE);
+	bus_setup_intr(smu_doorbell, sc->sc_doorbellirq,
+	    INTR_TYPE_MISC | INTR_MPSAFE, NULL, smu_doorbell_intr, dev,
+	    &sc->sc_doorbellirqcookie);
+	powerpc_config_intr(rman_get_start(sc->sc_doorbellirq),
+	    INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);
+
+	/*
+	 * Connect RTC interface.
+	 */
+	clock_register(dev, 1000);
+
+	/*
+	 * Learn about shutdown events
+	 */
+	EVENTHANDLER_REGISTER(shutdown_final, smu_shutdown, dev,
+	    SHUTDOWN_PRI_LAST);
+
+	return (bus_generic_attach(dev));
+}
+
+static const struct ofw_bus_devinfo *
+smu_get_devinfo(device_t bus, device_t dev)
+{
+
+	return (device_get_ivars(dev));
+}
+
+static void
+smu_send_cmd(device_t dev, struct smu_cmd *cmd)
+{
+	struct smu_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	mtx_assert(&sc->sc_mtx, MA_OWNED);
+
+	if (sc->sc_u3)
+		powerpc_pow_enabled = 0; /* SMU cannot work if we go to NAP */
+
+	sc->sc_cur_cmd = cmd;
+
+	/* Copy the command to the mailbox */
+	sc->sc_cmd->cmd = cmd->cmd;
+	sc->sc_cmd->len = cmd->len;
+	memcpy(sc->sc_cmd->data, cmd->data, sizeof(cmd->data));
+	bus_dmamap_sync(sc->sc_dmatag, sc->sc_cmd_dmamap, BUS_DMASYNC_PREWRITE);
+	bus_space_write_4(sc->sc_bt, sc->sc_mailbox, 0, sc->sc_cmd_phys);
+
+	/* Flush the cacheline it is in -- SMU bypasses the cache */
+	__asm __volatile("sync; dcbf 0,%0; sync" :: "r"(sc->sc_cmd): "memory");
+
+	/* Ring SMU doorbell */
+	macgpio_write(smu_doorbell, GPIO_DDR_OUTPUT);
+}
+
+static void
+smu_doorbell_intr(void *xdev)
+{
+	device_t smu;
+	struct smu_softc *sc;
+	int doorbell_ack;
+
+	smu = xdev;
+	doorbell_ack = macgpio_read(smu_doorbell);
+	sc = device_get_softc(smu);
+
+	if (doorbell_ack != (GPIO_DDR_OUTPUT | GPIO_LEVEL_RO | GPIO_DATA)) 
+		return;
+
+	mtx_lock(&sc->sc_mtx);
+
+	if (sc->sc_cur_cmd == NULL)	/* spurious */
+		goto done;
+
+	/* Check result. First invalidate the cache again... */
+	__asm __volatile("dcbf 0,%0; sync" :: "r"(sc->sc_cmd) : "memory");
+	
+	bus_dmamap_sync(sc->sc_dmatag, sc->sc_cmd_dmamap, BUS_DMASYNC_POSTREAD);
+
+	sc->sc_cur_cmd->cmd = sc->sc_cmd->cmd;
+	sc->sc_cur_cmd->len = sc->sc_cmd->len;
+	memcpy(sc->sc_cur_cmd->data, sc->sc_cmd->data,
+	    sizeof(sc->sc_cmd->data));
+	wakeup(sc->sc_cur_cmd);
+	sc->sc_cur_cmd = NULL;
+	if (sc->sc_u3)
+		powerpc_pow_enabled = 1;
+
+    done:
+	/* Queue next command if one is pending */
+	if (STAILQ_FIRST(&sc->sc_cmdq) != NULL) {
+		sc->sc_cur_cmd = STAILQ_FIRST(&sc->sc_cmdq);
+		STAILQ_REMOVE_HEAD(&sc->sc_cmdq, cmd_q);
+		smu_send_cmd(smu, sc->sc_cur_cmd);
+	}
+
+	mtx_unlock(&sc->sc_mtx);
+}
+
+static int
+smu_run_cmd(device_t dev, struct smu_cmd *cmd, int wait)
+{
+	struct smu_softc *sc;
+	uint8_t cmd_code;
+	int error;
+
+	sc = device_get_softc(dev);
+	cmd_code = cmd->cmd;
+
+	mtx_lock(&sc->sc_mtx);
+	if (sc->sc_cur_cmd != NULL) {
+		STAILQ_INSERT_TAIL(&sc->sc_cmdq, cmd, cmd_q);
+	} else
+		smu_send_cmd(dev, cmd);
+	mtx_unlock(&sc->sc_mtx);
+
+	if (!wait)
+		return (0);
+
+	if (sc->sc_doorbellirqid < 0) {
+		/* Poll if the IRQ has not been set up yet */
+		do {
+			DELAY(50);
+			smu_doorbell_intr(dev);
+		} while (sc->sc_cur_cmd != NULL);
+	} else {
+		/* smu_doorbell_intr will wake us when the command is ACK'ed */
+		error = tsleep(cmd, 0, "smu", 800 * hz / 1000);
+		if (error != 0)
+			smu_doorbell_intr(dev);	/* One last chance */
+		
+		if (error != 0) {
+		    mtx_lock(&sc->sc_mtx);
+		    if (cmd->cmd == cmd_code) {	/* Never processed */
+			/* Abort this command if we timed out */
+			if (sc->sc_cur_cmd == cmd)
+				sc->sc_cur_cmd = NULL;
+			else
+				STAILQ_REMOVE(&sc->sc_cmdq, cmd, smu_cmd,
+				    cmd_q);
+			mtx_unlock(&sc->sc_mtx);
+			return (error);
+		    }
+		    error = 0;
+		    mtx_unlock(&sc->sc_mtx);
+		}
+	}
+
+	/* SMU acks the command by inverting the command bits */
+	if (cmd->cmd == ((~cmd_code) & 0xff))
+		error = 0;
+	else
+		error = EIO;
+
+	return (error);
+}
+
+static int
+smu_get_datablock(device_t dev, int8_t id, uint8_t *buf, size_t len)
+{
+	struct smu_cmd cmd;
+	uint8_t addr[4];
+
+	cmd.cmd = SMU_PARTITION;
+	cmd.len = 2;
+	cmd.data[0] = SMU_PARTITION_LATEST;
+	cmd.data[1] = id; 
+
+	smu_run_cmd(dev, &cmd, 1);
+
+	addr[0] = addr[1] = 0;
+	addr[2] = cmd.data[0];
+	addr[3] = cmd.data[1];
+
+	cmd.cmd = SMU_MISC;
+	cmd.len = 7;
+	cmd.data[0] = SMU_MISC_GET_DATA;
+	cmd.data[1] = sizeof(addr);
+	memcpy(&cmd.data[2], addr, sizeof(addr));
+	cmd.data[6] = len;
+
+	smu_run_cmd(dev, &cmd, 1);
+	memcpy(buf, cmd.data, len);
+	return (0);
+}
+
+static void
+smu_slew_cpu_voltage(device_t dev, int to)
+{
+	struct smu_cmd cmd;
+
+	cmd.cmd = SMU_POWER;
+	cmd.len = 8;
+	cmd.data[0] = 'V';
+	cmd.data[1] = 'S'; 
+	cmd.data[2] = 'L'; 
+	cmd.data[3] = 'E'; 
+	cmd.data[4] = 'W'; 
+	cmd.data[5] = 0xff;
+	cmd.data[6] = 1;
+	cmd.data[7] = to;
+
+	smu_run_cmd(dev, &cmd, 1);
+}
+
+static void
+smu_cpufreq_pre_change(device_t dev, const struct cf_level *level)
+{
+	/*
+	 * Make sure the CPU voltage is raised before we raise
+	 * the clock.
+	 */
+		
+	if (level->rel_set[0].freq == 10000 /* max */)
+		smu_slew_cpu_voltage(dev, 0);
+}
+
+static void
+smu_cpufreq_post_change(device_t dev, const struct cf_level *level)
+{
+	/* We are safe to reduce CPU voltage after a downward transition */
+
+	if (level->rel_set[0].freq < 10000 /* max */)
+		smu_slew_cpu_voltage(dev, 1); /* XXX: 1/4 voltage for 970MP? */
+}
+
+/* Routines for probing the SMU doorbell GPIO */
+static int doorbell_probe(device_t dev);
+static int doorbell_attach(device_t dev);
+
+static device_method_t  doorbell_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		doorbell_probe),
+	DEVMETHOD(device_attach,	doorbell_attach),
+	{ 0, 0 },
+};
+
+static driver_t doorbell_driver = {
+	"smudoorbell",
+	doorbell_methods,
+	0
+};
+
+static devclass_t doorbell_devclass;
+
+DRIVER_MODULE(smudoorbell, macgpio, doorbell_driver, doorbell_devclass, 0, 0);
+
+static int
+doorbell_probe(device_t dev)
+{
+	const char *name = ofw_bus_get_name(dev);
+
+	if (strcmp(name, "smu-doorbell") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "SMU Doorbell GPIO");
+	device_quiet(dev);
+	return (0);
+}
+
+static int
+doorbell_attach(device_t dev)
+{
+	smu_doorbell = dev;
+	return (0);
+}
+
+/*
+ * Sensor and fan management
+ */
+
+static int
+smu_fan_check_old_style(struct smu_fan *fan)
+{
+	device_t smu = fan->dev;
+	struct smu_softc *sc = device_get_softc(smu);
+	struct smu_cmd cmd;
+	int error;
+
+	if (sc->old_style_fans != -1)
+		return (sc->old_style_fans);
+
+	/*
+	 * Apple has two fan control mechanisms. We can't distinguish
+	 * them except by seeing if the new one fails. If the new one
+	 * fails, use the old one.
+	 */
+	
+	cmd.cmd = SMU_FAN;
+	cmd.len = 2;
+	cmd.data[0] = 0x31;
+	cmd.data[1] = fan->reg;
+
+	do {
+		error = smu_run_cmd(smu, &cmd, 1);
+	} while (error == EWOULDBLOCK);
+
+	sc->old_style_fans = (error != 0);
+
+	return (sc->old_style_fans);
+}
+
+static int
+smu_fan_set_rpm(struct smu_fan *fan, int rpm)
+{
+	device_t smu = fan->dev;
+	struct smu_cmd cmd;
+	int error;
+
+	cmd.cmd = SMU_FAN;
+	error = EIO;
+
+	/* Clamp to allowed range */
+	rpm = max(fan->fan.min_rpm, rpm);
+	rpm = min(fan->fan.max_rpm, rpm);
+
+	smu_fan_check_old_style(fan);
+
+	if (!fan->old_style) {
+		cmd.len = 4;
+		cmd.data[0] = 0x30;
+		cmd.data[1] = fan->reg;
+		cmd.data[2] = (rpm >> 8) & 0xff;
+		cmd.data[3] = rpm & 0xff;
+
+		error = smu_run_cmd(smu, &cmd, 1);
+		if (error && error != EWOULDBLOCK)
+			fan->old_style = 1;
+	} else {
+		cmd.len = 14;
+		cmd.data[0] = 0x00; /* RPM fan. */
+		cmd.data[1] = 1 << fan->reg;
+		cmd.data[2 + 2*fan->reg] = (rpm >> 8) & 0xff;
+		cmd.data[3 + 2*fan->reg] = rpm & 0xff;
+		error = smu_run_cmd(smu, &cmd, 1);
+	}
+
+	if (error == 0)
+		fan->setpoint = rpm;
+
+	return (error);
+}
+
+static int
+smu_fan_read_rpm(struct smu_fan *fan)
+{
+	device_t smu = fan->dev;
+	struct smu_cmd cmd;
+	int rpm, error;
+
+	smu_fan_check_old_style(fan);
+
+	if (!fan->old_style) {
+		cmd.cmd = SMU_FAN;
+		cmd.len = 2;
+		cmd.data[0] = 0x31;
+		cmd.data[1] = fan->reg;
+
+		error = smu_run_cmd(smu, &cmd, 1);
+		if (error && error != EWOULDBLOCK)
+			fan->old_style = 1;
+
+		rpm = (cmd.data[0] << 8) | cmd.data[1];
+	}
+
+	if (fan->old_style) {
+		cmd.cmd = SMU_FAN;
+		cmd.len = 1;
+		cmd.data[0] = SMU_RPM_STATUS;
+
+		error = smu_run_cmd(smu, &cmd, 1);
+		if (error)
+			return (error);
+
+		rpm = (cmd.data[fan->reg*2+1] << 8) | cmd.data[fan->reg*2+2];
+	}
+
+	return (rpm);
+}
+static int
+smu_fan_set_pwm(struct smu_fan *fan, int pwm)
+{
+	device_t smu = fan->dev;
+	struct smu_cmd cmd;
+	int error;
+
+	cmd.cmd = SMU_FAN;
+	error = EIO;
+
+	/* Clamp to allowed range */
+	pwm = max(fan->fan.min_rpm, pwm);
+	pwm = min(fan->fan.max_rpm, pwm);
+
+	/*
+	 * Apple has two fan control mechanisms. We can't distinguish
+	 * them except by seeing if the new one fails. If the new one
+	 * fails, use the old one.
+	 */
+	
+	if (!fan->old_style) {
+		cmd.len = 4;
+		cmd.data[0] = 0x30;
+		cmd.data[1] = fan->reg;
+		cmd.data[2] = (pwm >> 8) & 0xff;
+		cmd.data[3] = pwm & 0xff;
+	
+		error = smu_run_cmd(smu, &cmd, 1);
+		if (error && error != EWOULDBLOCK)
+			fan->old_style = 1;
+	}
+
+	if (fan->old_style) {
+		cmd.len = 14;
+		cmd.data[0] = 0x10; /* PWM fan. */
+		cmd.data[1] = 1 << fan->reg;
+		cmd.data[2 + 2*fan->reg] = (pwm >> 8) & 0xff;
+		cmd.data[3 + 2*fan->reg] = pwm & 0xff;
+		error = smu_run_cmd(smu, &cmd, 1);
+	}
+
+	if (error == 0)
+		fan->setpoint = pwm;
+
+	return (error);
+}
+
+static int
+smu_fan_read_pwm(struct smu_fan *fan, int *pwm, int *rpm)
+{
+	device_t smu = fan->dev;
+	struct smu_cmd cmd;
+	int error;
+
+	if (!fan->old_style) {
+		cmd.cmd = SMU_FAN;
+		cmd.len = 2;
+		cmd.data[0] = 0x31;
+		cmd.data[1] = fan->reg;
+
+		error = smu_run_cmd(smu, &cmd, 1);
+		if (error && error != EWOULDBLOCK)
+			fan->old_style = 1;
+
+		*rpm = (cmd.data[0] << 8) | cmd.data[1];
+	}
+
+	if (fan->old_style) {
+		cmd.cmd = SMU_FAN;
+		cmd.len = 1;
+		cmd.data[0] = SMU_PWM_STATUS;
+
+		error = smu_run_cmd(smu, &cmd, 1);
+		if (error)
+			return (error);
+
+		*rpm = (cmd.data[fan->reg*2+1] << 8) | cmd.data[fan->reg*2+2];
+	}
+	if (fan->old_style) {
+		cmd.cmd = SMU_FAN;
+		cmd.len = 14;
+		cmd.data[0] = SMU_PWM_SETPOINT;
+		cmd.data[1] = 1 << fan->reg;
+
+		error = smu_run_cmd(smu, &cmd, 1);
+		if (error)
+			return (error);
+
+		*pwm = cmd.data[fan->reg*2+2];
+	}
+	return (0);
+}
+
+static int
+smu_fanrpm_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	device_t smu;
+	struct smu_softc *sc;
+	struct smu_fan *fan;
+	int pwm = 0, rpm, error = 0;
+
+	smu = arg1;
+	sc = device_get_softc(smu);
+	fan = &sc->sc_fans[arg2 & 0xff];
+
+	if (fan->type == SMU_FAN_RPM) {
+		rpm = smu_fan_read_rpm(fan);
+		if (rpm < 0)
+			return (rpm);
+
+		error = sysctl_handle_int(oidp, &rpm, 0, req);
+	} else {
+		error = smu_fan_read_pwm(fan, &pwm, &rpm);
+		if (error < 0)
+			return (EIO);
+
+		switch (arg2 & 0xff00) {
+		case SMU_PWM_SYSCTL_PWM:
+			error = sysctl_handle_int(oidp, &pwm, 0, req);
+			break;
+		case SMU_PWM_SYSCTL_RPM:
+			error = sysctl_handle_int(oidp, &rpm, 0, req);
+			break;
+		default:
+			/* This should never happen */
+			return (EINVAL);
+		};
+	}
+	/* We can only read the RPM from a PWM controlled fan, so return. */
+	if ((arg2 & 0xff00) == SMU_PWM_SYSCTL_RPM)
+		return (0);
+
+	if (error || !req->newptr)
+		return (error);
+
+	sc->sc_lastuserchange = time_uptime;
+
+	if (fan->type == SMU_FAN_RPM)
+		return (smu_fan_set_rpm(fan, rpm));
+	else
+		return (smu_fan_set_pwm(fan, pwm));
+}
+
+static void
+smu_fill_fan_prop(device_t dev, phandle_t child, int id)
+{
+	struct smu_fan *fan;
+	struct smu_softc *sc;
+	char type[32];
+
+	sc = device_get_softc(dev);
+	fan = &sc->sc_fans[id];
+
+	OF_getprop(child, "device_type", type, sizeof(type));
+	/* We have either RPM or PWM controlled fans. */
+	if (strcmp(type, "fan-rpm-control") == 0)
+		fan->type = SMU_FAN_RPM;
+	else
+		fan->type = SMU_FAN_PWM;
+
+	fan->dev = dev;
+	fan->old_style = 0;
+	OF_getprop(child, "reg", &fan->reg,
+		   sizeof(cell_t));
+	OF_getprop(child, "min-value", &fan->fan.min_rpm,
+		   sizeof(int));
+	OF_getprop(child, "max-value", &fan->fan.max_rpm,
+		   sizeof(int));
+	OF_getprop(child, "zone", &fan->fan.zone,
+		   sizeof(int));
+
+	if (OF_getprop(child, "unmanaged-value",
+		       &fan->fan.default_rpm,
+		       sizeof(int)) != sizeof(int))
+		fan->fan.default_rpm = fan->fan.max_rpm;
+
+	OF_getprop(child, "location", fan->fan.name,
+		   sizeof(fan->fan.name));
+
+	if (fan->type == SMU_FAN_RPM)
+		fan->setpoint = smu_fan_read_rpm(fan);
+	else
+		smu_fan_read_pwm(fan, &fan->setpoint, &fan->rpm);
+}
+
+/* On the first call count the number of fans. In the second call,
+ * after allocating the fan struct, fill the properties of the fans.
+ */
+static int
+smu_count_fans(device_t dev)
+{
+	struct smu_softc *sc;
+	phandle_t child, node, root;
+	int nfans = 0;
+
+	node = ofw_bus_get_node(dev);
+	sc = device_get_softc(dev);
+
+	/* First find the fanroots and count the number of fans. */
+	for (root = OF_child(node); root != 0; root = OF_peer(root)) {
+		char name[32];
+		memset(name, 0, sizeof(name));
+		OF_getprop(root, "name", name, sizeof(name));
+		if (strncmp(name, "rpm-fans", 9) == 0 ||
+		    strncmp(name, "pwm-fans", 9) == 0 ||
+		    strncmp(name, "fans", 5) == 0)
+			for (child = OF_child(root); child != 0;
+			     child = OF_peer(child)) {
+				nfans++;
+				/* When allocated, fill the fan properties. */
+				if (sc->sc_fans != NULL) {
+					smu_fill_fan_prop(dev, child,
+							  nfans - 1);
+				}
+			}
+	}
+	if (nfans == 0) {
+		device_printf(dev, "WARNING: No fans detected!\n");
+		return (0);
+	}
+	return (nfans);
+}
+
+static void
+smu_attach_fans(device_t dev, phandle_t fanroot)
+{
+	struct smu_fan *fan;
+	struct smu_softc *sc;
+	struct sysctl_oid *oid, *fanroot_oid;
+	struct sysctl_ctx_list *ctx;
+	char sysctl_name[32];
+	int i, j;
+
+	sc = device_get_softc(dev);
+
+	/* Get the number of fans. */
+	sc->sc_nfans = smu_count_fans(dev);
+	if (sc->sc_nfans == 0)
+		return;
+
+	/* Now we're able to allocate memory for the fans struct. */
+	sc->sc_fans = malloc(sc->sc_nfans * sizeof(struct smu_fan), M_SMU,
+	    M_WAITOK | M_ZERO);
+
+	/* Now fill in the properties. */
+	smu_count_fans(dev);
+	
+	/* Register fans with pmac_thermal */
+	for (i = 0; i < sc->sc_nfans; i++)
+		pmac_thermal_fan_register(&sc->sc_fans[i].fan);
+
+	ctx = device_get_sysctl_ctx(dev);
+	fanroot_oid = SYSCTL_ADD_NODE(ctx,
+	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "fans",
+	    CTLFLAG_RD, 0, "SMU Fan Information");
+
+	/* Add sysctls */
+	for (i = 0; i < sc->sc_nfans; i++) {
+		fan = &sc->sc_fans[i];
+		for (j = 0; j < strlen(fan->fan.name); j++) {
+			sysctl_name[j] = tolower(fan->fan.name[j]);
+			if (isspace(sysctl_name[j]))
+				sysctl_name[j] = '_';
+		}
+		sysctl_name[j] = 0;
+		if (fan->type == SMU_FAN_RPM) {
+			oid = SYSCTL_ADD_NODE(ctx,
+					      SYSCTL_CHILDREN(fanroot_oid),
+					      OID_AUTO, sysctl_name,
+					      CTLFLAG_RD, 0, "Fan Information");
+			SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+				       "minrpm", CTLFLAG_RD,
+				       &fan->fan.min_rpm, 0,
+				       "Minimum allowed RPM");
+			SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+				       "maxrpm", CTLFLAG_RD,
+				       &fan->fan.max_rpm, 0,
+				       "Maximum allowed RPM");
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+					"rpm",CTLTYPE_INT | CTLFLAG_RW |
+					CTLFLAG_MPSAFE, dev, i,
+					smu_fanrpm_sysctl, "I", "Fan RPM");
+
+			fan->fan.read = (int (*)(struct pmac_fan *))smu_fan_read_rpm;
+			fan->fan.set = (int (*)(struct pmac_fan *, int))smu_fan_set_rpm;
+
+		} else {
+			oid = SYSCTL_ADD_NODE(ctx,
+					      SYSCTL_CHILDREN(fanroot_oid),
+					      OID_AUTO, sysctl_name,
+					      CTLFLAG_RD, 0, "Fan Information");
+			SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+				       "minpwm", CTLFLAG_RD,
+				       &fan->fan.min_rpm, 0,
+				       "Minimum allowed PWM in %");
+			SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+				       "maxpwm", CTLFLAG_RD,
+				       &fan->fan.max_rpm, 0,
+				       "Maximum allowed PWM in %");
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+					"pwm",CTLTYPE_INT | CTLFLAG_RW |
+					CTLFLAG_MPSAFE, dev,
+					SMU_PWM_SYSCTL_PWM | i,
+					smu_fanrpm_sysctl, "I", "Fan PWM in %");
+			SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+					"rpm",CTLTYPE_INT | CTLFLAG_RD |
+					CTLFLAG_MPSAFE, dev,
+					SMU_PWM_SYSCTL_RPM | i,
+					smu_fanrpm_sysctl, "I", "Fan RPM");
+			fan->fan.read = NULL;
+			fan->fan.set = (int (*)(struct pmac_fan *, int))smu_fan_set_pwm;
+
+		}
+		if (bootverbose)
+			device_printf(dev, "Fan: %s type: %d\n",
+				      fan->fan.name, fan->type);
+	}
+}
+
+static int
+smu_sensor_read(struct smu_sensor *sens)
+{
+	device_t smu = sens->dev;
+	struct smu_cmd cmd;
+	struct smu_softc *sc;
+	int64_t value;
+	int error;
+
+	cmd.cmd = SMU_ADC;
+	cmd.len = 1;
+	cmd.data[0] = sens->reg;
+	error = 0;
+
+	error = smu_run_cmd(smu, &cmd, 1);
+	if (error != 0)
+		return (-1);
+	
+	sc = device_get_softc(smu);
+	value = (cmd.data[0] << 8) | cmd.data[1];
+
+	switch (sens->type) {
+	case SMU_TEMP_SENSOR:
+		value *= sc->sc_cpu_diode_scale;
+		value >>= 3;
+		value += ((int64_t)sc->sc_cpu_diode_offset) << 9;
+		value <<= 1;
+
+		/* Convert from 16.16 fixed point degC into integer 0.1 K. */
+		value = 10*(value >> 16) + ((10*(value & 0xffff)) >> 16) + 2732;
+		break;
+	case SMU_VOLTAGE_SENSOR:
+		value *= sc->sc_cpu_volt_scale;
+		value += sc->sc_cpu_volt_offset;
+		value <<= 4;
+
+		/* Convert from 16.16 fixed point V into mV. */
+		value *= 15625;
+		value /= 1024;
+		value /= 1000;
+		break;
+	case SMU_CURRENT_SENSOR:
+		value *= sc->sc_cpu_curr_scale;
+		value += sc->sc_cpu_curr_offset;
+		value <<= 4;
+
+		/* Convert from 16.16 fixed point A into mA. */
+		value *= 15625;
+		value /= 1024;
+		value /= 1000;
+		break;
+	case SMU_POWER_SENSOR:
+		value *= sc->sc_slots_pow_scale;
+		value += sc->sc_slots_pow_offset;
+		value <<= 4;
+
+		/* Convert from 16.16 fixed point W into mW. */
+		value *= 15625;
+		value /= 1024;
+		value /= 1000;
+		break;
+	}
+
+	return (value);
+}
+
+static int
+smu_sensor_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	device_t smu;
+	struct smu_softc *sc;
+	struct smu_sensor *sens;
+	int value, error;
+
+	smu = arg1;
+	sc = device_get_softc(smu);
+	sens = &sc->sc_sensors[arg2];
+
+	value = smu_sensor_read(sens);
+	if (value < 0)
+		return (EBUSY);
+
+	error = sysctl_handle_int(oidp, &value, 0, req);
+
+	return (error);
+}
+
+static void
+smu_attach_sensors(device_t dev, phandle_t sensroot)
+{
+	struct smu_sensor *sens;
+	struct smu_softc *sc;
+	struct sysctl_oid *sensroot_oid;
+	struct sysctl_ctx_list *ctx;
+	phandle_t child;
+	char type[32];
+	int i;
+
+	sc = device_get_softc(dev);
+	sc->sc_nsensors = 0;
+
+	for (child = OF_child(sensroot); child != 0; child = OF_peer(child))
+		sc->sc_nsensors++;
+
+	if (sc->sc_nsensors == 0) {
+		device_printf(dev, "WARNING: No sensors detected!\n");
+		return;
+	}
+
+	sc->sc_sensors = malloc(sc->sc_nsensors * sizeof(struct smu_sensor),
+	    M_SMU, M_WAITOK | M_ZERO);
+
+	sens = sc->sc_sensors;
+	sc->sc_nsensors = 0;
+
+	ctx = device_get_sysctl_ctx(dev);
+	sensroot_oid = SYSCTL_ADD_NODE(ctx,
+	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "sensors",
+	    CTLFLAG_RD, 0, "SMU Sensor Information");
+
+	for (child = OF_child(sensroot); child != 0; child = OF_peer(child)) {
+		char sysctl_name[40], sysctl_desc[40];
+		const char *units;
+
+		sens->dev = dev;
+		OF_getprop(child, "device_type", type, sizeof(type));
+
+		if (strcmp(type, "current-sensor") == 0) {
+			sens->type = SMU_CURRENT_SENSOR;
+			units = "mA";
+		} else if (strcmp(type, "temp-sensor") == 0) {
+			sens->type = SMU_TEMP_SENSOR;
+			units = "C";
+		} else if (strcmp(type, "voltage-sensor") == 0) {
+			sens->type = SMU_VOLTAGE_SENSOR;
+			units = "mV";
+		} else if (strcmp(type, "power-sensor") == 0) {
+			sens->type = SMU_POWER_SENSOR;
+			units = "mW";
+		} else {
+			continue;
+		}
+
+		OF_getprop(child, "reg", &sens->reg, sizeof(cell_t));
+		OF_getprop(child, "zone", &sens->therm.zone, sizeof(int));
+		OF_getprop(child, "location", sens->therm.name,
+		    sizeof(sens->therm.name));
+
+		for (i = 0; i < strlen(sens->therm.name); i++) {
+			sysctl_name[i] = tolower(sens->therm.name[i]);
+			if (isspace(sysctl_name[i]))
+				sysctl_name[i] = '_';
+		}
+		sysctl_name[i] = 0;
+
+		sprintf(sysctl_desc,"%s (%s)", sens->therm.name, units);
+
+		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(sensroot_oid), OID_AUTO,
+		    sysctl_name, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+		    dev, sc->sc_nsensors, smu_sensor_sysctl, 
+		    (sens->type == SMU_TEMP_SENSOR) ? "IK" : "I", sysctl_desc);
+
+		if (sens->type == SMU_TEMP_SENSOR) {
+			/* Make up some numbers */
+			sens->therm.target_temp = 500 + 2732; /* 50 C */
+			sens->therm.max_temp = 900 + 2732; /* 90 C */
+
+			sens->therm.read =
+			    (int (*)(struct pmac_therm *))smu_sensor_read;
+			pmac_thermal_sensor_register(&sens->therm);
+		}
+
+		sens++;
+		sc->sc_nsensors++;
+	}
+}
+
+static void
+smu_set_sleepled(void *xdev, int onoff)
+{
+	static struct smu_cmd cmd;
+	device_t smu = xdev;
+
+	cmd.cmd = SMU_MISC;
+	cmd.len = 3;
+	cmd.data[0] = SMU_MISC_LED_CTRL;
+	cmd.data[1] = 0;
+	cmd.data[2] = onoff; 
+
+	smu_run_cmd(smu, &cmd, 0);
+}
+
+static int
+smu_server_mode(SYSCTL_HANDLER_ARGS)
+{
+	struct smu_cmd cmd;
+	u_int server_mode;
+	device_t smu = arg1;
+	int error;
+	
+	cmd.cmd = SMU_POWER_EVENTS;
+	cmd.len = 1;
+	cmd.data[0] = SMU_PWR_GET_POWERUP;
+
+	error = smu_run_cmd(smu, &cmd, 1);
+
+	if (error)
+		return (error);
+
+	server_mode = (cmd.data[1] & SMU_WAKEUP_AC_INSERT) ? 1 : 0;
+
+	error = sysctl_handle_int(oidp, &server_mode, 0, req);
+
+	if (error || !req->newptr)
+		return (error);
+
+	if (server_mode == 1)
+		cmd.data[0] = SMU_PWR_SET_POWERUP;
+	else if (server_mode == 0)
+		cmd.data[0] = SMU_PWR_CLR_POWERUP;
+	else
+		return (EINVAL);
+
+	cmd.len = 3;
+	cmd.data[1] = 0;
+	cmd.data[2] = SMU_WAKEUP_AC_INSERT;
+
+	return (smu_run_cmd(smu, &cmd, 1));
+}
+
+static void
+smu_shutdown(void *xdev, int howto)
+{
+	device_t smu = xdev;
+	struct smu_cmd cmd;
+
+	cmd.cmd = SMU_POWER;
+	if (howto & RB_HALT)
+		strcpy(cmd.data, "SHUTDOWN");
+	else
+		strcpy(cmd.data, "RESTART");
+
+	cmd.len = strlen(cmd.data);
+
+	smu_run_cmd(smu, &cmd, 1);
+
+	for (;;);
+}
+
+static int
+smu_gettime(device_t dev, struct timespec *ts)
+{
+	struct smu_cmd cmd;
+	struct clocktime ct;
+
+	cmd.cmd = SMU_RTC;
+	cmd.len = 1;
+	cmd.data[0] = SMU_RTC_GET;
+
+	if (smu_run_cmd(dev, &cmd, 1) != 0)
+		return (ENXIO);
+
+	ct.nsec	= 0;
+	ct.sec	= bcd2bin(cmd.data[0]);
+	ct.min	= bcd2bin(cmd.data[1]);
+	ct.hour	= bcd2bin(cmd.data[2]);
+	ct.dow	= bcd2bin(cmd.data[3]);
+	ct.day	= bcd2bin(cmd.data[4]);
+	ct.mon	= bcd2bin(cmd.data[5]);
+	ct.year	= bcd2bin(cmd.data[6]) + 2000;
+
+	return (clock_ct_to_ts(&ct, ts));
+}
+
+static int
+smu_settime(device_t dev, struct timespec *ts)
+{
+	static struct smu_cmd cmd;
+	struct clocktime ct;
+
+	cmd.cmd = SMU_RTC;
+	cmd.len = 8;
+	cmd.data[0] = SMU_RTC_SET;
+
+	clock_ts_to_ct(ts, &ct);
+
+	cmd.data[1] = bin2bcd(ct.sec);
+	cmd.data[2] = bin2bcd(ct.min);
+	cmd.data[3] = bin2bcd(ct.hour);
+	cmd.data[4] = bin2bcd(ct.dow);
+	cmd.data[5] = bin2bcd(ct.day);
+	cmd.data[6] = bin2bcd(ct.mon);
+	cmd.data[7] = bin2bcd(ct.year - 2000);
+
+	return (smu_run_cmd(dev, &cmd, 0));
+}
+
+/* SMU I2C Interface */
+
+static int smuiic_probe(device_t dev);
+static int smuiic_attach(device_t dev);
+static int smuiic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs);
+static phandle_t smuiic_get_node(device_t bus, device_t dev);
+
+static device_method_t smuiic_methods[] = {
+	/* device interface */
+	DEVMETHOD(device_probe,         smuiic_probe),
+	DEVMETHOD(device_attach,        smuiic_attach),
+
+	/* iicbus interface */
+	DEVMETHOD(iicbus_callback,      iicbus_null_callback),
+	DEVMETHOD(iicbus_transfer,      smuiic_transfer),
+
+	/* ofw_bus interface */
+	DEVMETHOD(ofw_bus_get_node,     smuiic_get_node),
+
+	{ 0, 0 }
+};
+
+struct smuiic_softc {
+	struct mtx	sc_mtx;
+	volatile int	sc_iic_inuse;
+	int		sc_busno;
+};
+
+static driver_t smuiic_driver = {
+	"iichb",
+	smuiic_methods,
+	sizeof(struct smuiic_softc)
+};
+static devclass_t smuiic_devclass;
+
+DRIVER_MODULE(smuiic, smu, smuiic_driver, smuiic_devclass, 0, 0);
+
+static void
+smu_attach_i2c(device_t smu, phandle_t i2croot)
+{
+	phandle_t child;
+	device_t cdev;
+	struct ofw_bus_devinfo *dinfo;
+	char name[32];
+
+	for (child = OF_child(i2croot); child != 0; child = OF_peer(child)) {
+		if (OF_getprop(child, "name", name, sizeof(name)) <= 0)
+			continue;
+
+		if (strcmp(name, "i2c-bus") != 0 && strcmp(name, "i2c") != 0)
+			continue;
+
+		dinfo = malloc(sizeof(struct ofw_bus_devinfo), M_SMU,
+		    M_WAITOK | M_ZERO);
+		if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) {
+			free(dinfo, M_SMU);
+			continue;
+		}
+
+		cdev = device_add_child(smu, NULL, -1);
+		if (cdev == NULL) {
+			device_printf(smu, "<%s>: device_add_child failed\n",
+			    dinfo->obd_name);
+			ofw_bus_gen_destroy_devinfo(dinfo);
+			free(dinfo, M_SMU);
+			continue;
+		}
+		device_set_ivars(cdev, dinfo);
+	}
+}
+
+static int
+smuiic_probe(device_t dev)
+{
+	const char *name;
+
+	name = ofw_bus_get_name(dev);
+	if (name == NULL)
+		return (ENXIO);
+
+	if (strcmp(name, "i2c-bus") == 0 || strcmp(name, "i2c") == 0) {
+		device_set_desc(dev, "SMU I2C controller");
+		return (0);
+	}
+
+	return (ENXIO);
+}
+
+static int
+smuiic_attach(device_t dev)
+{
+	struct smuiic_softc *sc = device_get_softc(dev);
+	mtx_init(&sc->sc_mtx, "smuiic", NULL, MTX_DEF);
+	sc->sc_iic_inuse = 0;
+
+	/* Get our bus number */
+	OF_getprop(ofw_bus_get_node(dev), "reg", &sc->sc_busno,
+	    sizeof(sc->sc_busno));
+
+	/* Add the IIC bus layer */
+	device_add_child(dev, "iicbus", -1);
+
+	return (bus_generic_attach(dev));
+}
+
+static int
+smuiic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
+{
+	struct smuiic_softc *sc = device_get_softc(dev);
+	struct smu_cmd cmd;
+	int i, j, error;
+
+	mtx_lock(&sc->sc_mtx);
+	while (sc->sc_iic_inuse)
+		mtx_sleep(sc, &sc->sc_mtx, 0, "smuiic", 100);
+
+	sc->sc_iic_inuse = 1;
+	error = 0;
+
+	for (i = 0; i < nmsgs; i++) {
+		cmd.cmd = SMU_I2C;
+		cmd.data[0] = sc->sc_busno;
+		if (msgs[i].flags & IIC_M_NOSTOP)
+			cmd.data[1] = SMU_I2C_COMBINED;
+		else
+			cmd.data[1] = SMU_I2C_SIMPLE;
+
+		cmd.data[2] = msgs[i].slave;
+		if (msgs[i].flags & IIC_M_RD)
+			cmd.data[2] |= 1; 
+
+		if (msgs[i].flags & IIC_M_NOSTOP) {
+			KASSERT(msgs[i].len < 4,
+			    ("oversize I2C combined message"));
+
+			cmd.data[3] = min(msgs[i].len, 3);
+			memcpy(&cmd.data[4], msgs[i].buf, min(msgs[i].len, 3));
+			i++; /* Advance to next part of message */
+		} else {
+			cmd.data[3] = 0;
+			memset(&cmd.data[4], 0, 3);
+		}
+
+		cmd.data[7] = msgs[i].slave;
+		if (msgs[i].flags & IIC_M_RD)
+			cmd.data[7] |= 1; 
+
+		cmd.data[8] = msgs[i].len;
+		if (msgs[i].flags & IIC_M_RD) {
+			memset(&cmd.data[9], 0xff, msgs[i].len);
+			cmd.len = 9;
+		} else {
+			memcpy(&cmd.data[9], msgs[i].buf, msgs[i].len);
+			cmd.len = 9 + msgs[i].len;
+		}
+
+		mtx_unlock(&sc->sc_mtx);
+		smu_run_cmd(device_get_parent(dev), &cmd, 1);
+		mtx_lock(&sc->sc_mtx);
+
+		for (j = 0; j < 10; j++) {
+			cmd.cmd = SMU_I2C;
+			cmd.len = 1;
+			cmd.data[0] = 0;
+			memset(&cmd.data[1], 0xff, msgs[i].len);
+			
+			mtx_unlock(&sc->sc_mtx);
+			smu_run_cmd(device_get_parent(dev), &cmd, 1);
+			mtx_lock(&sc->sc_mtx);
+			
+			if (!(cmd.data[0] & 0x80))
+				break;
+
+			mtx_sleep(sc, &sc->sc_mtx, 0, "smuiic", 10);
+		}
+		
+		if (cmd.data[0] & 0x80) {
+			error = EIO;
+			msgs[i].len = 0;
+			goto exit;
+		}
+		memcpy(msgs[i].buf, &cmd.data[1], msgs[i].len);
+		msgs[i].len = cmd.len - 1;
+	}
+
+    exit:
+	sc->sc_iic_inuse = 0;
+	mtx_unlock(&sc->sc_mtx);
+	wakeup(sc);
+	return (error);
+}
+
+static phandle_t
+smuiic_get_node(device_t bus, device_t dev)
+{
+
+	return (ofw_bus_get_node(bus));
+}
+


Property changes on: trunk/sys/powerpc/powermac/smu.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/smusat.c
===================================================================
--- trunk/sys/powerpc/powermac/smusat.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/smusat.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,294 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 Nathan Whitehorn
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/smusat.c 231770 2012-02-15 16:59:24Z nwhitehorn $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/cpu.h>
+#include <sys/ctype.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
+
+#include <powerpc/powermac/powermac_thermal.h>
+
+struct smu_sensor {
+	struct pmac_therm therm;
+	device_t dev;
+
+	cell_t	reg;
+	enum {
+		SMU_CURRENT_SENSOR,
+		SMU_VOLTAGE_SENSOR,
+		SMU_POWER_SENSOR,
+		SMU_TEMP_SENSOR
+	} type;
+};
+
+static int	smusat_probe(device_t);
+static int	smusat_attach(device_t);
+static int	smusat_sensor_sysctl(SYSCTL_HANDLER_ARGS);
+static int	smusat_sensor_read(struct smu_sensor *sens);
+
+static MALLOC_DEFINE(M_SMUSAT, "smusat", "SMU Sattelite Sensors");
+
+static device_method_t  smusat_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		smusat_probe),
+	DEVMETHOD(device_attach,	smusat_attach),
+	{ 0, 0 },
+};
+
+struct smusat_softc {
+	struct smu_sensor *sc_sensors;
+	int	sc_nsensors;
+
+	uint8_t	sc_cache[16];
+	time_t	sc_last_update;
+};
+
+static driver_t smusat_driver = {
+	"smusat",
+	smusat_methods,
+	sizeof(struct smusat_softc)
+};
+
+static devclass_t smusat_devclass;
+
+DRIVER_MODULE(smusat, iicbus, smusat_driver, smusat_devclass, 0, 0);
+
+static int
+smusat_probe(device_t dev)
+{
+	const char *compat = ofw_bus_get_compat(dev);
+
+	if (compat == NULL || strcmp(compat, "smu-sat") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "SMU Satellite Sensors");
+	return (0);
+}
+
+static int
+smusat_attach(device_t dev)
+{
+	phandle_t child;
+	struct smu_sensor *sens;
+	struct smusat_softc *sc;
+	struct sysctl_oid *sensroot_oid;
+	struct sysctl_ctx_list *ctx;
+	char type[32];
+	int i;
+
+	sc = device_get_softc(dev);
+	sc->sc_nsensors = 0;
+	sc->sc_last_update = 0;
+
+	for (child = OF_child(ofw_bus_get_node(dev)); child != 0;
+	    child = OF_peer(child))
+		sc->sc_nsensors++;
+
+	if (sc->sc_nsensors == 0) {
+		device_printf(dev, "WARNING: No sensors detected!\n");
+		return (-1);
+	}
+	    
+	sc->sc_sensors = malloc(sc->sc_nsensors * sizeof(struct smu_sensor),
+	    M_SMUSAT, M_WAITOK | M_ZERO);
+
+	sens = sc->sc_sensors;
+	sc->sc_nsensors = 0;
+
+	ctx = device_get_sysctl_ctx(dev);
+	sensroot_oid = device_get_sysctl_tree(dev);
+
+	for (child = OF_child(ofw_bus_get_node(dev)); child != 0;
+	    child = OF_peer(child)) {
+		char sysctl_name[40], sysctl_desc[40];
+		const char *units;
+
+		sens->dev = dev;
+		sens->reg = 0;
+		OF_getprop(child, "reg", &sens->reg, sizeof(sens->reg));
+		if (sens->reg < 0x30)
+			continue;
+		sens->reg -= 0x30;
+
+		OF_getprop(child, "zone", &sens->therm.zone, sizeof(int));
+		OF_getprop(child, "location", sens->therm.name,
+		    sizeof(sens->therm.name));
+
+		OF_getprop(child, "device_type", type, sizeof(type));
+
+		if (strcmp(type, "current-sensor") == 0) {
+			sens->type = SMU_CURRENT_SENSOR;
+			units = "mA";
+		} else if (strcmp(type, "temp-sensor") == 0) {
+			sens->type = SMU_TEMP_SENSOR;
+			units = "C";
+		} else if (strcmp(type, "voltage-sensor") == 0) {
+			sens->type = SMU_VOLTAGE_SENSOR;
+			units = "mV";
+		} else if (strcmp(type, "power-sensor") == 0) {
+			sens->type = SMU_POWER_SENSOR;
+			units = "mW";
+		} else {
+			continue;
+		}
+
+		for (i = 0; i < strlen(sens->therm.name); i++) {
+			sysctl_name[i] = tolower(sens->therm.name[i]);
+			if (isspace(sysctl_name[i]))
+				sysctl_name[i] = '_';
+		}
+		sysctl_name[i] = 0;
+
+		sprintf(sysctl_desc,"%s (%s)", sens->therm.name, units);
+		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(sensroot_oid), OID_AUTO,
+		    sysctl_name, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev,
+		    sc->sc_nsensors, smusat_sensor_sysctl,
+		    (sens->type == SMU_TEMP_SENSOR) ? "IK" : "I", sysctl_desc);
+
+		if (sens->type == SMU_TEMP_SENSOR) {
+			/* Make up some numbers */
+			sens->therm.target_temp = 500 + 2732; /* 50 C */
+			sens->therm.max_temp = 900 + 2732; /* 90 C */
+			sens->therm.read =
+			    (int (*)(struct pmac_therm *))smusat_sensor_read;
+			pmac_thermal_sensor_register(&sens->therm);
+		}
+
+		sens++;
+		sc->sc_nsensors++;
+	}
+
+	return (0);
+}
+
+static int
+smusat_updatecache(device_t dev)
+{
+	uint8_t reg = 0x3f;
+	uint8_t	value[16];
+	struct smusat_softc *sc = device_get_softc(dev);
+	int error;
+	struct iic_msg msgs[2] = {
+	    {0, IIC_M_WR | IIC_M_NOSTOP, 1, &reg},
+	    {0, IIC_M_RD, 16, value},
+	};
+
+	msgs[0].slave = msgs[1].slave = iicbus_get_addr(dev);
+	error = iicbus_transfer(dev, msgs, 2);
+	if (error)
+		return (error);
+
+	sc->sc_last_update = time_uptime;
+	memcpy(sc->sc_cache, value, sizeof(value));
+	return (0);
+}
+
+static int
+smusat_sensor_read(struct smu_sensor *sens)
+{
+	int value, error;
+	device_t dev;
+	struct smusat_softc *sc;
+
+	dev = sens->dev;
+	sc = device_get_softc(dev);
+	error = 0;
+
+	if (time_uptime - sc->sc_last_update > 1)
+		error = smusat_updatecache(dev);
+	if (error)
+		return (-error);
+
+	value = (sc->sc_cache[sens->reg*2] << 8) +
+	    sc->sc_cache[sens->reg*2 + 1];
+	if (value == 0xffff) {
+		sc->sc_last_update = 0; /* Result was bad, don't cache */
+		return (-EINVAL);
+	}
+
+	switch (sens->type) {
+	case SMU_TEMP_SENSOR:
+		/* 16.16 */
+		value <<= 10;
+		/* From 16.16 to 0.1 C */
+		value = 10*(value >> 16) + ((10*(value & 0xffff)) >> 16) + 2732;
+		break;
+	case SMU_VOLTAGE_SENSOR:
+		/* 16.16 */
+		value <<= 4;
+		/* Kill the .16 */
+		value >>= 16;
+		break;
+	case SMU_CURRENT_SENSOR:
+		/* 16.16 */
+		value <<= 8;
+		/* Kill the .16 */
+		value >>= 16;
+		break;
+	case SMU_POWER_SENSOR:
+		/* Doesn't exist */
+		break;
+	}
+
+	return (value);
+}
+
+static int
+smusat_sensor_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	device_t dev;
+	struct smusat_softc *sc;
+	struct smu_sensor *sens;
+	int value, error;
+
+	dev = arg1;
+	sc = device_get_softc(dev);
+	sens = &sc->sc_sensors[arg2];
+
+	value = smusat_sensor_read(sens);
+	if (value < 0)
+		return (EBUSY);
+
+	error = sysctl_handle_int(oidp, &value, 0, req);
+
+	return (error);
+}
+


Property changes on: trunk/sys/powerpc/powermac/smusat.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/uninorth.c
===================================================================
--- trunk/sys/powerpc/powermac/uninorth.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/uninorth.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,673 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2002 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/uninorth.c 266160 2014-05-15 17:30:16Z ian $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <sys/rman.h>
+
+#include <powerpc/powermac/uninorthvar.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+/*
+ * Driver for the Uninorth chip itself.
+ */
+
+static MALLOC_DEFINE(M_UNIN, "unin", "unin device information");
+
+/*
+ * Device interface.
+ */
+
+static int  unin_chip_probe(device_t);
+static int  unin_chip_attach(device_t);
+
+/*
+ * Bus interface.
+ */
+static int  unin_chip_print_child(device_t dev, device_t child);
+static void unin_chip_probe_nomatch(device_t, device_t);
+static struct resource *unin_chip_alloc_resource(device_t, device_t, int, int *,
+						 u_long, u_long, u_long, u_int);
+static int  unin_chip_activate_resource(device_t, device_t, int, int,
+					struct resource *);
+static int  unin_chip_deactivate_resource(device_t, device_t, int, int,
+					  struct resource *);
+static int  unin_chip_release_resource(device_t, device_t, int, int,
+				       struct resource *);
+static struct resource_list *unin_chip_get_resource_list (device_t, device_t);
+
+/*
+ * OFW Bus interface
+ */
+
+static ofw_bus_get_devinfo_t unin_chip_get_devinfo;
+
+/*
+ * Local routines
+ */
+
+static void		unin_enable_gmac(device_t dev);
+static void		unin_enable_mpic(device_t dev);
+
+/*
+ * Driver methods.
+ */
+static device_method_t unin_chip_methods[] = {
+
+	/* Device interface */
+	DEVMETHOD(device_probe,         unin_chip_probe),
+	DEVMETHOD(device_attach,        unin_chip_attach),
+
+	/* Bus interface */
+	DEVMETHOD(bus_print_child,      unin_chip_print_child),
+	DEVMETHOD(bus_probe_nomatch,    unin_chip_probe_nomatch),
+	DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
+
+	DEVMETHOD(bus_alloc_resource,   unin_chip_alloc_resource),
+	DEVMETHOD(bus_release_resource, unin_chip_release_resource),
+	DEVMETHOD(bus_activate_resource, unin_chip_activate_resource),
+	DEVMETHOD(bus_deactivate_resource, unin_chip_deactivate_resource),
+	DEVMETHOD(bus_get_resource_list, unin_chip_get_resource_list),
+
+	DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
+
+        /* ofw_bus interface */
+	DEVMETHOD(ofw_bus_get_devinfo,	unin_chip_get_devinfo),
+	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
+	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
+	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
+	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
+	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
+
+	{ 0, 0 }
+};
+
+static driver_t	unin_chip_driver = {
+	"unin",
+	unin_chip_methods,
+	sizeof(struct unin_chip_softc)
+};
+
+static devclass_t	unin_chip_devclass;
+
+/*
+ * Assume there is only one unin chip in a PowerMac, so that pmu.c functions can
+ * suspend the chip after the whole rest of the device tree is suspended, not
+ * earlier.
+ */
+static device_t		unin_chip;
+
+DRIVER_MODULE(unin, ofwbus, unin_chip_driver, unin_chip_devclass, 0, 0);
+
+/*
+ * Add an interrupt to the dev's resource list if present
+ */
+static void
+unin_chip_add_intr(phandle_t devnode, struct unin_chip_devinfo *dinfo)
+{
+	phandle_t iparent;
+	int	*intr;
+	int	i, nintr;
+	int 	icells;
+
+	if (dinfo->udi_ninterrupts >= 6) {
+		printf("unin: device has more than 6 interrupts\n");
+		return;
+	}
+
+	nintr = OF_getprop_alloc(devnode, "interrupts", sizeof(*intr), 
+		(void **)&intr);
+	if (nintr == -1) {
+		nintr = OF_getprop_alloc(devnode, "AAPL,interrupts", 
+			sizeof(*intr), (void **)&intr);
+		if (nintr == -1)
+			return;
+	}
+
+	if (intr[0] == -1)
+		return;
+
+	if (OF_getprop(devnode, "interrupt-parent", &iparent, sizeof(iparent))
+	    <= 0)
+		panic("Interrupt but no interrupt parent!\n");
+
+	if (OF_searchprop(iparent, "#interrupt-cells", &icells, sizeof(icells))
+	    <= 0)
+		icells = 1;
+
+	for (i = 0; i < nintr; i+=icells) {
+		u_int irq = MAP_IRQ(iparent, intr[i]);
+
+		resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
+		    dinfo->udi_ninterrupts, irq, irq, 1);
+
+		if (icells > 1) {
+			powerpc_config_intr(irq,
+			    (intr[i+1] & 1) ? INTR_TRIGGER_LEVEL :
+			    INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);
+		}
+
+		dinfo->udi_interrupts[dinfo->udi_ninterrupts] = irq;
+		dinfo->udi_ninterrupts++;
+	}
+}
+
+static void
+unin_chip_add_reg(phandle_t devnode, struct unin_chip_devinfo *dinfo)
+{
+	struct	unin_chip_reg *reg;
+	int	i, nreg;
+
+	nreg = OF_getprop_alloc(devnode, "reg", sizeof(*reg), (void **)&reg);
+	if (nreg == -1)
+		return;
+
+	for (i = 0; i < nreg; i++) {
+		resource_list_add(&dinfo->udi_resources, SYS_RES_MEMORY, i,
+				  reg[i].mr_base,
+				  reg[i].mr_base + reg[i].mr_size,
+				  reg[i].mr_size);
+	}
+}
+
+static void
+unin_update_reg(device_t dev, uint32_t regoff, uint32_t set, uint32_t clr)
+{
+	volatile u_int *reg;
+	struct unin_chip_softc *sc;
+	u_int32_t tmpl;
+
+	sc = device_get_softc(dev);
+	reg = (void *)(sc->sc_addr + regoff);
+	tmpl = inl(reg);
+	tmpl &= ~clr;
+	tmpl |= set;
+	outl(reg, tmpl);
+}
+
+static void
+unin_enable_gmac(device_t dev)
+{
+	unin_update_reg(dev, UNIN_CLOCKCNTL, UNIN_CLOCKCNTL_GMAC, 0);
+}
+
+static void
+unin_enable_mpic(device_t dev)
+{
+	unin_update_reg(dev, UNIN_TOGGLE_REG, UNIN_MPIC_RESET | UNIN_MPIC_OUTPUT_ENABLE, 0);
+}
+
+static int
+unin_chip_probe(device_t dev)
+{
+	const char	*name;
+
+	name = ofw_bus_get_name(dev);
+
+	if (name == NULL)
+		return (ENXIO);
+
+	if (strcmp(name, "uni-n") != 0 && strcmp(name, "u3") != 0
+	    && strcmp(name, "u4") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "Apple UniNorth System Controller");
+	return (0);
+}
+
+static int
+unin_chip_attach(device_t dev)
+{
+	struct unin_chip_softc *sc;
+	struct unin_chip_devinfo *dinfo;
+	phandle_t  root;
+	phandle_t  child;
+	phandle_t  iparent;
+	device_t   cdev;
+	cell_t     acells, scells;
+	char compat[32];
+	char name[32];
+	u_int irq, reg[3];
+	int error, i = 0;
+
+	sc = device_get_softc(dev);
+	root = ofw_bus_get_node(dev);
+
+	if (OF_getprop(root, "reg", reg, sizeof(reg)) < 8)
+		return (ENXIO);
+
+	acells = scells = 1;
+	OF_getprop(OF_parent(root), "#address-cells", &acells, sizeof(acells));
+	OF_getprop(OF_parent(root), "#size-cells", &scells, sizeof(scells));
+
+	i = 0;
+	sc->sc_physaddr = reg[i++];
+	if (acells == 2) {
+		sc->sc_physaddr <<= 32;
+		sc->sc_physaddr |= reg[i++];
+	}
+	sc->sc_size = reg[i++];
+	if (scells == 2) {
+		sc->sc_size <<= 32;
+		sc->sc_size |= reg[i++];
+	}
+
+	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+	sc->sc_mem_rman.rm_descr = "UniNorth Device Memory";
+
+	error = rman_init(&sc->sc_mem_rman);
+
+	if (error) {
+		device_printf(dev, "rman_init() failed. error = %d\n", error);
+		return (error);
+	}
+
+	error = rman_manage_region(&sc->sc_mem_rman, sc->sc_physaddr,
+				   sc->sc_physaddr + sc->sc_size - 1);	
+	if (error) {
+		device_printf(dev,
+			      "rman_manage_region() failed. error = %d\n",
+			      error);
+		return (error);
+	}
+
+	if (unin_chip == NULL)
+		unin_chip = dev;
+
+        /*
+	 * Iterate through the sub-devices
+	 */
+	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
+		dinfo = malloc(sizeof(*dinfo), M_UNIN, M_WAITOK | M_ZERO);
+		if (ofw_bus_gen_setup_devinfo(&dinfo->udi_obdinfo, child)
+		    != 0)
+		{
+			free(dinfo, M_UNIN);
+			continue;
+		}
+
+		resource_list_init(&dinfo->udi_resources);
+		dinfo->udi_ninterrupts = 0;
+		unin_chip_add_intr(child, dinfo);
+
+		/*
+		 * Some Apple machines do have a bug in OF, they miss
+		 * the interrupt entries on the U3 I2C node. That means they
+		 * do not have an entry with number of interrupts nor the
+		 * entry of the interrupt parent handle.
+		 * We define an interrupt and hardwire it to the /u3/mpic
+		 * handle.
+		 */
+
+		if (OF_getprop(child, "name", name, sizeof(name)) <= 0)
+			device_printf(dev, "device has no name!\n");
+		if (dinfo->udi_ninterrupts == 0 &&
+		    (strcmp(name, "i2c-bus") == 0 ||
+		     strcmp(name, "i2c")  == 0)) {
+			if (OF_getprop(child, "interrupt-parent", &iparent,
+				       sizeof(iparent)) <= 0) {
+				iparent = OF_finddevice("/u3/mpic");
+				device_printf(dev, "Set /u3/mpic as iparent!\n");
+			}
+			/* Add an interrupt number 0 to the parent. */
+			irq = MAP_IRQ(iparent, 0);
+			resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
+					  dinfo->udi_ninterrupts, irq, irq, 1);
+			dinfo->udi_interrupts[dinfo->udi_ninterrupts] = irq;
+			dinfo->udi_ninterrupts++;
+		}
+
+		unin_chip_add_reg(child, dinfo);
+
+		cdev = device_add_child(dev, NULL, -1);
+		if (cdev == NULL) {
+			device_printf(dev, "<%s>: device_add_child failed\n",
+				      dinfo->udi_obdinfo.obd_name);
+			resource_list_free(&dinfo->udi_resources);
+			ofw_bus_gen_destroy_devinfo(&dinfo->udi_obdinfo);
+			free(dinfo, M_UNIN);
+			continue;
+		}
+
+		device_set_ivars(cdev, dinfo);
+	}
+
+	/*
+	 * Only map the first page, since that is where the registers
+	 * of interest lie.
+	 */
+	sc->sc_addr = (vm_offset_t)pmap_mapdev(sc->sc_physaddr, PAGE_SIZE);
+
+	sc->sc_version = *(u_int *)sc->sc_addr;
+	device_printf(dev, "Version %d\n", sc->sc_version);
+
+	/*
+	 * Enable the GMAC Ethernet cell and the integrated OpenPIC
+	 * if Open Firmware says they are used.
+	 */
+	for (child = OF_child(root); child; child = OF_peer(child)) {
+		memset(compat, 0, sizeof(compat));
+		OF_getprop(child, "compatible", compat, sizeof(compat));
+		if (strcmp(compat, "gmac") == 0)
+			unin_enable_gmac(dev);
+		if (strcmp(compat, "chrp,open-pic") == 0)
+			unin_enable_mpic(dev);
+	}
+	
+	/*
+	 * GMAC lives under the PCI bus, so just check if enet is gmac.
+	 */
+	child = OF_finddevice("enet");
+	memset(compat, 0, sizeof(compat));
+	OF_getprop(child, "compatible", compat, sizeof(compat));
+	if (strcmp(compat, "gmac") == 0)
+		unin_enable_gmac(dev);
+
+	return (bus_generic_attach(dev));
+}
+
+static int
+unin_chip_print_child(device_t dev, device_t child)
+{
+        struct unin_chip_devinfo *dinfo;
+        struct resource_list *rl;
+        int retval = 0;
+
+        dinfo = device_get_ivars(child);
+        rl = &dinfo->udi_resources;
+
+        retval += bus_print_child_header(dev, child);
+
+        retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
+        retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+
+        retval += bus_print_child_footer(dev, child);
+
+        return (retval);
+}
+
+static void
+unin_chip_probe_nomatch(device_t dev, device_t child)
+{
+        struct unin_chip_devinfo *dinfo;
+        struct resource_list *rl;
+	const char *type;
+
+	if (bootverbose) {
+		dinfo = device_get_ivars(child);
+		rl = &dinfo->udi_resources;
+
+		if ((type = ofw_bus_get_type(child)) == NULL)
+			type = "(unknown)";
+		device_printf(dev, "<%s, %s>", type, ofw_bus_get_name(child));
+		resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
+		resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+		printf(" (no driver attached)\n");
+	}
+}
+
+
+static struct resource *
+unin_chip_alloc_resource(device_t bus, device_t child, int type, int *rid,
+			 u_long start, u_long end, u_long count, u_int flags)
+{
+	struct		unin_chip_softc *sc;
+	int		needactivate;
+	struct		resource *rv;
+	struct		rman *rm;
+	u_long		adjstart, adjend, adjcount;
+	struct		unin_chip_devinfo *dinfo;
+	struct		resource_list_entry *rle;
+
+	sc = device_get_softc(bus);
+	dinfo = device_get_ivars(child);
+
+	needactivate = flags & RF_ACTIVE;
+	flags &= ~RF_ACTIVE;
+
+	switch (type) {
+	case SYS_RES_MEMORY:
+	case SYS_RES_IOPORT:
+		rle = resource_list_find(&dinfo->udi_resources, SYS_RES_MEMORY,
+					 *rid);
+		if (rle == NULL) {
+			device_printf(bus, "no rle for %s memory %d\n",
+				      device_get_nameunit(child), *rid);
+			return (NULL);
+		}
+
+		rle->end = rle->end - 1; /* Hack? */
+
+		if (start < rle->start)
+			adjstart = rle->start;
+		else if (start > rle->end)
+			adjstart = rle->end;
+		else
+			adjstart = start;
+
+		if (end < rle->start)
+			adjend = rle->start;
+		else if (end > rle->end)
+			adjend = rle->end;
+		else
+			adjend = end;
+
+		adjcount = adjend - adjstart;
+
+		rm = &sc->sc_mem_rman;
+		break;
+
+	case SYS_RES_IRQ:
+		/* Check for passthrough from subattachments. */
+		if (device_get_parent(child) != bus)
+			return BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
+						  type, rid, start, end, count,
+						  flags);
+
+		rle = resource_list_find(&dinfo->udi_resources, SYS_RES_IRQ,
+		    *rid);
+		if (rle == NULL) {
+			if (dinfo->udi_ninterrupts >= 6) {
+				device_printf(bus,
+					      "%s has more than 6 interrupts\n",
+					      device_get_nameunit(child));
+				return (NULL);
+			}
+			resource_list_add(&dinfo->udi_resources, SYS_RES_IRQ,
+					  dinfo->udi_ninterrupts, start, start,
+					  1);
+
+			dinfo->udi_interrupts[dinfo->udi_ninterrupts] = start;
+			dinfo->udi_ninterrupts++;
+		}
+
+		return (resource_list_alloc(&dinfo->udi_resources, bus, child,
+					    type, rid, start, end, count,
+					    flags));
+	default:
+		device_printf(bus, "unknown resource request from %s\n",
+			      device_get_nameunit(child));
+		return (NULL);
+	}
+
+	rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags,
+				   child);
+	if (rv == NULL) {
+		device_printf(bus,
+			      "failed to reserve resource %#lx - %#lx (%#lx)"
+			      " for %s\n", adjstart, adjend, adjcount,
+			      device_get_nameunit(child));
+		return (NULL);
+	}
+
+	rman_set_rid(rv, *rid);
+
+	if (needactivate) {
+		if (bus_activate_resource(child, type, *rid, rv) != 0) {
+                        device_printf(bus,
+				      "failed to activate resource for %s\n",
+				      device_get_nameunit(child));
+			rman_release_resource(rv);
+			return (NULL);
+                }
+        }
+
+	return (rv);
+}
+
+static int
+unin_chip_release_resource(device_t bus, device_t child, int type, int rid,
+			   struct resource *res)
+{
+	if (rman_get_flags(res) & RF_ACTIVE) {
+		int error = bus_deactivate_resource(child, type, rid, res);
+		if (error)
+			return error;
+	}
+
+	return (rman_release_resource(res));
+}
+
+static int
+unin_chip_activate_resource(device_t bus, device_t child, int type, int rid,
+			    struct resource *res)
+{
+	void    *p;
+
+	if (type == SYS_RES_IRQ)
+                return (bus_activate_resource(bus, type, rid, res));
+
+	if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
+		vm_offset_t start;
+
+		start = (vm_offset_t) rman_get_start(res);
+
+		if (bootverbose)
+			printf("unin mapdev: start %zx, len %ld\n", start,
+			       rman_get_size(res));
+
+		p = pmap_mapdev(start, (vm_size_t) rman_get_size(res));
+		if (p == NULL)
+			return (ENOMEM);
+		rman_set_virtual(res, p);
+		rman_set_bustag(res, &bs_be_tag);
+		rman_set_bushandle(res, (u_long)p);
+	}
+
+	return (rman_activate_resource(res));
+}
+
+
+static int
+unin_chip_deactivate_resource(device_t bus, device_t child, int type, int rid,
+			      struct resource *res)
+{
+        /*
+         * If this is a memory resource, unmap it.
+         */
+        if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
+		u_int32_t psize;
+		
+		psize = rman_get_size(res);
+		pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize);
+	}
+
+	return (rman_deactivate_resource(res));
+}
+
+
+static struct resource_list *
+unin_chip_get_resource_list (device_t dev, device_t child)
+{
+	struct unin_chip_devinfo *dinfo;
+
+	dinfo = device_get_ivars(child);
+	return (&dinfo->udi_resources);
+}
+
+static const struct ofw_bus_devinfo *
+unin_chip_get_devinfo(device_t dev, device_t child)
+{
+	struct unin_chip_devinfo *dinfo;
+
+	dinfo = device_get_ivars(child);
+	return (&dinfo->udi_obdinfo);
+}
+
+int
+unin_chip_wake(device_t dev)
+{
+
+	if (dev == NULL)
+		dev = unin_chip;
+	unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_NORMAL, UNIN_PWR_MASK);
+	DELAY(10);
+	unin_update_reg(dev, UNIN_HWINIT_STATE, UNIN_RUNNING, 0);
+	DELAY(100);
+
+	return (0);
+}
+
+int
+unin_chip_sleep(device_t dev, int idle)
+{
+	if (dev == NULL)
+		dev = unin_chip;
+
+	unin_update_reg(dev, UNIN_HWINIT_STATE, UNIN_SLEEPING, 0);
+	DELAY(10);
+	if (idle)
+		unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_IDLE2, UNIN_PWR_MASK);
+	else
+		unin_update_reg(dev, UNIN_PWR_MGMT, UNIN_PWR_SLEEP, UNIN_PWR_MASK);
+	DELAY(10);
+
+	return (0);
+}


Property changes on: trunk/sys/powerpc/powermac/uninorth.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/uninorthpci.c
===================================================================
--- trunk/sys/powerpc/powermac/uninorthpci.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/uninorthpci.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,265 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2002 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/uninorthpci.c 266160 2014-05-15 17:30:16Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <sys/rman.h>
+
+#include <powerpc/ofw/ofw_pci.h>
+#include <powerpc/powermac/uninorthvar.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include "pcib_if.h"
+
+#define	UNINORTH_DEBUG	0
+
+/*
+ * Device interface.
+ */
+static int		uninorth_probe(device_t);
+static int		uninorth_attach(device_t);
+
+/*
+ * pcib interface.
+ */
+static u_int32_t	uninorth_read_config(device_t, u_int, u_int, u_int,
+			    u_int, int);
+static void		uninorth_write_config(device_t, u_int, u_int, u_int,
+			    u_int, u_int32_t, int);
+
+/*
+ * Local routines.
+ */
+static int		uninorth_enable_config(struct uninorth_softc *, u_int,
+			    u_int, u_int, u_int);
+
+/*
+ * Driver methods.
+ */
+static device_method_t	uninorth_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		uninorth_probe),
+	DEVMETHOD(device_attach,	uninorth_attach),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_read_config,	uninorth_read_config),
+	DEVMETHOD(pcib_write_config,	uninorth_write_config),
+
+	DEVMETHOD_END
+};
+
+static devclass_t	uninorth_devclass;
+
+DEFINE_CLASS_1(pcib, uninorth_driver, uninorth_methods,
+    sizeof(struct uninorth_softc), ofw_pci_driver);
+DRIVER_MODULE(uninorth, ofwbus, uninorth_driver, uninorth_devclass, 0, 0);
+
+static int
+uninorth_probe(device_t dev)
+{
+	const char	*type, *compatible;
+
+	type = ofw_bus_get_type(dev);
+	compatible = ofw_bus_get_compat(dev);
+
+	if (type == NULL || compatible == NULL)
+		return (ENXIO);
+
+	if (strcmp(type, "pci") != 0)
+		return (ENXIO);
+
+	if (strcmp(compatible, "uni-north") == 0) {
+		device_set_desc(dev, "Apple UniNorth Host-PCI bridge");
+		return (0);
+	} else if (strcmp(compatible, "u3-agp") == 0) {
+		device_set_desc(dev, "Apple U3 Host-AGP bridge");
+		return (0);
+	} else if (strcmp(compatible, "u4-pcie") == 0) {
+		device_set_desc(dev, "IBM CPC945 PCI Express Root");
+		return (0);
+	}
+	
+	return (ENXIO);
+}
+
+static int
+uninorth_attach(device_t dev)
+{
+	struct		uninorth_softc *sc;
+	const char	*compatible;
+	phandle_t	node;
+	uint32_t	reg[3];
+	uint64_t	regbase;
+	cell_t		acells;
+
+	node = ofw_bus_get_node(dev);
+	sc = device_get_softc(dev);
+
+	if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8)
+		return (ENXIO);
+
+	sc->sc_ver = 0;
+	compatible = ofw_bus_get_compat(dev);
+	if (strcmp(compatible, "u3-agp") == 0)
+		sc->sc_ver = 3;
+	if (strcmp(compatible, "u4-pcie") == 0)
+		sc->sc_ver = 4;
+
+	acells = 1;
+	OF_getprop(OF_parent(node), "#address-cells", &acells, sizeof(acells));
+
+	regbase = reg[0];
+	if (acells == 2) {
+		regbase <<= 32;
+		regbase |= reg[1];
+	}
+
+	sc->sc_addr = (vm_offset_t)pmap_mapdev(regbase + 0x800000, PAGE_SIZE);
+	sc->sc_data = (vm_offset_t)pmap_mapdev(regbase + 0xc00000, PAGE_SIZE);
+
+	return (ofw_pci_attach(dev));
+}
+
+static u_int32_t
+uninorth_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
+    int width)
+{
+	struct		uninorth_softc *sc;
+	vm_offset_t	caoff;
+
+	sc = device_get_softc(dev);
+	caoff = sc->sc_data + (reg & 0x07);
+
+	if (uninorth_enable_config(sc, bus, slot, func, reg) != 0) {
+		switch (width) {
+		case 1: 
+			return (in8rb(caoff));
+			break;
+		case 2:
+			return (in16rb(caoff));
+			break;
+		case 4:
+			return (in32rb(caoff));
+			break;
+		}
+	}
+
+	return (0xffffffff);
+}
+
+static void
+uninorth_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+    u_int reg, u_int32_t val, int width)
+{
+	struct		uninorth_softc *sc;
+	vm_offset_t	caoff;
+
+	sc = device_get_softc(dev);
+	caoff = sc->sc_data + (reg & 0x07);
+
+	if (uninorth_enable_config(sc, bus, slot, func, reg)) {
+		switch (width) {
+		case 1:
+			out8rb(caoff, val);
+			break;
+		case 2:
+			out16rb(caoff, val);
+			break;
+		case 4:
+			out32rb(caoff, val);
+			break;
+		}
+	}
+}
+
+static int
+uninorth_enable_config(struct uninorth_softc *sc, u_int bus, u_int slot,
+    u_int func, u_int reg)
+{
+	uint32_t	cfgval;
+	uint32_t	pass;
+
+	if (resource_int_value(device_get_name(sc->pci_sc.sc_dev),
+	        device_get_unit(sc->pci_sc.sc_dev), "skipslot", &pass) == 0) {
+		if (pass == slot)
+			return (0);
+	}
+
+	/*
+	 * Issue type 0 configuration space accesses for the root bus.
+	 *
+	 * NOTE: On U4, issue only type 1 accesses. There is a secret
+	 * PCI Express <-> PCI Express bridge not present in the device tree,
+	 * and we need to route all of our configuration space through it.
+	 */
+	if (sc->pci_sc.sc_bus == bus && sc->sc_ver < 4) {
+		/*
+		 * No slots less than 11 on the primary bus on U3 and lower
+		 */
+		if (slot < 11)
+			return (0);
+
+		cfgval = (1 << slot) | (func << 8) | (reg & 0xfc);
+	} else {
+		cfgval = (bus << 16) | (slot << 11) | (func << 8) |
+		    (reg & 0xfc) | 1;
+	}
+
+	/* Set extended register bits on U4 */
+	if (sc->sc_ver == 4)
+		cfgval |= (reg >> 8) << 28;
+
+	do {
+		out32rb(sc->sc_addr, cfgval);
+	} while (in32rb(sc->sc_addr) != cfgval);
+
+	return (1);
+}
+


Property changes on: trunk/sys/powerpc/powermac/uninorthpci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/uninorthvar.h
===================================================================
--- trunk/sys/powerpc/powermac/uninorthvar.h	                        (rev 0)
+++ trunk/sys/powerpc/powermac/uninorthvar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,108 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2002 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/uninorthvar.h 266019 2014-05-14 14:08:45Z ian $
+ */
+
+#ifndef	_POWERPC_POWERMAC_UNINORTHVAR_H_
+#define	_POWERPC_POWERMAC_UNINORTHVAR_H_
+
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofw_pci.h>
+#include <powerpc/ofw/ofw_pci.h>
+
+struct uninorth_softc {
+	struct ofw_pci_softc	pci_sc;
+	vm_offset_t		sc_addr;
+	vm_offset_t		sc_data;
+	int			sc_ver;
+};
+
+struct unin_chip_softc {
+	uint64_t		sc_physaddr;
+	uint64_t		sc_size;
+	vm_offset_t		sc_addr;
+	struct rman  		sc_mem_rman;
+	int			sc_version;
+};
+
+/*
+ * Format of a unin reg property entry.
+ */
+struct unin_chip_reg {
+        u_int32_t       mr_base;
+        u_int32_t       mr_size;
+};
+
+/*
+ * Per unin device structure.
+ */
+struct unin_chip_devinfo {
+        int        udi_interrupts[6];
+        int        udi_ninterrupts;
+        int        udi_base;   
+        struct ofw_bus_devinfo udi_obdinfo;
+        struct resource_list udi_resources;
+};
+
+/*
+ * Version register
+ */
+#define UNIN_VERS       0x0
+
+/*
+ * Clock-control register
+ */
+#define UNIN_CLOCKCNTL		0x20
+#define UNIN_CLOCKCNTL_GMAC	0x2
+
+/*
+ * Power management register
+ */
+#define UNIN_PWR_MGMT		0x30
+#define UNIN_PWR_NORMAL		0x00
+#define UNIN_PWR_IDLE2		0x01
+#define UNIN_PWR_SLEEP		0x02
+#define UNIN_PWR_SAVE		0x03
+#define UNIN_PWR_MASK		0x03
+
+/*
+ * Hardware initialization state register
+ */
+#define UNIN_HWINIT_STATE	0x70
+#define UNIN_SLEEPING		0x01
+#define UNIN_RUNNING		0x02
+
+
+/*
+ * Toggle registers
+ */
+#define UNIN_TOGGLE_REG		0xe0
+#define UNIN_MPIC_RESET		0x2
+#define UNIN_MPIC_OUTPUT_ENABLE	0x4
+
+extern int unin_chip_sleep(device_t dev, int idle);
+extern int unin_chip_wake(device_t dev);
+#endif  /* _POWERPC_POWERMAC_UNINORTHVAR_H_ */


Property changes on: trunk/sys/powerpc/powermac/uninorthvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/vcoregpio.c
===================================================================
--- trunk/sys/powerpc/powermac/vcoregpio.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/vcoregpio.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,113 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2009 Nathan Whitehorn
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/vcoregpio.c 193156 2009-05-31 09:01:23Z nwhitehorn $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
+
+#include <powerpc/powermac/macgpiovar.h>
+
+static int	vcoregpio_probe(device_t);
+static int	vcoregpio_attach(device_t);
+static void	vcoregpio_pre_change(device_t, const struct cf_level *level);
+static void	vcoregpio_post_change(device_t, const struct cf_level *level);
+
+static device_method_t  vcoregpio_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		vcoregpio_probe),
+	DEVMETHOD(device_attach,	vcoregpio_attach),
+	{ 0, 0 },
+};
+
+static driver_t vcoregpio_driver = {
+	"vcoregpio",
+	vcoregpio_methods,
+	0
+};
+
+static devclass_t vcoregpio_devclass;
+
+DRIVER_MODULE(vcoregpio, macgpio, vcoregpio_driver, vcoregpio_devclass, 0, 0);
+
+static int
+vcoregpio_probe(device_t dev)
+{
+	const char *name = ofw_bus_get_name(dev);
+
+	if (strcmp(name, "cpu-vcore-select") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "CPU Core Voltage Control");
+	return (0);
+}
+
+static int
+vcoregpio_attach(device_t dev)
+{
+	EVENTHANDLER_REGISTER(cpufreq_pre_change, vcoregpio_pre_change, dev,
+	    EVENTHANDLER_PRI_ANY);
+	EVENTHANDLER_REGISTER(cpufreq_post_change, vcoregpio_post_change, dev,
+	    EVENTHANDLER_PRI_ANY);
+
+	return (0);
+}
+
+static void
+vcoregpio_pre_change(device_t dev, const struct cf_level *level)
+{
+	if (level->rel_set[0].freq == 10000 /* max */) {
+		/*
+		 * Make sure the CPU voltage is raised before we raise
+		 * the clock.
+		 */
+		macgpio_write(dev, GPIO_DDR_OUTPUT | 1);
+		DELAY(1000);
+	}
+}
+
+static void
+vcoregpio_post_change(device_t dev, const struct cf_level *level)
+{
+	if (level->rel_set[0].freq < 10000 /* max */) {
+		DELAY(1000);
+		/* We are safe to reduce CPU voltage now */
+		macgpio_write(dev, GPIO_DDR_OUTPUT | 0);
+	}
+}
+


Property changes on: trunk/sys/powerpc/powermac/vcoregpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/viareg.h
===================================================================
--- trunk/sys/powerpc/powermac/viareg.h	                        (rev 0)
+++ trunk/sys/powerpc/powermac/viareg.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,52 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2008 Nathan Whitehorn
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powermac/viareg.h 260674 2014-01-15 06:17:15Z jhibbits $
+ */
+
+#ifndef	_POWERPC_VIAREG_H_
+#define	_POWERPC_VIAREG_H_
+
+/* VIA interface registers */
+#define vBufB		0x0000	/* register B */
+#define vDirB		0x0400	/* data direction register */
+#define vDirA		0x0600	/* data direction register */
+#define vT1C		0x0800	/* Timer 1 counter Lo */
+#define vT1CH		0x0a00	/* Timer 1 counter Hi */
+#define vSR		0x1400	/* shift register */
+#define vACR		0x1600	/* aux control register */
+#define vPCR		0x1800	/* peripheral control register */
+#define vIFR		0x1a00	/* interrupt flag register */
+#define vIER		0x1c00	/* interrupt enable register */
+#define vBufA		0x1e00	/* register A */
+
+#define vPB		0x0000
+#define vPB3		0x08
+#define vPB4		0x10
+#define vPB5		0x20
+#define vSR_INT		0x04
+#define vSR_OUT		0x10
+
+#endif /* _POWERPC_VIAREG_H_ */


Property changes on: trunk/sys/powerpc/powermac/viareg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powermac/windtunnel.c
===================================================================
--- trunk/sys/powerpc/powermac/windtunnel.c	                        (rev 0)
+++ trunk/sys/powerpc/powermac/windtunnel.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,241 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Justin Hibbits
+ * Copyright (c) 2010 Andreas Tobler
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powermac/windtunnel.c 230035 2012-01-12 22:21:20Z jhibbits $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/callout.h>
+#include <sys/conf.h>
+#include <sys/cpu.h>
+#include <sys/ctype.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/limits.h>
+#include <sys/reboot.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/unistd.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <powerpc/powermac/powermac_thermal.h>
+
+struct adm1030_softc {
+	struct pmac_fan fan;
+	device_t	sc_dev;
+	struct intr_config_hook enum_hook;
+	uint32_t	sc_addr;
+	int		sc_pwm;
+};
+
+/* Regular bus attachment functions */
+static int	adm1030_probe(device_t);
+static int	adm1030_attach(device_t);
+
+/* Utility functions */
+static void	adm1030_start(void *xdev);
+static int	adm1030_write_byte(device_t dev, uint32_t addr, uint8_t reg, uint8_t buf);
+static int	adm1030_set(struct adm1030_softc *fan, int pwm);
+static int	adm1030_sysctl(SYSCTL_HANDLER_ARGS);
+
+static device_method_t adm1030_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe, adm1030_probe),
+	DEVMETHOD(device_attach, adm1030_attach),
+	{0, 0},
+};
+
+static driver_t	adm1030_driver = {
+	"adm1030",
+	adm1030_methods,
+	sizeof(struct adm1030_softc)
+};
+
+static devclass_t adm1030_devclass;
+
+DRIVER_MODULE(adm1030, iicbus, adm1030_driver, adm1030_devclass, 0, 0);
+
+static int
+adm1030_write_byte(device_t dev, uint32_t addr, uint8_t reg, uint8_t byte)
+{
+	unsigned char	buf[4];
+	int try = 0;
+
+	struct iic_msg	msg[] = {
+		{addr, IIC_M_WR, 0, buf}
+	};
+
+	msg[0].len = 2;
+	buf[0] = reg;
+	buf[1] = byte;
+
+	for (;;)
+	{
+		if (iicbus_transfer(dev, msg, 1) == 0)
+			return (0);
+
+		if (++try > 5) {
+			device_printf(dev, "iicbus write failed\n");
+			return (-1);
+		}
+		pause("adm1030_write_byte", hz);
+	}
+}
+
+static int
+adm1030_probe(device_t dev)
+{
+	const char     *name, *compatible;
+	struct adm1030_softc *sc;
+	phandle_t	handle;
+	phandle_t	thermostat;
+
+	name = ofw_bus_get_name(dev);
+	compatible = ofw_bus_get_compat(dev);
+	handle = ofw_bus_get_node(dev);
+
+	if (!name)
+		return (ENXIO);
+
+	if (strcmp(name, "fan") != 0 || strcmp(compatible, "adm1030") != 0)
+		return (ENXIO);
+
+	/* This driver can only be used if there's an associated temp sensor. */
+	if (OF_getprop(handle, "platform-getTemp", &thermostat, sizeof(thermostat)) < 0)
+		return (ENXIO);
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+	sc->sc_addr = iicbus_get_addr(dev);
+
+	device_set_desc(dev, "G4 MDD Fan driver");
+
+	return (0);
+}
+
+static int
+adm1030_attach(device_t dev)
+{
+	struct adm1030_softc *sc;
+	struct sysctl_ctx_list *ctx;
+	struct sysctl_oid *tree;
+
+	sc = device_get_softc(dev);
+
+	sc->enum_hook.ich_func = adm1030_start;
+	sc->enum_hook.ich_arg = dev;
+
+	/*
+	 * Wait until interrupts are available, which won't be until the openpic is
+	 * intialized.
+	 */
+
+	if (config_intrhook_establish(&sc->enum_hook) != 0)
+		return (ENOMEM);
+
+	ctx = device_get_sysctl_ctx(dev);
+	tree = device_get_sysctl_tree(dev);
+	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "pwm",
+			CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev,
+			0, adm1030_sysctl, "I", "Fan PWM Rate");
+
+	return (0);
+}
+
+static void
+adm1030_start(void *xdev)
+{
+	struct adm1030_softc *sc;
+
+	device_t	dev = (device_t) xdev;
+
+	sc = device_get_softc(dev);
+
+	/* Start the adm1030 device. */
+	adm1030_write_byte(sc->sc_dev, sc->sc_addr, 0x1, 0x1);
+	adm1030_write_byte(sc->sc_dev, sc->sc_addr, 0x0, 0x95);
+	adm1030_write_byte(sc->sc_dev, sc->sc_addr, 0x23, 0x91);
+
+	/* Use the RPM fields as PWM duty cycles. */
+	sc->fan.min_rpm = 0;
+	sc->fan.max_rpm = 0x0F;
+	sc->fan.default_rpm = 2;
+
+	strcpy(sc->fan.name, "MDD Case fan");
+	sc->fan.zone = 0;
+	sc->fan.read = NULL;
+	sc->fan.set = (int (*)(struct pmac_fan *, int))adm1030_set;
+	config_intrhook_disestablish(&sc->enum_hook);
+
+	pmac_thermal_fan_register(&sc->fan);
+}
+
+static int adm1030_set(struct adm1030_softc *fan, int pwm)
+{
+	/* Clamp the PWM to 0-0xF, one nibble. */
+	if (pwm > 0xF)
+		pwm = 0xF;
+	if (pwm < 0)
+		pwm = 0;
+
+	if (adm1030_write_byte(fan->sc_dev, fan->sc_addr, 0x22, pwm) < 0)
+		return (-1);
+
+	fan->sc_pwm = pwm;
+	return (0);
+}
+
+static int
+adm1030_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	device_t adm1030;
+	struct adm1030_softc *sc;
+	int pwm, error;
+
+	adm1030 = arg1;
+	sc = device_get_softc(adm1030);
+
+	pwm = sc->sc_pwm;
+
+	error = sysctl_handle_int(oidp, &pwm, 0, req);
+
+	if (error || !req->newptr)
+		return (error);
+
+	return (adm1030_set(sc, pwm));
+}


Property changes on: trunk/sys/powerpc/powermac/windtunnel.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/altivec.c
===================================================================
--- trunk/sys/powerpc/powerpc/altivec.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/altivec.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,153 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: fpu.c,v 1.5 2001/07/22 11:29:46 wiz Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/altivec.c 188860 2009-02-20 17:48:40Z nwhitehorn $");
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/limits.h>
+
+#include <machine/altivec.h>
+#include <machine/pcb.h>
+#include <machine/psl.h>
+
+void
+enable_vec(struct thread *td)
+{
+	int	msr;
+	struct	pcb *pcb;
+	struct	trapframe *tf;
+
+	pcb = td->td_pcb;
+	tf = trapframe(td);
+
+	/*
+	 * Save the thread's Altivec CPU number, and set the CPU's current
+	 * vector thread
+	 */
+	td->td_pcb->pcb_veccpu = PCPU_GET(cpuid);
+	PCPU_SET(vecthread, td);
+
+	/*
+	 * Enable the vector unit for when the thread returns from the
+	 * exception. If this is the first time the unit has been used by
+	 * the thread, initialise the vector registers and VSCR to 0, and
+	 * set the flag to indicate that the vector unit is in use.
+	 */
+	tf->srr1 |= PSL_VEC;
+	if (!(pcb->pcb_flags & PCB_VEC)) {
+		memset(&pcb->pcb_vec, 0, sizeof pcb->pcb_vec);
+		pcb->pcb_flags |= PCB_VEC;
+	}
+
+	/*
+	 * Temporarily enable the vector unit so the registers
+	 * can be restored.
+	 */
+	msr = mfmsr();
+	mtmsr(msr | PSL_VEC);
+	isync();
+
+	/*
+	 * Restore VSCR by first loading it into a vector and then into VSCR.
+	 * (this needs to done before loading the user's vector registers
+	 * since we need to use a scratch vector register)
+	 */
+	__asm __volatile("vxor 0,0,0; lvewx 0,0,%0; mtvscr 0" \
+			  :: "b"(&pcb->pcb_vec.vscr));
+
+#define LVX(n)   __asm ("lvx " #n ",0,%0" \
+		:: "b"(&pcb->pcb_vec.vr[n]));
+	LVX(0);		LVX(1);		LVX(2);		LVX(3);
+	LVX(4);		LVX(5);		LVX(6);		LVX(7);
+	LVX(8);		LVX(9);		LVX(10);	LVX(11);
+	LVX(12);	LVX(13);	LVX(14);	LVX(15);
+	LVX(16);	LVX(17);	LVX(18);	LVX(19);
+	LVX(20);	LVX(21);	LVX(22);	LVX(23);
+	LVX(24);	LVX(25);	LVX(26);	LVX(27);
+	LVX(28);	LVX(29);	LVX(30);	LVX(31);
+#undef LVX
+
+	isync();
+	mtmsr(msr);
+}
+
+void
+save_vec(struct thread *td)
+{
+	int	msr;
+	struct	pcb *pcb;
+
+	pcb = td->td_pcb;
+
+	/*
+	 * Temporarily re-enable the vector unit during the save
+	 */
+	msr = mfmsr();
+	mtmsr(msr | PSL_VEC);
+	isync();
+
+	/*
+	 * Save the vector registers and VSCR to the PCB
+	 */
+#define STVX(n)   __asm ("stvx %1,0,%0" \
+		:: "b"(pcb->pcb_vec.vr[n]), "n"(n));
+	STVX(0);	STVX(1);	STVX(2);	STVX(3);
+	STVX(4);	STVX(5);	STVX(6);	STVX(7);
+	STVX(8);	STVX(9);	STVX(10);	STVX(11);
+	STVX(12);	STVX(13);	STVX(14);	STVX(15);
+	STVX(16);	STVX(17);	STVX(18);	STVX(19);
+	STVX(20);	STVX(21);	STVX(22);	STVX(23);
+	STVX(24);	STVX(25);	STVX(26);	STVX(27);
+	STVX(28);	STVX(29);	STVX(30);	STVX(31);
+#undef STVX
+
+	__asm __volatile("mfvscr 0; stvewx 0,0,%0" :: "b"(&pcb->pcb_vec.vscr));
+
+	/*
+	 * Disable vector unit again
+	 */
+	isync();
+	mtmsr(msr);
+
+	/*
+	 * Clear the current vec thread and pcb's CPU id
+	 * XXX should this be left clear to allow lazy save/restore ?
+	 */
+	pcb->pcb_veccpu = INT_MAX;
+	PCPU_SET(vecthread, NULL);
+}
+


Property changes on: trunk/sys/powerpc/powerpc/altivec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/autoconf.c
===================================================================
--- trunk/sys/powerpc/powerpc/autoconf.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/autoconf.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,95 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1998 Doug Rabson
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "opt_isa.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/autoconf.c 191450 2009-04-24 03:51:11Z marcel $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <sys/kernel.h>
+
+#include <machine/intr_machdep.h>
+
+#ifdef DEV_ISA
+extern void isa_probe_children(device_t dev);
+
+device_t isa_bus_device;
+#endif
+
+static device_t nexusdev;
+
+static void	configure_first(void *);
+static void	configure(void *);
+static void	configure_final(void *);
+
+SYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL);
+/* SI_ORDER_SECOND is hookable */
+SYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL);
+/* SI_ORDER_MIDDLE is hookable */
+SYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL);
+
+/*
+ * Determine i/o configuration for a machine.
+ */
+static void
+configure_first(void *dummy)
+{
+
+	nexusdev = device_add_child(root_bus, "nexus", 0);
+}
+
+static void
+configure(void *dummy)
+{
+
+	root_bus_configure();
+#ifdef DEV_ISA
+	if (isa_bus_device)
+		isa_probe_children(isa_bus_device);
+#endif
+}
+
+static void
+configure_final(void *dummy)
+{
+
+	/*
+	 * Now that we're guaranteed to have a PIC driver (or we'll never
+	 * have one), program it with all the previously setup interrupts.
+	 */
+	powerpc_enable_intr();
+
+	/* Enable external interrupts. */
+	mtmsr(mfmsr() | PSL_EE);
+
+	cninit_finish();
+	cold = 0;
+}


Property changes on: trunk/sys/powerpc/powerpc/autoconf.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/bcopy.c
===================================================================
--- trunk/sys/powerpc/powerpc/bcopy.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/bcopy.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,150 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ * 4. 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char *sccsid = "from: @(#)bcopy.c      5.11 (Berkeley) 6/21/91";
+#endif
+#if 0
+static char *rcsid = "$NetBSD: bcopy.c,v 1.2 1997/04/16 22:09:41 thorpej Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/bcopy.c 209850 2010-07-09 14:01:18Z nwhitehorn $");
+
+#include <sys/param.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#else
+#include <string.h>
+#endif
+
+/*
+ * sizeof(word) MUST BE A POWER OF TWO
+ * SO THAT wmask BELOW IS ALL ONES
+ */
+typedef	long	word;		/* "word" used for optimal copy speed */
+
+#define	wsize	sizeof(word)
+#define wmask	(wsize - 1)
+
+/*
+ * Copy a block of memory, handling overlap.
+ * This is the routine that actually implements
+ * (the portable versions of) bcopy, memcpy, and memmove.
+ */
+void *
+memcpy(void *dst0, const void *src0, size_t length)
+{
+	char		*dst;
+	const char	*src;
+	size_t		t;
+
+	dst = dst0;
+	src = src0;
+
+	if (length == 0 || dst == src) {	/* nothing to do */
+		goto done;
+	}
+
+	/*
+	 * Macros: loop-t-times; and loop-t-times, t>0
+	 */
+#define	TLOOP(s) if (t) TLOOP1(s)
+#define	TLOOP1(s) do { s; } while (--t)
+
+	if ((unsigned long)dst < (unsigned long)src) {
+		/*
+		 * Copy forward.
+		 */
+		t = (size_t)src;	/* only need low bits */
+
+		if ((t | (uintptr_t)dst) & wmask) {
+			/*
+			 * Try to align operands.  This cannot be done
+			 * unless the low bits match.
+			 */
+			if ((t ^ (uintptr_t)dst) & wmask || length < wsize) {
+				t = length;
+			} else {
+				t = wsize - (t & wmask);
+			}
+
+			length -= t;
+			TLOOP1(*dst++ = *src++);
+		}
+		/*
+		 * Copy whole words, then mop up any trailing bytes.
+		 */
+		t = length / wsize;
+		TLOOP(*(word *)dst = *(const word *)src; src += wsize;
+		    dst += wsize);
+		t = length & wmask;
+		TLOOP(*dst++ = *src++);
+	} else {
+		/*
+		 * Copy backwards.  Otherwise essentially the same.
+		 * Alignment works as before, except that it takes
+		 * (t&wmask) bytes to align, not wsize-(t&wmask).
+		 */
+		src += length;
+		dst += length;
+		t = (uintptr_t)src;
+
+		if ((t | (uintptr_t)dst) & wmask) {
+			if ((t ^ (uintptr_t)dst) & wmask || length <= wsize) {
+				t = length;
+			} else {
+				t &= wmask;
+			}
+
+			length -= t;
+			TLOOP1(*--dst = *--src);
+		}
+		t = length / wsize;
+		TLOOP(src -= wsize; dst -= wsize;
+		    *(word *)dst = *(const word *)src);
+		t = length & wmask;
+		TLOOP(*--dst = *--src);
+	}
+done:
+	return (dst0);
+}
+
+void
+bcopy(const void *src0, void *dst0, size_t length)
+{
+
+	memcpy(dst0, src0, length);
+}
+


Property changes on: trunk/sys/powerpc/powerpc/bcopy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/bus_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/bus_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/bus_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,968 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Semihalf, Rafal Jaworowski <raj at semihalf.com>
+ * Copyright (c) 1996, 1997, 1998 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/bus_machdep.c 265996 2014-05-14 00:51:26Z ian $");
+
+#define	KTR_BE_IO	0
+#define	KTR_LE_IO	0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/ktr.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/pio.h>
+#include <machine/md_var.h>
+
+#define TODO panic("%s: not implemented", __func__)
+
+#define	MAX_EARLYBOOT_MAPPINGS	6
+
+static struct {
+	vm_offset_t virt;
+	bus_addr_t addr;
+	bus_size_t size;
+	int flags;
+} earlyboot_mappings[MAX_EARLYBOOT_MAPPINGS];
+static int earlyboot_map_idx = 0;
+
+void bs_remap_earlyboot(void);
+
+static __inline void *
+__ppc_ba(bus_space_handle_t bsh, bus_size_t ofs)
+{
+	return ((void *)(bsh + ofs));
+}
+
+static int
+bs_gen_map(bus_addr_t addr, bus_size_t size, int flags,
+    bus_space_handle_t *bshp)
+{
+	vm_memattr_t ma;
+
+	/*
+	 * Record what we did if we haven't enabled the MMU yet. We
+	 * will need to remap it as soon as the MMU comes up.
+	 */
+	if (!pmap_bootstrapped) {
+		KASSERT(earlyboot_map_idx < MAX_EARLYBOOT_MAPPINGS,
+		    ("%s: too many early boot mapping requests", __func__));
+		earlyboot_mappings[earlyboot_map_idx].addr = addr;
+		earlyboot_mappings[earlyboot_map_idx].virt =
+		    pmap_early_io_map(addr, size);
+		earlyboot_mappings[earlyboot_map_idx].size = size;
+		earlyboot_mappings[earlyboot_map_idx].flags = flags;
+		*bshp = earlyboot_mappings[earlyboot_map_idx].virt;
+		earlyboot_map_idx++;
+	} else {
+		ma = VM_MEMATTR_DEFAULT;
+		switch (flags) {
+			case BUS_SPACE_MAP_CACHEABLE:
+				ma = VM_MEMATTR_CACHEABLE;
+				break;
+			case BUS_SPACE_MAP_PREFETCHABLE:
+				ma = VM_MEMATTR_PREFETCHABLE;
+				break;
+		}
+		*bshp = (bus_space_handle_t)pmap_mapdev_attr(addr, size, ma);
+	}
+
+	return (0);
+}
+
+void
+bs_remap_earlyboot(void)
+{
+	int i;
+	vm_offset_t pa, spa, va;
+	vm_memattr_t ma;
+
+	for (i = 0; i < earlyboot_map_idx; i++) {
+		spa = earlyboot_mappings[i].addr;
+		if (spa == earlyboot_mappings[i].virt &&
+		   pmap_dev_direct_mapped(spa, earlyboot_mappings[i].size) == 0)
+			continue;
+
+		ma = VM_MEMATTR_DEFAULT;
+		switch (earlyboot_mappings[i].flags) {
+			case BUS_SPACE_MAP_CACHEABLE:
+				ma = VM_MEMATTR_CACHEABLE;
+				break;
+			case BUS_SPACE_MAP_PREFETCHABLE:
+				ma = VM_MEMATTR_PREFETCHABLE;
+				break;
+		}
+
+		pa = trunc_page(spa);
+		va = trunc_page(earlyboot_mappings[i].virt);
+		while (pa < spa + earlyboot_mappings[i].size) {
+			pmap_kenter_attr(va, pa, ma);
+			va += PAGE_SIZE;
+			pa += PAGE_SIZE;
+		}
+	}
+}
+
+static void
+bs_gen_unmap(bus_size_t size __unused)
+{
+}
+
+static int
+bs_gen_subregion(bus_space_handle_t bsh, bus_size_t ofs,
+    bus_size_t size __unused, bus_space_handle_t *nbshp)
+{
+	*nbshp = bsh + ofs;
+	return (0);
+}
+
+static int
+bs_gen_alloc(bus_addr_t rstart __unused, bus_addr_t rend __unused,
+    bus_size_t size __unused, bus_size_t alignment __unused,
+    bus_size_t boundary __unused, int flags __unused,
+    bus_addr_t *bpap __unused, bus_space_handle_t *bshp __unused)
+{
+	TODO;
+}
+
+static void
+bs_gen_free(bus_space_handle_t bsh __unused, bus_size_t size __unused)
+{
+	TODO;
+}
+
+static void
+bs_gen_barrier(bus_space_handle_t bsh __unused, bus_size_t ofs __unused,
+    bus_size_t size __unused, int flags __unused)
+{
+
+	powerpc_iomb();
+}
+
+/*
+ * Big-endian access functions
+ */
+static uint8_t
+bs_be_rs_1(bus_space_handle_t bsh, bus_size_t ofs)
+{
+	volatile uint8_t *addr;
+	uint8_t res;
+
+	addr = __ppc_ba(bsh, ofs);
+	res = *addr;
+	powerpc_iomb();
+	CTR4(KTR_BE_IO, "%s(bsh=%#x, ofs=%#x) = %#x", __func__, bsh, ofs, res);
+	return (res);
+}
+
+static uint16_t
+bs_be_rs_2(bus_space_handle_t bsh, bus_size_t ofs)
+{
+	volatile uint16_t *addr;
+	uint16_t res;
+
+	addr = __ppc_ba(bsh, ofs);
+	res = *addr;
+	powerpc_iomb();
+	CTR4(KTR_BE_IO, "%s(bsh=%#x, ofs=%#x) = %#x", __func__, bsh, ofs, res);
+	return (res);
+}
+
+static uint32_t
+bs_be_rs_4(bus_space_handle_t bsh, bus_size_t ofs)
+{
+	volatile uint32_t *addr;
+	uint32_t res;
+
+	addr = __ppc_ba(bsh, ofs);
+	res = *addr;
+	powerpc_iomb();
+	CTR4(KTR_BE_IO, "%s(bsh=%#x, ofs=%#x) = %#x", __func__, bsh, ofs, res);
+	return (res);
+}
+
+static uint64_t
+bs_be_rs_8(bus_space_handle_t bsh, bus_size_t ofs)
+{
+	volatile uint64_t *addr;
+	uint64_t res;
+
+	addr = __ppc_ba(bsh, ofs);
+	res = *addr;
+	powerpc_iomb();
+	return (res);
+}
+
+static void
+bs_be_rm_1(bus_space_handle_t bsh, bus_size_t ofs, uint8_t *addr, size_t cnt)
+{
+	ins8(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_be_rm_2(bus_space_handle_t bsh, bus_size_t ofs, uint16_t *addr, size_t cnt)
+{
+	ins16(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_be_rm_4(bus_space_handle_t bsh, bus_size_t ofs, uint32_t *addr, size_t cnt)
+{
+	ins32(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_be_rm_8(bus_space_handle_t bsh, bus_size_t ofs, uint64_t *addr, size_t cnt)
+{
+	ins64(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_be_rr_1(bus_space_handle_t bsh, bus_size_t ofs, uint8_t *addr, size_t cnt)
+{
+	volatile uint8_t *s = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*addr++ = *s++;
+	powerpc_iomb();
+}
+
+static void
+bs_be_rr_2(bus_space_handle_t bsh, bus_size_t ofs, uint16_t *addr, size_t cnt)
+{
+	volatile uint16_t *s = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*addr++ = *s++;
+	powerpc_iomb();
+}
+
+static void
+bs_be_rr_4(bus_space_handle_t bsh, bus_size_t ofs, uint32_t *addr, size_t cnt)
+{
+	volatile uint32_t *s = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*addr++ = *s++;
+	powerpc_iomb();
+}
+
+static void
+bs_be_rr_8(bus_space_handle_t bsh, bus_size_t ofs, uint64_t *addr, size_t cnt)
+{
+	volatile uint64_t *s = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*addr++ = *s++;
+	powerpc_iomb();
+}
+
+static void
+bs_be_ws_1(bus_space_handle_t bsh, bus_size_t ofs, uint8_t val)
+{
+	volatile uint8_t *addr;
+
+	addr = __ppc_ba(bsh, ofs);
+	*addr = val;
+	powerpc_iomb();
+	CTR4(KTR_BE_IO, "%s(bsh=%#x, ofs=%#x, val=%#x)", __func__, bsh, ofs, val);
+}
+
+static void
+bs_be_ws_2(bus_space_handle_t bsh, bus_size_t ofs, uint16_t val)
+{
+	volatile uint16_t *addr;
+
+	addr = __ppc_ba(bsh, ofs);
+	*addr = val;
+	powerpc_iomb();
+	CTR4(KTR_BE_IO, "%s(bsh=%#x, ofs=%#x, val=%#x)", __func__, bsh, ofs, val);
+}
+
+static void
+bs_be_ws_4(bus_space_handle_t bsh, bus_size_t ofs, uint32_t val)
+{
+	volatile uint32_t *addr;
+
+	addr = __ppc_ba(bsh, ofs);
+	*addr = val;
+	powerpc_iomb();
+	CTR4(KTR_BE_IO, "%s(bsh=%#x, ofs=%#x, val=%#x)", __func__, bsh, ofs, val);
+}
+
+static void
+bs_be_ws_8(bus_space_handle_t bsh, bus_size_t ofs, uint64_t val)
+{
+	volatile uint64_t *addr;
+
+	addr = __ppc_ba(bsh, ofs);
+	*addr = val;
+	powerpc_iomb();
+}
+
+static void
+bs_be_wm_1(bus_space_handle_t bsh, bus_size_t ofs, const uint8_t *addr,
+    bus_size_t cnt)
+{
+	outsb(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_be_wm_2(bus_space_handle_t bsh, bus_size_t ofs, const uint16_t *addr,
+    bus_size_t cnt)
+{
+	outsw(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_be_wm_4(bus_space_handle_t bsh, bus_size_t ofs, const uint32_t *addr,
+    bus_size_t cnt)
+{
+	outsl(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_be_wm_8(bus_space_handle_t bsh, bus_size_t ofs, const uint64_t *addr,
+    bus_size_t cnt)
+{
+	outsll(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_be_wr_1(bus_space_handle_t bsh, bus_size_t ofs, const uint8_t *addr,
+    size_t cnt)
+{
+	volatile uint8_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d++ = *addr++;
+	powerpc_iomb();
+}
+
+static void
+bs_be_wr_2(bus_space_handle_t bsh, bus_size_t ofs, const uint16_t *addr,
+    size_t cnt)
+{
+	volatile uint16_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d++ = *addr++;
+	powerpc_iomb();
+}
+
+static void
+bs_be_wr_4(bus_space_handle_t bsh, bus_size_t ofs, const uint32_t *addr,
+    size_t cnt)
+{
+	volatile uint32_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d++ = *addr++;
+	powerpc_iomb();
+}
+
+static void
+bs_be_wr_8(bus_space_handle_t bsh, bus_size_t ofs, const uint64_t *addr,
+    size_t cnt)
+{
+	volatile uint64_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d++ = *addr++;
+	powerpc_iomb();
+}
+
+static void
+bs_be_sm_1(bus_space_handle_t bsh, bus_size_t ofs, uint8_t val, size_t cnt)
+{
+	volatile uint8_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d = val;
+	powerpc_iomb();
+}
+
+static void
+bs_be_sm_2(bus_space_handle_t bsh, bus_size_t ofs, uint16_t val, size_t cnt)
+{
+	volatile uint16_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d = val;
+	powerpc_iomb();
+}
+
+static void
+bs_be_sm_4(bus_space_handle_t bsh, bus_size_t ofs, uint32_t val, size_t cnt)
+{
+	volatile uint32_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d = val;
+	powerpc_iomb();
+}
+
+static void
+bs_be_sm_8(bus_space_handle_t bsh, bus_size_t ofs, uint64_t val, size_t cnt)
+{
+	volatile uint64_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d = val;
+	powerpc_iomb();
+}
+
+static void
+bs_be_sr_1(bus_space_handle_t bsh, bus_size_t ofs, uint8_t val, size_t cnt)
+{
+	volatile uint8_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d++ = val;
+	powerpc_iomb();
+}
+
+static void
+bs_be_sr_2(bus_space_handle_t bsh, bus_size_t ofs, uint16_t val, size_t cnt)
+{
+	volatile uint16_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d++ = val;
+	powerpc_iomb();
+}
+
+static void
+bs_be_sr_4(bus_space_handle_t bsh, bus_size_t ofs, uint32_t val, size_t cnt)
+{
+	volatile uint32_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d++ = val;
+	powerpc_iomb();
+}
+
+static void
+bs_be_sr_8(bus_space_handle_t bsh, bus_size_t ofs, uint64_t val, size_t cnt)
+{
+	volatile uint64_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d++ = val;
+	powerpc_iomb();
+}
+
+/*
+ * Little-endian access functions
+ */
+static uint8_t
+bs_le_rs_1(bus_space_handle_t bsh, bus_size_t ofs)
+{
+	volatile uint8_t *addr;
+	uint8_t res;
+
+	addr = __ppc_ba(bsh, ofs);
+	res = *addr;
+	powerpc_iomb();
+	CTR4(KTR_LE_IO, "%s(bsh=%#x, ofs=%#x) = %#x", __func__, bsh, ofs, res);
+	return (res);
+}
+
+static uint16_t
+bs_le_rs_2(bus_space_handle_t bsh, bus_size_t ofs)
+{
+	volatile uint16_t *addr;
+	uint16_t res;
+
+	addr = __ppc_ba(bsh, ofs);
+	__asm __volatile("lhbrx %0, 0, %1" : "=r"(res) : "r"(addr));
+	powerpc_iomb();
+	CTR4(KTR_LE_IO, "%s(bsh=%#x, ofs=%#x) = %#x", __func__, bsh, ofs, res);
+	return (res);
+}
+
+static uint32_t
+bs_le_rs_4(bus_space_handle_t bsh, bus_size_t ofs)
+{
+	volatile uint32_t *addr;
+	uint32_t res;
+
+	addr = __ppc_ba(bsh, ofs);
+	__asm __volatile("lwbrx %0, 0, %1" : "=r"(res) : "r"(addr));
+	powerpc_iomb();
+	CTR4(KTR_LE_IO, "%s(bsh=%#x, ofs=%#x) = %#x", __func__, bsh, ofs, res);
+	return (res);
+}
+
+static uint64_t
+bs_le_rs_8(bus_space_handle_t bsh, bus_size_t ofs)
+{
+	TODO;
+}
+
+static void
+bs_le_rm_1(bus_space_handle_t bsh, bus_size_t ofs, uint8_t *addr, size_t cnt)
+{
+	ins8(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_le_rm_2(bus_space_handle_t bsh, bus_size_t ofs, uint16_t *addr, size_t cnt)
+{
+	ins16rb(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_le_rm_4(bus_space_handle_t bsh, bus_size_t ofs, uint32_t *addr, size_t cnt)
+{
+	ins32rb(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_le_rm_8(bus_space_handle_t bshh, bus_size_t ofs, uint64_t *addr, size_t cnt)
+{
+	TODO;
+}
+
+static void
+bs_le_rr_1(bus_space_handle_t bsh, bus_size_t ofs, uint8_t *addr, size_t cnt)
+{
+	volatile uint8_t *s = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*addr++ = *s++;
+	powerpc_iomb();
+}
+
+static void
+bs_le_rr_2(bus_space_handle_t bsh, bus_size_t ofs, uint16_t *addr, size_t cnt)
+{
+	volatile uint16_t *s = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*addr++ = in16rb(s++);
+	powerpc_iomb();
+}
+
+static void
+bs_le_rr_4(bus_space_handle_t bsh, bus_size_t ofs, uint32_t *addr, size_t cnt)
+{
+	volatile uint32_t *s = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*addr++ = in32rb(s++);
+	powerpc_iomb();
+}
+
+static void
+bs_le_rr_8(bus_space_handle_t bsh, bus_size_t ofs, uint64_t *addr, size_t cnt)
+{
+	TODO;
+}
+
+static void
+bs_le_ws_1(bus_space_handle_t bsh, bus_size_t ofs, uint8_t val)
+{
+	volatile uint8_t *addr;
+
+	addr = __ppc_ba(bsh, ofs);
+	*addr = val;
+	powerpc_iomb();
+	CTR4(KTR_LE_IO, "%s(bsh=%#x, ofs=%#x, val=%#x)", __func__, bsh, ofs, val);
+}
+
+static void
+bs_le_ws_2(bus_space_handle_t bsh, bus_size_t ofs, uint16_t val)
+{
+	volatile uint16_t *addr;
+ 
+	addr = __ppc_ba(bsh, ofs);
+	__asm __volatile("sthbrx %0, 0, %1" :: "r"(val), "r"(addr));
+	powerpc_iomb();
+	CTR4(KTR_LE_IO, "%s(bsh=%#x, ofs=%#x, val=%#x)", __func__, bsh, ofs, val);
+}
+
+static void
+bs_le_ws_4(bus_space_handle_t bsh, bus_size_t ofs, uint32_t val)
+{
+	volatile uint32_t *addr;
+
+	addr = __ppc_ba(bsh, ofs);
+	__asm __volatile("stwbrx %0, 0, %1" :: "r"(val), "r"(addr));
+	powerpc_iomb();
+	CTR4(KTR_LE_IO, "%s(bsh=%#x, ofs=%#x, val=%#x)", __func__, bsh, ofs, val);
+}
+
+static void
+bs_le_ws_8(bus_space_handle_t bsh, bus_size_t ofs, uint64_t val)
+{
+	TODO;
+}
+
+static void
+bs_le_wm_1(bus_space_handle_t bsh, bus_size_t ofs, const uint8_t *addr,
+    bus_size_t cnt)
+{
+	outs8(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_le_wm_2(bus_space_handle_t bsh, bus_size_t ofs, const uint16_t *addr,
+    bus_size_t cnt)
+{
+	outs16rb(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_le_wm_4(bus_space_handle_t bsh, bus_size_t ofs, const uint32_t *addr,
+    bus_size_t cnt)
+{
+	outs32rb(__ppc_ba(bsh, ofs), addr, cnt);
+}
+
+static void
+bs_le_wm_8(bus_space_handle_t bsh, bus_size_t ofs, const uint64_t *addr,
+    bus_size_t cnt)
+{
+	TODO;
+}
+
+static void
+bs_le_wr_1(bus_space_handle_t bsh, bus_size_t ofs, const uint8_t *addr,
+    size_t cnt)
+{
+	volatile uint8_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d++ = *addr++;
+	powerpc_iomb();
+}
+
+static void
+bs_le_wr_2(bus_space_handle_t bsh, bus_size_t ofs, const uint16_t *addr,
+    size_t cnt)
+{
+	volatile uint16_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		out16rb(d++, *addr++);
+	powerpc_iomb();
+}
+
+static void
+bs_le_wr_4(bus_space_handle_t bsh, bus_size_t ofs, const uint32_t *addr,
+    size_t cnt)
+{
+	volatile uint32_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		out32rb(d++, *addr++);
+	powerpc_iomb();
+}
+
+static void
+bs_le_wr_8(bus_space_handle_t bsh, bus_size_t ofs, const uint64_t *addr,
+    size_t cnt)
+{
+	TODO;
+}
+
+static void
+bs_le_sm_1(bus_space_handle_t bsh, bus_size_t ofs, uint8_t val, size_t cnt)
+{
+	volatile uint8_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d = val;
+	powerpc_iomb();
+}
+
+static void
+bs_le_sm_2(bus_space_handle_t bsh, bus_size_t ofs, uint16_t val, size_t cnt)
+{
+	volatile uint16_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		out16rb(d, val);
+	powerpc_iomb();
+}
+
+static void
+bs_le_sm_4(bus_space_handle_t bsh, bus_size_t ofs, uint32_t val, size_t cnt)
+{
+	volatile uint32_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		out32rb(d, val);
+	powerpc_iomb();
+}
+
+static void
+bs_le_sm_8(bus_space_handle_t bsh, bus_size_t ofs, uint64_t val, size_t cnt)
+{
+	TODO;
+}
+
+static void
+bs_le_sr_1(bus_space_handle_t bsh, bus_size_t ofs, uint8_t val, size_t cnt)
+{
+	volatile uint8_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		*d++ = val;
+	powerpc_iomb();
+}
+
+static void
+bs_le_sr_2(bus_space_handle_t bsh, bus_size_t ofs, uint16_t val, size_t cnt)
+{
+	volatile uint16_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		out16rb(d++, val);
+	powerpc_iomb();
+}
+
+static void
+bs_le_sr_4(bus_space_handle_t bsh, bus_size_t ofs, uint32_t val, size_t cnt)
+{
+	volatile uint32_t *d = __ppc_ba(bsh, ofs);
+
+	while (cnt--)
+		out32rb(d++, val);
+	powerpc_iomb();
+}
+
+static void
+bs_le_sr_8(bus_space_handle_t bsh, bus_size_t ofs, uint64_t val, size_t cnt)
+{
+	TODO;
+}
+
+struct bus_space bs_be_tag = {
+	/* mapping/unmapping */
+	bs_gen_map,
+	bs_gen_unmap,
+	bs_gen_subregion,
+
+	/* allocation/deallocation */
+	bs_gen_alloc,
+	bs_gen_free,
+
+	/* barrier */
+	bs_gen_barrier,
+
+	/* read (single) */
+	bs_be_rs_1,
+	bs_be_rs_2,
+	bs_be_rs_4,
+	bs_be_rs_8,
+
+	bs_be_rs_2,
+	bs_be_rs_4,
+	bs_be_rs_8,
+
+	/* read multiple */
+	bs_be_rm_1,
+	bs_be_rm_2,
+	bs_be_rm_4,
+	bs_be_rm_8,
+
+	bs_be_rm_2,
+	bs_be_rm_4,
+	bs_be_rm_8,
+
+	/* read region */
+	bs_be_rr_1,
+	bs_be_rr_2,
+	bs_be_rr_4,
+	bs_be_rr_8,
+
+	bs_be_rr_2,
+	bs_be_rr_4,
+	bs_be_rr_8,
+
+	/* write (single) */
+	bs_be_ws_1,
+	bs_be_ws_2,
+	bs_be_ws_4,
+	bs_be_ws_8,
+
+	bs_be_ws_2,
+	bs_be_ws_4,
+	bs_be_ws_8,
+
+	/* write multiple */
+	bs_be_wm_1,
+	bs_be_wm_2,
+	bs_be_wm_4,
+	bs_be_wm_8,
+
+	bs_be_wm_2,
+	bs_be_wm_4,
+	bs_be_wm_8,
+
+	/* write region */
+	bs_be_wr_1,
+	bs_be_wr_2,
+	bs_be_wr_4,
+	bs_be_wr_8,
+
+	bs_be_wr_2,
+	bs_be_wr_4,
+	bs_be_wr_8,
+
+	/* set multiple */
+	bs_be_sm_1,
+	bs_be_sm_2,
+	bs_be_sm_4,
+	bs_be_sm_8,
+
+	bs_be_sm_2,
+	bs_be_sm_4,
+	bs_be_sm_8,
+
+	/* set region */
+	bs_be_sr_1,
+	bs_be_sr_2,
+	bs_be_sr_4,
+	bs_be_sr_8,
+
+	bs_be_sr_2,
+	bs_be_sr_4,
+	bs_be_sr_8,
+};
+
+struct bus_space bs_le_tag = {
+	/* mapping/unmapping */
+	bs_gen_map,
+	bs_gen_unmap,
+	bs_gen_subregion,
+
+	/* allocation/deallocation */
+	bs_gen_alloc,
+	bs_gen_free,
+
+	/* barrier */
+	bs_gen_barrier,
+
+	/* read (single) */
+	bs_le_rs_1,
+	bs_le_rs_2,
+	bs_le_rs_4,
+	bs_le_rs_8,
+
+	bs_be_rs_2,
+	bs_be_rs_4,
+	bs_be_rs_8,
+
+	/* read multiple */
+	bs_le_rm_1,
+	bs_le_rm_2,
+	bs_le_rm_4,
+	bs_le_rm_8,
+
+	bs_be_rm_2,
+	bs_be_rm_4,
+	bs_be_rm_8,
+
+	/* read region */
+	bs_le_rr_1,
+	bs_le_rr_2,
+	bs_le_rr_4,
+	bs_le_rr_8,
+
+	bs_be_rr_2,
+	bs_be_rr_4,
+	bs_be_rr_8,
+
+	/* write (single) */
+	bs_le_ws_1,
+	bs_le_ws_2,
+	bs_le_ws_4,
+	bs_le_ws_8,
+
+	bs_be_ws_2,
+	bs_be_ws_4,
+	bs_be_ws_8,
+
+	/* write multiple */
+	bs_le_wm_1,
+	bs_le_wm_2,
+	bs_le_wm_4,
+	bs_le_wm_8,
+
+	bs_be_wm_2,
+	bs_be_wm_4,
+	bs_be_wm_8,
+
+	/* write region */
+	bs_le_wr_1,
+	bs_le_wr_2,
+	bs_le_wr_4,
+	bs_le_wr_8,
+
+	bs_be_wr_2,
+	bs_be_wr_4,
+	bs_be_wr_8,
+
+	/* set multiple */
+	bs_le_sm_1,
+	bs_le_sm_2,
+	bs_le_sm_4,
+	bs_le_sm_8,
+
+	bs_be_sm_2,
+	bs_be_sm_4,
+	bs_be_sm_8,
+
+	/* set region */
+	bs_le_sr_1,
+	bs_le_sr_2,
+	bs_le_sr_4,
+	bs_le_sr_8,
+
+	bs_be_sr_2,
+	bs_be_sr_4,
+	bs_be_sr_8,
+};


Property changes on: trunk/sys/powerpc/powerpc/bus_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/busdma_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/busdma_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/busdma_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,1200 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1997, 1998 Justin T. Gibbs.
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 2. 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 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 AUTHOR 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.
+ */
+
+/*
+ * From amd64/busdma_machdep.c, r204214
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/busdma_machdep.c 294677 2016-01-24 19:21:53Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/memdesc.h>
+#include <sys/mutex.h>
+#include <sys/sysctl.h>
+#include <sys/uio.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+
+#include <machine/atomic.h>
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+#include <machine/md_var.h>
+
+#include "iommu_if.h"
+
+#define MAX_BPAGES MIN(8192, physmem/40)
+
+struct bounce_zone;
+
+struct bus_dma_tag {
+	bus_dma_tag_t	  parent;
+	bus_size_t	  alignment;
+	bus_addr_t	  boundary;
+	bus_addr_t	  lowaddr;
+	bus_addr_t	  highaddr;
+	bus_dma_filter_t *filter;
+	void		 *filterarg;
+	bus_size_t	  maxsize;
+	u_int		  nsegments;
+	bus_size_t	  maxsegsz;
+	int		  flags;
+	int		  ref_count;
+	int		  map_count;
+	bus_dma_lock_t	 *lockfunc;
+	void		 *lockfuncarg;
+	struct bounce_zone *bounce_zone;
+	device_t	  iommu;
+	void		 *iommu_cookie;
+};
+
+struct bounce_page {
+	vm_offset_t	vaddr;		/* kva of bounce buffer */
+	bus_addr_t	busaddr;	/* Physical address */
+	vm_offset_t	datavaddr;	/* kva of client data */
+	bus_addr_t	dataaddr;	/* client physical address */
+	bus_size_t	datacount;	/* client data count */
+	STAILQ_ENTRY(bounce_page) links;
+};
+
+int busdma_swi_pending;
+
+struct bounce_zone {
+	STAILQ_ENTRY(bounce_zone) links;
+	STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
+	int		total_bpages;
+	int		free_bpages;
+	int		reserved_bpages;
+	int		active_bpages;
+	int		total_bounced;
+	int		total_deferred;
+	int		map_count;
+	bus_size_t	alignment;
+	bus_addr_t	lowaddr;
+	char		zoneid[8];
+	char		lowaddrid[20];
+	struct sysctl_ctx_list sysctl_tree;
+	struct sysctl_oid *sysctl_tree_top;
+};
+
+static struct mtx bounce_lock;
+static int total_bpages;
+static int busdma_zonecount;
+static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
+
+static SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD, 0, "Busdma parameters");
+SYSCTL_INT(_hw_busdma, OID_AUTO, total_bpages, CTLFLAG_RD, &total_bpages, 0,
+	   "Total bounce pages");
+
+struct bus_dmamap {
+	struct bp_list	       bpages;
+	int		       pagesneeded;
+	int		       pagesreserved;
+	bus_dma_tag_t	       dmat;
+	struct memdesc	       mem;
+	bus_dma_segment_t     *segments;
+	int		       nsegs;
+	bus_dmamap_callback_t *callback;
+	void		      *callback_arg;
+	STAILQ_ENTRY(bus_dmamap) links;
+	int		       contigalloc;
+};
+
+static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
+static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist;
+
+static void init_bounce_pages(void *dummy);
+static int alloc_bounce_zone(bus_dma_tag_t dmat);
+static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages);
+static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
+				int commit);
+static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map,
+				  vm_offset_t vaddr, bus_addr_t addr,
+				  bus_size_t size);
+static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage);
+static __inline int run_filter(bus_dma_tag_t dmat, bus_addr_t paddr);
+
+/*
+ * Return true if a match is made.
+ *
+ * To find a match walk the chain of bus_dma_tag_t's looking for 'paddr'.
+ *
+ * If paddr is within the bounds of the dma tag then call the filter callback
+ * to check for a match, if there is no filter callback then assume a match.
+ */
+static __inline int
+run_filter(bus_dma_tag_t dmat, bus_addr_t paddr)
+{
+	int retval;
+
+	retval = 0;
+
+	do {
+		if (dmat->filter == NULL && dmat->iommu == NULL &&
+		    paddr > dmat->lowaddr && paddr <= dmat->highaddr)
+			retval = 1;
+		if (dmat->filter == NULL &&
+		    (paddr & (dmat->alignment - 1)) != 0)
+			retval = 1;
+		if (dmat->filter != NULL &&
+		    (*dmat->filter)(dmat->filterarg, paddr) != 0)
+			retval = 1;
+
+		dmat = dmat->parent;		
+	} while (retval == 0 && dmat != NULL);
+	return (retval);
+}
+
+/*
+ * Convenience function for manipulating driver locks from busdma (during
+ * busdma_swi, for example).  Drivers that don't provide their own locks
+ * should specify &Giant to dmat->lockfuncarg.  Drivers that use their own
+ * non-mutex locking scheme don't have to use this at all.
+ */
+void
+busdma_lock_mutex(void *arg, bus_dma_lock_op_t op)
+{
+	struct mtx *dmtx;
+
+	dmtx = (struct mtx *)arg;
+	switch (op) {
+	case BUS_DMA_LOCK:
+		mtx_lock(dmtx);
+		break;
+	case BUS_DMA_UNLOCK:
+		mtx_unlock(dmtx);
+		break;
+	default:
+		panic("Unknown operation 0x%x for busdma_lock_mutex!", op);
+	}
+}
+
+/*
+ * dflt_lock should never get called.  It gets put into the dma tag when
+ * lockfunc == NULL, which is only valid if the maps that are associated
+ * with the tag are meant to never be defered.
+ * XXX Should have a way to identify which driver is responsible here.
+ */
+static void
+dflt_lock(void *arg, bus_dma_lock_op_t op)
+{
+	panic("driver error: busdma dflt_lock called");
+}
+
+#define BUS_DMA_COULD_BOUNCE	BUS_DMA_BUS3
+#define BUS_DMA_MIN_ALLOC_COMP	BUS_DMA_BUS4
+/*
+ * Allocate a device specific dma_tag.
+ */
+int
+bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
+		   bus_addr_t boundary, bus_addr_t lowaddr,
+		   bus_addr_t highaddr, bus_dma_filter_t *filter,
+		   void *filterarg, bus_size_t maxsize, int nsegments,
+		   bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
+		   void *lockfuncarg, bus_dma_tag_t *dmat)
+{
+	bus_dma_tag_t newtag;
+	int error = 0;
+
+	/* Basic sanity checking */
+	if (boundary != 0 && boundary < maxsegsz)
+		maxsegsz = boundary;
+
+	if (maxsegsz == 0) {
+		return (EINVAL);
+	}
+
+	/* Return a NULL tag on failure */
+	*dmat = NULL;
+
+	newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF,
+	    M_ZERO | M_NOWAIT);
+	if (newtag == NULL) {
+		CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
+		    __func__, newtag, 0, error);
+		return (ENOMEM);
+	}
+
+	newtag->parent = parent;
+	newtag->alignment = alignment;
+	newtag->boundary = boundary;
+	newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1);
+	newtag->highaddr = trunc_page((vm_paddr_t)highaddr) + (PAGE_SIZE - 1);
+	newtag->filter = filter;
+	newtag->filterarg = filterarg;
+	newtag->maxsize = maxsize;
+	newtag->nsegments = nsegments;
+	newtag->maxsegsz = maxsegsz;
+	newtag->flags = flags;
+	newtag->ref_count = 1; /* Count ourself */
+	newtag->map_count = 0;
+	if (lockfunc != NULL) {
+		newtag->lockfunc = lockfunc;
+		newtag->lockfuncarg = lockfuncarg;
+	} else {
+		newtag->lockfunc = dflt_lock;
+		newtag->lockfuncarg = NULL;
+	}
+
+	/* Take into account any restrictions imposed by our parent tag */
+	if (parent != NULL) {
+		newtag->lowaddr = MIN(parent->lowaddr, newtag->lowaddr);
+		newtag->highaddr = MAX(parent->highaddr, newtag->highaddr);
+		if (newtag->boundary == 0)
+			newtag->boundary = parent->boundary;
+		else if (parent->boundary != 0)
+			newtag->boundary = MIN(parent->boundary,
+					       newtag->boundary);
+		if (newtag->filter == NULL) {
+			/*
+			 * Short circuit looking at our parent directly
+			 * since we have encapsulated all of its information
+			 */
+			newtag->filter = parent->filter;
+			newtag->filterarg = parent->filterarg;
+			newtag->parent = parent->parent;
+		}
+		if (newtag->parent != NULL)
+			atomic_add_int(&parent->ref_count, 1);
+		newtag->iommu = parent->iommu;
+		newtag->iommu_cookie = parent->iommu_cookie;
+	}
+
+	if (newtag->lowaddr < ptoa((vm_paddr_t)Maxmem) && newtag->iommu == NULL)
+		newtag->flags |= BUS_DMA_COULD_BOUNCE;
+
+	if (newtag->alignment > 1)
+		newtag->flags |= BUS_DMA_COULD_BOUNCE;
+
+	if (((newtag->flags & BUS_DMA_COULD_BOUNCE) != 0) &&
+	    (flags & BUS_DMA_ALLOCNOW) != 0) {
+		struct bounce_zone *bz;
+
+		/* Must bounce */
+
+		if ((error = alloc_bounce_zone(newtag)) != 0) {
+			free(newtag, M_DEVBUF);
+			return (error);
+		}
+		bz = newtag->bounce_zone;
+
+		if (ptoa(bz->total_bpages) < maxsize) {
+			int pages;
+
+			pages = atop(maxsize) - bz->total_bpages;
+
+			/* Add pages to our bounce pool */
+			if (alloc_bounce_pages(newtag, pages) < pages)
+				error = ENOMEM;
+		}
+		/* Performed initial allocation */
+		newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
+	}
+	
+	if (error != 0) {
+		free(newtag, M_DEVBUF);
+	} else {
+		*dmat = newtag;
+	}
+	CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
+	    __func__, newtag, (newtag != NULL ? newtag->flags : 0), error);
+	return (error);
+}
+
+int
+bus_dma_tag_destroy(bus_dma_tag_t dmat)
+{
+	bus_dma_tag_t dmat_copy;
+	int error;
+
+	error = 0;
+	dmat_copy = dmat;
+
+	if (dmat != NULL) {
+
+		if (dmat->map_count != 0) {
+			error = EBUSY;
+			goto out;
+		}
+
+		while (dmat != NULL) {
+			bus_dma_tag_t parent;
+
+			parent = dmat->parent;
+			atomic_subtract_int(&dmat->ref_count, 1);
+			if (dmat->ref_count == 0) {
+				free(dmat, M_DEVBUF);
+				/*
+				 * Last reference count, so
+				 * release our reference
+				 * count on our parent.
+				 */
+				dmat = parent;
+			} else
+				dmat = NULL;
+		}
+	}
+out:
+	CTR3(KTR_BUSDMA, "%s tag %p error %d", __func__, dmat_copy, error);
+	return (error);
+}
+
+/*
+ * Allocate a handle for mapping from kva/uva/physical
+ * address space into bus device space.
+ */
+int
+bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
+{
+	int error;
+
+	error = 0;
+
+	*mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF,
+				     M_NOWAIT | M_ZERO);
+	if (*mapp == NULL) {
+		CTR3(KTR_BUSDMA, "%s: tag %p error %d",
+		    __func__, dmat, ENOMEM);
+		return (ENOMEM);
+	}
+
+
+	/*
+	 * Bouncing might be required if the driver asks for an active
+	 * exclusion region, a data alignment that is stricter than 1, and/or
+	 * an active address boundary.
+	 */
+	if (dmat->flags & BUS_DMA_COULD_BOUNCE) {
+
+		/* Must bounce */
+		struct bounce_zone *bz;
+		int maxpages;
+
+		if (dmat->bounce_zone == NULL) {
+			if ((error = alloc_bounce_zone(dmat)) != 0)
+				return (error);
+		}
+		bz = dmat->bounce_zone;
+
+		/* Initialize the new map */
+		STAILQ_INIT(&((*mapp)->bpages));
+
+		/*
+		 * Attempt to add pages to our pool on a per-instance
+		 * basis up to a sane limit.
+		 */
+		if (dmat->alignment > 1)
+			maxpages = MAX_BPAGES;
+		else
+			maxpages = MIN(MAX_BPAGES, Maxmem -atop(dmat->lowaddr));
+		if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0
+		 || (bz->map_count > 0 && bz->total_bpages < maxpages)) {
+			int pages;
+
+			pages = MAX(atop(dmat->maxsize), 1);
+			pages = MIN(maxpages - bz->total_bpages, pages);
+			pages = MAX(pages, 1);
+			if (alloc_bounce_pages(dmat, pages) < pages)
+				error = ENOMEM;
+
+			if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0) {
+				if (error == 0)
+					dmat->flags |= BUS_DMA_MIN_ALLOC_COMP;
+			} else {
+				error = 0;
+			}
+		}
+		bz->map_count++;
+	}
+
+	(*mapp)->nsegs = 0;
+	(*mapp)->segments = (bus_dma_segment_t *)malloc(
+	    sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
+	    M_NOWAIT);
+	if ((*mapp)->segments == NULL) {
+		CTR3(KTR_BUSDMA, "%s: tag %p error %d",
+		    __func__, dmat, ENOMEM);
+		return (ENOMEM);
+	}
+
+	if (error == 0)
+		dmat->map_count++;
+	CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
+	    __func__, dmat, dmat->flags, error);
+	return (error);
+}
+
+/*
+ * Destroy a handle for mapping from kva/uva/physical
+ * address space into bus device space.
+ */
+int
+bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+	if (dmat->flags & BUS_DMA_COULD_BOUNCE) {
+		if (STAILQ_FIRST(&map->bpages) != NULL) {
+			CTR3(KTR_BUSDMA, "%s: tag %p error %d",
+			    __func__, dmat, EBUSY);
+			return (EBUSY);
+		}
+		if (dmat->bounce_zone)
+			dmat->bounce_zone->map_count--;
+	}
+	free(map->segments, M_DEVBUF);
+	free(map, M_DEVBUF);
+	dmat->map_count--;
+	CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat);
+	return (0);
+}
+
+
+/*
+ * Allocate a piece of memory that can be efficiently mapped into
+ * bus device space based on the constraints lited in the dma tag.
+ * A dmamap to for use with dmamap_load is also allocated.
+ */
+int
+bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
+		 bus_dmamap_t *mapp)
+{
+	vm_memattr_t attr;
+	int mflags;
+
+	if (flags & BUS_DMA_NOWAIT)
+		mflags = M_NOWAIT;
+	else
+		mflags = M_WAITOK;
+
+	bus_dmamap_create(dmat, flags, mapp);
+
+	if (flags & BUS_DMA_ZERO)
+		mflags |= M_ZERO;
+#ifdef NOTYET
+	if (flags & BUS_DMA_NOCACHE)
+		attr = VM_MEMATTR_UNCACHEABLE;
+	else
+#endif
+		attr = VM_MEMATTR_DEFAULT;
+
+	/* 
+	 * XXX:
+	 * (dmat->alignment <= dmat->maxsize) is just a quick hack; the exact
+	 * alignment guarantees of malloc need to be nailed down, and the
+	 * code below should be rewritten to take that into account.
+	 *
+	 * In the meantime, we'll warn the user if malloc gets it wrong.
+	 */
+	if ((dmat->maxsize <= PAGE_SIZE) &&
+	   (dmat->alignment <= dmat->maxsize) &&
+	    dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) &&
+	    attr == VM_MEMATTR_DEFAULT) {
+		*vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);
+	} else {
+		/*
+		 * XXX Use Contigmalloc until it is merged into this facility
+		 *     and handles multi-seg allocations.  Nobody is doing
+		 *     multi-seg allocations yet though.
+		 * XXX Certain AGP hardware does.
+		 */
+		*vaddr = (void *)kmem_alloc_contig(kmem_arena, dmat->maxsize,
+		    mflags, 0ul, dmat->lowaddr, dmat->alignment ?
+		    dmat->alignment : 1ul, dmat->boundary, attr);
+		(*mapp)->contigalloc = 1;
+	}
+	if (*vaddr == NULL) {
+		CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
+		    __func__, dmat, dmat->flags, ENOMEM);
+		return (ENOMEM);
+	} else if (vtophys(*vaddr) & (dmat->alignment - 1)) {
+		printf("bus_dmamem_alloc failed to align memory properly.\n");
+	}
+	CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
+	    __func__, dmat, dmat->flags, 0);
+	return (0);
+}
+
+/*
+ * Free a piece of memory and it's allociated dmamap, that was allocated
+ * via bus_dmamem_alloc.  Make the same choice for free/contigfree.
+ */
+void
+bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
+{
+
+	if (!map->contigalloc)
+		free(vaddr, M_DEVBUF);
+	else
+		kmem_free(kmem_arena, (vm_offset_t)vaddr, dmat->maxsize);
+	bus_dmamap_destroy(dmat, map);
+	CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
+}
+
+static void
+_bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
+    bus_size_t buflen, int flags)
+{
+	bus_addr_t curaddr;
+	bus_size_t sgsize;
+
+	if (map->pagesneeded == 0) {
+		CTR4(KTR_BUSDMA, "lowaddr= %d Maxmem= %d, boundary= %d, "
+		    "alignment= %d", dmat->lowaddr, ptoa((vm_paddr_t)Maxmem),
+		    dmat->boundary, dmat->alignment);
+		CTR2(KTR_BUSDMA, "map= %p, pagesneeded= %d", map, map->pagesneeded);
+		/*
+		 * Count the number of bounce pages
+		 * needed in order to complete this transfer
+		 */
+		curaddr = buf;
+		while (buflen != 0) {
+			sgsize = MIN(buflen, dmat->maxsegsz);
+			if (run_filter(dmat, curaddr) != 0) {
+				sgsize = MIN(sgsize, PAGE_SIZE);
+				map->pagesneeded++;
+			}
+			curaddr += sgsize;
+			buflen -= sgsize;
+		}
+		CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded);
+	}
+}
+
+static void
+_bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap,
+    void *buf, bus_size_t buflen, int flags)
+{
+        vm_offset_t vaddr;
+        vm_offset_t vendaddr;
+        bus_addr_t paddr;
+
+	if (map->pagesneeded == 0) {
+		CTR4(KTR_BUSDMA, "lowaddr= %d Maxmem= %d, boundary= %d, "
+		    "alignment= %d", dmat->lowaddr, ptoa((vm_paddr_t)Maxmem),
+		    dmat->boundary, dmat->alignment);
+		CTR2(KTR_BUSDMA, "map= %p, pagesneeded= %d", map, map->pagesneeded);
+		/*
+		 * Count the number of bounce pages
+		 * needed in order to complete this transfer
+		 */
+		vaddr = (vm_offset_t)buf;
+		vendaddr = (vm_offset_t)buf + buflen;
+
+		while (vaddr < vendaddr) {
+			bus_size_t sg_len;
+
+			sg_len = PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK);
+			if (pmap == kernel_pmap)
+				paddr = pmap_kextract(vaddr);
+			else
+				paddr = pmap_extract(pmap, vaddr);
+			if (run_filter(dmat, paddr) != 0) {
+				sg_len = roundup2(sg_len, dmat->alignment);
+				map->pagesneeded++;
+			}
+			vaddr += sg_len;
+		}
+		CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded);
+	}
+}
+
+static int
+_bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags)
+{
+
+	/* Reserve Necessary Bounce Pages */
+	mtx_lock(&bounce_lock);
+	if (flags & BUS_DMA_NOWAIT) {
+		if (reserve_bounce_pages(dmat, map, 0) != 0) {
+			mtx_unlock(&bounce_lock);
+			return (ENOMEM);
+		}
+	} else {
+		if (reserve_bounce_pages(dmat, map, 1) != 0) {
+			/* Queue us for resources */
+			STAILQ_INSERT_TAIL(&bounce_map_waitinglist,
+			    map, links);
+			mtx_unlock(&bounce_lock);
+			return (EINPROGRESS);
+		}
+	}
+	mtx_unlock(&bounce_lock);
+
+	return (0);
+}
+
+/*
+ * Add a single contiguous physical range to the segment list.
+ */
+static int
+_bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr,
+		   bus_size_t sgsize, bus_dma_segment_t *segs, int *segp)
+{
+	bus_addr_t baddr, bmask;
+	int seg;
+
+	/*
+	 * Make sure we don't cross any boundaries.
+	 */
+	bmask = ~(dmat->boundary - 1);
+	if (dmat->boundary > 0) {
+		baddr = (curaddr + dmat->boundary) & bmask;
+		if (sgsize > (baddr - curaddr))
+			sgsize = (baddr - curaddr);
+	}
+
+	/*
+	 * Insert chunk into a segment, coalescing with
+	 * previous segment if possible.
+	 */
+	seg = *segp;
+	if (seg == -1) {
+		seg = 0;
+		segs[seg].ds_addr = curaddr;
+		segs[seg].ds_len = sgsize;
+	} else {
+		if (curaddr == segs[seg].ds_addr + segs[seg].ds_len &&
+		    (segs[seg].ds_len + sgsize) <= dmat->maxsegsz &&
+		    (dmat->boundary == 0 ||
+		     (segs[seg].ds_addr & bmask) == (curaddr & bmask)))
+			segs[seg].ds_len += sgsize;
+		else {
+			if (++seg >= dmat->nsegments)
+				return (0);
+			segs[seg].ds_addr = curaddr;
+			segs[seg].ds_len = sgsize;
+		}
+	}
+	*segp = seg;
+	return (sgsize);
+}
+
+/*
+ * Utility function to load a physical buffer.  segp contains
+ * the starting segment on entrace, and the ending segment on exit.
+ */
+int
+_bus_dmamap_load_phys(bus_dma_tag_t dmat,
+		      bus_dmamap_t map,
+		      vm_paddr_t buf, bus_size_t buflen,
+		      int flags,
+		      bus_dma_segment_t *segs,
+		      int *segp)
+{
+	bus_addr_t curaddr;
+	bus_size_t sgsize;
+	int error;
+
+	if (segs == NULL)
+		segs = map->segments;
+
+	if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
+		_bus_dmamap_count_phys(dmat, map, buf, buflen, flags);
+		if (map->pagesneeded != 0) {
+			error = _bus_dmamap_reserve_pages(dmat, map, flags);
+			if (error)
+				return (error);
+		}
+	}
+
+	while (buflen > 0) {
+		curaddr = buf;
+		sgsize = MIN(buflen, dmat->maxsegsz);
+		if (map->pagesneeded != 0 && run_filter(dmat, curaddr)) {
+			sgsize = MIN(sgsize, PAGE_SIZE);
+			curaddr = add_bounce_page(dmat, map, 0, curaddr,
+			    sgsize);
+		}
+		sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
+		    segp);
+		if (sgsize == 0)
+			break;
+		buf += sgsize;
+		buflen -= sgsize;
+	}
+
+	/*
+	 * Did we fit?
+	 */
+	return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */
+}
+
+int
+_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
+    struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
+    bus_dma_segment_t *segs, int *segp)
+{
+
+	return (bus_dmamap_load_ma_triv(dmat, map, ma, tlen, ma_offs, flags,
+	    segs, segp));
+}
+
+/*
+ * Utility function to load a linear buffer.  segp contains
+ * the starting segment on entrance, and the ending segment on exit.
+ */
+int
+_bus_dmamap_load_buffer(bus_dma_tag_t dmat,
+    			bus_dmamap_t map,
+			void *buf, bus_size_t buflen,
+			pmap_t pmap,
+			int flags,
+			bus_dma_segment_t *segs,
+			int *segp)
+{
+	bus_size_t sgsize;
+	bus_addr_t curaddr;
+	vm_offset_t vaddr;
+	int error;
+
+	if (segs == NULL)
+		segs = map->segments;
+
+	if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
+		_bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags);
+		if (map->pagesneeded != 0) {
+			error = _bus_dmamap_reserve_pages(dmat, map, flags);
+			if (error)
+				return (error);
+		}
+	}
+
+	vaddr = (vm_offset_t)buf;
+
+	while (buflen > 0) {
+		bus_size_t max_sgsize;
+
+		/*
+		 * Get the physical address for this segment.
+		 */
+		if (pmap == kernel_pmap)
+			curaddr = pmap_kextract(vaddr);
+		else
+			curaddr = pmap_extract(pmap, vaddr);
+
+		/*
+		 * Compute the segment size, and adjust counts.
+		 */
+		max_sgsize = MIN(buflen, dmat->maxsegsz);
+		sgsize = PAGE_SIZE - ((vm_offset_t)curaddr & PAGE_MASK);
+		if (map->pagesneeded != 0 && run_filter(dmat, curaddr)) {
+			sgsize = roundup2(sgsize, dmat->alignment);
+			sgsize = MIN(sgsize, max_sgsize);
+			curaddr = add_bounce_page(dmat, map, vaddr, curaddr,
+			    sgsize);
+		} else {
+			sgsize = MIN(sgsize, max_sgsize);
+		}
+
+		sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs,
+		    segp);
+		if (sgsize == 0)
+			break;
+		vaddr += sgsize;
+		buflen -= sgsize;
+	}
+
+	/*
+	 * Did we fit?
+	 */
+	return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */
+}
+
+void
+__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
+		    struct memdesc *mem, bus_dmamap_callback_t *callback,
+		    void *callback_arg)
+{
+
+	if (dmat->flags & BUS_DMA_COULD_BOUNCE) {
+		map->dmat = dmat;
+		map->mem = *mem;
+		map->callback = callback;
+		map->callback_arg = callback_arg;
+	}
+}
+
+bus_dma_segment_t *
+_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map,
+		     bus_dma_segment_t *segs, int nsegs, int error)
+{
+
+	map->nsegs = nsegs;
+	if (segs != NULL)
+		memcpy(map->segments, segs, map->nsegs*sizeof(segs[0]));
+	if (dmat->iommu != NULL)
+		IOMMU_MAP(dmat->iommu, map->segments, &map->nsegs,
+		    dmat->lowaddr, dmat->highaddr, dmat->alignment,
+		    dmat->boundary, dmat->iommu_cookie);
+
+	if (segs != NULL)
+		memcpy(segs, map->segments, map->nsegs*sizeof(segs[0]));
+	else
+		segs = map->segments;
+
+	return (segs);
+}
+
+/*
+ * Release the mapping held by map.
+ */
+void
+_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+	struct bounce_page *bpage;
+
+	if (dmat->iommu) {
+		IOMMU_UNMAP(dmat->iommu, map->segments, map->nsegs, dmat->iommu_cookie);
+		map->nsegs = 0;
+	}
+
+	while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
+		STAILQ_REMOVE_HEAD(&map->bpages, links);
+		free_bounce_page(dmat, bpage);
+	}
+}
+
+void
+_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
+{
+	struct bounce_page *bpage;
+
+	if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
+		/*
+		 * Handle data bouncing.  We might also
+		 * want to add support for invalidating
+		 * the caches on broken hardware
+		 */
+		CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
+		    "performing bounce", __func__, dmat, dmat->flags, op);
+
+		if (op & BUS_DMASYNC_PREWRITE) {
+			while (bpage != NULL) {
+				if (bpage->datavaddr != 0)
+					bcopy((void *)bpage->datavaddr,
+					      (void *)bpage->vaddr,
+					      bpage->datacount);
+				else
+					physcopyout(bpage->dataaddr,
+					    (void *)bpage->vaddr,
+					    bpage->datacount);
+				bpage = STAILQ_NEXT(bpage, links);
+			}
+			dmat->bounce_zone->total_bounced++;
+		}
+
+		if (op & BUS_DMASYNC_POSTREAD) {
+			while (bpage != NULL) {
+				if (bpage->datavaddr != 0)
+					bcopy((void *)bpage->vaddr,
+					      (void *)bpage->datavaddr,
+					      bpage->datacount);
+				else
+					physcopyin((void *)bpage->vaddr,
+					    bpage->dataaddr, bpage->datacount);
+				bpage = STAILQ_NEXT(bpage, links);
+			}
+			dmat->bounce_zone->total_bounced++;
+		}
+	}
+
+	powerpc_sync();
+}
+
+static void
+init_bounce_pages(void *dummy __unused)
+{
+
+	total_bpages = 0;
+	STAILQ_INIT(&bounce_zone_list);
+	STAILQ_INIT(&bounce_map_waitinglist);
+	STAILQ_INIT(&bounce_map_callbacklist);
+	mtx_init(&bounce_lock, "bounce pages lock", NULL, MTX_DEF);
+}
+SYSINIT(bpages, SI_SUB_LOCK, SI_ORDER_ANY, init_bounce_pages, NULL);
+
+static struct sysctl_ctx_list *
+busdma_sysctl_tree(struct bounce_zone *bz)
+{
+	return (&bz->sysctl_tree);
+}
+
+static struct sysctl_oid *
+busdma_sysctl_tree_top(struct bounce_zone *bz)
+{
+	return (bz->sysctl_tree_top);
+}
+
+static int
+alloc_bounce_zone(bus_dma_tag_t dmat)
+{
+	struct bounce_zone *bz;
+
+	/* Check to see if we already have a suitable zone */
+	STAILQ_FOREACH(bz, &bounce_zone_list, links) {
+		if ((dmat->alignment <= bz->alignment)
+		 && (dmat->lowaddr >= bz->lowaddr)) {
+			dmat->bounce_zone = bz;
+			return (0);
+		}
+	}
+
+	if ((bz = (struct bounce_zone *)malloc(sizeof(*bz), M_DEVBUF,
+	    M_NOWAIT | M_ZERO)) == NULL)
+		return (ENOMEM);
+
+	STAILQ_INIT(&bz->bounce_page_list);
+	bz->free_bpages = 0;
+	bz->reserved_bpages = 0;
+	bz->active_bpages = 0;
+	bz->lowaddr = dmat->lowaddr;
+	bz->alignment = MAX(dmat->alignment, PAGE_SIZE);
+	bz->map_count = 0;
+	snprintf(bz->zoneid, 8, "zone%d", busdma_zonecount);
+	busdma_zonecount++;
+	snprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr);
+	STAILQ_INSERT_TAIL(&bounce_zone_list, bz, links);
+	dmat->bounce_zone = bz;
+
+	sysctl_ctx_init(&bz->sysctl_tree);
+	bz->sysctl_tree_top = SYSCTL_ADD_NODE(&bz->sysctl_tree,
+	    SYSCTL_STATIC_CHILDREN(_hw_busdma), OID_AUTO, bz->zoneid,
+	    CTLFLAG_RD, 0, "");
+	if (bz->sysctl_tree_top == NULL) {
+		sysctl_ctx_free(&bz->sysctl_tree);
+		return (0);	/* XXX error code? */
+	}
+
+	SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+	    "total_bpages", CTLFLAG_RD, &bz->total_bpages, 0,
+	    "Total bounce pages");
+	SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+	    "free_bpages", CTLFLAG_RD, &bz->free_bpages, 0,
+	    "Free bounce pages");
+	SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+	    "reserved_bpages", CTLFLAG_RD, &bz->reserved_bpages, 0,
+	    "Reserved bounce pages");
+	SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+	    "active_bpages", CTLFLAG_RD, &bz->active_bpages, 0,
+	    "Active bounce pages");
+	SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+	    "total_bounced", CTLFLAG_RD, &bz->total_bounced, 0,
+	    "Total bounce requests");
+	SYSCTL_ADD_INT(busdma_sysctl_tree(bz),
+	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+	    "total_deferred", CTLFLAG_RD, &bz->total_deferred, 0,
+	    "Total bounce requests that were deferred");
+	SYSCTL_ADD_STRING(busdma_sysctl_tree(bz),
+	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+	    "lowaddr", CTLFLAG_RD, bz->lowaddrid, 0, "");
+	SYSCTL_ADD_UAUTO(busdma_sysctl_tree(bz),
+	    SYSCTL_CHILDREN(busdma_sysctl_tree_top(bz)), OID_AUTO,
+	    "alignment", CTLFLAG_RD, &bz->alignment, "");
+
+	return (0);
+}
+
+static int
+alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages)
+{
+	struct bounce_zone *bz;
+	int count;
+
+	bz = dmat->bounce_zone;
+	count = 0;
+	while (numpages > 0) {
+		struct bounce_page *bpage;
+
+		bpage = (struct bounce_page *)malloc(sizeof(*bpage), M_DEVBUF,
+						     M_NOWAIT | M_ZERO);
+
+		if (bpage == NULL)
+			break;
+		bpage->vaddr = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF,
+							 M_NOWAIT, 0ul,
+							 bz->lowaddr,
+							 PAGE_SIZE,
+							 0);
+		if (bpage->vaddr == 0) {
+			free(bpage, M_DEVBUF);
+			break;
+		}
+		bpage->busaddr = pmap_kextract(bpage->vaddr);
+		mtx_lock(&bounce_lock);
+		STAILQ_INSERT_TAIL(&bz->bounce_page_list, bpage, links);
+		total_bpages++;
+		bz->total_bpages++;
+		bz->free_bpages++;
+		mtx_unlock(&bounce_lock);
+		count++;
+		numpages--;
+	}
+	return (count);
+}
+
+static int
+reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit)
+{
+	struct bounce_zone *bz;
+	int pages;
+
+	mtx_assert(&bounce_lock, MA_OWNED);
+	bz = dmat->bounce_zone;
+	pages = MIN(bz->free_bpages, map->pagesneeded - map->pagesreserved);
+	if (commit == 0 && map->pagesneeded > (map->pagesreserved + pages))
+		return (map->pagesneeded - (map->pagesreserved + pages));
+	bz->free_bpages -= pages;
+	bz->reserved_bpages += pages;
+	map->pagesreserved += pages;
+	pages = map->pagesneeded - map->pagesreserved;
+
+	return (pages);
+}
+
+static bus_addr_t
+add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr,
+		bus_addr_t addr, bus_size_t size)
+{
+	struct bounce_zone *bz;
+	struct bounce_page *bpage;
+
+	KASSERT(dmat->bounce_zone != NULL, ("no bounce zone in dma tag"));
+
+	bz = dmat->bounce_zone;
+	if (map->pagesneeded == 0)
+		panic("add_bounce_page: map doesn't need any pages");
+	map->pagesneeded--;
+
+	if (map->pagesreserved == 0)
+		panic("add_bounce_page: map doesn't need any pages");
+	map->pagesreserved--;
+
+	mtx_lock(&bounce_lock);
+	bpage = STAILQ_FIRST(&bz->bounce_page_list);
+	if (bpage == NULL)
+		panic("add_bounce_page: free page list is empty");
+
+	STAILQ_REMOVE_HEAD(&bz->bounce_page_list, links);
+	bz->reserved_bpages--;
+	bz->active_bpages++;
+	mtx_unlock(&bounce_lock);
+
+	if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
+		/* Page offset needs to be preserved. */
+		bpage->vaddr |= addr & PAGE_MASK;
+		bpage->busaddr |= addr & PAGE_MASK;
+	}
+	bpage->datavaddr = vaddr;
+	bpage->dataaddr = addr;
+	bpage->datacount = size;
+	STAILQ_INSERT_TAIL(&(map->bpages), bpage, links);
+	return (bpage->busaddr);
+}
+
+static void
+free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
+{
+	struct bus_dmamap *map;
+	struct bounce_zone *bz;
+
+	bz = dmat->bounce_zone;
+	bpage->datavaddr = 0;
+	bpage->datacount = 0;
+	if (dmat->flags & BUS_DMA_KEEP_PG_OFFSET) {
+		/*
+		 * Reset the bounce page to start at offset 0.  Other uses
+		 * of this bounce page may need to store a full page of
+		 * data and/or assume it starts on a page boundary.
+		 */
+		bpage->vaddr &= ~PAGE_MASK;
+		bpage->busaddr &= ~PAGE_MASK;
+	}
+
+	mtx_lock(&bounce_lock);
+	STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
+	bz->free_bpages++;
+	bz->active_bpages--;
+	if ((map = STAILQ_FIRST(&bounce_map_waitinglist)) != NULL) {
+		if (reserve_bounce_pages(map->dmat, map, 1) == 0) {
+			STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
+			STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
+					   map, links);
+			busdma_swi_pending = 1;
+			bz->total_deferred++;
+			swi_sched(vm_ih, 0);
+		}
+	}
+	mtx_unlock(&bounce_lock);
+}
+
+void
+busdma_swi(void)
+{
+	bus_dma_tag_t dmat;
+	struct bus_dmamap *map;
+
+	mtx_lock(&bounce_lock);
+	while ((map = STAILQ_FIRST(&bounce_map_callbacklist)) != NULL) {
+		STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links);
+		mtx_unlock(&bounce_lock);
+		dmat = map->dmat;
+		(dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK);
+		bus_dmamap_load_mem(map->dmat, map, &map->mem,
+				    map->callback, map->callback_arg,
+				    BUS_DMA_WAITOK);
+		(dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK);
+		mtx_lock(&bounce_lock);
+	}
+	mtx_unlock(&bounce_lock);
+}
+
+int
+bus_dma_tag_set_iommu(bus_dma_tag_t tag, struct device *iommu, void *cookie)
+{
+	tag->iommu = iommu;
+	tag->iommu_cookie = cookie;
+
+	return (0);
+}
+


Property changes on: trunk/sys/powerpc/powerpc/busdma_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/clock.c
===================================================================
--- trunk/sys/powerpc/powerpc/clock.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/clock.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,309 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: clock.c,v 1.9 2000/01/19 02:52:19 msaitoh Exp $
+ */
+/*
+ * Copyright (C) 2001 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/clock.c 265954 2014-05-13 16:59:50Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/pcpu.h>
+#include <sys/sysctl.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <machine/clock.h>
+#include <machine/cpu.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/smp.h>
+
+/*
+ * Initially we assume a processor with a bus frequency of 12.5 MHz.
+ */
+static int		initialized = 0;
+static u_long		ns_per_tick = 80;
+static u_long		ticks_per_sec = 12500000;
+static u_long		*decr_counts[MAXCPU];
+
+static int		decr_et_start(struct eventtimer *et,
+    sbintime_t first, sbintime_t period);
+static int		decr_et_stop(struct eventtimer *et);
+static timecounter_get_t	decr_get_timecount;
+
+struct decr_state {
+	int	mode;	/* 0 - off, 1 - periodic, 2 - one-shot. */
+	int32_t	div;	/* Periodic divisor. */
+};
+static DPCPU_DEFINE(struct decr_state, decr_state);
+
+static struct eventtimer	decr_et;
+static struct timecounter	decr_tc = {
+	decr_get_timecount,	/* get_timecount */
+	0,			/* no poll_pps */
+	~0u,			/* counter_mask */
+	0,			/* frequency */
+	"timebase"		/* name */
+};
+
+/*
+ * Decrementer interrupt handler.
+ */
+void
+decr_intr(struct trapframe *frame)
+{
+	struct decr_state *s = DPCPU_PTR(decr_state);
+	int		nticks = 0;
+	int32_t		val;
+
+	if (!initialized)
+		return;
+
+	(*decr_counts[curcpu])++;
+
+#ifdef BOOKE
+	/*
+	 * Interrupt handler must reset DIS to avoid getting another
+	 * interrupt once EE is enabled.
+	 */
+	mtspr(SPR_TSR, TSR_DIS);
+#endif
+
+	if (s->mode == 1) {
+		/*
+		 * Based on the actual time delay since the last decrementer
+		 * reload, we arrange for earlier interrupt next time.
+		 */
+		__asm ("mfdec %0" : "=r"(val));
+		while (val < 0) {
+			val += s->div;
+			nticks++;
+		}
+		mtdec(val);
+	} else if (s->mode == 2) {
+		nticks = 1;
+		decr_et_stop(NULL);
+	}
+
+	while (nticks-- > 0) {
+		if (decr_et.et_active)
+			decr_et.et_event_cb(&decr_et, decr_et.et_arg);
+	}
+}
+
+void
+cpu_initclocks(void)
+{
+
+	decr_tc_init();
+	cpu_initclocks_bsp();
+}
+
+/*
+ * BSP early initialization.
+ */
+void
+decr_init(void)
+{
+	struct cpuref cpu;
+	char buf[32];
+
+	/*
+	 * Check the BSP's timebase frequency. Sometimes we can't find the BSP,
+	 * so fall back to the first CPU in this case.
+	 */
+	if (platform_smp_get_bsp(&cpu) != 0)
+		platform_smp_first_cpu(&cpu);
+	ticks_per_sec = platform_timebase_freq(&cpu);
+	ns_per_tick = 1000000000 / ticks_per_sec;
+
+	set_cputicker(mftb, ticks_per_sec, 0);
+	snprintf(buf, sizeof(buf), "cpu%d:decrementer", curcpu);
+	intrcnt_add(buf, &decr_counts[curcpu]);
+	decr_et_stop(NULL);
+	initialized = 1;
+}
+
+#ifdef SMP
+/*
+ * AP early initialization.
+ */
+void
+decr_ap_init(void)
+{
+	char buf[32];
+
+	snprintf(buf, sizeof(buf), "cpu%d:decrementer", curcpu);
+	intrcnt_add(buf, &decr_counts[curcpu]);
+	decr_et_stop(NULL);
+}
+#endif
+
+/*
+ * Final initialization.
+ */
+void
+decr_tc_init(void)
+{
+
+	decr_tc.tc_frequency = ticks_per_sec;
+	tc_init(&decr_tc);
+	decr_et.et_name = "decrementer";
+	decr_et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT |
+	    ET_FLAGS_PERCPU;
+	decr_et.et_quality = 1000;
+	decr_et.et_frequency = ticks_per_sec;
+	decr_et.et_min_period = (0x00000002LLU << 32) / ticks_per_sec;
+	decr_et.et_max_period = (0x7fffffffLLU << 32) / ticks_per_sec;
+	decr_et.et_start = decr_et_start;
+	decr_et.et_stop = decr_et_stop;
+	decr_et.et_priv = NULL;
+	et_register(&decr_et);
+}
+
+/*
+ * Event timer start method.
+ */
+static int
+decr_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
+{
+	struct decr_state *s = DPCPU_PTR(decr_state);
+	uint32_t fdiv;
+#ifdef BOOKE
+	uint32_t tcr;
+#endif
+
+	if (period != 0) {
+		s->mode = 1;
+		s->div = (decr_et.et_frequency * period) >> 32;
+	} else {
+		s->mode = 2;
+		s->div = 0;
+	}
+	if (first != 0)
+		fdiv = (decr_et.et_frequency * first) >> 32;
+	else
+		fdiv = s->div;
+
+#ifdef BOOKE
+	tcr = mfspr(SPR_TCR);
+	tcr |= TCR_DIE;
+	if (s->mode == 1) {
+		mtspr(SPR_DECAR, s->div);
+		tcr |= TCR_ARE;
+	} else
+		tcr &= ~TCR_ARE;
+	mtdec(fdiv);
+	mtspr(SPR_TCR, tcr);
+#else
+	mtdec(fdiv);
+#endif
+
+	return (0);
+}
+
+/*
+ * Event timer stop method.
+ */
+static int
+decr_et_stop(struct eventtimer *et)
+{
+	struct decr_state *s = DPCPU_PTR(decr_state);
+#ifdef BOOKE
+	uint32_t tcr;
+#endif
+
+	s->mode = 0;
+	s->div = 0x7fffffff;
+#ifdef BOOKE
+	tcr = mfspr(SPR_TCR);
+	tcr &= ~(TCR_DIE | TCR_ARE);
+	mtspr(SPR_TCR, tcr);
+#else
+	mtdec(s->div);
+#endif
+	return (0);
+}
+
+/*
+ * Timecounter get method.
+ */
+static unsigned
+decr_get_timecount(struct timecounter *tc)
+{
+	return (mftb());
+}
+
+/*
+ * Wait for about n microseconds (at least!).
+ */
+void
+DELAY(int n)
+{
+	u_quad_t	tb, ttb;
+
+	tb = mftb();
+	ttb = tb + (n * 1000 + ns_per_tick - 1) / ns_per_tick;
+	while (tb < ttb)
+		tb = mftb();
+}
+


Property changes on: trunk/sys/powerpc/powerpc/clock.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/copyinout.c
===================================================================
--- trunk/sys/powerpc/powerpc/copyinout.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/copyinout.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,612 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2002 Benno Rice
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+*/
+/*-
+ * Copyright (C) 1993 Wolfgang Solfrank.
+ * Copyright (C) 1993 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/copyinout.c 274648 2014-11-18 12:53:32Z kib $");
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+
+#include <machine/pcb.h>
+#include <machine/sr.h>
+#include <machine/slb.h>
+#include <machine/vmparam.h>
+
+int	setfault(faultbuf);	/* defined in locore.S */
+
+#ifdef AIM
+/*
+ * Makes sure that the right segment of userspace is mapped in.
+ */
+
+#ifdef __powerpc64__
+static __inline void
+set_user_sr(pmap_t pm, volatile const void *addr)
+{
+	struct slb *slb;
+	register_t slbv;
+
+	/* Try lockless look-up first */
+	slb = user_va_to_slb_entry(pm, (vm_offset_t)addr);
+
+	if (slb == NULL) {
+		/* If it isn't there, we need to pre-fault the VSID */
+		PMAP_LOCK(pm);
+		slbv = va_to_vsid(pm, (vm_offset_t)addr) << SLBV_VSID_SHIFT;
+		PMAP_UNLOCK(pm);
+	} else {
+		slbv = slb->slbv;
+	}
+
+	/* Mark segment no-execute */
+	slbv |= SLBV_N;
+
+	/* If we have already set this VSID, we can just return */
+	if (curthread->td_pcb->pcb_cpu.aim.usr_vsid == slbv) 
+		return;
+
+	__asm __volatile("isync");
+	curthread->td_pcb->pcb_cpu.aim.usr_segm =
+	    (uintptr_t)addr >> ADDR_SR_SHFT;
+	curthread->td_pcb->pcb_cpu.aim.usr_vsid = slbv;
+	__asm __volatile ("slbie %0; slbmte %1, %2; isync" ::
+	    "r"(USER_ADDR), "r"(slbv), "r"(USER_SLB_SLBE));
+}
+#else
+static __inline void
+set_user_sr(pmap_t pm, volatile const void *addr)
+{
+	register_t vsid;
+
+	vsid = va_to_vsid(pm, (vm_offset_t)addr);
+
+	/* Mark segment no-execute */
+	vsid |= SR_N;
+
+	/* If we have already set this VSID, we can just return */
+	if (curthread->td_pcb->pcb_cpu.aim.usr_vsid == vsid)
+		return;
+
+	__asm __volatile("isync");
+	curthread->td_pcb->pcb_cpu.aim.usr_segm =
+	    (uintptr_t)addr >> ADDR_SR_SHFT;
+	curthread->td_pcb->pcb_cpu.aim.usr_vsid = vsid;
+	__asm __volatile("mtsr %0,%1; isync" :: "n"(USER_SR), "r"(vsid));
+}
+#endif
+
+static __inline int
+map_user_ptr(pmap_t pm, volatile const void *uaddr, void **kaddr, size_t ulen,
+    size_t *klen)
+{
+	size_t l;
+
+	*kaddr = (char *)USER_ADDR + ((uintptr_t)uaddr & ~SEGMENT_MASK);
+
+	l = ((char *)USER_ADDR + SEGMENT_LENGTH) - (char *)(*kaddr);
+	if (l > ulen)
+		l = ulen;
+	if (klen)
+		*klen = l;
+	else if (l != ulen)
+		return (EFAULT);
+
+	set_user_sr(pm, uaddr);
+
+	return (0);
+}
+#else /* Book-E uses a combined kernel/user mapping */
+static __inline int
+map_user_ptr(pmap_t pm, volatile const void *uaddr, void **kaddr, size_t ulen,
+    size_t *klen)
+{
+
+	if ((uintptr_t)uaddr + ulen > VM_MAXUSER_ADDRESS + PAGE_SIZE)
+		return (EFAULT);
+
+	*kaddr = (void *)(uintptr_t)uaddr;
+	if (klen)
+		*klen = ulen;
+
+	return (0);
+}
+#endif
+
+int
+copyout(const void *kaddr, void *udaddr, size_t len)
+{
+	struct		thread *td;
+	pmap_t		pm;
+	faultbuf	env;
+	const char	*kp;
+	char		*up, *p;
+	size_t		l;
+
+	td = curthread;
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (EFAULT);
+	}
+
+	kp = kaddr;
+	up = udaddr;
+
+	while (len > 0) {
+		if (map_user_ptr(pm, udaddr, (void **)&p, len, &l)) {
+			td->td_pcb->pcb_onfault = NULL;
+			return (EFAULT);
+		}
+
+		bcopy(kp, p, l);
+
+		up += l;
+		kp += l;
+		len -= l;
+	}
+
+	td->td_pcb->pcb_onfault = NULL;
+	return (0);
+}
+
+int
+copyin(const void *udaddr, void *kaddr, size_t len)
+{
+	struct		thread *td;
+	pmap_t		pm;
+	faultbuf	env;
+	const char	*up;
+	char		*kp, *p;
+	size_t		l;
+
+	td = curthread;
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (EFAULT);
+	}
+
+	kp = kaddr;
+	up = udaddr;
+
+	while (len > 0) {
+		if (map_user_ptr(pm, udaddr, (void **)&p, len, &l)) {
+			td->td_pcb->pcb_onfault = NULL;
+			return (EFAULT);
+		}
+
+		bcopy(p, kp, l);
+
+		up += l;
+		kp += l;
+		len -= l;
+	}
+
+	td->td_pcb->pcb_onfault = NULL;
+	return (0);
+}
+
+int
+copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
+{
+	const char	*up;
+	char		*kp;
+	size_t		l;
+	int		rv, c;
+
+	kp = kaddr;
+	up = udaddr;
+
+	rv = ENAMETOOLONG;
+
+	for (l = 0; len-- > 0; l++) {
+		if ((c = fubyte(up++)) < 0) {
+			rv = EFAULT;
+			break;
+		}
+
+		if (!(*kp++ = c)) {
+			l++;
+			rv = 0;
+			break;
+		}
+	}
+
+	if (done != NULL) {
+		*done = l;
+	}
+
+	return (rv);
+}
+
+int
+subyte(volatile void *addr, int byte)
+{
+	struct		thread *td;
+	pmap_t		pm;
+	faultbuf	env;
+	char		*p;
+
+	td = curthread;
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	*p = (char)byte;
+
+	td->td_pcb->pcb_onfault = NULL;
+	return (0);
+}
+
+#ifdef __powerpc64__
+int
+suword32(volatile void *addr, int word)
+{
+	struct		thread *td;
+	pmap_t		pm;
+	faultbuf	env;
+	int		*p;
+
+	td = curthread;
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	*p = word;
+
+	td->td_pcb->pcb_onfault = NULL;
+	return (0);
+}
+#endif
+
+int
+suword(volatile void *addr, long word)
+{
+	struct		thread *td;
+	pmap_t		pm;
+	faultbuf	env;
+	long		*p;
+
+	td = curthread;
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	*p = word;
+
+	td->td_pcb->pcb_onfault = NULL;
+	return (0);
+}
+
+#ifdef __powerpc64__
+int
+suword64(volatile void *addr, int64_t word)
+{
+	return (suword(addr, (long)word));
+}
+#else
+int
+suword32(volatile void *addr, int32_t word)
+{
+	return (suword(addr, (long)word));
+}
+#endif
+
+int
+fubyte(volatile const void *addr)
+{
+	struct		thread *td;
+	pmap_t		pm;
+	faultbuf	env;
+	u_char		*p;
+	int		val;
+
+	td = curthread;
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	val = *p;
+
+	td->td_pcb->pcb_onfault = NULL;
+	return (val);
+}
+
+int
+fuword16(volatile const void *addr)
+{
+	struct		thread *td;
+	pmap_t		pm;
+	faultbuf	env;
+	uint16_t	*p, val;
+
+	td = curthread;
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	val = *p;
+
+	td->td_pcb->pcb_onfault = NULL;
+	return (val);
+}
+
+int
+fueword32(volatile const void *addr, int32_t *val)
+{
+	struct		thread *td;
+	pmap_t		pm;
+	faultbuf	env;
+	int32_t		*p;
+
+	td = curthread;
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	*val = *p;
+
+	td->td_pcb->pcb_onfault = NULL;
+	return (0);
+}
+
+#ifdef __powerpc64__
+int
+fueword64(volatile const void *addr, int64_t *val)
+{
+	struct		thread *td;
+	pmap_t		pm;
+	faultbuf	env;
+	int64_t		*p;
+
+	td = curthread;
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	*val = *p;
+
+	td->td_pcb->pcb_onfault = NULL;
+	return (0);
+}
+#endif
+
+int
+fueword(volatile const void *addr, long *val)
+{
+	struct		thread *td;
+	pmap_t		pm;
+	faultbuf	env;
+	long		*p;
+
+	td = curthread;
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	if (map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	*val = *p;
+
+	td->td_pcb->pcb_onfault = NULL;
+	return (0);
+}
+
+int
+casueword32(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp,
+    uint32_t new)
+{
+	struct thread *td;
+	pmap_t pm;
+	faultbuf env;
+	uint32_t *p, val;
+
+	td = curthread;
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	if (map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p, sizeof(*p),
+	    NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	__asm __volatile (
+		"1:\tlwarx %0, 0, %2\n\t"	/* load old value */
+		"cmplw %3, %0\n\t"		/* compare */
+		"bne 2f\n\t"			/* exit if not equal */
+		"stwcx. %4, 0, %2\n\t"      	/* attempt to store */
+		"bne- 1b\n\t"			/* spin if failed */
+		"b 3f\n\t"			/* we've succeeded */
+		"2:\n\t"
+		"stwcx. %0, 0, %2\n\t"       	/* clear reservation (74xx) */
+		"3:\n\t"
+		: "=&r" (val), "=m" (*p)
+		: "r" (p), "r" (old), "r" (new), "m" (*p)
+		: "cc", "memory");
+
+	td->td_pcb->pcb_onfault = NULL;
+
+	*oldvalp = val;
+	return (0);
+}
+
+#ifndef __powerpc64__
+int
+casueword(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new)
+{
+
+	return (casueword32((volatile uint32_t *)addr, old,
+	    (uint32_t *)oldvalp, new));
+}
+#else
+int
+casueword(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new)
+{
+	struct thread *td;
+	pmap_t pm;
+	faultbuf env;
+	u_long *p, val;
+
+	td = curthread;
+	pm = &td->td_proc->p_vmspace->vm_pmap;
+
+	if (setfault(env)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	if (map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p, sizeof(*p),
+	    NULL)) {
+		td->td_pcb->pcb_onfault = NULL;
+		return (-1);
+	}
+
+	__asm __volatile (
+		"1:\tldarx %0, 0, %2\n\t"	/* load old value */
+		"cmpld %3, %0\n\t"		/* compare */
+		"bne 2f\n\t"			/* exit if not equal */
+		"stdcx. %4, 0, %2\n\t"      	/* attempt to store */
+		"bne- 1b\n\t"			/* spin if failed */
+		"b 3f\n\t"			/* we've succeeded */
+		"2:\n\t"
+		"stdcx. %0, 0, %2\n\t"       	/* clear reservation (74xx) */
+		"3:\n\t"
+		: "=&r" (val), "=m" (*p)
+		: "r" (p), "r" (old), "r" (new), "m" (*p)
+		: "cc", "memory");
+
+	td->td_pcb->pcb_onfault = NULL;
+
+	*oldvalp = val;
+	return (0);
+}
+#endif


Property changes on: trunk/sys/powerpc/powerpc/copyinout.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/copystr.c
===================================================================
--- trunk/sys/powerpc/powerpc/copystr.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/copystr.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,69 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 1995 Wolfgang Solfrank.
+ * Copyright (C) 1995 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.
+ *
+ *	$NetBSD: copystr.c,v 1.3 2000/06/08 06:47:17 kleink Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/copystr.c 113038 2003-04-03 21:36:33Z obrien $");
+
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+
+/*
+ * Emulate copyinstr.
+ */
+int
+copystr(kfaddr, kdaddr, len, done)
+	const void *kfaddr;
+	void *kdaddr;
+	size_t len;
+	size_t *done;
+{
+	const u_char *kfp = kfaddr;
+	u_char *kdp = kdaddr;
+	size_t l;
+	int rv;
+	
+	rv = ENAMETOOLONG;
+	for (l = 0; len-- > 0; l++) {
+		if (!(*kdp++ = *kfp++)) {
+			l++;
+			rv = 0;
+			break;
+		}
+	}
+	if (done != NULL) {
+		*done = l;
+	}
+	return rv;
+}


Property changes on: trunk/sys/powerpc/powerpc/copystr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/cpu.c
===================================================================
--- trunk/sys/powerpc/powerpc/cpu.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/cpu.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,659 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2001 Matt Thomas.
+ * Copyright (c) 2001 Tsubai Masanari.
+ * Copyright (c) 1998, 1999, 2001 Internet Research Institute, Inc.
+ * 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
+ *	Internet Research Institute, Inc.
+ * 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.
+ */
+/*-
+ * Copyright (C) 2003 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ *
+ * from $NetBSD: cpu_subr.c,v 1.1 2003/02/03 17:10:09 matt Exp $
+ * $FreeBSD: stable/10/sys/powerpc/powerpc/cpu.c 273736 2014-10-27 14:38:00Z hselasky $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/hid.h>
+#include <machine/md_var.h>
+#include <machine/smp.h>
+#include <machine/spr.h>
+
+#include <dev/ofw/openfirm.h>
+
+static void	cpu_6xx_setup(int cpuid, uint16_t vers);
+static void	cpu_970_setup(int cpuid, uint16_t vers);
+static void	cpu_booke_setup(int cpuid, uint16_t vers);
+
+int powerpc_pow_enabled;
+void (*cpu_idle_hook)(sbintime_t) = NULL;
+static void	cpu_idle_60x(sbintime_t);
+static void	cpu_idle_booke(sbintime_t);
+
+struct cputab {
+	const char	*name;
+	uint16_t	version;
+	uint16_t	revfmt;
+	int		features;	/* Do not include PPC_FEATURE_32 or
+					 * PPC_FEATURE_HAS_MMU */
+	void		(*cpu_setup)(int cpuid, uint16_t vers);
+};
+#define	REVFMT_MAJMIN	1	/* %u.%u */
+#define	REVFMT_HEX	2	/* 0x%04x */
+#define	REVFMT_DEC	3	/* %u */
+static const struct cputab models[] = {
+        { "Motorola PowerPC 601",	MPC601,		REVFMT_DEC,
+	   PPC_FEATURE_HAS_FPU | PPC_FEATURE_UNIFIED_CACHE, cpu_6xx_setup },
+        { "Motorola PowerPC 602",	MPC602,		REVFMT_DEC,
+	   PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 603",	MPC603,		REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 603e",	MPC603e,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 603ev",	MPC603ev,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 604",	MPC604,		REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 604ev",	MPC604ev,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 620",	MPC620,		REVFMT_HEX,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL },
+        { "Motorola PowerPC 750",	MPC750,		REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "IBM PowerPC 750FX",		IBM750FX,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "IBM PowerPC 970",		IBM970,		REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU,
+	   cpu_970_setup },
+        { "IBM PowerPC 970FX",		IBM970FX,	REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU,
+	   cpu_970_setup },
+        { "IBM PowerPC 970GX",		IBM970GX,	REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU,
+	   cpu_970_setup },
+        { "IBM PowerPC 970MP",		IBM970MP,	REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU,
+	   cpu_970_setup },
+        { "IBM POWER4",		IBMPOWER4,	REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL },
+        { "IBM POWER4+",	IBMPOWER4PLUS,	REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL },
+        { "IBM POWER5",		IBMPOWER5,	REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL },
+        { "IBM POWER5+",	IBMPOWER5PLUS,	REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL },
+        { "IBM POWER6",		IBMPOWER6,	REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU,
+	   NULL },
+        { "IBM POWER7",		IBMPOWER7,	REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU,
+	   NULL },
+        { "IBM POWER7+",	IBMPOWER7PLUS,	REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU,
+	   NULL },
+        { "IBM POWER8",		IBMPOWER8,	REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU,
+	   NULL },
+        { "Motorola PowerPC 7400",	MPC7400,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 7410",	MPC7410,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 7450",	MPC7450,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 7455",	MPC7455,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 7457",	MPC7457,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 7447A",	MPC7447A,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 7448",	MPC7448,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 8240",	MPC8240,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Motorola PowerPC 8245",	MPC8245,	REVFMT_MAJMIN,
+	   PPC_FEATURE_HAS_FPU, cpu_6xx_setup },
+        { "Freescale e500v1 core",	FSL_E500v1,	REVFMT_MAJMIN,
+	   0, cpu_booke_setup },
+        { "Freescale e500v2 core",	FSL_E500v2,	REVFMT_MAJMIN,
+	   0, cpu_booke_setup },
+	{ "Freescale e500mc core",	FSL_E500mc,	REVFMT_MAJMIN,
+	   0, cpu_booke_setup },
+	{ "Freescale e5500 core",	FSL_E5500,	REVFMT_MAJMIN,
+	   0, cpu_booke_setup },
+        { "IBM Cell Broadband Engine",	IBMCELLBE,	REVFMT_MAJMIN,
+	   PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU,
+	   NULL},
+        { "Unknown PowerPC CPU",	0,		REVFMT_HEX, 0, NULL },
+};
+
+static void	cpu_6xx_print_cacheinfo(u_int, uint16_t);
+static int	cpu_feature_bit(SYSCTL_HANDLER_ARGS);
+
+static char model[64];
+SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, "");
+
+int cpu_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU;
+SYSCTL_OPAQUE(_hw, OID_AUTO, cpu_features, CTLFLAG_RD,
+    &cpu_features, sizeof(cpu_features), "IX", "PowerPC CPU features");
+
+/* Provide some user-friendly aliases for bits in cpu_features */
+SYSCTL_PROC(_hw, OID_AUTO, floatingpoint, CTLTYPE_INT | CTLFLAG_RD,
+    0, PPC_FEATURE_HAS_FPU, cpu_feature_bit, "I",
+    "Floating point instructions executed in hardware");
+SYSCTL_PROC(_hw, OID_AUTO, altivec, CTLTYPE_INT | CTLFLAG_RD,
+    0, PPC_FEATURE_HAS_ALTIVEC, cpu_feature_bit, "I", "CPU supports Altivec");
+
+void
+cpu_setup(u_int cpuid)
+{
+	u_int		pvr, maj, min;
+	uint16_t	vers, rev, revfmt;
+	uint64_t	cps;
+	const struct	cputab *cp;
+	const char	*name;
+
+	pvr = mfpvr();
+	vers = pvr >> 16;
+	rev = pvr;
+	switch (vers) {
+		case MPC7410:
+			min = (pvr >> 0) & 0xff;
+			maj = min <= 4 ? 1 : 2;
+			break;
+		case FSL_E500v1:
+		case FSL_E500v2:
+		case FSL_E500mc:
+		case FSL_E5500:
+			maj = (pvr >>  4) & 0xf;
+			min = (pvr >>  0) & 0xf;
+			break;
+		default:
+			maj = (pvr >>  8) & 0xf;
+			min = (pvr >>  0) & 0xf;
+	}
+
+	for (cp = models; cp->version != 0; cp++) {
+		if (cp->version == vers)
+			break;
+	}
+
+	revfmt = cp->revfmt;
+	name = cp->name;
+	if (rev == MPC750 && pvr == 15) {
+		name = "Motorola MPC755";
+		revfmt = REVFMT_HEX;
+	}
+	strncpy(model, name, sizeof(model) - 1);
+
+	printf("cpu%d: %s revision ", cpuid, name);
+
+	switch (revfmt) {
+		case REVFMT_MAJMIN:
+			printf("%u.%u", maj, min);
+			break;
+		case REVFMT_HEX:
+			printf("0x%04x", rev);
+			break;
+		case REVFMT_DEC:
+			printf("%u", rev);
+			break;
+	}
+
+	if (cpu_est_clockrate(0, &cps) == 0)
+		printf(", %jd.%02jd MHz", cps / 1000000, (cps / 10000) % 100);
+	printf("\n");
+
+	cpu_features |= cp->features;
+	printf("cpu%d: Features %b\n", cpuid, cpu_features,
+	    PPC_FEATURE_BITMASK);
+
+	/*
+	 * Configure CPU
+	 */
+	if (cp->cpu_setup != NULL)
+		cp->cpu_setup(cpuid, vers);
+}
+
+/* Get current clock frequency for the given cpu id. */
+int
+cpu_est_clockrate(int cpu_id, uint64_t *cps)
+{
+	uint16_t	vers;
+	register_t	msr;
+	phandle_t	cpu, dev, root;
+	int		res  = 0;
+	char		buf[8];
+
+	vers = mfpvr() >> 16;
+	msr = mfmsr();
+	mtmsr(msr & ~PSL_EE);
+
+	switch (vers) {
+		case MPC7450:
+		case MPC7455:
+		case MPC7457:
+		case MPC750:
+		case IBM750FX:
+		case MPC7400:
+		case MPC7410:
+		case MPC7447A:
+		case MPC7448:
+			mtspr(SPR_MMCR0, SPR_MMCR0_FC);
+			mtspr(SPR_PMC1, 0);
+			mtspr(SPR_MMCR0, SPR_MMCR0_PMC1SEL(PMCN_CYCLES));
+			DELAY(1000);
+			*cps = (mfspr(SPR_PMC1) * 1000) + 4999;
+			mtspr(SPR_MMCR0, SPR_MMCR0_FC);
+
+			mtmsr(msr);
+			return (0);
+		case IBM970:
+		case IBM970FX:
+		case IBM970MP:
+			isync();
+			mtspr(SPR_970MMCR0, SPR_MMCR0_FC);
+			isync();
+			mtspr(SPR_970MMCR1, 0);
+			mtspr(SPR_970MMCRA, 0);
+			mtspr(SPR_970PMC1, 0);
+			mtspr(SPR_970MMCR0,
+			    SPR_970MMCR0_PMC1SEL(PMC970N_CYCLES));
+			isync();
+			DELAY(1000);
+			powerpc_sync();
+			mtspr(SPR_970MMCR0, SPR_MMCR0_FC);
+			*cps = (mfspr(SPR_970PMC1) * 1000) + 4999;
+
+			mtmsr(msr);
+			return (0);
+
+		default:
+			root = OF_peer(0);
+			if (root == 0)
+				return (ENXIO);
+
+			dev = OF_child(root);
+			while (dev != 0) {
+				res = OF_getprop(dev, "name", buf, sizeof(buf));
+				if (res > 0 && strcmp(buf, "cpus") == 0)
+					break;
+				dev = OF_peer(dev);
+			}
+			cpu = OF_child(dev);
+			while (cpu != 0) {
+				res = OF_getprop(cpu, "device_type", buf,
+						sizeof(buf));
+				if (res > 0 && strcmp(buf, "cpu") == 0)
+					break;
+				cpu = OF_peer(cpu);
+			}
+			if (cpu == 0)
+				return (ENOENT);
+			if (OF_getprop(cpu, "ibm,extended-clock-frequency",
+			    cps, sizeof(*cps)) >= 0) {
+				return (0);
+			} else if (OF_getprop(cpu, "clock-frequency", cps, 
+			    sizeof(cell_t)) >= 0) {
+				*cps >>= 32;
+				return (0);
+			} else {
+				return (ENOENT);
+			}
+	}
+}
+
+void
+cpu_6xx_setup(int cpuid, uint16_t vers)
+{
+	register_t hid0, pvr;
+	const char *bitmask;
+
+	hid0 = mfspr(SPR_HID0);
+	pvr = mfpvr();
+
+	/*
+	 * Configure power-saving mode.
+	 */
+	switch (vers) {
+		case MPC603:
+		case MPC603e:
+		case MPC603ev:
+		case MPC604ev:
+		case MPC750:
+		case IBM750FX:
+		case MPC7400:
+		case MPC7410:
+		case MPC8240:
+		case MPC8245:
+			/* Select DOZE mode. */
+			hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP);
+			hid0 |= HID0_DOZE | HID0_DPM;
+			powerpc_pow_enabled = 1;
+			break;
+
+		case MPC7448:
+		case MPC7447A:
+		case MPC7457:
+		case MPC7455:
+		case MPC7450:
+			/* Enable the 7450 branch caches */
+			hid0 |= HID0_SGE | HID0_BTIC;
+			hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT;
+			/* Disable BTIC on 7450 Rev 2.0 or earlier and on 7457 */
+			if (((pvr >> 16) == MPC7450 && (pvr & 0xFFFF) <= 0x0200)
+					|| (pvr >> 16) == MPC7457)
+				hid0 &= ~HID0_BTIC;
+			/* Select NAP mode. */
+			hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP);
+			hid0 |= HID0_NAP | HID0_DPM;
+			powerpc_pow_enabled = 1;
+			break;
+
+		default:
+			/* No power-saving mode is available. */ ;
+	}
+
+	switch (vers) {
+		case IBM750FX:
+		case MPC750:
+			hid0 &= ~HID0_DBP;		/* XXX correct? */
+			hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT;
+			break;
+
+		case MPC7400:
+		case MPC7410:
+			hid0 &= ~HID0_SPD;
+			hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT;
+			hid0 |= HID0_EIEC;
+			break;
+
+	}
+
+	mtspr(SPR_HID0, hid0);
+
+	if (bootverbose)
+		cpu_6xx_print_cacheinfo(cpuid, vers);
+
+	switch (vers) {
+		case MPC7447A:
+		case MPC7448:
+		case MPC7450:
+		case MPC7455:
+		case MPC7457:
+			bitmask = HID0_7450_BITMASK;
+			break;
+		default:
+			bitmask = HID0_BITMASK;
+			break;
+	}
+
+	printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, bitmask);
+
+	if (cpu_idle_hook == NULL)
+		cpu_idle_hook = cpu_idle_60x;
+}
+
+
+static void
+cpu_6xx_print_cacheinfo(u_int cpuid, uint16_t vers)
+{
+	register_t hid;
+
+	hid = mfspr(SPR_HID0);
+	printf("cpu%u: ", cpuid);
+	printf("L1 I-cache %sabled, ", (hid & HID0_ICE) ? "en" : "dis");
+	printf("L1 D-cache %sabled\n", (hid & HID0_DCE) ? "en" : "dis");
+
+	printf("cpu%u: ", cpuid);
+  	if (mfspr(SPR_L2CR) & L2CR_L2E) {
+		switch (vers) {
+		case MPC7450:
+		case MPC7455:
+		case MPC7457:
+			printf("256KB L2 cache, ");
+			if (mfspr(SPR_L3CR) & L3CR_L3E)
+				printf("%cMB L3 backside cache",
+				    mfspr(SPR_L3CR) & L3CR_L3SIZ ? '2' : '1');
+			else
+				printf("L3 cache disabled");
+			printf("\n");
+			break;
+		case IBM750FX:
+			printf("512KB L2 cache\n");
+			break; 
+		default:
+			switch (mfspr(SPR_L2CR) & L2CR_L2SIZ) {
+			case L2SIZ_256K:
+				printf("256KB ");
+				break;
+			case L2SIZ_512K:
+				printf("512KB ");
+				break;
+			case L2SIZ_1M:
+				printf("1MB ");
+				break;
+			}
+			printf("write-%s", (mfspr(SPR_L2CR) & L2CR_L2WT)
+			    ? "through" : "back");
+			if (mfspr(SPR_L2CR) & L2CR_L2PE)
+				printf(", with parity");
+			printf(" backside cache\n");
+			break;
+		}
+	} else
+		printf("L2 cache disabled\n");
+}
+
+static void
+cpu_booke_setup(int cpuid, uint16_t vers)
+{
+#ifdef BOOKE_E500
+	register_t hid0;
+
+	hid0 = mfspr(SPR_HID0);
+
+	/* Programe power-management mode. */
+	hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP);
+	hid0 |= HID0_DOZE;
+
+	mtspr(SPR_HID0, hid0);
+
+	printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, HID0_E500_BITMASK);
+#endif
+
+	if (cpu_idle_hook == NULL)
+		cpu_idle_hook = cpu_idle_booke;
+}
+
+static void
+cpu_970_setup(int cpuid, uint16_t vers)
+{
+#ifdef AIM
+	uint32_t hid0_hi, hid0_lo;
+
+	__asm __volatile ("mfspr %0,%2; clrldi %1,%0,32; srdi %0,%0,32;"
+	    : "=r" (hid0_hi), "=r" (hid0_lo) : "K" (SPR_HID0));
+
+	/* Configure power-saving mode */
+	switch (vers) {
+	case IBM970MP:
+		hid0_hi |= (HID0_DEEPNAP | HID0_NAP | HID0_DPM);
+		hid0_hi &= ~HID0_DOZE;
+		break;
+	default:
+		hid0_hi |= (HID0_NAP | HID0_DPM);
+		hid0_hi &= ~(HID0_DOZE | HID0_DEEPNAP);
+		break;
+	}
+	powerpc_pow_enabled = 1;
+
+	__asm __volatile (" \
+		sync; isync;					\
+		sldi	%0,%0,32; or %0,%0,%1;			\
+		mtspr	%2, %0;					\
+		mfspr   %0, %2; mfspr   %0, %2; mfspr   %0, %2; \
+		mfspr   %0, %2; mfspr   %0, %2; mfspr   %0, %2; \
+		sync; isync"
+	    :: "r" (hid0_hi), "r"(hid0_lo), "K" (SPR_HID0));
+
+	__asm __volatile ("mfspr %0,%1; srdi %0,%0,32;"
+	    : "=r" (hid0_hi) : "K" (SPR_HID0));
+	printf("cpu%d: HID0 %b\n", cpuid, (int)(hid0_hi), HID0_970_BITMASK);
+#endif
+
+	cpu_idle_hook = cpu_idle_60x;
+}
+
+static int
+cpu_feature_bit(SYSCTL_HANDLER_ARGS)
+{
+	int result;
+
+	result = (cpu_features & arg2) ? 1 : 0;
+
+	return (sysctl_handle_int(oidp, &result, 0, req));
+}
+
+void
+cpu_idle(int busy)
+{
+	sbintime_t sbt = -1;
+
+#ifdef INVARIANTS
+	if ((mfmsr() & PSL_EE) != PSL_EE) {
+		struct thread *td = curthread;
+		printf("td msr %#lx\n", (u_long)td->td_md.md_saved_msr);
+		panic("ints disabled in idleproc!");
+	}
+#endif
+
+	CTR2(KTR_SPARE2, "cpu_idle(%d) at %d",
+	    busy, curcpu);
+
+	if (cpu_idle_hook != NULL) {
+		if (!busy) {
+			critical_enter();
+			sbt = cpu_idleclock();
+		}
+		cpu_idle_hook(sbt);
+		if (!busy) {
+			cpu_activeclock();
+			critical_exit();
+		}
+	}
+
+	CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done",
+	    busy, curcpu);
+}
+
+int
+cpu_idle_wakeup(int cpu)
+{
+	return (0);
+}
+
+static void
+cpu_idle_60x(sbintime_t sbt)
+{
+	register_t msr;
+	uint16_t vers;
+
+	if (!powerpc_pow_enabled)
+		return;
+
+	msr = mfmsr();
+	vers = mfpvr() >> 16;
+
+#ifdef AIM
+	switch (vers) {
+	case IBM970:
+	case IBM970FX:
+	case IBM970MP:
+	case MPC7447A:
+	case MPC7448:
+	case MPC7450:
+	case MPC7455:
+	case MPC7457:
+		__asm __volatile("\
+			    dssall; sync; mtmsr %0; isync"
+			    :: "r"(msr | PSL_POW));
+		break;
+	default:
+		powerpc_sync();
+		mtmsr(msr | PSL_POW);
+		isync();
+		break;
+	}
+#endif
+}
+
+static void
+cpu_idle_booke(sbintime_t sbt)
+{
+	register_t msr;
+
+	msr = mfmsr();
+
+#ifdef E500
+	/* Freescale E500 core RM section 6.4.1. */
+	__asm __volatile("msync; mtmsr %0; isync" ::
+	    "r" (msr | PSL_WE));
+#endif
+}
+


Property changes on: trunk/sys/powerpc/powerpc/cpu.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/db_disasm.c
===================================================================
--- trunk/sys/powerpc/powerpc/db_disasm.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/db_disasm.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,963 @@
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/powerpc/powerpc/db_disasm.c 104435 2002-10-04 01:19:18Z grehan $	*/
+/*	$NetBSD: db_disasm.c,v 1.12 2002/01/05 22:07:26 jhawk Exp $	*/
+/*	$OpenBSD: db_disasm.c,v 1.2 1996/12/28 06:21:48 rahnds Exp $	*/
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+
+#include <machine/db_machdep.h>
+#include <machine/trap.h>
+
+#include <ddb/ddb.h>
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_variables.h>
+#include <ddb/db_output.h>
+
+enum function_mask {
+	Op_A    =	0x00000001,
+	Op_B    =	0x00000002,
+	Op_BI   =	0x00000004,
+	Op_BO   =	0x00000008,
+	Op_CRM  =	0x00000010,
+	Op_D    =	0x00000020, /* yes, Op_S and Op_D are the same */
+	Op_S    =	0x00000020,
+	Op_FM   =	0x00000040,
+	Op_IMM  =	0x00000080,
+	Op_LK   =	0x00000100,
+	Op_Rc   =	0x00000200,
+	Op_AA	=	Op_LK | Op_Rc, /* kludge (reduce Op_s) */
+	Op_LKM	=	Op_AA,
+	Op_RcM	=	Op_AA,
+	Op_OE   =	0x00000400,
+	Op_SR   =	0x00000800,
+	Op_TO   =	0x00001000,
+	Op_sign =	0x00002000,
+	Op_const =	0x00004000,
+	Op_SIMM =	Op_const | Op_sign,
+	Op_UIMM =	Op_const,
+	Op_d	=	Op_const | Op_sign,
+	Op_crbA =	0x00008000,
+	Op_crbB =	0x00010000,
+	Op_WS	=	Op_crbB,	/* kludge, same field as crbB */
+	Op_crbD =	0x00020000,
+	Op_crfD =	0x00040000,
+	Op_crfS =	0x00080000,
+	Op_ds   =	0x00100000,
+	Op_me   =	0x00200000,
+	Op_spr  =	0x00400000,
+	Op_dcr  =	Op_spr,		/* out of bits - cheat with Op_spr */
+	Op_tbr  =	0x00800000,
+
+	Op_L	=	0x01000000,
+	Op_BD	=	0x02000000,
+	Op_LI	=	0x04000000,
+	Op_C	=	0x08000000,
+
+	Op_NB	=	0x10000000,
+
+	Op_sh_mb_sh =	0x20000000,
+	Op_sh   =	0x40000000,
+	Op_SH	=	Op_sh | Op_sh_mb_sh,
+	Op_mb	=	0x80000000,
+	Op_MB	=	Op_mb | Op_sh_mb_sh,
+	Op_ME	=	Op_MB,
+
+};
+
+struct opcode {
+	char *name;
+	u_int32_t mask;
+	u_int32_t code;
+	enum function_mask func;
+};
+
+typedef u_int32_t instr_t;
+typedef void (op_class_func) (instr_t, vm_offset_t);
+
+u_int32_t extract_field(u_int32_t value, u_int32_t base, u_int32_t width);
+void disasm_fields(const struct opcode *popcode, instr_t instr, vm_offset_t loc,
+    char *disasm_str);
+void dis_ppc(const struct opcode *opcodeset, instr_t instr, vm_offset_t loc);
+
+op_class_func op_ill, op_base;
+op_class_func op_cl_x13, op_cl_x1e, op_cl_x1f;
+op_class_func op_cl_x3a, op_cl_x3b;
+op_class_func op_cl_x3e, op_cl_x3f;
+
+op_class_func *opcodes_base[] = {
+/*x00*/	op_ill,		op_ill,		op_base,	op_ill,
+/*x04*/	op_ill,		op_ill,		op_ill,		op_base,
+/*x08*/	op_base,	op_base,	op_ill,		op_base,	
+/*x0C*/ op_base,	op_base,	op_base/*XXX*/,	op_base/*XXX*/,
+/*x10*/ op_base,	op_base,	op_base,	op_cl_x13,
+/*x14*/	op_base,	op_base,	op_ill,		op_base,
+/*x18*/	op_base,	op_base,	op_base,	op_base,
+/*x1C*/ op_base,	op_base,	op_cl_x1e,	op_cl_x1f,
+/*x20*/	op_base,	op_base,	op_base,	op_base,
+/*x24*/	op_base,	op_base,	op_base,	op_base,
+/*x28*/	op_base,	op_base,	op_base,	op_base,
+/*x2C*/	op_base,	op_base,	op_base,	op_base,
+/*x30*/	op_base,	op_base,	op_base,	op_base,
+/*x34*/	op_base,	op_base,	op_base,	op_base,
+/*x38*/ op_ill,		op_ill,		op_cl_x3a,	op_cl_x3b,
+/*x3C*/	op_ill,		op_ill,		op_cl_x3e,	op_cl_x3f
+};
+
+
+/* This table could be modified to make significant the "reserved" fields
+ * of the opcodes, But I didn't feel like it when typing in the table,
+ * I would recommend that this table be looked over for errors, 
+ * This was derived from the table in Appendix A.2 of (Mot part # MPCFPE/AD)
+ * PowerPC Microprocessor Family: The Programming Environments
+ */
+	
+const struct opcode opcodes[] = {
+	{ "tdi",	0xfc000000, 0x08000000, Op_TO | Op_A | Op_SIMM },
+	{ "twi",	0xfc000000, 0x0c000000, Op_TO | Op_A | Op_SIMM },
+	{ "mulli",	0xfc000000, 0x1c000000, Op_D | Op_A | Op_SIMM },
+	{ "subfic",	0xfc000000, 0x20000000, Op_D | Op_A | Op_SIMM },
+	{ "cmpli",	0xfc000000, 0x28000000, Op_crfD | Op_L | Op_A | Op_SIMM },
+	{ "cmpi",	0xfc000000, 0x2c000000, Op_crfD | Op_L | Op_A | Op_SIMM },
+	{ "addic",	0xfc000000, 0x30000000, Op_D | Op_A | Op_SIMM },
+	{ "addic.",	0xfc000000, 0x34000000, Op_D | Op_A | Op_SIMM },
+	{ "addi",	0xfc000000, 0x38000000, Op_D | Op_A | Op_SIMM },
+	{ "addis",	0xfc000000, 0x3c000000, Op_D | Op_A | Op_SIMM },
+	{ "bc",		0xfc000000, 0x40000000, Op_BO | Op_BI | Op_BD | Op_AA | Op_LK },
+	{ "sc",		0xffffffff, 0x44000002, Op_BO | Op_BI | Op_BD | Op_AA | Op_LK },
+	{ "b",		0xfc000000, 0x48000000, Op_LI | Op_AA | Op_LK },
+
+	{ "rlwimi",	0xfc000000, 0x50000000, Op_S | Op_A | Op_SH | Op_MB | Op_ME | Op_Rc },
+	{ "rlwinm",	0xfc000000, 0x54000000, Op_S | Op_A | Op_SH | Op_MB | Op_ME | Op_Rc },
+	{ "rlwnm",	0xfc000000, 0x5c000000, Op_S | Op_A | Op_SH | Op_MB | Op_ME | Op_Rc },
+
+	{ "ori",	0xfc000000, 0x60000000, Op_S | Op_A | Op_UIMM },
+	{ "oris",	0xfc000000, 0x64000000, Op_S | Op_A | Op_UIMM },
+	{ "xori",	0xfc000000, 0x68000000, Op_S | Op_A | Op_UIMM },
+	{ "xoris",	0xfc000000, 0x6c000000, Op_S | Op_A | Op_UIMM },
+
+	{ "andi.",	0xfc000000, 0x70000000, Op_S | Op_A | Op_UIMM },
+	{ "andis.",	0xfc000000, 0x74000000, Op_S | Op_A | Op_UIMM },
+
+	{ "lwz",	0xfc000000, 0x80000000, Op_D | Op_A | Op_d },
+	{ "lwzu",	0xfc000000, 0x84000000, Op_D | Op_A | Op_d },
+	{ "lbz",	0xfc000000, 0x88000000, Op_D | Op_A | Op_d },
+	{ "lbzu",	0xfc000000, 0x8c000000, Op_D | Op_A | Op_d },
+	{ "stw",	0xfc000000, 0x90000000, Op_S | Op_A | Op_d },
+	{ "stwu",	0xfc000000, 0x94000000, Op_S | Op_A | Op_d },
+	{ "stb",	0xfc000000, 0x98000000, Op_S | Op_A | Op_d },
+	{ "stbu",	0xfc000000, 0x9c000000, Op_S | Op_A | Op_d },
+
+	{ "lhz",	0xfc000000, 0xa0000000, Op_D | Op_A | Op_d },
+	{ "lhzu",	0xfc000000, 0xa4000000, Op_D | Op_A | Op_d },
+	{ "lha",	0xfc000000, 0xa8000000, Op_D | Op_A | Op_d },
+	{ "lhau",	0xfc000000, 0xac000000, Op_D | Op_A | Op_d },
+	{ "sth",	0xfc000000, 0xb0000000, Op_S | Op_A | Op_d },
+	{ "sthu",	0xfc000000, 0xb4000000, Op_S | Op_A | Op_d },
+	{ "lmw",	0xfc000000, 0xb8000000, Op_D | Op_A | Op_d },
+	{ "stmw",	0xfc000000, 0xbc000000, Op_S | Op_A | Op_d },
+
+	{ "lfs",	0xfc000000, 0xc0000000, Op_D | Op_A | Op_d },
+	{ "lfsu",	0xfc000000, 0xc4000000, Op_D | Op_A | Op_d },
+	{ "lfd",	0xfc000000, 0xc8000000, Op_D | Op_A | Op_d },
+	{ "lfdu",	0xfc000000, 0xcc000000, Op_D | Op_A | Op_d },
+
+	{ "stfs",	0xfc000000, 0xd0000000, Op_S | Op_A | Op_d },
+	{ "stfsu",	0xfc000000, 0xd4000000, Op_S | Op_A | Op_d },
+	{ "stfd",	0xfc000000, 0xd8000000, Op_S | Op_A | Op_d },
+	{ "stfdu",	0xfc000000, 0xdc000000, Op_S | Op_A | Op_d },
+	{ "",		0x0,		0x0, 0 }
+
+};
+/* 13 * 4 = 4c */
+const struct opcode opcodes_13[] = {
+/* 0x13 << 2 */
+	{ "mcrf",	0xfc0007fe, 0x4c000000, Op_crfD | Op_crfS },
+	{ "bclr",	0xfc0007fe, 0x4c000020, Op_BO | Op_BI | Op_LK },
+	{ "crnor",	0xfc0007fe, 0x4c000042, Op_crbD | Op_crbA | Op_crbB },
+	{ "rfi",	0xfc0007fe, 0x4c000064, 0 },
+	{ "crandc",	0xfc0007fe, 0x4c000102, Op_BO | Op_BI | Op_LK },
+	{ "isync",	0xfc0007fe, 0x4c00012c, 0 },
+	{ "crxor",	0xfc0007fe, 0x4c000182, Op_crbD | Op_crbA | Op_crbB },
+	{ "crnand",	0xfc0007fe, 0x4c0001c2, Op_crbD | Op_crbA | Op_crbB },
+	{ "crand",	0xfc0007fe, 0x4c000202, Op_crbD | Op_crbA | Op_crbB },
+	{ "creqv",	0xfc0007fe, 0x4c000242, Op_crbD | Op_crbA | Op_crbB },
+	{ "crorc",	0xfc0007fe, 0x4c000342, Op_crbD | Op_crbA | Op_crbB },
+	{ "cror",	0xfc0007fe, 0x4c000382, Op_crbD | Op_crbA | Op_crbB },
+	{ "bcctr",	0xfc0007fe, 0x4c000420, Op_BO | Op_BI | Op_LK },
+	{ "",		0x0,		0x0, 0 }
+};
+
+/* 1e * 4 = 78 */
+const struct opcode opcodes_1e[] = {
+	{ "rldicl",	0xfc00001c, 0x78000000, Op_S | Op_A | Op_sh | Op_mb | Op_Rc },
+	{ "rldicr",	0xfc00001c, 0x78000004, Op_S | Op_A | Op_sh | Op_me | Op_Rc },
+	{ "rldic",	0xfc00001c, 0x78000008, Op_S | Op_A | Op_sh | Op_mb | Op_Rc },
+	{ "rldimi",	0xfc00001c, 0x7800000c, Op_S | Op_A | Op_sh | Op_mb | Op_Rc },
+	{ "rldcl",	0xfc00003e, 0x78000010, Op_S | Op_A | Op_B | Op_mb | Op_Rc },
+	{ "rldcr",	0xfc00003e, 0x78000012, Op_S | Op_A | Op_B | Op_me | Op_Rc },
+	{ "",		0x0,		0x0, 0 }
+};
+
+/* 1f * 4 = 7c */
+const struct opcode opcodes_1f[] = {
+/* 1f << 2 */
+	{ "cmp",	0xfc0007fe, 0x7c000000, Op_S | Op_A | Op_B | Op_me | Op_Rc },
+	{ "tw",		0xfc0007fe, 0x7c000008, Op_TO | Op_A | Op_B },
+	{ "subfc",	0xfc0003fe, 0x7c000010, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "mulhdu",	0xfc0007fe, 0x7c000012, Op_D | Op_A | Op_B | Op_Rc },
+	{ "addc",	0xfc0003fe, 0x7c000014, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "mulhwu",	0xfc0007fe, 0x7c000016, Op_D | Op_A | Op_B | Op_Rc },
+
+	{ "mfcr",	0xfc0007fe, 0x7c000026, Op_D },
+	{ "lwarx",	0xfc0007fe, 0x7c000028, Op_D | Op_A | Op_B },
+	{ "ldx",	0xfc0007fe, 0x7c00002a, Op_D | Op_A | Op_B },
+	{ "lwzx",	0xfc0007fe, 0x7c00002e, Op_D | Op_A | Op_B },
+	{ "slw",	0xfc0007fe, 0x7c000030, Op_D | Op_A | Op_B | Op_Rc },
+	{ "cntlzw",	0xfc0007fe, 0x7c000034, Op_D | Op_A | Op_Rc },
+	{ "sld",	0xfc0007fe, 0x7c000036, Op_D | Op_A | Op_B | Op_Rc },
+	{ "and",	0xfc0007fe, 0x7c000038, Op_D | Op_A | Op_B | Op_Rc },
+	{ "cmpl",	0xfc0007fe, 0x7c000040, Op_crfD | Op_L | Op_A | Op_B },
+	{ "subf",	0xfc0003fe, 0x7c000050, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "ldux",	0xfc0007fe, 0x7c00006a, Op_D | Op_A | Op_B },
+	{ "dcbst",	0xfc0007fe, 0x7c00006c, Op_A | Op_B },
+	{ "lwzux",	0xfc0007fe, 0x7c00006e, Op_D | Op_A | Op_B },
+	{ "cntlzd",	0xfc0007fe, 0x7c000074, Op_S | Op_A | Op_Rc },
+	{ "andc",	0xfc0007fe, 0x7c000078, Op_S | Op_A | Op_B | Op_Rc },
+	{ "td",		0xfc0007fe, 0x7c000088, Op_TO | Op_A | Op_B },
+	{ "mulhd",	0xfc0007fe, 0x7c000092, Op_D | Op_A | Op_B | Op_Rc },
+	{ "mulhw",	0xfc0007fe, 0x7c000096, Op_D | Op_A | Op_B | Op_Rc },
+	{ "mfmsr",	0xfc0007fe, 0x7c0000a6, Op_D },
+	{ "ldarx",	0xfc0007fe, 0x7c0000a8, Op_D | Op_A | Op_B },
+	{ "dcbf",	0xfc0007fe, 0x7c0000ac, Op_A | Op_B },
+	{ "lbzx",	0xfc0007fe, 0x7c0000ae, Op_D | Op_A | Op_B },
+	{ "neg",	0xfc0003fe, 0x7c0000d0, Op_D | Op_A | Op_OE | Op_Rc },
+	{ "lbzux",	0xfc0007fe, 0x7c0000ee, Op_D | Op_A | Op_B },
+	{ "nor",	0xfc0007fe, 0x7c0000f8, Op_S | Op_A | Op_B | Op_Rc },
+	{ "wrtee",	0xfc0003ff, 0x7c000106, Op_S },
+	{ "subfe",	0xfc0003fe, 0x7c000110, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "adde",	0xfc0003fe, 0x7c000114, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "mtcrf",	0xfc0007fe, 0x7c000120, Op_S | Op_CRM },
+	{ "mtmsr",	0xfc0007fe, 0x7c000124, Op_S },
+	{ "stdx",	0xfc0007fe, 0x7c00012a, Op_S | Op_A | Op_B },
+	{ "stwcx.",	0xfc0007ff, 0x7c00012d, Op_S | Op_A | Op_B },
+	{ "stwx",	0xfc0007fe, 0x7c00012e, Op_S | Op_A | Op_B },
+	{ "wrteei",	0xfc0003fe, 0x7c000146 },	/* XXX: out of flags! */
+	{ "stdux",	0xfc0007fe, 0x7c00016a, Op_S | Op_A | Op_B },
+	{ "stwux",	0xfc0007fe, 0x7c00016e, Op_S | Op_A | Op_B },
+	{ "subfze",	0xfc0003fe, 0x7c000190, Op_D | Op_A | Op_OE | Op_Rc },
+	{ "addze",	0xfc0003fe, 0x7c000194, Op_D | Op_A | Op_OE | Op_Rc },
+	{ "mtsr",	0xfc0007fe, 0x7c0001a4, Op_S | Op_SR },
+	{ "stdcx.",	0xfc0007ff, 0x7c0001ad, Op_S | Op_A | Op_B },
+	{ "stbx",	0xfc0007fe, 0x7c0001ae, Op_S | Op_A | Op_B },
+	{ "subfme",	0xfc0003fe, 0x7c0001d0, Op_D | Op_A | Op_OE | Op_Rc },
+	{ "mulld",	0xfc0003fe, 0x7c0001d2, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "addme",	0xfc0003fe, 0x7c0001d4, Op_D | Op_A | Op_OE | Op_Rc },
+	{ "mullw",	0xfc0003fe, 0x7c0001d6, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "mtsrin",	0xfc0007fe, 0x7c0001e4, Op_S | Op_B },
+	{ "dcbtst",	0xfc0007fe, 0x7c0001ec, Op_A | Op_B },
+	{ "stbux",	0xfc0007fe, 0x7c0001ee, Op_S | Op_A | Op_B },
+	{ "add",	0xfc0003fe, 0x7c000214, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "dcbt",	0xfc0007fe, 0x7c00022c, Op_A | Op_B },
+	{ "lhzx",	0xfc0007ff, 0x7c00022e, Op_D | Op_A | Op_B },
+	{ "eqv",	0xfc0007fe, 0x7c000238, Op_S | Op_A | Op_B | Op_Rc },
+	{ "tlbie",	0xfc0007fe, 0x7c000264, Op_B },
+	{ "eciwx",	0xfc0007fe, 0x7c00026c, Op_D | Op_A | Op_B },
+	{ "lhzux",	0xfc0007fe, 0x7c00026e, Op_D | Op_A | Op_B },
+	{ "xor",	0xfc0007fe, 0x7c000278, Op_S | Op_A | Op_B | Op_Rc },
+	{ "mfdcr",	0xfc0007fe, 0x7c000286, Op_D | Op_dcr },
+	{ "mfspr",	0xfc0007fe, 0x7c0002a6, Op_D | Op_spr },
+	{ "lwax",	0xfc0007fe, 0x7c0002aa, Op_D | Op_A | Op_B },
+	{ "lhax",	0xfc0007fe, 0x7c0002ae, Op_D | Op_A | Op_B },
+	{ "tlbia",	0xfc0007fe, 0x7c0002e4, 0 },
+	{ "mftb",	0xfc0007fe, 0x7c0002e6, Op_D | Op_tbr },
+	{ "lwaux",	0xfc0007fe, 0x7c0002ea, Op_D | Op_A | Op_B },
+	{ "lhaux",	0xfc0007fe, 0x7c0002ee, Op_D | Op_A | Op_B },
+	{ "sthx",	0xfc0007fe, 0x7c00032e, Op_S | Op_A | Op_B },
+	{ "orc",	0xfc0007fe, 0x7c000338, Op_S | Op_A | Op_B | Op_Rc },
+	{ "ecowx",	0xfc0007fe, 0x7c00036c, Op_S | Op_A | Op_B | Op_Rc },
+	{ "slbie",	0xfc0007fc, 0x7c000364, Op_B },
+	{ "sthux",	0xfc0007fe, 0x7c00036e, Op_S | Op_A | Op_B },
+	{ "or",		0xfc0007fe, 0x7c000378, Op_S | Op_A | Op_B | Op_Rc },
+	{ "mtdcr",	0xfc0007fe, 0x7c000386, Op_S | Op_dcr },
+	{ "divdu",	0xfc0003fe, 0x7c000392, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "divwu",	0xfc0003fe, 0x7c000396, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "mtspr",	0xfc0007fe, 0x7c0003a6, Op_S | Op_spr },
+	{ "dcbi",	0xfc0007fe, 0x7c0003ac, Op_A | Op_B },
+	{ "nand",	0xfc0007fe, 0x7c0003b8, Op_S | Op_A | Op_B | Op_Rc },
+	{ "dcread",	0xfc0007fe, 0x7c0003cc, Op_D | Op_A | Op_B },
+	{ "divd",	0xfc0003fe, 0x7c0003d2, Op_S | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "divw",	0xfc0003fe, 0x7c0003d6, Op_S | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "slbia",	0xfc0003fe, 0x7c0003e4, Op_S | Op_A | Op_B | Op_OE | Op_Rc },
+	{ "mcrxr",	0xfc0007fe, 0x7c000400, Op_crfD },
+	{ "lswx",	0xfc0007fe, 0x7c00042a, Op_D | Op_A | Op_B },
+	{ "lwbrx",	0xfc0007fe, 0x7c00042c, Op_D | Op_A | Op_B },
+	{ "lfsx",	0xfc0007fe, 0x7c00042e, Op_D | Op_A | Op_B },
+	{ "srw",	0xfc0007fe, 0x7c000430, Op_S | Op_A | Op_B | Op_Rc },
+	{ "srd",	0xfc0007fe, 0x7c000436, Op_S | Op_A | Op_B | Op_Rc },
+	{ "tlbsync",	0xfc0007fe, 0x7c00046c, 0 },
+	{ "lfsux",	0xfc0007fe, 0x7c00046e, Op_D | Op_A | Op_B },
+	{ "mfsr",	0xfc0007fe, 0x7c0004a6, Op_D | Op_SR },
+	{ "lswi",	0xfc0007fe, 0x7c0004aa, Op_D | Op_A | Op_NB },
+	{ "sync",	0xfc0007fe, 0x7c0004ac, 0 },
+	{ "lfdx",	0xfc0007fe, 0x7c0004ae, Op_D | Op_A | Op_B },
+	{ "lfdux",	0xfc0007fe, 0x7c0004ee, Op_D | Op_A | Op_B },
+	{ "mfsrin",	0xfc0007fe, 0x7c000526, Op_D | Op_B },
+	{ "stswx",	0xfc0007fe, 0x7c00052a, Op_S | Op_A | Op_B },
+	{ "stwbrx",	0xfc0007fe, 0x7c00052c, Op_S | Op_A | Op_B },
+	{ "stfsx",	0xfc0007fe, 0x7c00052e, Op_S | Op_A | Op_B },
+	{ "stfsux",	0xfc0007fe, 0x7c00056e, Op_S | Op_A | Op_B },
+	{ "stswi",	0xfc0007fe, 0x7c0005aa, Op_S | Op_A | Op_NB },
+	{ "stfdx",	0xfc0007fe, 0x7c0005ae, Op_S | Op_A | Op_B },
+	{ "stfdux",	0xfc0007fe, 0x7c0005ee, Op_S | Op_A | Op_B },
+	{ "lhbrx",	0xfc0007fe, 0x7c00062c, Op_D | Op_A | Op_B },
+	{ "sraw",	0xfc0007fe, 0x7c000630, Op_S | Op_A | Op_B },
+	{ "srad",	0xfc0007fe, 0x7c000634, Op_S | Op_A | Op_B | Op_Rc },
+	{ "srawi",	0xfc0007fe, 0x7c000670, Op_S | Op_A | Op_B | Op_Rc },
+	{ "sradi",	0xfc0007fc, 0x7c000674, Op_S | Op_A | Op_sh },
+	{ "eieio",	0xfc0007fe, 0x7c0006ac, 0 },
+	{ "tlbsx",	0xfc0007fe, 0x7c000724, Op_S | Op_A | Op_B | Op_Rc },
+	{ "sthbrx",	0xfc0007fe, 0x7c00072c, Op_S | Op_A | Op_B },
+	{ "extsh",	0xfc0007fe, 0x7c000734, Op_S | Op_A | Op_B | Op_Rc },
+	{ "tlbre",	0xfc0007fe, 0x7c000764, Op_D | Op_A | Op_WS },
+	{ "extsb",	0xfc0007fe, 0x7c000774, Op_S | Op_A | Op_Rc },
+	{ "icbi",	0xfc0007fe, 0x7c0007ac, Op_A | Op_B },
+	{ "tlbwe",	0xfc0007fe, 0x7c0007a4, Op_S | Op_A | Op_WS },
+	{ "stfiwx",	0xfc0007fe, 0x7c0007ae, Op_S | Op_A | Op_B },
+	{ "extsw",	0xfc0007fe, 0x7c0007b4, Op_S | Op_A | Op_Rc },
+	{ "dcbz",	0xfc0007fe, 0x7c0007ec, Op_A | Op_B },
+	{ "",		0x0,		0x0, 0 }
+};
+
+/* 3a * 4 = e8 */
+const struct opcode opcodes_3a[] = {
+	{ "ld",		0xfc000003, 0xe8000000, Op_D | Op_A | Op_ds },
+	{ "ldu",	0xfc000003, 0xe8000001, Op_D | Op_A | Op_ds },
+	{ "lwa",	0xfc000003, 0xe8000002, Op_D | Op_A | Op_ds },
+	{ "",		0x0,		0x0, 0 }
+};
+/* 3b * 4 = ec */
+const struct opcode opcodes_3b[] = {
+	{ "fdivs",	0xfc00003e, 0xec000024, Op_D | Op_A | Op_B | Op_Rc },
+	{ "fsubs",	0xfc00003e, 0xec000028, Op_D | Op_A | Op_B | Op_Rc },
+
+	{ "fadds",	0xfc00003e, 0xec00002a, Op_D | Op_A | Op_B | Op_Rc },
+	{ "fsqrts",	0xfc00003e, 0xec00002c, Op_D | Op_B | Op_Rc },
+	{ "fres",	0xfc00003e, 0xec000030, Op_D | Op_B | Op_Rc },
+	{ "fmuls",	0xfc00003e, 0xec000032, Op_D | Op_A | Op_C | Op_Rc },
+	{ "fmsubs",	0xfc00003e, 0xec000038, Op_D | Op_A | Op_B | Op_C | Op_Rc },
+	{ "fmadds",	0xfc00003e, 0xec00003a, Op_D | Op_A | Op_B | Op_C | Op_Rc },
+	{ "fnmsubs",	0xfc00003e, 0xec00003c, Op_D | Op_A | Op_B | Op_C | Op_Rc },
+	{ "fnmadds",	0xfc00003e, 0xec00003e, Op_D | Op_A | Op_B | Op_C | Op_Rc },
+	{ "",		0x0,		0x0, 0 }
+};
+/* 3e * 4 = f8 */
+const struct opcode opcodes_3e[] = {
+	{ "std",	0xfc000003, 0xf8000000, Op_S | Op_A | Op_ds },
+	{ "stdu",	0xfc000003, 0xf8000001, Op_S | Op_A | Op_ds },
+	{ "",		0x0,		0x0, 0 }
+};
+
+/* 3f * 4 = fc */
+const struct opcode opcodes_3f[] = {
+	{ "fcmpu",	0xfc0007fe, 0xfc000000, Op_crfD | Op_A | Op_B },
+	{ "frsp",	0xfc0007fe, 0xfc000018, Op_D | Op_B | Op_Rc },
+	{ "fctiw",	0xfc0007fe, 0xfc00001c, Op_D | Op_B | Op_Rc },
+	{ "fctiwz",	0xfc0007fe, 0xfc00001e, Op_D | Op_B | Op_Rc },
+
+	{ "fdiv",	0xfc00003e, 0xfc000024, Op_D | Op_A | Op_B | Op_Rc },
+	{ "fsub",	0xfc00003e, 0xfc000028, Op_D | Op_A | Op_B | Op_Rc },
+	{ "fadd",	0xfc00003e, 0xfc00002a, Op_D | Op_A | Op_B | Op_Rc },
+	{ "fsqrt",	0xfc00003e, 0xfc00002c, Op_D | Op_B | Op_Rc },
+	{ "fsel",	0xfc00003e, 0xfc00002e, Op_D | Op_A | Op_B | Op_C | Op_Rc },
+	{ "fmul",	0xfc00003e, 0xfc000032, Op_D | Op_A | Op_C | Op_Rc },
+	{ "frsqrte",	0xfc00003e, 0xfc000034, Op_D | Op_B | Op_Rc },
+	{ "fmsub",	0xfc00003e, 0xfc000038, Op_D | Op_A | Op_B | Op_C | Op_Rc },
+	{ "fmadd",	0xfc00003e, 0xfc00003a, Op_D | Op_A | Op_B | Op_C | Op_Rc },
+	{ "fnmsub",	0xfc00003e, 0xfc00003c, Op_D | Op_A | Op_B | Op_C | Op_Rc },
+	{ "fnmadd",	0xfc00003e, 0xfc00003e, Op_D | Op_A | Op_B | Op_C | Op_Rc },
+
+	{ "fcmpo",	0xfc0007fe, 0xfc000040, Op_crfD | Op_A | Op_B },
+	{ "mtfsb1",	0xfc0007fe, 0xfc00004c, Op_crfD | Op_Rc },
+	{ "fneg",	0xfc0007fe, 0xfc000050, Op_D | Op_B | Op_Rc },
+	{ "mcrfs",	0xfc0007fe, 0xfc000080, Op_D | Op_B | Op_Rc },
+	{ "mtfsb0",	0xfc0007fe, 0xfc00008c, Op_crfD | Op_Rc },
+	{ "fmr",	0xfc0007fe, 0xfc000090, Op_D | Op_B | Op_Rc },
+	{ "mtfsfi",	0xfc0007fe, 0xfc00010c, Op_crfD | Op_IMM | Op_Rc },
+
+	{ "fnabs",	0xfc0007fe, 0xfc000110, Op_D | Op_B | Op_Rc },
+	{ "fabs",	0xfc0007fe, 0xfc000210, Op_D | Op_B | Op_Rc },
+	{ "mffs",	0xfc0007fe, 0xfc00048e, Op_D | Op_B | Op_Rc },
+	{ "mtfsf",	0xfc0007fe, 0xfc00058e, Op_FM | Op_B | Op_Rc },
+	{ "fctid",	0xfc0007fe, 0xfc00065c, Op_D | Op_B | Op_Rc },
+	{ "fctidz",	0xfc0007fe, 0xfc00065e, Op_D | Op_B | Op_Rc },
+	{ "fcfid",	0xfc0007fe, 0xfc00069c, Op_D | Op_B | Op_Rc },
+	{ "",		0x0,		0x0, 0 }
+};
+
+
+struct specialreg {
+	int reg;
+	char *name;
+};
+
+const struct specialreg sprregs[] = {
+	{ 0x001, "xer" },
+	{ 0x008, "lr" },
+	{ 0x009, "ctr" },
+	{ 0x012, "dsisr" },
+	{ 0x013, "dar" },
+	{ 0x016, "dec" },
+	{ 0x019, "sdr1" },
+	{ 0x01a, "srr0" },
+	{ 0x01b, "srr1" },
+	{ 0x100, "usprg0" },
+	{ 0x110, "sprg0" },
+	{ 0x111, "sprg1" },
+	{ 0x112, "sprg2" },
+	{ 0x113, "sprg3" },
+	{ 0x114, "sprg4" },
+	{ 0x115, "sprg5" },
+	{ 0x116, "sprg6" },
+	{ 0x117, "sprg7" },
+	{ 0x118, "asr" },
+	{ 0x11a, "aer" },
+	{ 0x11c, "tbl" },
+	{ 0x11d, "tbu" },
+	{ 0x11f, "pvr" },
+	{ 0x210, "ibat0u" },
+	{ 0x211, "ibat0l" },
+	{ 0x212, "ibat1u" },
+	{ 0x213, "ibat1l" },
+	{ 0x214, "ibat2u" },
+	{ 0x215, "ibat2l" },
+	{ 0x216, "ibat3u" },
+	{ 0x217, "ibat3l" },
+	{ 0x218, "dbat0u" },
+	{ 0x219, "dbat0l" },
+	{ 0x21a, "dbat1u" },
+	{ 0x21b, "dbat1l" },
+	{ 0x21c, "dbat2u" },
+	{ 0x21d, "dbat2l" },
+	{ 0x21e, "dbat3u" },
+	{ 0x21f, "dbat3l" },
+	{ 0x3b0, "zpr" },
+	{ 0x3b1, "pid" },
+	{ 0x3b3, "ccr0" },
+	{ 0x3b4, "iac3" },
+	{ 0x3b5, "iac4" },
+	{ 0x3b6, "dvc1" },
+	{ 0x3b7, "dvc2" },
+	{ 0x3b9, "sgr" },
+	{ 0x3ba, "dcwr" },
+	{ 0x3bb, "sler" },
+	{ 0x3bc, "su0r" },
+	{ 0x3bd, "dbcr1" },
+	{ 0x3d3, "icdbdr" },
+	{ 0x3d4, "esr" },
+	{ 0x3d5, "dear" },
+	{ 0x3d6, "evpr" },
+	{ 0x3d8, "tsr" },
+	{ 0x3da, "tcr" },
+	{ 0x3db, "pit" },
+	{ 0x3de, "srr2" },
+	{ 0x3df, "srr3" },
+	{ 0x3f0, "dbsr" },
+	{ 0x3f2, "dbcr0" },
+	{ 0x3f4, "iac1" },
+	{ 0x3f5, "iac2" },
+	{ 0x3f6, "dac1" },
+	{ 0x3f7, "dac2" },
+	{ 0x3f9, "l2cr" },
+	{ 0x3fa, "dccr" },
+	{ 0x3fb, "iccr" },
+	{ 0x3ff, "pir" },
+	{ 0, NULL }
+};
+
+const struct specialreg dcrregs[] = {
+	{ 0x010, "sdram0_cfgaddr" },
+	{ 0x011, "sdram0_cfgdata" },
+	{ 0x012, "ebc0_cfgaddr" },
+	{ 0x013, "ebc0_cfgdata" },
+	{ 0x014, "dcp0_cfgaddr" },
+	{ 0x015, "dcp0_cfgdata" },
+	{ 0x018, "ocm0_isarc" },
+	{ 0x019, "ocm0_iscntl" },
+	{ 0x01a, "ocm0_dsarc" },
+	{ 0x01b, "ocm0_dscntl" },
+	{ 0x084, "plb0_besr" },
+	{ 0x086, "plb0_bear" },
+	{ 0x087, "plb0_acr" },
+	{ 0x0a0, "pob0_besr0" },
+	{ 0x0a2, "pob0_bear" },
+	{ 0x0a4, "pob0_besr1" },
+	{ 0x0b0, "cpc0_pllmr" },
+	{ 0x0b1, "cpc0_cr0" },
+	{ 0x0b2, "cpc0_cr1" },
+	{ 0x0b4, "cpc0_psr" },
+	{ 0x0b5, "cpc0_jtagid" },
+	{ 0x0b8, "cpc0_sr" },
+	{ 0x0b9, "cpc0_er" },
+	{ 0x0ba, "cpc0_fr" },
+	{ 0x0c0, "uic0_sr" },
+	{ 0x0c2, "uic0_er" },
+	{ 0x0c3, "uic0_cr" },
+	{ 0x0c4, "uic0_pr" },
+	{ 0x0c5, "uic0_tr" },
+	{ 0x0c6, "uic0_msr" },
+	{ 0x0c7, "uic0_vr" },
+	{ 0x0c8, "uic0_vcr" },
+	{ 0x100, "dma0_cr0" },
+	{ 0x101, "dma0_ct0" },
+	{ 0x102, "dma0_da0" },
+	{ 0x103, "dma0_sa0" },
+	{ 0x104, "dma0_sg0" },
+	{ 0x108, "dma0_cr1" },
+	{ 0x109, "dma0_ct1" },
+	{ 0x10a, "dma0_da1" },
+	{ 0x10b, "dma0_sa1" },
+	{ 0x10c, "dma0_sg1" },
+	{ 0x110, "dma0_cr2" },
+	{ 0x111, "dma0_ct2" },
+	{ 0x112, "dma0_da2" },
+	{ 0x113, "dma0_sa2" },
+	{ 0x114, "dma0_sg2" },
+	{ 0x118, "dma0_cr3" },
+	{ 0x119, "dma0_ct3" },
+	{ 0x11a, "dma0_da3" },
+	{ 0x11b, "dma0_sa3" },
+	{ 0x11c, "dma0_sg3" },
+	{ 0x120, "dma0_sr" },
+	{ 0x123, "dma0_sgc" },
+	{ 0x125, "dma0_slp" },
+	{ 0x126, "dma0_pol" },
+	{ 0x180, "mal0_cfg" },
+	{ 0x181, "mal0_esr" },
+	{ 0x182, "mal0_ier" },
+	{ 0x184, "mal0_txcasr" },
+	{ 0x185, "mal0_txcarr" },
+	{ 0x186, "mal0_txeobisr" },
+	{ 0x187, "mal0_txdeir" },
+	{ 0x190, "mal0_rxcasr" },
+	{ 0x191, "mal0_rxcarr" },
+	{ 0x192, "mal0_rxeobisr" },
+	{ 0x193, "mal0_rxdeir" },
+	{ 0x1a0, "mal0_txctp0r" },
+	{ 0x1a1, "mal0_txctp1r" },
+	{ 0x1a2, "mal0_txctp2r" },
+	{ 0x1a3, "mal0_txctp3r" },
+	{ 0x1c0, "mal0_rxctp0r" },
+	{ 0x1e0, "mal0_rcbs0" },
+	{ 0, NULL }
+};
+
+void
+op_ill(instr_t instr, vm_offset_t loc)
+{
+	db_printf("illegal instruction %x\n", instr);
+}
+
+u_int32_t
+extract_field(u_int32_t value, u_int32_t base, u_int32_t width)
+{
+	u_int32_t mask = (1 << width) - 1;
+	return ((value >> base) & mask);
+}
+
+const struct opcode * search_op(const struct opcode *);
+
+void
+disasm_fields(const struct opcode *popcode, instr_t instr, vm_offset_t loc, 
+	char *disasm_str)
+{
+	char * pstr;
+	enum function_mask func;
+
+	pstr = disasm_str;
+
+	func =  popcode->func;
+	if (func & Op_OE) {
+		u_int OE;
+		/* also for Op_S (they are the same) */
+		OE = extract_field(instr, 31 - 21, 1);
+		if (OE) {
+			pstr += sprintf(pstr, "o");
+		}
+		func &= ~Op_OE;
+	}
+	switch (func & Op_LKM) {
+	case Op_Rc:
+		if (instr & 0x1) {
+			pstr += sprintf(pstr, ".");
+		}
+		break;
+	case Op_AA:
+		if (instr & 0x2) {
+			pstr += sprintf(pstr, "a");
+			loc = 0; /* Absolute address */
+		}
+	case Op_LK:
+		if (instr & 0x1) {
+			pstr += sprintf(pstr, "l");
+		}
+		break;
+	default:
+		func &= ~Op_LKM;
+	}
+	pstr += sprintf(pstr, "\t");
+
+	/* XXX: special cases here, out of flags in a 32bit word. */
+	if (strcmp(popcode->name, "wrteei") == 0) {
+		int E;
+		E = extract_field(instr, 31 - 16, 5);
+		pstr += sprintf(pstr, "%d", E);
+		return;
+	}
+	/* XXX: end of special cases here. */
+
+	if (func & Op_D) {
+		u_int D;
+		/* also for Op_S (they are the same) */
+		D = extract_field(instr, 31 - 10, 5);
+		pstr += sprintf(pstr, "r%d, ", D);
+		func &= ~Op_D;
+	}
+	if (func & Op_crbD) {
+		u_int crbD;
+		crbD = extract_field(instr, 31 - 10, 5);
+		pstr += sprintf(pstr, "crb%d, ", crbD);
+		func &= ~Op_crbD;
+	}
+	if (func & Op_crfD) {
+		u_int crfD;
+		crfD = extract_field(instr, 31 - 8, 3);
+		pstr += sprintf(pstr, "crf%d, ", crfD);
+		func &= ~Op_crfD;
+	}
+	if (func & Op_L) {
+		u_int L;
+		L = extract_field(instr, 31 - 10, 1);
+		if (L) {
+			pstr += sprintf(pstr, "L, ");
+		}
+		func &= ~Op_L;
+	}
+	if (func & Op_FM) {
+		u_int FM;
+		FM = extract_field(instr, 31 - 10, 8);
+		pstr += sprintf(pstr, "%d, ", FM);
+		func &= ~Op_FM;
+	}
+	if (func & Op_TO) {
+		u_int TO;
+		TO = extract_field(instr, 31 - 10, 1);
+		pstr += sprintf(pstr, "%d, ", TO);
+		func &= ~Op_TO;
+	}
+	if (func & Op_crfS) {
+		u_int crfS;
+		crfS = extract_field(instr, 31 - 13, 3);
+		pstr += sprintf(pstr, "%d, ", crfS);
+		func &= ~Op_crfS;
+	}
+	if (func & Op_BO) {
+		u_int BO;
+		BO = extract_field(instr, 31 - 10, 5);
+		pstr += sprintf(pstr, "%d, ", BO);
+		func &= ~Op_BO;
+	}
+	if (func & Op_A) {
+		u_int A;
+		A = extract_field(instr, 31 - 15, 5);
+		pstr += sprintf(pstr, "r%d, ", A);
+		func &= ~Op_A;
+	}
+	if (func & Op_B) {
+		u_int B;
+		B = extract_field(instr, 31 - 20, 5);
+		pstr += sprintf(pstr, "r%d, ", B);
+		func &= ~Op_B;
+	}
+	if (func & Op_C) {
+		u_int C;
+		C = extract_field(instr, 31 - 25, 5);
+		pstr += sprintf(pstr, "r%d, ", C);
+		func &= ~Op_C;
+	}
+	if (func & Op_BI) {
+		u_int BI;
+		BI = extract_field(instr, 31 - 10, 5);
+		pstr += sprintf(pstr, "%d, ", BI);
+		func &= ~Op_BI;
+	}
+	if (func & Op_crbA) {
+		u_int crbA;
+		crbA = extract_field(instr, 31 - 15, 5);
+		pstr += sprintf(pstr, "%d, ", crbA);
+		func &= ~Op_crbA;
+	}
+	if (func & Op_crbB) {
+		u_int crbB;
+		crbB = extract_field(instr, 31 - 20, 5);
+		pstr += sprintf(pstr, "%d, ", crbB);
+		func &= ~Op_crbB;
+	}
+	if (func & Op_CRM) {
+		u_int CRM;
+		CRM = extract_field(instr, 31 - 19, 8);
+		pstr += sprintf(pstr, "0x%x, ", CRM);
+		func &= ~Op_CRM;
+	}
+	if (func & Op_LI) {
+		int LI;
+		LI = extract_field(instr, 31 - 29, 24);
+		/* Need to sign extend and shift up 2, then add addr */
+		LI = LI << 8;
+		LI = LI >> 6;
+		LI += loc;
+		pstr += sprintf (pstr, "0x%x, ", LI);
+		func &= ~Op_LI;
+	}
+	switch (func & Op_SIMM) {
+		u_int IMM;
+	case Op_SIMM: /* same as Op_d */
+		IMM = extract_field(instr, 31 - 31, 16);
+		if (IMM & 0x8000) {
+			pstr += sprintf(pstr, "-");
+			IMM = 0x10000-IMM;
+		}
+		func &= ~Op_SIMM;
+		goto common;
+	case Op_UIMM:
+		IMM = extract_field(instr, 31 - 31, 16);
+		func &= ~Op_UIMM;
+		goto common;
+	common:
+		pstr += sprintf(pstr, "0x%x", IMM);
+		break;
+	default:
+		break;
+	}
+	if (func & Op_BD) {
+		u_int BD;
+		BD = extract_field(instr, 31 - 29, 14);
+		pstr += sprintf(pstr, "0x%x, ", BD);
+		func &= ~Op_BD;
+	}
+	if (func & Op_ds) {
+		u_int ds;
+		ds = extract_field(instr, 31 - 29, 14) << 2;
+		pstr += sprintf(pstr, "0x%x, ", ds);
+		func &= ~Op_ds;
+	}
+	if (func & Op_spr) {
+		u_int spr;
+		u_int sprl;
+		u_int sprh;
+		const struct specialreg *regs;
+		int i;
+		sprl = extract_field(instr, 31 - 15, 5);
+		sprh = extract_field(instr, 31 - 20, 5);
+		spr = sprh << 5 | sprl;
+
+		/* ugly hack - out of bitfields in the function mask */
+		if (popcode->name[2] == 'd')	/* m.Dcr */
+			regs = dcrregs;
+		else
+			regs = sprregs;
+		for (i = 0; regs[i].name != NULL; i++)
+			if (spr == regs[i].reg)
+				break;
+		if (regs[i].reg == 0)
+			pstr += sprintf(pstr, "[unknown special reg (%d)]", spr);
+		else
+			pstr += sprintf(pstr, "%s", regs[i].name);
+		func &= ~Op_spr;
+	}
+
+	if (func & Op_me) {
+		u_int me, mel, meh;
+		mel = extract_field(instr, 31 - 25, 4);
+		meh = extract_field(instr, 31 - 26, 1);
+		me = meh << 4 | mel;
+		pstr += sprintf(pstr, ", 0x%x", me);
+		func &= ~Op_me;
+	}
+	if ((func & Op_MB) && (func & Op_sh_mb_sh)) {
+		u_int MB;
+		u_int ME;
+		MB = extract_field(instr, 31 - 20, 5);
+		pstr += sprintf(pstr, ", %d", MB);
+		ME = extract_field(instr, 31 - 25, 5);
+		pstr += sprintf(pstr, ", %d", ME);
+	}
+	if ((func & Op_SH) && (func & Op_sh_mb_sh)) {
+		u_int SH;
+		SH = extract_field(instr, 31 - 20, 5);
+		pstr += sprintf(pstr, ", %d", SH);
+	}
+	if ((func & Op_sh) && ! (func & Op_sh_mb_sh)) {
+		u_int sh, shl, shh;
+		shl = extract_field(instr, 31 - 19, 4);
+		shh = extract_field(instr, 31 - 20, 1);
+		sh = shh << 4 | shl;
+		pstr += sprintf(pstr, ", %d", sh);
+	}
+	if ((func & Op_mb) && ! (func & Op_sh_mb_sh)) {
+		u_int mb, mbl, mbh;
+		mbl = extract_field(instr, 31 - 25, 4);
+		mbh = extract_field(instr, 31 - 26, 1);
+		mb = mbh << 4 | mbl;
+		pstr += sprintf(pstr, ", %d", mb);
+	}
+	if ((func & Op_me) && ! (func & Op_sh_mb_sh)) {
+		u_int me, mel, meh;
+		mel = extract_field(instr, 31 - 25, 4);
+		meh = extract_field(instr, 31 - 26, 1);
+		me = meh << 4 | mel;
+		pstr += sprintf(pstr, ", %d", me);
+	}
+	if (func & Op_tbr) {
+		u_int tbr;
+		u_int tbrl;
+		u_int tbrh;
+		char *reg;
+		tbrl = extract_field(instr, 31 - 15, 5);
+		tbrh = extract_field(instr, 31 - 20, 5);
+		tbr = tbrh << 5 | tbrl;
+
+		switch (tbr) {
+		case 268:
+			reg = "tbl";
+			break;
+		case 269:
+			reg = "tbu";
+			break;
+		default:
+			reg = 0;
+		}
+		if (reg == 0)
+			pstr += sprintf(pstr, ", [unknown tbr %d ]", tbr);
+		else
+			pstr += sprintf(pstr, ", %s", reg);
+		func &= ~Op_tbr;
+	}
+	if (func & Op_SR) {
+		u_int SR;
+		SR = extract_field(instr, 31 - 15, 3);
+		pstr += sprintf(pstr, ", sr%d", SR);
+		func &= ~Op_SR;
+	}
+	if (func & Op_NB) {
+		u_int NB;
+		NB = extract_field(instr, 31 - 20, 5);
+		if (NB == 0)
+			NB = 32;
+		pstr += sprintf(pstr, ", %d", NB);
+		func &= ~Op_SR;
+	}
+	if (func & Op_IMM) {
+		u_int IMM;
+		IMM = extract_field(instr, 31 - 19, 4);
+		pstr += sprintf(pstr, ", %d", IMM);
+		func &= ~Op_SR;
+	}
+}
+
+void
+op_base(instr_t instr, vm_offset_t loc)
+{
+	dis_ppc(opcodes, instr, loc);
+}
+
+void
+op_cl_x13(instr_t instr, vm_offset_t loc)
+{
+	dis_ppc(opcodes_13, instr, loc);
+}
+
+void
+op_cl_x1e(instr_t instr, vm_offset_t loc)
+{
+	dis_ppc(opcodes_1e, instr, loc);
+}
+
+void
+op_cl_x1f(instr_t instr, vm_offset_t loc)
+{
+	dis_ppc(opcodes_1f, instr, loc);
+}
+
+void
+op_cl_x3a(instr_t instr, vm_offset_t loc)
+{
+	dis_ppc(opcodes_3a, instr, loc);
+}
+
+void
+op_cl_x3b(instr_t instr, vm_offset_t loc)
+{
+	dis_ppc(opcodes_3b, instr, loc);
+}
+
+void
+op_cl_x3e(instr_t instr, vm_offset_t loc)
+{
+	dis_ppc(opcodes_3e, instr, loc);
+}
+
+void
+op_cl_x3f(instr_t instr, vm_offset_t loc)
+{
+	dis_ppc(opcodes_3f, instr, loc);
+}
+
+void
+dis_ppc(const struct opcode *opcodeset, instr_t instr, vm_offset_t loc)
+{
+	const struct opcode *op;
+	int found = 0;
+	int i;
+	char disasm_str[30];
+
+	for (i = 0, op = &opcodeset[0];
+	    found == 0 && op->mask != 0;
+	    i++, op = &opcodeset[i]) {
+		if ((instr & op->mask) == op->code) {
+			found = 1;
+			disasm_fields(op, instr, loc, disasm_str);
+			db_printf("%s%s\n", op->name, disasm_str);
+			return;
+		}
+	}
+	op_ill(instr, loc);
+}
+
+db_addr_t
+db_disasm(db_addr_t loc, boolean_t extended)
+{
+	int class;
+	instr_t opcode;
+	opcode = *(instr_t *)(loc);
+	class = opcode >> 26;
+	(opcodes_base[class])(opcode, loc);
+
+	return (loc + 4);
+}
+
+vm_offset_t opc_disasm(vm_offset_t loc, int);
+
+vm_offset_t
+opc_disasm(vm_offset_t loc, int xin)
+{
+	int class;
+	instr_t opcode;
+	opcode = xin;
+	class = opcode >> 26;
+	(opcodes_base[class])(opcode, loc);
+
+	return (loc + 4);
+}


Property changes on: trunk/sys/powerpc/powerpc/db_disasm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/db_hwwatch.c
===================================================================
--- trunk/sys/powerpc/powerpc/db_hwwatch.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/db_hwwatch.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,55 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2002 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powerpc/db_hwwatch.c 149925 2005-09-10 03:01:25Z marcel $
+ */
+#include <sys/param.h>
+
+#include <vm/vm.h>
+
+#include <ddb/ddb.h>
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_variables.h>
+#include <ddb/db_watch.h>
+
+int
+db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
+{
+
+	return (0);
+}
+
+int
+db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
+{
+
+	return (0);
+}
+
+void
+db_md_list_watchpoints(void)
+{
+}


Property changes on: trunk/sys/powerpc/powerpc/db_hwwatch.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/db_interface.c
===================================================================
--- trunk/sys/powerpc/powerpc/db_interface.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/db_interface.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,86 @@
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/powerpc/powerpc/db_interface.c 209975 2010-07-13 05:32:19Z nwhitehorn $ */
+/*	$NetBSD: db_interface.c,v 1.20 2002/05/13 20:30:09 matt Exp $ */
+/*	$OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $	*/
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/cons.h>
+#include <sys/kdb.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+
+#include <machine/kdb.h>
+#include <machine/md_var.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <ddb/ddb.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_command.h>
+#include <ddb/db_access.h>
+#include <ddb/db_output.h>
+
+#include <dev/ofw/openfirm.h>
+
+int
+db_read_bytes(vm_offset_t addr, size_t size, char *data)
+{
+	jmp_buf jb;
+	void *prev_jb;
+	char *src;
+	int ret;
+
+	prev_jb = kdb_jmpbuf(jb);
+	ret = setjmp(jb);
+	if (ret == 0) {
+		src = (char *)addr;
+
+		if (size == 4)
+			*((int *)data) = *((int *)src);
+		else if (size == 2)
+			*((short *)data) = *((short *)src);
+		else
+			while (size-- > 0)
+				*data++ = *src++;
+	}
+	(void)kdb_jmpbuf(prev_jb);
+	return (ret);
+}
+
+int
+db_write_bytes(vm_offset_t addr, size_t size, char *data)
+{
+	jmp_buf jb;
+	void *prev_jb;
+	char *dst;
+	size_t cnt;
+	int ret;
+
+	prev_jb = kdb_jmpbuf(jb);
+	ret = setjmp(jb);
+	if (ret == 0) {
+		dst = (char *)addr;
+		cnt = size;
+
+		while (cnt-- > 0)
+			*dst++ = *data++;
+		kdb_cpu_sync_icache((void *)addr, size);
+	}
+	(void)kdb_jmpbuf(prev_jb);
+	return (ret);
+}
+
+void
+db_show_mdpcpu(struct pcpu *pc)
+{
+
+	db_printf("PPC: hwref   = %#zx\n", pc->pc_hwref);
+	db_printf("PPC: ipimask = %#x\n", pc->pc_ipimask);
+	db_printf("PPC: pir     = %#x\n", pc->pc_pir);
+}


Property changes on: trunk/sys/powerpc/powerpc/db_interface.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/db_trace.c
===================================================================
--- trunk/sys/powerpc/powerpc/db_trace.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/db_trace.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,327 @@
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/powerpc/powerpc/db_trace.c 236141 2012-05-27 10:25:20Z raj $ */
+/*	$NetBSD: db_trace.c,v 1.20 2002/05/13 20:30:09 matt Exp $	*/
+/*	$OpenBSD: db_trace.c,v 1.3 1997/03/21 02:10:48 niklas Exp $	*/
+
+/*-
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution at CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/proc.h>
+#include <sys/stack.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+
+#include <machine/db_machdep.h>
+#include <machine/pcb.h>
+#include <machine/spr.h>
+#include <machine/stack.h>
+#include <machine/trap.h>
+
+#include <ddb/ddb.h>
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_variables.h>
+
+static db_varfcn_t db_frame;
+
+#define DB_OFFSET(x)	(db_expr_t *)offsetof(struct trapframe, x)
+
+#ifdef __powerpc64__
+#define	CALLOFFSET	8	/* Include TOC reload slot */
+#else
+#define	CALLOFFSET	4
+#endif
+
+struct db_variable db_regs[] = {
+	{ "r0",	 DB_OFFSET(fixreg[0]),	db_frame },
+	{ "r1",	 DB_OFFSET(fixreg[1]),	db_frame },
+	{ "r2",	 DB_OFFSET(fixreg[2]),	db_frame },
+	{ "r3",	 DB_OFFSET(fixreg[3]),	db_frame },
+	{ "r4",	 DB_OFFSET(fixreg[4]),	db_frame },
+	{ "r5",	 DB_OFFSET(fixreg[5]),	db_frame },
+	{ "r6",	 DB_OFFSET(fixreg[6]),	db_frame },
+	{ "r7",	 DB_OFFSET(fixreg[7]),	db_frame },
+	{ "r8",	 DB_OFFSET(fixreg[8]),	db_frame },
+	{ "r9",	 DB_OFFSET(fixreg[9]),	db_frame },
+	{ "r10", DB_OFFSET(fixreg[10]),	db_frame },
+	{ "r11", DB_OFFSET(fixreg[11]),	db_frame },
+	{ "r12", DB_OFFSET(fixreg[12]),	db_frame },
+	{ "r13", DB_OFFSET(fixreg[13]),	db_frame },
+	{ "r14", DB_OFFSET(fixreg[14]),	db_frame },
+	{ "r15", DB_OFFSET(fixreg[15]),	db_frame },
+	{ "r16", DB_OFFSET(fixreg[16]),	db_frame },
+	{ "r17", DB_OFFSET(fixreg[17]),	db_frame },
+	{ "r18", DB_OFFSET(fixreg[18]),	db_frame },
+	{ "r19", DB_OFFSET(fixreg[19]),	db_frame },
+	{ "r20", DB_OFFSET(fixreg[20]),	db_frame },
+	{ "r21", DB_OFFSET(fixreg[21]),	db_frame },
+	{ "r22", DB_OFFSET(fixreg[22]),	db_frame },
+	{ "r23", DB_OFFSET(fixreg[23]),	db_frame },
+	{ "r24", DB_OFFSET(fixreg[24]),	db_frame },
+	{ "r25", DB_OFFSET(fixreg[25]),	db_frame },
+	{ "r26", DB_OFFSET(fixreg[26]),	db_frame },
+	{ "r27", DB_OFFSET(fixreg[27]),	db_frame },
+	{ "r28", DB_OFFSET(fixreg[28]),	db_frame },
+	{ "r29", DB_OFFSET(fixreg[29]),	db_frame },
+	{ "r30", DB_OFFSET(fixreg[30]),	db_frame },
+	{ "r31", DB_OFFSET(fixreg[31]),	db_frame },
+	{ "srr0", DB_OFFSET(srr0),	db_frame },
+	{ "srr1", DB_OFFSET(srr1),	db_frame },
+	{ "lr",	 DB_OFFSET(lr),		db_frame },
+	{ "ctr", DB_OFFSET(ctr),	db_frame },
+	{ "cr",	 DB_OFFSET(cr),		db_frame },
+	{ "xer", DB_OFFSET(xer),	db_frame },
+#ifdef AIM
+	{ "dar", DB_OFFSET(cpu.aim.dar),	db_frame },
+	{ "dsisr", DB_OFFSET(cpu.aim.dsisr),	db_frame },
+#endif
+#if defined(BOOKE)
+	{ "dear", DB_OFFSET(cpu.booke.dear),	db_frame },
+	{ "esr", DB_OFFSET(cpu.booke.esr),	db_frame },
+#endif
+};
+struct db_variable *db_eregs = db_regs + sizeof (db_regs)/sizeof (db_regs[0]);
+
+/*
+ * register variable handling
+ */
+static int
+db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
+{
+	register_t *reg;
+
+	if (kdb_frame == NULL)
+		return (0);
+        reg = (register_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep);
+        if (op == DB_VAR_GET)
+                *valuep = *reg;
+        else
+                *reg = *valuep;
+        return (1);
+}
+
+
+/*
+ *	Frame tracing.
+ */
+static int
+db_backtrace(struct thread *td, db_addr_t fp, int count)
+{
+	db_addr_t stackframe, lr, *args;
+	db_expr_t diff;
+	c_db_sym_t sym;
+	const char *symname;
+	boolean_t kernel_only = TRUE;
+	boolean_t full = FALSE;
+
+#if 0
+	{
+		register char *cp = modif;
+		register char c;
+
+		while ((c = *cp++) != 0) {
+			if (c == 't')
+				trace_thread = TRUE;
+			if (c == 'u')
+				kernel_only = FALSE;
+			if (c == 'f')
+				full = TRUE;
+		}
+	}
+#endif
+
+	stackframe = fp;
+
+	while (!db_pager_quit) {
+		if (stackframe < PAGE_SIZE)
+			break;
+
+		/*
+		 * Locate the next frame by grabbing the backchain ptr
+		 * from frame[0]
+		 */
+		stackframe = *(db_addr_t *)stackframe;
+
+	next_frame:
+	    #ifdef __powerpc64__
+		/* The saved arg values start at frame[6] */
+		args = (db_addr_t *)(stackframe + 48);
+	    #else
+		/* The saved arg values start at frame[2] */
+		args = (db_addr_t *)(stackframe + 8);
+	    #endif
+
+		if (stackframe < PAGE_SIZE)
+			break;
+
+	        if (count-- == 0)
+			break;
+
+		/*
+		 * Extract link register from frame and subtract
+		 * 4 to convert into calling address (as opposed to
+		 * return address)
+		 */
+	    #ifdef __powerpc64__
+		lr = *(db_addr_t *)(stackframe + 16) - 4;
+	    #else
+		lr = *(db_addr_t *)(stackframe + 4) - 4;
+	    #endif
+		if ((lr & 3) || (lr < 0x100)) {
+			db_printf("saved LR(0x%zx) is invalid.", lr);
+			break;
+		}
+
+		#ifdef __powerpc64__
+		db_printf("0x%016lx: ", stackframe);
+		#else
+		db_printf("0x%08x: ", stackframe);
+		#endif
+
+		/*
+		 * The trap code labels the return addresses from the
+		 * call to C code as 'trapexit' and 'asttrapexit. Use this
+		 * to determine if the callframe has to traverse a saved
+		 * trap context
+		 */
+		if ((lr + CALLOFFSET == (db_addr_t) &trapexit) ||
+		    (lr + CALLOFFSET == (db_addr_t) &asttrapexit)) {
+			const char *trapstr;
+			struct trapframe *tf = (struct trapframe *)(args);
+			db_printf("%s ", tf->srr1 & PSL_PR ? "user" : "kernel");
+			switch (tf->exc) {
+			case EXC_DSI:
+				/* XXX take advantage of the union. */
+				db_printf("DSI %s trap @ %#zx by ",
+				    (tf->cpu.aim.dsisr & DSISR_STORE) ? "write"
+				    : "read", tf->cpu.aim.dar);
+				goto print_trap;
+			case EXC_ALI:
+				/* XXX take advantage of the union. */
+				db_printf("ALI trap @ %#zx (xSR %#x) ",
+				    tf->cpu.aim.dar,
+				    (uint32_t)tf->cpu.aim.dsisr);
+				goto print_trap;
+#ifdef __powerpc64__
+			case EXC_DSE:
+				db_printf("DSE trap @ %#zx by ",
+				    tf->cpu.aim.dar);
+				goto print_trap;
+			case EXC_ISE:
+				db_printf("ISE trap @ %#zx by ", tf->srr0);
+				goto print_trap;
+#endif
+			case EXC_ISI: trapstr = "ISI"; break;
+			case EXC_PGM: trapstr = "PGM"; break;
+			case EXC_SC: trapstr = "SC"; break;
+			case EXC_EXI: trapstr = "EXI"; break;
+			case EXC_MCHK: trapstr = "MCHK"; break;
+#if !defined(BOOKE)
+			case EXC_VEC: trapstr = "VEC"; break;
+			case EXC_FPA: trapstr = "FPA"; break;
+			case EXC_BPT: trapstr = "BPT"; break;
+			case EXC_TRC: trapstr = "TRC"; break;
+			case EXC_RUNMODETRC: trapstr = "RUNMODETRC"; break;
+			case EXC_SMI: trapstr = "SMI"; break;
+			case EXC_RST: trapstr = "RST"; break;
+#endif
+			case EXC_FPU: trapstr = "FPU"; break;
+			case EXC_DECR: trapstr = "DECR"; break;
+			case EXC_PERF: trapstr = "PERF"; break;
+			default: trapstr = NULL; break;
+			}
+			if (trapstr != NULL) {
+				db_printf("%s trap by ", trapstr);
+			} else {
+				db_printf("trap %#zx by ", tf->exc);
+			}
+
+		   print_trap:
+			lr = (db_addr_t) tf->srr0;
+			diff = 0;
+			symname = NULL;
+			sym = db_search_symbol(lr, DB_STGY_ANY, &diff);
+			db_symbol_values(sym, &symname, 0);
+			if (symname == NULL || !strcmp(symname, "end")) {
+				db_printf("%#zx: srr1=%#zx\n", lr, tf->srr1);
+			} else {
+				db_printf("%s+%#zx: srr1=%#zx\n", symname, diff,
+				    tf->srr1);
+			}
+			db_printf("%-10s  r1=%#zx cr=%#x xer=%#x ctr=%#zx",
+			    "", tf->fixreg[1], (uint32_t)tf->cr,
+			    (uint32_t)tf->xer, tf->ctr);
+			if (tf->exc == EXC_DSI)
+				db_printf(" sr=%#x",
+				    (uint32_t)tf->cpu.aim.dsisr);
+			db_printf("\n");
+			stackframe = (db_addr_t) tf->fixreg[1];
+			if (kernel_only && (tf->srr1 & PSL_PR))
+				break;
+			goto next_frame;
+		}
+
+		diff = 0;
+		symname = NULL;
+		sym = db_search_symbol(lr, DB_STGY_ANY, &diff);
+		db_symbol_values(sym, &symname, 0);
+		if (symname == NULL || !strcmp(symname, "end"))
+			db_printf("at %zx", lr);
+		else
+			db_printf("at %s+%#zx", symname, diff);
+		if (full)
+			/* Print all the args stored in that stackframe. */
+			db_printf("(%zx, %zx, %zx, %zx, %zx, %zx, %zx, %zx)",
+				args[0], args[1], args[2], args[3],
+				args[4], args[5], args[6], args[7]);
+		db_printf("\n");
+	}
+
+	return (0);
+}
+
+void
+db_trace_self(void)
+{
+	db_addr_t addr;
+
+	addr = (db_addr_t)__builtin_frame_address(1);
+	db_backtrace(curthread, addr, -1);
+}
+
+int
+db_trace_thread(struct thread *td, int count)
+{
+	struct pcb *ctx;
+
+	ctx = kdb_thr_ctx(td);
+	return (db_backtrace(td, (db_addr_t)ctx->pcb_sp, count));
+}


Property changes on: trunk/sys/powerpc/powerpc/db_trace.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/dump_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/dump_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/dump_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,312 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2002 Marcel Moolenaar
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/dump_machdep.c 221173 2011-04-28 16:02:05Z attilio $");
+
+#include "opt_watchdog.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/kernel.h>
+#include <sys/kerneldump.h>
+#include <sys/sysctl.h>
+#ifdef SW_WATCHDOG
+#include <sys/watchdog.h>
+#endif
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/elf.h>
+#include <machine/md_var.h>
+
+CTASSERT(sizeof(struct kerneldumpheader) == 512);
+
+/*
+ * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
+ * is to protect us from metadata and to protect metadata from us.
+ */
+#define	SIZEOF_METADATA		(64*1024)
+
+#define	MD_ALIGN(x)	(((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
+#define	DEV_ALIGN(x)	(((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
+
+typedef int callback_t(struct pmap_md *, int, void *);
+
+static struct kerneldumpheader kdh;
+static off_t dumplo, fileofs;
+
+/* Handle buffered writes. */
+static char buffer[DEV_BSIZE];
+static size_t fragsz;
+
+int dumpsys_minidump = 1;
+SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RD, &dumpsys_minidump, 0,
+    "Kernel makes compressed crash dumps");
+
+static int
+buf_write(struct dumperinfo *di, char *ptr, size_t sz)
+{
+	size_t len;
+	int error;
+
+	while (sz) {
+		len = DEV_BSIZE - fragsz;
+		if (len > sz)
+			len = sz;
+		bcopy(ptr, buffer + fragsz, len);
+		fragsz += len;
+		ptr += len;
+		sz -= len;
+		if (fragsz == DEV_BSIZE) {
+			error = di->dumper(di->priv, buffer, 0, dumplo,
+			    DEV_BSIZE);
+			if (error)
+				return error;
+			dumplo += DEV_BSIZE;
+			fragsz = 0;
+		}
+	}
+
+	return (0);
+}
+
+static int
+buf_flush(struct dumperinfo *di)
+{
+	int error;
+
+	if (fragsz == 0)
+		return (0);
+
+	error = di->dumper(di->priv, buffer, 0, dumplo, DEV_BSIZE);
+	dumplo += DEV_BSIZE;
+	fragsz = 0;
+	return (error);
+}
+
+static int
+cb_dumpdata(struct pmap_md *md, int seqnr, void *arg)
+{
+	struct dumperinfo *di = (struct dumperinfo*)arg;
+	vm_offset_t va;
+	size_t counter, ofs, resid, sz;
+	int c, error, twiddle;
+
+	error = 0;
+	counter = 0;	/* Update twiddle every 16MB */
+	twiddle = 0;
+
+	ofs = 0;	/* Logical offset within the chunk */
+	resid = md->md_size;
+
+	printf("  chunk %d: %lu bytes ", seqnr, (u_long)resid);
+
+	while (resid) {
+		sz = (resid > DFLTPHYS) ? DFLTPHYS : resid;
+		va = pmap_dumpsys_map(md, ofs, &sz);
+		counter += sz;
+		if (counter >> 24) {
+			printf("%c\b", "|/-\\"[twiddle++ & 3]);
+			counter &= (1<<24) - 1;
+		}
+#ifdef SW_WATCHDOG
+		wdog_kern_pat(WD_LASTVAL);
+#endif
+		error = di->dumper(di->priv, (void*)va, 0, dumplo, sz);
+		pmap_dumpsys_unmap(md, ofs, va);
+		if (error)
+			break;
+		dumplo += sz;
+		resid -= sz;
+		ofs += sz;
+
+		/* Check for user abort. */
+		c = cncheckc();
+		if (c == 0x03)
+			return (ECANCELED);
+		if (c != -1)
+			printf("(CTRL-C to abort)  ");
+	}
+	printf("... %s\n", (error) ? "fail" : "ok");
+	return (error);
+}
+
+static int
+cb_dumphdr(struct pmap_md *md, int seqnr, void *arg)
+{
+	struct dumperinfo *di = (struct dumperinfo*)arg;
+	Elf32_Phdr phdr;
+	int error;
+
+	bzero(&phdr, sizeof(phdr));
+	phdr.p_type = PT_LOAD;
+	phdr.p_flags = PF_R;			/* XXX */
+	phdr.p_offset = fileofs;
+	phdr.p_vaddr = md->md_vaddr;
+	phdr.p_paddr = md->md_paddr;
+	phdr.p_filesz = md->md_size;
+	phdr.p_memsz = md->md_size;
+	phdr.p_align = PAGE_SIZE;
+
+	error = buf_write(di, (char*)&phdr, sizeof(phdr));
+	fileofs += phdr.p_filesz;
+	return (error);
+}
+
+static int
+cb_size(struct pmap_md *md, int seqnr, void *arg)
+{
+	uint32_t *sz = (uint32_t*)arg;
+
+	*sz += md->md_size;
+	return (0);
+}
+
+static int
+foreach_chunk(callback_t cb, void *arg)
+{
+	struct pmap_md *md;
+	int error, seqnr;
+
+	seqnr = 0;
+	md = pmap_scan_md(NULL);
+	while (md != NULL) {
+		error = (*cb)(md, seqnr++, arg);
+		if (error)
+			return (-error);
+		md = pmap_scan_md(md);
+	}
+	return (seqnr);
+}
+
+void
+dumpsys(struct dumperinfo *di)
+{
+	Elf32_Ehdr ehdr;
+	uint32_t dumpsize;
+	off_t hdrgap;
+	size_t hdrsz;
+	int error;
+
+	bzero(&ehdr, sizeof(ehdr));
+	ehdr.e_ident[EI_MAG0] = ELFMAG0;
+	ehdr.e_ident[EI_MAG1] = ELFMAG1;
+	ehdr.e_ident[EI_MAG2] = ELFMAG2;
+	ehdr.e_ident[EI_MAG3] = ELFMAG3;
+	ehdr.e_ident[EI_CLASS] = ELFCLASS32;
+#if BYTE_ORDER == LITTLE_ENDIAN
+	ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+#else
+	ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
+#endif
+	ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+	ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE;	/* XXX big picture? */
+	ehdr.e_type = ET_CORE;
+	ehdr.e_machine = EM_PPC;
+	ehdr.e_phoff = sizeof(ehdr);
+	ehdr.e_ehsize = sizeof(ehdr);
+	ehdr.e_phentsize = sizeof(Elf32_Phdr);
+	ehdr.e_shentsize = sizeof(Elf32_Shdr);
+
+	/* Calculate dump size. */
+	dumpsize = 0L;
+	ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
+	hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
+	fileofs = MD_ALIGN(hdrsz);
+	dumpsize += fileofs;
+	hdrgap = fileofs - DEV_ALIGN(hdrsz);
+
+	/* For block devices, determine the dump offset on the device. */
+	if (di->mediasize > 0) {
+		if (di->mediasize <
+		    SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
+			error = ENOSPC;
+			goto fail;
+		}
+		dumplo = di->mediaoffset + di->mediasize - dumpsize;
+		dumplo -= sizeof(kdh) * 2;
+	} else
+		dumplo = 0;
+
+	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_POWERPC_VERSION, dumpsize,
+	    di->blocksize);
+
+	printf("Dumping %u MB (%d chunks)\n", dumpsize >> 20,
+	    ehdr.e_phnum);
+
+	/* Dump leader */
+	error = di->dumper(di->priv, &kdh, 0, dumplo, sizeof(kdh));
+	if (error)
+		goto fail;
+	dumplo += sizeof(kdh);
+
+	/* Dump ELF header */
+	error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
+	if (error)
+		goto fail;
+
+	/* Dump program headers */
+	error = foreach_chunk(cb_dumphdr, di);
+	if (error < 0)
+		goto fail;
+	buf_flush(di);
+
+	/*
+	 * All headers are written using blocked I/O, so we know the
+	 * current offset is (still) block aligned. Skip the alignement
+	 * in the file to have the segment contents aligned at page
+	 * boundary. We cannot use MD_ALIGN on dumplo, because we don't
+	 * care and may very well be unaligned within the dump device.
+	 */
+	dumplo += hdrgap;
+
+	/* Dump memory chunks (updates dumplo) */
+	error = foreach_chunk(cb_dumpdata, di);
+	if (error < 0)
+		goto fail;
+
+	/* Dump trailer */
+	error = di->dumper(di->priv, &kdh, 0, dumplo, sizeof(kdh));
+	if (error)
+		goto fail;
+
+	/* Signal completion, signoff and exit stage left. */
+	di->dumper(di->priv, NULL, 0, 0, 0);
+	printf("\nDump complete\n");
+	return;
+
+ fail:
+	if (error < 0)
+		error = -error;
+
+	if (error == ECANCELED)
+		printf("\nDump aborted\n");
+	else
+		printf("\n** DUMP FAILED (ERROR %d) **\n", error);
+}


Property changes on: trunk/sys/powerpc/powerpc/dump_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/elf32_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/elf32_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/elf32_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,277 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 1996-1998 John D. Polstra.
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powerpc/elf32_machdep.c 294136 2016-01-16 07:56:49Z dchagin $
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+
+#define __ELF_WORD_SIZE 32
+
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/namei.h>
+#include <sys/fcntl.h>
+#include <sys/sysent.h>
+#include <sys/imgact_elf.h>
+#include <sys/syscall.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
+#include <sys/linker.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+
+#include <machine/cpu.h>
+#include <machine/elf.h>
+#include <machine/reg.h>
+#include <machine/md_var.h>
+
+#ifdef __powerpc64__
+#include <compat/freebsd32/freebsd32_proto.h>
+#include <compat/freebsd32/freebsd32_util.h>
+
+extern const char *freebsd32_syscallnames[];
+#endif
+
+struct sysentvec elf32_freebsd_sysvec = {
+	.sv_size	= SYS_MAXSYSCALL,
+#ifdef __powerpc64__
+	.sv_table	= freebsd32_sysent,
+#else
+	.sv_table	= sysent,
+#endif
+	.sv_mask	= 0,
+	.sv_sigsize	= 0,
+	.sv_sigtbl	= NULL,
+	.sv_errsize	= 0,
+	.sv_errtbl	= NULL,
+	.sv_transtrap	= NULL,
+	.sv_fixup	= __elfN(freebsd_fixup),
+	.sv_sendsig	= sendsig,
+	.sv_sigcode	= sigcode32,
+	.sv_szsigcode	= &szsigcode32,
+	.sv_prepsyscall	= NULL,
+	.sv_name	= "FreeBSD ELF32",
+	.sv_coredump	= __elfN(coredump),
+	.sv_imgact_try	= NULL,
+	.sv_minsigstksz	= MINSIGSTKSZ,
+	.sv_pagesize	= PAGE_SIZE,
+	.sv_minuser	= VM_MIN_ADDRESS,
+	.sv_stackprot	= VM_PROT_ALL,
+#ifdef __powerpc64__
+	.sv_maxuser	= VM_MAXUSER_ADDRESS,
+	.sv_usrstack	= FREEBSD32_USRSTACK,
+	.sv_psstrings	= FREEBSD32_PS_STRINGS,
+	.sv_copyout_strings = freebsd32_copyout_strings,
+	.sv_setregs	= ppc32_setregs,
+	.sv_syscallnames = freebsd32_syscallnames,
+#else
+	.sv_maxuser	= VM_MAXUSER_ADDRESS,
+	.sv_usrstack	= USRSTACK,
+	.sv_psstrings	= PS_STRINGS,
+	.sv_copyout_strings = exec_copyout_strings,
+	.sv_setregs	= exec_setregs,
+	.sv_syscallnames = syscallnames,
+#endif
+	.sv_fixlimit	= NULL,
+	.sv_maxssiz	= NULL,
+	.sv_flags	= SV_ABI_FREEBSD | SV_ILP32 | SV_SHP,
+	.sv_set_syscall_retval = cpu_set_syscall_retval,
+	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
+	.sv_shared_page_base = FREEBSD32_SHAREDPAGE,
+	.sv_shared_page_len = PAGE_SIZE,
+	.sv_schedtail	= NULL,
+	.sv_thread_detach = NULL,
+	.sv_trap	= NULL,
+};
+INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
+
+static Elf32_Brandinfo freebsd_brand_info = {
+	.brand		= ELFOSABI_FREEBSD,
+	.machine	= EM_PPC,
+	.compat_3_brand	= "FreeBSD",
+	.emul_path	= NULL,
+	.interp_path	= "/libexec/ld-elf.so.1",
+	.sysvec		= &elf32_freebsd_sysvec,
+#ifdef __powerpc64__
+	.interp_newpath	= "/libexec/ld-elf32.so.1",
+#else
+	.interp_newpath	= NULL,
+#endif
+	.brand_note	= &elf32_freebsd_brandnote,
+	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
+    (sysinit_cfunc_t) elf32_insert_brand_entry,
+    &freebsd_brand_info);
+
+static Elf32_Brandinfo freebsd_brand_oinfo = {
+	.brand		= ELFOSABI_FREEBSD,
+	.machine	= EM_PPC,
+	.compat_3_brand	= "FreeBSD",
+	.emul_path	= NULL,
+	.interp_path	= "/usr/libexec/ld-elf.so.1",
+	.sysvec		= &elf32_freebsd_sysvec,
+	.interp_newpath	= NULL,
+	.brand_note	= &elf32_freebsd_brandnote,
+	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
+	(sysinit_cfunc_t) elf32_insert_brand_entry,
+	&freebsd_brand_oinfo);
+
+void
+elf32_dump_thread(struct thread *td __unused, void *dst __unused,
+    size_t *off __unused)
+{
+}
+
+#ifndef __powerpc64__
+/* Process one elf relocation with addend. */
+static int
+elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
+    int type, int local, elf_lookup_fn lookup)
+{
+	Elf_Addr *where;
+	Elf_Half *hwhere;
+	Elf_Addr addr;
+	Elf_Addr addend;
+	Elf_Word rtype, symidx;
+	const Elf_Rela *rela;
+	int error;
+
+	switch (type) {
+	case ELF_RELOC_REL:
+		panic("PPC only supports RELA relocations");
+		break;
+	case ELF_RELOC_RELA:
+		rela = (const Elf_Rela *)data;
+		where = (Elf_Addr *) ((uintptr_t)relocbase + rela->r_offset);
+		hwhere = (Elf_Half *) ((uintptr_t)relocbase + rela->r_offset);
+		addend = rela->r_addend;
+		rtype = ELF_R_TYPE(rela->r_info);
+		symidx = ELF_R_SYM(rela->r_info);
+		break;
+	default:
+		panic("elf_reloc: unknown relocation mode %d\n", type);
+	}
+
+	switch (rtype) {
+
+	case R_PPC_NONE:
+		break;
+
+	case R_PPC_ADDR32: /* word32 S + A */
+		error = lookup(lf, symidx, 1, &addr);
+		if (error != 0)
+			return -1;
+		addr += addend;
+	       	*where = addr;
+			break;
+
+	case R_PPC_ADDR16_LO: /* #lo(S) */
+		error = lookup(lf, symidx, 1, &addr);
+		if (error != 0)
+			return -1;
+		/*
+		 * addend values are sometimes relative to sections
+		 * (i.e. .rodata) in rela, where in reality they
+		 * are relative to relocbase. Detect this condition.
+		 */
+		if (addr > relocbase && addr <= (relocbase + addend))
+			addr = relocbase + addend;
+		else
+			addr += addend;
+		*hwhere = addr & 0xffff;
+		break;
+
+	case R_PPC_ADDR16_HA: /* #ha(S) */
+		error = lookup(lf, symidx, 1, &addr);
+		if (error != 0)
+			return -1;
+		/*
+		 * addend values are sometimes relative to sections
+		 * (i.e. .rodata) in rela, where in reality they
+		 * are relative to relocbase. Detect this condition.
+		 */
+		if (addr > relocbase && addr <= (relocbase + addend))
+			addr = relocbase + addend;
+		else
+			addr += addend;
+		*hwhere = ((addr >> 16) + ((addr & 0x8000) ? 1 : 0))
+		    & 0xffff;
+		break;
+
+	case R_PPC_RELATIVE: /* word32 B + A */
+		*where = elf_relocaddr(lf, relocbase + addend);
+		break;
+
+	default:
+		printf("kldload: unexpected relocation type %d\n",
+		    (int) rtype);
+		return -1;
+	}
+	return(0);
+}
+
+int
+elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
+    elf_lookup_fn lookup)
+{
+
+	return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
+}
+
+int
+elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
+    int type, elf_lookup_fn lookup)
+{
+
+	return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
+}
+
+int
+elf_cpu_load_file(linker_file_t lf)
+{
+	/* Only sync the cache for non-kernel modules */
+	if (lf->id != 1)
+		__syncicache(lf->address, lf->size);
+	return (0);
+}
+
+int
+elf_cpu_unload_file(linker_file_t lf __unused)
+{
+
+	return (0);
+}
+#endif


Property changes on: trunk/sys/powerpc/powerpc/elf32_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/elf64_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/elf64_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/elf64_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,219 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 1996-1998 John D. Polstra.
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powerpc/elf64_machdep.c 294136 2016-01-16 07:56:49Z dchagin $
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/namei.h>
+#include <sys/fcntl.h>
+#include <sys/sysent.h>
+#include <sys/imgact_elf.h>
+#include <sys/syscall.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
+#include <sys/linker.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+
+#include <machine/cpu.h>
+#include <machine/elf.h>
+#include <machine/md_var.h>
+
+struct sysentvec elf64_freebsd_sysvec = {
+	.sv_size	= SYS_MAXSYSCALL,
+	.sv_table	= sysent,
+	.sv_mask	= 0,
+	.sv_sigsize	= 0,
+	.sv_sigtbl	= NULL,
+	.sv_errsize	= 0,
+	.sv_errtbl	= NULL,
+	.sv_transtrap	= NULL,
+	.sv_fixup	= __elfN(freebsd_fixup),
+	.sv_sendsig	= sendsig,
+	.sv_sigcode	= sigcode64,
+	.sv_szsigcode	= &szsigcode64,
+	.sv_prepsyscall	= NULL,
+	.sv_name	= "FreeBSD ELF64",
+	.sv_coredump	= __elfN(coredump),
+	.sv_imgact_try	= NULL,
+	.sv_minsigstksz	= MINSIGSTKSZ,
+	.sv_pagesize	= PAGE_SIZE,
+	.sv_minuser	= VM_MIN_ADDRESS,
+	.sv_maxuser	= VM_MAXUSER_ADDRESS,
+	.sv_usrstack	= USRSTACK,
+	.sv_psstrings	= PS_STRINGS,
+	.sv_stackprot	= VM_PROT_ALL,
+	.sv_copyout_strings = exec_copyout_strings,
+	.sv_setregs	= exec_setregs,
+	.sv_fixlimit	= NULL,
+	.sv_maxssiz	= NULL,
+	.sv_flags	= SV_ABI_FREEBSD | SV_LP64 | SV_SHP,
+	.sv_set_syscall_retval = cpu_set_syscall_retval,
+	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
+	.sv_syscallnames = syscallnames,
+	.sv_shared_page_base = SHAREDPAGE,
+	.sv_shared_page_len = PAGE_SIZE,
+	.sv_schedtail	= NULL,
+	.sv_thread_detach = NULL,
+	.sv_trap	= NULL,
+};
+INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
+
+static Elf64_Brandinfo freebsd_brand_info = {
+	.brand		= ELFOSABI_FREEBSD,
+	.machine	= EM_PPC64,
+	.compat_3_brand	= "FreeBSD",
+	.emul_path	= NULL,
+	.interp_path	= "/libexec/ld-elf.so.1",
+	.sysvec		= &elf64_freebsd_sysvec,
+	.interp_newpath	= NULL,
+	.brand_note	= &elf64_freebsd_brandnote,
+	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
+    (sysinit_cfunc_t) elf64_insert_brand_entry,
+    &freebsd_brand_info);
+
+static Elf64_Brandinfo freebsd_brand_oinfo = {
+	.brand		= ELFOSABI_FREEBSD,
+	.machine	= EM_PPC64,
+	.compat_3_brand	= "FreeBSD",
+	.emul_path	= NULL,
+	.interp_path	= "/usr/libexec/ld-elf.so.1",
+	.sysvec		= &elf64_freebsd_sysvec,
+	.interp_newpath	= NULL,
+	.brand_note	= &elf64_freebsd_brandnote,
+	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
+	(sysinit_cfunc_t) elf64_insert_brand_entry,
+	&freebsd_brand_oinfo);
+
+void
+elf64_dump_thread(struct thread *td __unused, void *dst __unused,
+    size_t *off __unused)
+{
+}
+
+
+/* Process one elf relocation with addend. */
+static int
+elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
+    int type, int local, elf_lookup_fn lookup)
+{
+	Elf_Addr *where;
+	Elf_Addr addr;
+	Elf_Addr addend;
+	Elf_Word rtype, symidx;
+	const Elf_Rela *rela;
+	int error;
+
+	switch (type) {
+	case ELF_RELOC_REL:
+		panic("PPC only supports RELA relocations");
+		break;
+	case ELF_RELOC_RELA:
+		rela = (const Elf_Rela *)data;
+		where = (Elf_Addr *) (relocbase + rela->r_offset);
+		addend = rela->r_addend;
+		rtype = ELF_R_TYPE(rela->r_info);
+		symidx = ELF_R_SYM(rela->r_info);
+		break;
+	default:
+		panic("elf_reloc: unknown relocation mode %d\n", type);
+	}
+
+	switch (rtype) {
+
+	case R_PPC_NONE:
+		break;
+
+	case R_PPC64_ADDR64:	/* doubleword64 S + A */
+		error = lookup(lf, symidx, 1, &addr);
+		if (error != 0)
+			return -1;
+		addr += addend;
+		*where = addr;
+		break;
+
+	case R_PPC_RELATIVE:	/* doubleword64 B + A */
+		*where = elf_relocaddr(lf, relocbase + addend);
+		break;
+
+	case R_PPC_JMP_SLOT:	/* function descriptor copy */
+		lookup(lf, symidx, 1, &addr);
+		memcpy(where, (Elf_Addr *)addr, 3*sizeof(Elf_Addr));
+		__asm __volatile("dcbst 0,%0; sync" :: "r"(where) : "memory");
+		break;
+
+	default:
+		printf("kldload: unexpected relocation type %d\n",
+		    (int) rtype);
+		return -1;
+	}
+	return(0);
+}
+
+int
+elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
+    elf_lookup_fn lookup)
+{
+
+	return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
+}
+
+int
+elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
+    int type, elf_lookup_fn lookup)
+{
+
+	return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
+}
+
+int
+elf_cpu_load_file(linker_file_t lf)
+{
+	/* Only sync the cache for non-kernel modules */
+	if (lf->id != 1)
+		__syncicache(lf->address, lf->size);
+	return (0);
+}
+
+int
+elf_cpu_unload_file(linker_file_t lf __unused)
+{
+
+	return (0);
+}


Property changes on: trunk/sys/powerpc/powerpc/elf64_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/exec_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/exec_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/exec_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,1070 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ */
+/*-
+ * Copyright (C) 2001 Benno Rice
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ *	$NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/exec_machdep.c 301428 2016-06-05 07:34:10Z dchagin $");
+
+#include "opt_compat.h"
+#include "opt_fpu_emu.h"
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <sys/cpu.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/signalvar.h>
+#include <sys/syscallsubr.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/ucontext.h>
+#include <sys/uio.h>
+
+#include <machine/altivec.h>
+#include <machine/cpu.h>
+#include <machine/elf.h>
+#include <machine/fpu.h>
+#include <machine/pcb.h>
+#include <machine/reg.h>
+#include <machine/sigframe.h>
+#include <machine/trap.h>
+#include <machine/vmparam.h>
+
+#ifdef FPU_EMU
+#include <powerpc/fpu/fpu_extern.h>
+#endif
+
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32_signal.h>
+#include <compat/freebsd32/freebsd32_util.h>
+#include <compat/freebsd32/freebsd32_proto.h>
+
+typedef struct __ucontext32 {
+	sigset_t		uc_sigmask;
+	mcontext32_t		uc_mcontext;
+	uint32_t		uc_link;
+	struct sigaltstack32    uc_stack;
+	uint32_t		uc_flags;
+	uint32_t		__spare__[4];
+} ucontext32_t;
+
+struct sigframe32 {
+	ucontext32_t		sf_uc;
+	struct siginfo32	sf_si;
+};
+
+static int	grab_mcontext32(struct thread *td, mcontext32_t *, int flags);
+#endif
+
+static int	grab_mcontext(struct thread *, mcontext_t *, int);
+
+void
+sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
+{
+	struct trapframe *tf;
+	struct sigacts *psp;
+	struct sigframe sf;
+	struct thread *td;
+	struct proc *p;
+	#ifdef COMPAT_FREEBSD32
+	struct siginfo32 siginfo32;
+	struct sigframe32 sf32;
+	#endif
+	size_t sfpsize;
+	caddr_t sfp, usfp;
+	int oonstack, rndfsize;
+	int sig;
+	int code;
+
+	td = curthread;
+	p = td->td_proc;
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+
+	psp = p->p_sigacts;
+	mtx_assert(&psp->ps_mtx, MA_OWNED);
+	tf = td->td_frame;
+	oonstack = sigonstack(tf->fixreg[1]);
+
+	/*
+	 * Fill siginfo structure.
+	 */
+	ksi->ksi_info.si_signo = ksi->ksi_signo;
+	#ifdef AIM
+	ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ? 
+	    tf->cpu.aim.dar : tf->srr0);
+	#else
+	ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ? 
+	    tf->cpu.booke.dear : tf->srr0);
+	#endif
+
+	#ifdef COMPAT_FREEBSD32
+	if (SV_PROC_FLAG(p, SV_ILP32)) {
+		siginfo_to_siginfo32(&ksi->ksi_info, &siginfo32);
+		sig = siginfo32.si_signo;
+		code = siginfo32.si_code;
+		sfp = (caddr_t)&sf32;
+		sfpsize = sizeof(sf32);
+		rndfsize = ((sizeof(sf32) + 15) / 16) * 16;
+
+		/*
+		 * Save user context
+		 */
+
+		memset(&sf32, 0, sizeof(sf32));
+		grab_mcontext32(td, &sf32.sf_uc.uc_mcontext, 0);
+
+		sf32.sf_uc.uc_sigmask = *mask;
+		sf32.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
+		sf32.sf_uc.uc_stack.ss_size = (uint32_t)td->td_sigstk.ss_size;
+		sf32.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
+		    ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
+
+		sf32.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
+	} else {
+	#endif
+		sig = ksi->ksi_signo;
+		code = ksi->ksi_code;
+		sfp = (caddr_t)&sf;
+		sfpsize = sizeof(sf);
+		#ifdef __powerpc64__
+		/*
+		 * 64-bit PPC defines a 288 byte scratch region
+		 * below the stack.
+		 */
+		rndfsize = 288 + ((sizeof(sf) + 47) / 48) * 48;
+		#else
+		rndfsize = ((sizeof(sf) + 15) / 16) * 16;
+		#endif
+
+		/*
+		 * Save user context
+		 */
+
+		memset(&sf, 0, sizeof(sf));
+		grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0);
+
+		sf.sf_uc.uc_sigmask = *mask;
+		sf.sf_uc.uc_stack = td->td_sigstk;
+		sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
+		    ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
+
+		sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
+	#ifdef COMPAT_FREEBSD32
+	}
+	#endif
+
+	CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
+	     catcher, sig);
+
+	/*
+	 * Allocate and validate space for the signal handler context.
+	 */
+	if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
+	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
+		usfp = (void *)(((uintptr_t)td->td_sigstk.ss_sp +
+		   td->td_sigstk.ss_size - rndfsize) & ~0xFul);
+	} else {
+		usfp = (void *)((tf->fixreg[1] - rndfsize) & ~0xFul);
+	}
+
+	/*
+	 * Save the floating-point state, if necessary, then copy it.
+	 */
+	/* XXX */
+
+	/*
+	 * Set up the registers to return to sigcode.
+	 *
+	 *   r1/sp - sigframe ptr
+	 *   lr    - sig function, dispatched to by blrl in trampoline
+	 *   r3    - sig number
+	 *   r4    - SIGINFO ? &siginfo : exception code
+	 *   r5    - user context
+	 *   srr0  - trampoline function addr
+	 */
+	tf->lr = (register_t)catcher;
+	tf->fixreg[1] = (register_t)usfp;
+	tf->fixreg[FIRSTARG] = sig;
+	#ifdef COMPAT_FREEBSD32
+	tf->fixreg[FIRSTARG+2] = (register_t)usfp +
+	    ((SV_PROC_FLAG(p, SV_ILP32)) ?
+	    offsetof(struct sigframe32, sf_uc) :
+	    offsetof(struct sigframe, sf_uc));
+	#else
+	tf->fixreg[FIRSTARG+2] = (register_t)usfp +
+	    offsetof(struct sigframe, sf_uc);
+	#endif
+	if (SIGISMEMBER(psp->ps_siginfo, sig)) {
+		/*
+		 * Signal handler installed with SA_SIGINFO.
+		 */
+		#ifdef COMPAT_FREEBSD32
+		if (SV_PROC_FLAG(p, SV_ILP32)) {
+			sf32.sf_si = siginfo32;
+			tf->fixreg[FIRSTARG+1] = (register_t)usfp +
+			    offsetof(struct sigframe32, sf_si);
+			sf32.sf_si = siginfo32;
+		} else  {
+		#endif
+			tf->fixreg[FIRSTARG+1] = (register_t)usfp +
+			    offsetof(struct sigframe, sf_si);
+			sf.sf_si = ksi->ksi_info;
+		#ifdef COMPAT_FREEBSD32
+		}
+		#endif
+	} else {
+		/* Old FreeBSD-style arguments. */
+		tf->fixreg[FIRSTARG+1] = code;
+		#ifdef AIM
+		tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 
+		    tf->cpu.aim.dar : tf->srr0;
+		#else
+		tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 
+		    tf->cpu.booke.dear : tf->srr0;
+		#endif
+	}
+	mtx_unlock(&psp->ps_mtx);
+	PROC_UNLOCK(p);
+
+	tf->srr0 = (register_t)p->p_sysent->sv_sigcode_base;
+
+	/*
+	 * copy the frame out to userland.
+	 */
+	if (copyout(sfp, usfp, sfpsize) != 0) {
+		/*
+		 * Process has trashed its stack. Kill it.
+		 */
+		CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
+		PROC_LOCK(p);
+		sigexit(td, SIGILL);
+	}
+
+	CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
+	     tf->srr0, tf->fixreg[1]);
+
+	PROC_LOCK(p);
+	mtx_lock(&psp->ps_mtx);
+}
+
+int
+sys_sigreturn(struct thread *td, struct sigreturn_args *uap)
+{
+	ucontext_t uc;
+	int error;
+
+	CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
+
+	if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
+		CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
+		return (EFAULT);
+	}
+
+	error = set_mcontext(td, &uc.uc_mcontext);
+	if (error != 0)
+		return (error);
+
+	kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
+
+	CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
+	     td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
+
+	return (EJUSTRETURN);
+}
+
+#ifdef COMPAT_FREEBSD4
+int
+freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
+{
+
+	return sys_sigreturn(td, (struct sigreturn_args *)uap);
+}
+#endif
+
+/*
+ * Construct a PCB from a trapframe. This is called from kdb_trap() where
+ * we want to start a backtrace from the function that caused us to enter
+ * the debugger. We have the context in the trapframe, but base the trace
+ * on the PCB. The PCB doesn't have to be perfect, as long as it contains
+ * enough for a backtrace.
+ */
+void
+makectx(struct trapframe *tf, struct pcb *pcb)
+{
+
+	pcb->pcb_lr = tf->srr0;
+	pcb->pcb_sp = tf->fixreg[1];
+}
+
+/*
+ * get_mcontext/sendsig helper routine that doesn't touch the
+ * proc lock
+ */
+static int
+grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
+{
+	struct pcb *pcb;
+
+	pcb = td->td_pcb;
+
+	memset(mcp, 0, sizeof(mcontext_t));
+
+	mcp->mc_vers = _MC_VERSION;
+	mcp->mc_flags = 0;
+	memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe));
+	if (flags & GET_MC_CLEAR_RET) {
+		mcp->mc_gpr[3] = 0;
+		mcp->mc_gpr[4] = 0;
+	}
+
+	/*
+	 * This assumes that floating-point context is *not* lazy,
+	 * so if the thread has used FP there would have been a
+	 * FP-unavailable exception that would have set things up
+	 * correctly.
+	 */
+	if (pcb->pcb_flags & PCB_FPREGS) {
+		if (pcb->pcb_flags & PCB_FPU) {
+			KASSERT(td == curthread,
+				("get_mcontext: fp save not curthread"));
+			critical_enter();
+			save_fpu(td);
+			critical_exit();
+		}
+		mcp->mc_flags |= _MC_FP_VALID;
+		memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
+		memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*sizeof(double));
+	}
+
+	/*
+	 * Repeat for Altivec context
+	 */
+
+	if (pcb->pcb_flags & PCB_VEC) {
+		KASSERT(td == curthread,
+			("get_mcontext: fp save not curthread"));
+		critical_enter();
+		save_vec(td);
+		critical_exit();
+		mcp->mc_flags |= _MC_AV_VALID;
+		mcp->mc_vscr  = pcb->pcb_vec.vscr;
+		mcp->mc_vrsave =  pcb->pcb_vec.vrsave;
+		memcpy(mcp->mc_avec, pcb->pcb_vec.vr, sizeof(mcp->mc_avec));
+	}
+
+	mcp->mc_len = sizeof(*mcp);
+
+	return (0);
+}
+
+int
+get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
+{
+	int error;
+
+	error = grab_mcontext(td, mcp, flags);
+	if (error == 0) {
+		PROC_LOCK(curthread->td_proc);
+		mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
+		PROC_UNLOCK(curthread->td_proc);
+	}
+
+	return (error);
+}
+
+int
+set_mcontext(struct thread *td, mcontext_t *mcp)
+{
+	struct pcb *pcb;
+	struct trapframe *tf;
+	register_t tls;
+
+	pcb = td->td_pcb;
+	tf = td->td_frame;
+
+	if (mcp->mc_vers != _MC_VERSION || mcp->mc_len != sizeof(*mcp))
+		return (EINVAL);
+
+	/*
+	 * Don't let the user set privileged MSR bits
+	 */
+	if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) {
+		return (EINVAL);
+	}
+
+	/* Copy trapframe, preserving TLS pointer across context change */
+	if (SV_PROC_FLAG(td->td_proc, SV_LP64))
+		tls = tf->fixreg[13];
+	else
+		tls = tf->fixreg[2];
+	memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
+	if (SV_PROC_FLAG(td->td_proc, SV_LP64))
+		tf->fixreg[13] = tls;
+	else
+		tf->fixreg[2] = tls;
+
+	if (mcp->mc_flags & _MC_FP_VALID) {
+		/* enable_fpu() will happen lazily on a fault */
+		pcb->pcb_flags |= PCB_FPREGS;
+		memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double));
+		memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double));
+	}
+
+	if (mcp->mc_flags & _MC_AV_VALID) {
+		if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) {
+			critical_enter();
+			enable_vec(td);
+			critical_exit();
+		}
+		pcb->pcb_vec.vscr = mcp->mc_vscr;
+		pcb->pcb_vec.vrsave = mcp->mc_vrsave;
+		memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec));
+	}
+
+	return (0);
+}
+
+/*
+ * Set set up registers on exec.
+ */
+void
+exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
+{
+	struct trapframe	*tf;
+	register_t		argc;
+	#ifdef __powerpc64__
+	register_t		entry_desc[3];
+	#endif
+
+	tf = trapframe(td);
+	bzero(tf, sizeof *tf);
+	#ifdef __powerpc64__
+	tf->fixreg[1] = -roundup(-stack + 48, 16);
+	#else
+	tf->fixreg[1] = -roundup(-stack + 8, 16);
+	#endif
+
+	/*
+	 * Set up arguments for _start():
+	 *	_start(argc, argv, envp, obj, cleanup, ps_strings);
+	 *
+	 * Notes:
+	 *	- obj and cleanup are the auxilliary and termination
+	 *	  vectors.  They are fixed up by ld.elf_so.
+	 *	- ps_strings is a NetBSD extention, and will be
+	 * 	  ignored by executables which are strictly
+	 *	  compliant with the SVR4 ABI.
+	 *
+	 * XXX We have to set both regs and retval here due to different
+	 * XXX calling convention in trap.c and init_main.c.
+	 */
+
+	/* Collect argc from the user stack */
+	argc = fuword((void *)stack);
+
+        /*
+         * XXX PG: these get overwritten in the syscall return code.
+         * execve() should return EJUSTRETURN, like it does on NetBSD.
+         * Emulate by setting the syscall return value cells. The
+         * registers still have to be set for init's fork trampoline.
+         */
+        td->td_retval[0] = argc;
+        td->td_retval[1] = stack + sizeof(register_t);
+	tf->fixreg[3] = argc;
+	tf->fixreg[4] = stack + sizeof(register_t);
+	tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t);
+	tf->fixreg[6] = 0;				/* auxillary vector */
+	tf->fixreg[7] = 0;				/* termination vector */
+	tf->fixreg[8] = (register_t)imgp->ps_strings;	/* NetBSD extension */
+
+	#ifdef __powerpc64__
+	/*
+	 * For 64-bit, we need to disentangle the function descriptor
+	 * 
+	 * 0. entry point
+	 * 1. TOC value (r2)
+	 * 2. Environment pointer (r11)
+	 */
+
+	(void)copyin((void *)imgp->entry_addr, entry_desc, sizeof(entry_desc));
+	tf->srr0 = entry_desc[0] + imgp->reloc_base;
+	tf->fixreg[2] = entry_desc[1] + imgp->reloc_base;
+	tf->fixreg[11] = entry_desc[2] + imgp->reloc_base;
+	tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT;
+	if (mfmsr() & PSL_HV)
+		tf->srr1 |= PSL_HV;
+	#else
+	tf->srr0 = imgp->entry_addr;
+	tf->srr1 = PSL_USERSET | PSL_FE_DFLT;
+	#endif
+	td->td_pcb->pcb_flags = 0;
+}
+
+#ifdef COMPAT_FREEBSD32
+void
+ppc32_setregs(struct thread *td, struct image_params *imgp, u_long stack)
+{
+	struct trapframe	*tf;
+	uint32_t		argc;
+
+	tf = trapframe(td);
+	bzero(tf, sizeof *tf);
+	tf->fixreg[1] = -roundup(-stack + 8, 16);
+
+	argc = fuword32((void *)stack);
+
+        td->td_retval[0] = argc;
+        td->td_retval[1] = stack + sizeof(uint32_t);
+	tf->fixreg[3] = argc;
+	tf->fixreg[4] = stack + sizeof(uint32_t);
+	tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t);
+	tf->fixreg[6] = 0;				/* auxillary vector */
+	tf->fixreg[7] = 0;				/* termination vector */
+	tf->fixreg[8] = (register_t)imgp->ps_strings;	/* NetBSD extension */
+
+	tf->srr0 = imgp->entry_addr;
+	tf->srr1 = PSL_USERSET | PSL_FE_DFLT;
+	tf->srr1 &= ~PSL_SF;
+	if (mfmsr() & PSL_HV)
+		tf->srr1 |= PSL_HV;
+	td->td_pcb->pcb_flags = 0;
+}
+#endif
+
+int
+fill_regs(struct thread *td, struct reg *regs)
+{
+	struct trapframe *tf;
+
+	tf = td->td_frame;
+	memcpy(regs, tf, sizeof(struct reg));
+
+	return (0);
+}
+
+int
+fill_dbregs(struct thread *td, struct dbreg *dbregs)
+{
+	/* No debug registers on PowerPC */
+	return (ENOSYS);
+}
+
+int
+fill_fpregs(struct thread *td, struct fpreg *fpregs)
+{
+	struct pcb *pcb;
+
+	pcb = td->td_pcb;
+
+	if ((pcb->pcb_flags & PCB_FPREGS) == 0)
+		memset(fpregs, 0, sizeof(struct fpreg));
+	else
+		memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg));
+
+	return (0);
+}
+
+int
+set_regs(struct thread *td, struct reg *regs)
+{
+	struct trapframe *tf;
+
+	tf = td->td_frame;
+	memcpy(tf, regs, sizeof(struct reg));
+	
+	return (0);
+}
+
+int
+set_dbregs(struct thread *td, struct dbreg *dbregs)
+{
+	/* No debug registers on PowerPC */
+	return (ENOSYS);
+}
+
+int
+set_fpregs(struct thread *td, struct fpreg *fpregs)
+{
+	struct pcb *pcb;
+
+	pcb = td->td_pcb;
+	pcb->pcb_flags |= PCB_FPREGS;
+	memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg));
+
+	return (0);
+}
+
+#ifdef COMPAT_FREEBSD32
+int
+set_regs32(struct thread *td, struct reg32 *regs)
+{
+	struct trapframe *tf;
+	int i;
+
+	tf = td->td_frame;
+	for (i = 0; i < 32; i++)
+		tf->fixreg[i] = regs->fixreg[i];
+	tf->lr = regs->lr;
+	tf->cr = regs->cr;
+	tf->xer = regs->xer;
+	tf->ctr = regs->ctr;
+	tf->srr0 = regs->pc;
+
+	return (0);
+}
+
+int
+fill_regs32(struct thread *td, struct reg32 *regs)
+{
+	struct trapframe *tf;
+	int i;
+
+	tf = td->td_frame;
+	for (i = 0; i < 32; i++)
+		regs->fixreg[i] = tf->fixreg[i];
+	regs->lr = tf->lr;
+	regs->cr = tf->cr;
+	regs->xer = tf->xer;
+	regs->ctr = tf->ctr;
+	regs->pc = tf->srr0;
+
+	return (0);
+}
+
+static int
+grab_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
+{
+	mcontext_t mcp64;
+	int i, error;
+
+	error = grab_mcontext(td, &mcp64, flags);
+	if (error != 0)
+		return (error);
+	
+	mcp->mc_vers = mcp64.mc_vers;
+	mcp->mc_flags = mcp64.mc_flags;
+	mcp->mc_onstack = mcp64.mc_onstack;
+	mcp->mc_len = mcp64.mc_len;
+	memcpy(mcp->mc_avec,mcp64.mc_avec,sizeof(mcp64.mc_avec));
+	memcpy(mcp->mc_av,mcp64.mc_av,sizeof(mcp64.mc_av));
+	for (i = 0; i < 42; i++)
+		mcp->mc_frame[i] = mcp64.mc_frame[i];
+	memcpy(mcp->mc_fpreg,mcp64.mc_fpreg,sizeof(mcp64.mc_fpreg));
+
+	return (0);
+}
+
+static int
+get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
+{
+	int error;
+
+	error = grab_mcontext32(td, mcp, flags);
+	if (error == 0) {
+		PROC_LOCK(curthread->td_proc);
+		mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
+		PROC_UNLOCK(curthread->td_proc);
+	}
+
+	return (error);
+}
+
+static int
+set_mcontext32(struct thread *td, mcontext32_t *mcp)
+{
+	mcontext_t mcp64;
+	int i, error;
+
+	mcp64.mc_vers = mcp->mc_vers;
+	mcp64.mc_flags = mcp->mc_flags;
+	mcp64.mc_onstack = mcp->mc_onstack;
+	mcp64.mc_len = mcp->mc_len;
+	memcpy(mcp64.mc_avec,mcp->mc_avec,sizeof(mcp64.mc_avec));
+	memcpy(mcp64.mc_av,mcp->mc_av,sizeof(mcp64.mc_av));
+	for (i = 0; i < 42; i++)
+		mcp64.mc_frame[i] = mcp->mc_frame[i];
+	mcp64.mc_srr1 |= (td->td_frame->srr1 & 0xFFFFFFFF00000000ULL);
+	memcpy(mcp64.mc_fpreg,mcp->mc_fpreg,sizeof(mcp64.mc_fpreg));
+
+	error = set_mcontext(td, &mcp64);
+
+	return (error);
+}
+#endif
+
+#ifdef COMPAT_FREEBSD32
+int
+freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap)
+{
+	ucontext32_t uc;
+	int error;
+
+	CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
+
+	if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
+		CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
+		return (EFAULT);
+	}
+
+	error = set_mcontext32(td, &uc.uc_mcontext);
+	if (error != 0)
+		return (error);
+
+	kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
+
+	CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
+	     td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
+
+	return (EJUSTRETURN);
+}
+
+/*
+ * The first two fields of a ucontext_t are the signal mask and the machine
+ * context.  The next field is uc_link; we want to avoid destroying the link
+ * when copying out contexts.
+ */
+#define	UC32_COPY_SIZE	offsetof(ucontext32_t, uc_link)
+
+int
+freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
+{
+	ucontext32_t uc;
+	int ret;
+
+	if (uap->ucp == NULL)
+		ret = EINVAL;
+	else {
+		get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
+		PROC_LOCK(td->td_proc);
+		uc.uc_sigmask = td->td_sigmask;
+		PROC_UNLOCK(td->td_proc);
+		ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE);
+	}
+	return (ret);
+}
+
+int
+freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
+{
+	ucontext32_t uc;
+	int ret;	
+
+	if (uap->ucp == NULL)
+		ret = EINVAL;
+	else {
+		ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
+		if (ret == 0) {
+			ret = set_mcontext32(td, &uc.uc_mcontext);
+			if (ret == 0) {
+				kern_sigprocmask(td, SIG_SETMASK,
+				    &uc.uc_sigmask, NULL, 0);
+			}
+		}
+	}
+	return (ret == 0 ? EJUSTRETURN : ret);
+}
+
+int
+freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
+{
+	ucontext32_t uc;
+	int ret;
+
+	if (uap->oucp == NULL || uap->ucp == NULL)
+		ret = EINVAL;
+	else {
+		get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
+		PROC_LOCK(td->td_proc);
+		uc.uc_sigmask = td->td_sigmask;
+		PROC_UNLOCK(td->td_proc);
+		ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE);
+		if (ret == 0) {
+			ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
+			if (ret == 0) {
+				ret = set_mcontext32(td, &uc.uc_mcontext);
+				if (ret == 0) {
+					kern_sigprocmask(td, SIG_SETMASK,
+					    &uc.uc_sigmask, NULL, 0);
+				}
+			}
+		}
+	}
+	return (ret == 0 ? EJUSTRETURN : ret);
+}
+
+#endif
+
+void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+	struct proc *p;
+	struct trapframe *tf;
+	int fixup;
+
+	if (error == EJUSTRETURN)
+		return;
+
+	p = td->td_proc;
+	tf = td->td_frame;
+
+	if (tf->fixreg[0] == SYS___syscall &&
+	    (SV_PROC_FLAG(p, SV_ILP32))) {
+		int code = tf->fixreg[FIRSTARG + 1];
+		if (p->p_sysent->sv_mask)
+			code &= p->p_sysent->sv_mask;
+		fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek) ?
+		    1 : 0;
+	} else
+		fixup = 0;
+
+	switch (error) {
+	case 0:
+		if (fixup) {
+			/*
+			 * 64-bit return, 32-bit syscall. Fixup byte order
+			 */
+			tf->fixreg[FIRSTARG] = 0;
+			tf->fixreg[FIRSTARG + 1] = td->td_retval[0];
+		} else {
+			tf->fixreg[FIRSTARG] = td->td_retval[0];
+			tf->fixreg[FIRSTARG + 1] = td->td_retval[1];
+		}
+		tf->cr &= ~0x10000000;		/* Unset summary overflow */
+		break;
+	case ERESTART:
+		/*
+		 * Set user's pc back to redo the system call.
+		 */
+		tf->srr0 -= 4;
+		break;
+	default:
+		tf->fixreg[FIRSTARG] = SV_ABI_ERRNO(p, error);
+		tf->cr |= 0x10000000;		/* Set summary overflow */
+		break;
+	}
+}
+
+/*
+ * Threading functions
+ */
+void
+cpu_thread_exit(struct thread *td)
+{
+}
+
+void
+cpu_thread_clean(struct thread *td)
+{
+}
+
+void
+cpu_thread_alloc(struct thread *td)
+{
+	struct pcb *pcb;
+
+	pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
+	    sizeof(struct pcb)) & ~0x2fUL);
+	td->td_pcb = pcb;
+	td->td_frame = (struct trapframe *)pcb - 1;
+}
+
+void
+cpu_thread_free(struct thread *td)
+{
+}
+
+int
+cpu_set_user_tls(struct thread *td, void *tls_base)
+{
+
+	if (SV_PROC_FLAG(td->td_proc, SV_LP64))
+		td->td_frame->fixreg[13] = (register_t)tls_base + 0x7010;
+	else
+		td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008;
+	return (0);
+}
+
+void
+cpu_set_upcall(struct thread *td, struct thread *td0)
+{
+	struct pcb *pcb2;
+	struct trapframe *tf;
+	struct callframe *cf;
+
+	pcb2 = td->td_pcb;
+
+	/* Copy the upcall pcb */
+	bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
+
+	/* Create a stack for the new thread */
+	tf = td->td_frame;
+	bcopy(td0->td_frame, tf, sizeof(struct trapframe));
+	tf->fixreg[FIRSTARG] = 0;
+	tf->fixreg[FIRSTARG + 1] = 0;
+	tf->cr &= ~0x10000000;
+
+	/* Set registers for trampoline to user mode. */
+	cf = (struct callframe *)tf - 1;
+	memset(cf, 0, sizeof(struct callframe));
+	cf->cf_func = (register_t)fork_return;
+	cf->cf_arg0 = (register_t)td;
+	cf->cf_arg1 = (register_t)tf;
+
+	pcb2->pcb_sp = (register_t)cf;
+	#ifdef __powerpc64__
+	pcb2->pcb_lr = ((register_t *)fork_trampoline)[0];
+	pcb2->pcb_toc = ((register_t *)fork_trampoline)[1];
+	#else
+	pcb2->pcb_lr = (register_t)fork_trampoline;
+	#endif
+	pcb2->pcb_cpu.aim.usr_vsid = 0;
+
+	/* Setup to release spin count in fork_exit(). */
+	td->td_md.md_spinlock_count = 1;
+	td->td_md.md_saved_msr = PSL_KERNSET;
+}
+
+void
+cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
+	stack_t *stack)
+{
+	struct trapframe *tf;
+	uintptr_t sp;
+
+	tf = td->td_frame;
+	/* align stack and alloc space for frame ptr and saved LR */
+	#ifdef __powerpc64__
+	sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 48) &
+	    ~0x1f;
+	#else
+	sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) &
+	    ~0x1f;
+	#endif
+	bzero(tf, sizeof(struct trapframe));
+
+	tf->fixreg[1] = (register_t)sp;
+	tf->fixreg[3] = (register_t)arg;
+	if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+		tf->srr0 = (register_t)entry;
+		tf->srr1 = PSL_USERSET | PSL_FE_DFLT;
+		#ifdef __powerpc64__
+		tf->srr1 &= ~PSL_SF;
+		#endif
+	} else {
+	    #ifdef __powerpc64__
+		register_t entry_desc[3];
+		(void)copyin((void *)entry, entry_desc, sizeof(entry_desc));
+		tf->srr0 = entry_desc[0];
+		tf->fixreg[2] = entry_desc[1];
+		tf->fixreg[11] = entry_desc[2];
+		tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT;
+	    #endif
+	}
+
+	#ifdef __powerpc64__
+	if (mfmsr() & PSL_HV)
+		tf->srr1 |= PSL_HV;
+	#endif
+	td->td_pcb->pcb_flags = 0;
+
+	td->td_retval[0] = (register_t)entry;
+	td->td_retval[1] = 0;
+}
+
+int
+ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb)
+{
+	uint32_t instr;
+	int reg, sig;
+
+	instr = fuword32((void *)frame->srr0);
+	sig = SIGILL;
+
+	if ((instr & 0xfc1fffff) == 0x7c1f42a6) {	/* mfpvr */
+		reg = (instr & ~0xfc1fffff) >> 21;
+		frame->fixreg[reg] = mfpvr();
+		frame->srr0 += 4;
+		return (0);
+	}
+
+	if ((instr & 0xfc000ffe) == 0x7c0004ac) {	/* various sync */
+		powerpc_sync(); /* Do a heavy-weight sync */
+		frame->srr0 += 4;
+		return (0);
+	}
+
+#ifdef FPU_EMU
+	if (!(pcb->pcb_flags & PCB_FPREGS)) {
+		bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu));
+		pcb->pcb_flags |= PCB_FPREGS;
+	}
+	sig = fpu_emulate(frame, (struct fpreg *)&pcb->pcb_fpu);
+#endif
+
+	return (sig);
+}
+


Property changes on: trunk/sys/powerpc/powerpc/exec_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/fpu.c
===================================================================
--- trunk/sys/powerpc/powerpc/fpu.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/fpu.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,153 @@
+/* $MidnightBSD$ */
+/*-
+ * 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.
+ *
+ *	$NetBSD: fpu.c,v 1.5 2001/07/22 11:29:46 wiz Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/fpu.c 266004 2014-05-14 04:42:38Z ian $");
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/limits.h>
+
+#include <machine/fpu.h>
+#include <machine/pcb.h>
+#include <machine/psl.h>
+
+void
+enable_fpu(struct thread *td)
+{
+	int	msr;
+	struct	pcb *pcb;
+	struct	trapframe *tf;
+
+	pcb = td->td_pcb;
+	tf = trapframe(td);
+
+	/*
+	 * Save the thread's FPU CPU number, and set the CPU's current
+	 * FPU thread
+	 */
+	td->td_pcb->pcb_fpcpu = PCPU_GET(cpuid);
+	PCPU_SET(fputhread, td);
+
+	/*
+	 * Enable the FPU for when the thread returns from the exception.
+	 * If this is the first time the FPU has been used by the thread,
+	 * initialise the FPU registers and FPSCR to 0, and set the flag
+	 * to indicate that the FPU is in use.
+	 */
+	pcb->pcb_flags |= PCB_FPU;
+	tf->srr1 |= PSL_FP;
+	if (!(pcb->pcb_flags & PCB_FPREGS)) {
+		memset(&pcb->pcb_fpu, 0, sizeof pcb->pcb_fpu);
+		pcb->pcb_flags |= PCB_FPREGS;
+	}
+
+	/*
+	 * Temporarily enable floating-point so the registers
+	 * can be restored.
+	 */
+	msr = mfmsr();
+	mtmsr(msr | PSL_FP);
+	isync();
+
+	/*
+	 * Load the floating point registers and FPSCR from the PCB.
+	 * (A value of 0xff for mtfsf specifies that all 8 4-bit fields
+	 * of the saved FPSCR are to be loaded from the FPU reg).
+	 */
+	__asm __volatile ("lfd 0,0(%0); mtfsf 0xff,0"
+			  :: "b"(&pcb->pcb_fpu.fpscr));
+
+#define LFP(n)   __asm ("lfd " #n ", 0(%0)" \
+		:: "b"(&pcb->pcb_fpu.fpr[n]));
+	LFP(0);		LFP(1);		LFP(2);		LFP(3);
+	LFP(4);		LFP(5);		LFP(6);		LFP(7);
+	LFP(8);		LFP(9);		LFP(10);	LFP(11);
+	LFP(12);	LFP(13);	LFP(14);	LFP(15);
+	LFP(16);	LFP(17);	LFP(18);	LFP(19);
+	LFP(20);	LFP(21);	LFP(22);	LFP(23);
+	LFP(24);	LFP(25);	LFP(26);	LFP(27);
+	LFP(28);	LFP(29);	LFP(30);	LFP(31);
+#undef LFP
+
+	isync();
+	mtmsr(msr);
+}
+
+void
+save_fpu(struct thread *td)
+{
+	int	msr;
+	struct	pcb *pcb;
+
+	pcb = td->td_pcb;
+
+	/*
+	 * Temporarily re-enable floating-point during the save
+	 */
+	msr = mfmsr();
+	mtmsr(msr | PSL_FP);
+	isync();
+
+	/*
+	 * Save the floating-point registers and FPSCR to the PCB
+	 */
+#define SFP(n)   __asm ("stfd " #n ", 0(%0)" \
+		:: "b"(&pcb->pcb_fpu.fpr[n]));
+	SFP(0);		SFP(1);		SFP(2);		SFP(3);
+	SFP(4);		SFP(5);		SFP(6);		SFP(7);
+	SFP(8);		SFP(9);		SFP(10);	SFP(11);
+	SFP(12);	SFP(13);	SFP(14);	SFP(15);
+	SFP(16);	SFP(17);	SFP(18);	SFP(19);
+	SFP(20);	SFP(21);	SFP(22);	SFP(23);
+	SFP(24);	SFP(25);	SFP(26);	SFP(27);
+	SFP(28);	SFP(29);	SFP(30);	SFP(31);
+#undef SFP
+	__asm __volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr));
+
+	/*
+	 * Disable floating-point again
+	 */
+	isync();
+	mtmsr(msr);
+
+	/*
+	 * Clear the current fp thread and pcb's CPU id
+	 * XXX should this be left clear to allow lazy save/restore ?
+	 */
+	pcb->pcb_fpcpu = INT_MAX;
+	PCPU_SET(fputhread, NULL);
+}
+


Property changes on: trunk/sys/powerpc/powerpc/fpu.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/fuswintr.c
===================================================================
--- trunk/sys/powerpc/powerpc/fuswintr.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/fuswintr.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,52 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 1994 Wolfgang Solfrank.
+ * Copyright (C) 1994 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.
+ *
+ * $NetBSD: fuswintr.c,v 1.2 2000/06/08 07:29:54 kleink Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/fuswintr.c 113038 2003-04-03 21:36:33Z obrien $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/resourcevar.h>
+
+/*
+ * Emulate fuswintr
+ *
+ * Simply return fault for all cases
+ */
+int
+fuswintr(void *addr)
+{
+
+	return -1;
+}


Property changes on: trunk/sys/powerpc/powerpc/fuswintr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/gdb_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/gdb_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/gdb_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,100 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2006 Marcel Moolenaar
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/gdb_machdep.c 236141 2012-05-27 10:25:20Z raj $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/signal.h>
+
+#include <machine/gdb_machdep.h>
+#include <machine/pcb.h>
+#include <machine/reg.h>
+
+#include <machine/hid.h>
+#include <machine/spr.h>
+
+#include <machine/trap.h>
+
+#include <gdb/gdb.h>
+#include <gdb/gdb_int.h>
+
+void *
+gdb_cpu_getreg(int regnum, size_t *regsz)
+{
+
+	*regsz = gdb_cpu_regsz(regnum);
+
+	if (kdb_thread == curthread) {
+		if (regnum == 0 || (regnum >= 2 && regnum <= 31))
+			return (kdb_frame->fixreg + regnum);
+		if (regnum == 64)
+			return (&kdb_frame->srr0);
+		if (regnum == 67)
+			return (&kdb_frame->lr);
+	}
+
+	if (regnum == 1)
+		return (&kdb_thrctx->pcb_sp);
+	if (regnum >= 14 && regnum <= 31)
+		return (kdb_thrctx->pcb_context + (regnum - 14));
+	if (regnum == 64)
+		return (&kdb_thrctx->pcb_lr);
+
+	return (NULL);
+}
+
+void
+gdb_cpu_setreg(int regnum, void *val)
+{
+
+	switch (regnum) {
+	case GDB_REG_PC:
+		break;
+	}
+}
+
+int
+gdb_cpu_signal(int vector, int dummy __unused)
+{
+#if defined(BOOKE)
+	if (vector == EXC_DEBUG || vector == EXC_PGM)
+		return (SIGTRAP);
+#else
+	if (vector == EXC_TRC || vector == EXC_RUNMODETRC)
+		return (SIGTRAP);
+#endif
+
+	if (vector <= 255)
+		return (vector);
+	else
+		return (SIGEMT);
+}


Property changes on: trunk/sys/powerpc/powerpc/gdb_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/genassym.c
===================================================================
--- trunk/sys/powerpc/powerpc/genassym.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/genassym.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,260 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ * 4. 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.
+ *
+ *	from: @(#)genassym.c	5.11 (Berkeley) 5/10/91
+ * $FreeBSD: stable/10/sys/powerpc/powerpc/genassym.c 266003 2014-05-14 04:14:58Z ian $
+ */
+
+#include <sys/param.h>
+#include <sys/assym.h>
+#include <sys/errno.h>
+#include <sys/ktr.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+#include <sys/signal.h>
+#include <sys/smp.h>
+#include <sys/systm.h>
+#include <sys/ucontext.h>
+#include <sys/ucontext.h>
+#include <sys/vmmeter.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+
+#include <machine/pcb.h>
+#include <machine/pmap.h>
+#include <machine/psl.h>
+#include <machine/sigframe.h>
+
+ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
+ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb));
+ASSYM(PC_CURPMAP, offsetof(struct pcpu, pc_curpmap));
+ASSYM(PC_TEMPSAVE, offsetof(struct pcpu, pc_tempsave));
+ASSYM(PC_DISISAVE, offsetof(struct pcpu, pc_disisave));
+ASSYM(PC_DBSAVE, offsetof(struct pcpu, pc_dbsave));
+ASSYM(PC_RESTORE, offsetof(struct pcpu, pc_restore));
+
+#if defined(BOOKE)
+ASSYM(PC_BOOKE_CRITSAVE, offsetof(struct pcpu, pc_booke_critsave));
+ASSYM(PC_BOOKE_MCHKSAVE, offsetof(struct pcpu, pc_booke_mchksave));
+ASSYM(PC_BOOKE_TLBSAVE, offsetof(struct pcpu, pc_booke_tlbsave));
+ASSYM(PC_BOOKE_TLB_LEVEL, offsetof(struct pcpu, pc_booke_tlb_level));
+ASSYM(PC_BOOKE_TLB_LOCK, offsetof(struct pcpu, pc_booke_tlb_lock));
+#endif
+
+ASSYM(CPUSAVE_R27, CPUSAVE_R27*sizeof(register_t));
+ASSYM(CPUSAVE_R28, CPUSAVE_R28*sizeof(register_t));
+ASSYM(CPUSAVE_R29, CPUSAVE_R29*sizeof(register_t));
+ASSYM(CPUSAVE_R30, CPUSAVE_R30*sizeof(register_t));
+ASSYM(CPUSAVE_R31, CPUSAVE_R31*sizeof(register_t));
+ASSYM(CPUSAVE_SRR0, CPUSAVE_SRR0*sizeof(register_t));
+ASSYM(CPUSAVE_SRR1, CPUSAVE_SRR1*sizeof(register_t));
+ASSYM(CPUSAVE_AIM_DAR, CPUSAVE_AIM_DAR*sizeof(register_t));
+ASSYM(CPUSAVE_AIM_DSISR, CPUSAVE_AIM_DSISR*sizeof(register_t));
+ASSYM(CPUSAVE_BOOKE_DEAR, CPUSAVE_BOOKE_DEAR*sizeof(register_t));
+ASSYM(CPUSAVE_BOOKE_ESR, CPUSAVE_BOOKE_ESR*sizeof(register_t));
+
+ASSYM(TLBSAVE_BOOKE_LR, TLBSAVE_BOOKE_LR*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_CR, TLBSAVE_BOOKE_CR*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_SRR0, TLBSAVE_BOOKE_SRR0*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_SRR1, TLBSAVE_BOOKE_SRR1*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_R20, TLBSAVE_BOOKE_R20*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_R21, TLBSAVE_BOOKE_R21*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_R22, TLBSAVE_BOOKE_R22*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_R23, TLBSAVE_BOOKE_R23*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_R24, TLBSAVE_BOOKE_R24*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_R25, TLBSAVE_BOOKE_R25*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_R26, TLBSAVE_BOOKE_R26*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_R27, TLBSAVE_BOOKE_R27*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_R28, TLBSAVE_BOOKE_R28*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_R29, TLBSAVE_BOOKE_R29*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_R30, TLBSAVE_BOOKE_R30*sizeof(register_t));
+ASSYM(TLBSAVE_BOOKE_R31, TLBSAVE_BOOKE_R31*sizeof(register_t));
+
+ASSYM(MTX_LOCK, offsetof(struct mtx, mtx_lock));
+
+#if defined(AIM)
+ASSYM(USER_ADDR, USER_ADDR);
+#ifdef __powerpc64__
+ASSYM(PC_KERNSLB, offsetof(struct pcpu, pc_slb));
+ASSYM(PC_USERSLB, offsetof(struct pcpu, pc_userslb));
+ASSYM(PC_SLBSAVE, offsetof(struct pcpu, pc_slbsave));
+ASSYM(PC_SLBSTACK, offsetof(struct pcpu, pc_slbstack));
+ASSYM(USER_SLB_SLOT, USER_SLB_SLOT);
+ASSYM(USER_SLB_SLBE, USER_SLB_SLBE);
+ASSYM(SEGMENT_MASK, SEGMENT_MASK);
+#else
+ASSYM(PM_SR, offsetof(struct pmap, pm_sr));
+ASSYM(USER_SR, USER_SR);
+#endif
+#elif defined(BOOKE)
+ASSYM(PM_PDIR, offsetof(struct pmap, pm_pdir));
+ASSYM(PTE_RPN, offsetof(struct pte, rpn));
+ASSYM(PTE_FLAGS, offsetof(struct pte, flags));
+#if defined(BOOKE_E500)
+ASSYM(TLB0_ENTRY_SIZE, sizeof(struct tlb_entry));
+#endif
+#endif
+
+#ifdef __powerpc64__
+ASSYM(FSP, 48);
+#else
+ASSYM(FSP, 8);
+#endif
+ASSYM(FRAMELEN, FRAMELEN);
+ASSYM(FRAME_0, offsetof(struct trapframe, fixreg[0]));
+ASSYM(FRAME_1, offsetof(struct trapframe, fixreg[1]));
+ASSYM(FRAME_2, offsetof(struct trapframe, fixreg[2]));
+ASSYM(FRAME_3, offsetof(struct trapframe, fixreg[3]));
+ASSYM(FRAME_4, offsetof(struct trapframe, fixreg[4]));
+ASSYM(FRAME_5, offsetof(struct trapframe, fixreg[5]));
+ASSYM(FRAME_6, offsetof(struct trapframe, fixreg[6]));
+ASSYM(FRAME_7, offsetof(struct trapframe, fixreg[7]));
+ASSYM(FRAME_8, offsetof(struct trapframe, fixreg[8]));
+ASSYM(FRAME_9, offsetof(struct trapframe, fixreg[9]));
+ASSYM(FRAME_10, offsetof(struct trapframe, fixreg[10]));
+ASSYM(FRAME_11, offsetof(struct trapframe, fixreg[11]));
+ASSYM(FRAME_12, offsetof(struct trapframe, fixreg[12]));
+ASSYM(FRAME_13, offsetof(struct trapframe, fixreg[13]));
+ASSYM(FRAME_14, offsetof(struct trapframe, fixreg[14]));
+ASSYM(FRAME_15, offsetof(struct trapframe, fixreg[15]));
+ASSYM(FRAME_16, offsetof(struct trapframe, fixreg[16]));
+ASSYM(FRAME_17, offsetof(struct trapframe, fixreg[17]));
+ASSYM(FRAME_18, offsetof(struct trapframe, fixreg[18]));
+ASSYM(FRAME_19, offsetof(struct trapframe, fixreg[19]));
+ASSYM(FRAME_20, offsetof(struct trapframe, fixreg[20]));
+ASSYM(FRAME_21, offsetof(struct trapframe, fixreg[21]));
+ASSYM(FRAME_22, offsetof(struct trapframe, fixreg[22]));
+ASSYM(FRAME_23, offsetof(struct trapframe, fixreg[23]));
+ASSYM(FRAME_24, offsetof(struct trapframe, fixreg[24]));
+ASSYM(FRAME_25, offsetof(struct trapframe, fixreg[25]));
+ASSYM(FRAME_26, offsetof(struct trapframe, fixreg[26]));
+ASSYM(FRAME_27, offsetof(struct trapframe, fixreg[27]));
+ASSYM(FRAME_28, offsetof(struct trapframe, fixreg[28]));
+ASSYM(FRAME_29, offsetof(struct trapframe, fixreg[29]));
+ASSYM(FRAME_30, offsetof(struct trapframe, fixreg[30]));
+ASSYM(FRAME_31, offsetof(struct trapframe, fixreg[31]));
+ASSYM(FRAME_LR, offsetof(struct trapframe, lr));
+ASSYM(FRAME_CR, offsetof(struct trapframe, cr));
+ASSYM(FRAME_CTR, offsetof(struct trapframe, ctr));
+ASSYM(FRAME_XER, offsetof(struct trapframe, xer));
+ASSYM(FRAME_SRR0, offsetof(struct trapframe, srr0));
+ASSYM(FRAME_SRR1, offsetof(struct trapframe, srr1));
+ASSYM(FRAME_EXC, offsetof(struct trapframe, exc));
+ASSYM(FRAME_AIM_DAR, offsetof(struct trapframe, cpu.aim.dar));
+ASSYM(FRAME_AIM_DSISR, offsetof(struct trapframe, cpu.aim.dsisr));
+ASSYM(FRAME_BOOKE_DEAR, offsetof(struct trapframe, cpu.booke.dear));
+ASSYM(FRAME_BOOKE_ESR, offsetof(struct trapframe, cpu.booke.esr));
+ASSYM(FRAME_BOOKE_DBCR0, offsetof(struct trapframe, cpu.booke.dbcr0));
+
+ASSYM(CF_FUNC, offsetof(struct callframe, cf_func));
+ASSYM(CF_ARG0, offsetof(struct callframe, cf_arg0));
+ASSYM(CF_ARG1, offsetof(struct callframe, cf_arg1));
+ASSYM(CF_SIZE, sizeof(struct callframe));
+
+ASSYM(PCB_CONTEXT, offsetof(struct pcb, pcb_context));
+ASSYM(PCB_CR, offsetof(struct pcb, pcb_cr));
+ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp));
+ASSYM(PCB_TOC, offsetof(struct pcb, pcb_toc));
+ASSYM(PCB_LR, offsetof(struct pcb, pcb_lr));
+ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
+ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
+ASSYM(PCB_FPU, PCB_FPU);
+ASSYM(PCB_VEC, PCB_VEC);
+
+ASSYM(PCB_AIM_USR_VSID, offsetof(struct pcb, pcb_cpu.aim.usr_vsid));
+ASSYM(PCB_BOOKE_DBCR0, offsetof(struct pcb, pcb_cpu.booke.dbcr0));
+
+ASSYM(TD_LOCK, offsetof(struct thread, td_lock));
+ASSYM(TD_PROC, offsetof(struct thread, td_proc));
+ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
+
+ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace));
+
+ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap));
+
+ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
+
+ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
+ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
+
+ASSYM(SF_UC, offsetof(struct sigframe, sf_uc));
+
+ASSYM(KERNBASE, KERNBASE);
+ASSYM(MAXCOMLEN, MAXCOMLEN);
+
+ASSYM(PSL_DE, PSL_DE);
+ASSYM(PSL_DS, PSL_DS);
+ASSYM(PSL_IS, PSL_IS);
+ASSYM(PSL_CE, PSL_CE);
+ASSYM(PSL_UCLE, PSL_UCLE);
+ASSYM(PSL_WE, PSL_WE);
+ASSYM(PSL_UBLE, PSL_UBLE);
+
+#if defined(BOOKE_E500)
+ASSYM(PSL_KERNSET_INIT, PSL_KERNSET_INIT);
+#endif
+
+#if defined(AIM) && defined(__powerpc64__)
+ASSYM(PSL_SF, PSL_SF);
+ASSYM(PSL_HV, PSL_HV);
+#endif
+
+ASSYM(PSL_POW, PSL_POW);
+ASSYM(PSL_ILE, PSL_ILE);
+ASSYM(PSL_LE, PSL_LE);
+ASSYM(PSL_SE, PSL_SE);
+ASSYM(PSL_RI, PSL_RI);
+ASSYM(PSL_DR, PSL_DR);
+ASSYM(PSL_IP, PSL_IP);
+ASSYM(PSL_IR, PSL_IR);
+
+ASSYM(PSL_FE_DIS, PSL_FE_DIS);
+ASSYM(PSL_FE_NONREC, PSL_FE_NONREC);
+ASSYM(PSL_FE_PREC, PSL_FE_PREC);
+ASSYM(PSL_FE_REC, PSL_FE_REC);
+
+ASSYM(PSL_VEC, PSL_VEC);
+ASSYM(PSL_BE, PSL_BE);
+ASSYM(PSL_EE, PSL_EE);
+ASSYM(PSL_FE0, PSL_FE0);
+ASSYM(PSL_FE1, PSL_FE1);
+ASSYM(PSL_FP, PSL_FP);
+ASSYM(PSL_ME, PSL_ME);
+ASSYM(PSL_PR, PSL_PR);
+ASSYM(PSL_PMM, PSL_PMM);
+ASSYM(PSL_KERNSET, PSL_KERNSET);
+ASSYM(PSL_USERSET, PSL_USERSET);
+ASSYM(PSL_USERSTATIC, PSL_USERSTATIC);
+


Property changes on: trunk/sys/powerpc/powerpc/genassym.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/in_cksum.c
===================================================================
--- trunk/sys/powerpc/powerpc/in_cksum.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/in_cksum.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,251 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/powerpc/in_cksum.c 209975 2010-07-13 05:32:19Z nwhitehorn $ */
+/* $NetBSD: in_cksum.c,v 1.7 1997/09/02 13:18:15 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1988, 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1996
+ *	Matt Thomas <matt at 3am-software.com>
+ *
+ * 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 University of
+ *	California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ *	@(#)in_cksum.c	8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/systm.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <machine/in_cksum.h>
+
+/*
+ * Checksum routine for Internet Protocol family headers
+ *    (Portable Alpha version).
+ *
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ */
+
+#define ADDCARRY(x)  (x > 65535 ? x -= 65535 : x)
+#define REDUCE32							  \
+    {									  \
+	q_util.q = sum;							  \
+	sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3];	  \
+    }
+#define REDUCE16							  \
+    {									  \
+	q_util.q = sum;							  \
+	l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
+	sum = l_util.s[0] + l_util.s[1];				  \
+	ADDCARRY(sum);							  \
+    }
+
+static const u_int32_t in_masks[] = {
+#if 0
+	/*0 bytes*/ /*1 byte*/	/*2 bytes*/ /*3 bytes*/
+	0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF,	/* offset 0 */
+	0x00000000, 0x0000FF00, 0x00FFFF00, 0xFFFFFF00,	/* offset 1 */
+	0x00000000, 0x00FF0000, 0xFFFF0000, 0xFFFF0000,	/* offset 2 */
+	0x00000000, 0xFF000000, 0xFF000000, 0xFF000000,	/* offset 3 */
+#else
+	/*0 bytes*/ /*1 byte*/	/*2 bytes*/ /*3 bytes*/
+	0x00000000, 0xFF000000, 0xFFFF0000, 0xFFFFFF00,	/* offset 0 */
+	0x00000000, 0x00FF0000, 0x00FFFF00, 0x00FFFFFF,	/* offset 1 */
+	0x00000000, 0x0000FF00, 0x0000FFFF, 0x0000FFFF,	/* offset 2 */
+	0x00000000, 0x000000FF, 0x000000FF, 0x000000FF,	/* offset 3 */
+#endif
+};
+
+union l_util {
+	u_int16_t s[2];
+	u_int32_t l;
+};
+union q_util {
+	u_int16_t s[4];
+	u_int32_t l[2];
+	u_int64_t q;
+};
+
+static u_int64_t
+in_cksumdata(const void *buf, int len)
+{
+	const u_int32_t *lw = (const u_int32_t *) buf;
+	u_int64_t sum = 0;
+	u_int64_t prefilled;
+	int offset;
+	union q_util q_util;
+
+	if ((3 & (long) lw) == 0 && len == 20) {
+	     sum = (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4];
+	     REDUCE32;
+	     return sum;
+	}
+
+	if ((offset = 3 & (long) lw) != 0) {
+		const u_int32_t *masks = in_masks + (offset << 2);
+		lw = (u_int32_t *) (((long) lw) - offset);
+		sum = *lw++ & masks[len >= 3 ? 3 : len];
+		len -= 4 - offset;
+		if (len <= 0) {
+			REDUCE32;
+			return sum;
+		}
+	}
+#if 0
+	/*
+	 * Force to cache line boundary.
+	 */
+	offset = 32 - (0x1f & (long) lw);
+	if (offset < 32 && len > offset) {
+		len -= offset;
+		if (4 & offset) {
+			sum += (u_int64_t) lw[0];
+			lw += 1;
+		}
+		if (8 & offset) {
+			sum += (u_int64_t) lw[0] + lw[1];
+			lw += 2;
+		}
+		if (16 & offset) {
+			sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3];
+			lw += 4;
+		}
+	}
+#endif
+	/*
+	 * access prefilling to start load of next cache line.
+	 * then add current cache line
+	 * save result of prefilling for loop iteration.
+	 */
+	prefilled = lw[0];
+	while ((len -= 32) >= 4) {
+		u_int64_t prefilling = lw[8];
+		sum += prefilled + lw[1] + lw[2] + lw[3]
+			+ lw[4] + lw[5] + lw[6] + lw[7];
+		lw += 8;
+		prefilled = prefilling;
+	}
+	if (len >= 0) {
+		sum += prefilled + lw[1] + lw[2] + lw[3]
+			+ lw[4] + lw[5] + lw[6] + lw[7];
+		lw += 8;
+	} else {
+		len += 32;
+	}
+	while ((len -= 16) >= 0) {
+		sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3];
+		lw += 4;
+	}
+	len += 16;
+	while ((len -= 4) >= 0) {
+		sum += (u_int64_t) *lw++;
+	}
+	len += 4;
+	if (len > 0)
+		sum += (u_int64_t) (in_masks[len] & *lw);
+	REDUCE32;
+	return sum;
+}
+
+u_short
+in_addword(u_short a, u_short b)
+{
+	u_int64_t sum = a + b;
+
+	ADDCARRY(sum);
+	return (sum);
+}
+
+u_short
+in_pseudo(u_int32_t a, u_int32_t b, u_int32_t c)
+{
+	u_int64_t sum;
+	union q_util q_util;
+	union l_util l_util;
+		    
+	sum = (u_int64_t) a + b + c;
+	REDUCE16;
+	return (sum);
+}
+
+u_short
+in_cksum_skip(struct mbuf *m, int len, int skip)
+{
+	u_int64_t sum = 0;
+	int mlen = 0;
+	int clen = 0;
+	caddr_t addr;
+	union q_util q_util;
+	union l_util l_util;
+
+        len -= skip;
+        for (; skip && m; m = m->m_next) {
+                if (m->m_len > skip) {
+                        mlen = m->m_len - skip;
+			addr = mtod(m, caddr_t) + skip;
+                        goto skip_start;
+                } else {
+                        skip -= m->m_len;
+                }
+        }
+
+	for (; m && len; m = m->m_next) {
+		if (m->m_len == 0)
+			continue;
+		mlen = m->m_len;
+		addr = mtod(m, caddr_t);
+skip_start:
+		if (len < mlen)
+			mlen = len;
+
+		if ((clen ^ (long) addr) & 1)
+		    sum += in_cksumdata(addr, mlen) << 8;
+		else
+		    sum += in_cksumdata(addr, mlen);
+
+		clen += mlen;
+		len -= mlen;
+	}
+	REDUCE16;
+	return (~sum & 0xffff);
+}
+
+u_int in_cksum_hdr(const struct ip *ip)
+{
+    u_int64_t sum = in_cksumdata(ip, sizeof(struct ip));
+    union q_util q_util;
+    union l_util l_util;
+    REDUCE16;
+    return (~sum & 0xffff);
+}


Property changes on: trunk/sys/powerpc/powerpc/in_cksum.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/intr_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/intr_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/intr_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,607 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ * 4. 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.
+ */
+/*-
+ * Copyright (c) 2002 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ *	from: @(#)isa.c	7.2 (Berkeley) 5/13/91
+ *	form: src/sys/i386/isa/intr_machdep.c,v 1.57 2001/07/20
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powerpc/intr_machdep.c 266676 2014-05-26 01:37:43Z nwhitehorn $
+ */
+
+#include "opt_isa.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/bus.h>
+#include <sys/cpuset.h>
+#include <sys/interrupt.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/smp.h>
+#include <sys/syslog.h>
+#include <sys/vmmeter.h>
+#include <sys/proc.h>
+
+#include <machine/frame.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/smp.h>
+#include <machine/trap.h>
+
+#include "pic_if.h"
+
+#define	MAX_STRAY_LOG	5
+
+static MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data");
+
+struct powerpc_intr {
+	struct intr_event *event;
+	long	*cntp;
+	u_int	irq;
+	device_t pic;
+	u_int	intline;
+	u_int	vector;
+	u_int	cntindex;
+	cpuset_t cpu;
+	enum intr_trigger trig;
+	enum intr_polarity pol;
+	int	fwcode;
+	int	ipi;
+};
+
+struct pic {
+	device_t dev;
+	uint32_t node;
+	u_int	irqs;
+	u_int	ipis;
+	int	base;
+};
+
+static u_int intrcnt_index = 0;
+static struct mtx intr_table_lock;
+static struct powerpc_intr *powerpc_intrs[INTR_VECTORS];
+static struct pic piclist[MAX_PICS];
+static u_int nvectors;		/* Allocated vectors */
+static u_int npics;		/* PICs registered */
+#ifdef DEV_ISA
+static u_int nirqs = 16;	/* Allocated IRQS (ISA pre-allocated). */
+#else
+static u_int nirqs = 0;		/* Allocated IRQs. */
+#endif
+static u_int stray_count;
+
+device_t root_pic;
+
+#ifdef SMP
+static void *ipi_cookie;
+#endif
+
+static void
+intr_init(void *dummy __unused)
+{
+
+	mtx_init(&intr_table_lock, "intr sources lock", NULL, MTX_DEF);
+}
+SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL);
+
+#ifdef SMP
+static void
+smp_intr_init(void *dummy __unused)
+{
+	struct powerpc_intr *i;
+	int vector;
+
+	for (vector = 0; vector < nvectors; vector++) {
+		i = powerpc_intrs[vector];
+		if (i != NULL && i->pic == root_pic)
+			PIC_BIND(i->pic, i->intline, i->cpu);
+	}
+}
+SYSINIT(smp_intr_init, SI_SUB_SMP, SI_ORDER_ANY, smp_intr_init, NULL);
+#endif
+
+static void
+intrcnt_setname(const char *name, int index)
+{
+
+	snprintf(intrnames + (MAXCOMLEN + 1) * index, MAXCOMLEN + 1, "%-*s",
+	    MAXCOMLEN, name);
+}
+
+void
+intrcnt_add(const char *name, u_long **countp)
+{
+	int idx;
+
+	idx = atomic_fetchadd_int(&intrcnt_index, 1);
+	*countp = &intrcnt[idx];
+	intrcnt_setname(name, idx);
+}
+
+static struct powerpc_intr *
+intr_lookup(u_int irq)
+{
+	char intrname[16];
+	struct powerpc_intr *i, *iscan;
+	int vector;
+
+	mtx_lock(&intr_table_lock);
+	for (vector = 0; vector < nvectors; vector++) {
+		i = powerpc_intrs[vector];
+		if (i != NULL && i->irq == irq) {
+			mtx_unlock(&intr_table_lock);
+			return (i);
+		}
+	}
+
+	i = malloc(sizeof(*i), M_INTR, M_NOWAIT);
+	if (i == NULL) {
+		mtx_unlock(&intr_table_lock);
+		return (NULL);
+	}
+
+	i->event = NULL;
+	i->cntp = NULL;
+	i->trig = INTR_TRIGGER_CONFORM;
+	i->pol = INTR_POLARITY_CONFORM;
+	i->irq = irq;
+	i->pic = NULL;
+	i->vector = -1;
+	i->fwcode = 0;
+	i->ipi = 0;
+
+#ifdef SMP
+	i->cpu = all_cpus;
+#else
+	CPU_SETOF(0, &i->cpu);
+#endif
+
+	for (vector = 0; vector < INTR_VECTORS && vector <= nvectors;
+	    vector++) {
+		iscan = powerpc_intrs[vector];
+		if (iscan != NULL && iscan->irq == irq)
+			break;
+		if (iscan == NULL && i->vector == -1)
+			i->vector = vector;
+		iscan = NULL;
+	}
+
+	if (iscan == NULL && i->vector != -1) {
+		powerpc_intrs[i->vector] = i;
+		i->cntindex = atomic_fetchadd_int(&intrcnt_index, 1);
+		i->cntp = &intrcnt[i->cntindex];
+		sprintf(intrname, "irq%u:", i->irq);
+		intrcnt_setname(intrname, i->cntindex);
+		nvectors++;
+	}
+	mtx_unlock(&intr_table_lock);
+
+	if (iscan != NULL || i->vector == -1) {
+		free(i, M_INTR);
+		i = iscan;
+	}
+
+	return (i);
+}
+
+static int
+powerpc_map_irq(struct powerpc_intr *i)
+{
+	struct pic *p;
+	u_int cnt;
+	int idx;
+
+	for (idx = 0; idx < npics; idx++) {
+		p = &piclist[idx];
+		cnt = p->irqs + p->ipis;
+		if (i->irq >= p->base && i->irq < p->base + cnt)
+			break;
+	}
+	if (idx == npics)
+		return (EINVAL);
+
+	i->intline = i->irq - p->base;
+	i->pic = p->dev;
+
+	/* Try a best guess if that failed */
+	if (i->pic == NULL)
+		i->pic = root_pic;
+
+	return (0);
+}
+
+static void
+powerpc_intr_eoi(void *arg)
+{
+	struct powerpc_intr *i = arg;
+
+	PIC_EOI(i->pic, i->intline);
+}
+
+static void
+powerpc_intr_pre_ithread(void *arg)
+{
+	struct powerpc_intr *i = arg;
+
+	PIC_MASK(i->pic, i->intline);
+	PIC_EOI(i->pic, i->intline);
+}
+
+static void
+powerpc_intr_post_ithread(void *arg)
+{
+	struct powerpc_intr *i = arg;
+
+	PIC_UNMASK(i->pic, i->intline);
+}
+
+static int
+powerpc_assign_intr_cpu(void *arg, u_char cpu)
+{
+#ifdef SMP
+	struct powerpc_intr *i = arg;
+
+	if (cpu == NOCPU)
+		i->cpu = all_cpus;
+	else
+		CPU_SETOF(cpu, &i->cpu);
+
+	if (!cold && i->pic != NULL && i->pic == root_pic)
+		PIC_BIND(i->pic, i->intline, i->cpu);
+
+	return (0);
+#else
+	return (EOPNOTSUPP);
+#endif
+}
+
+void
+powerpc_register_pic(device_t dev, uint32_t node, u_int irqs, u_int ipis,
+    u_int atpic)
+{
+	struct pic *p;
+	u_int irq;
+	int idx;
+
+	mtx_lock(&intr_table_lock);
+
+	/* XXX see powerpc_get_irq(). */
+	for (idx = 0; idx < npics; idx++) {
+		p = &piclist[idx];
+		if (p->node != node)
+			continue;
+		if (node != 0 || p->dev == dev)
+			break;
+	}
+	p = &piclist[idx];
+
+	p->dev = dev;
+	p->node = node;
+	p->irqs = irqs;
+	p->ipis = ipis;
+	if (idx == npics) {
+#ifdef DEV_ISA
+		p->base = (atpic) ? 0 : nirqs;
+#else
+		p->base = nirqs;
+#endif
+		irq = p->base + irqs + ipis;
+		nirqs = MAX(nirqs, irq);
+		npics++;
+	}
+
+	mtx_unlock(&intr_table_lock);
+}
+
+u_int
+powerpc_get_irq(uint32_t node, u_int pin)
+{
+	int idx;
+
+	if (node == 0)
+		return (pin);
+
+	mtx_lock(&intr_table_lock);
+	for (idx = 0; idx < npics; idx++) {
+		if (piclist[idx].node == node) {
+			mtx_unlock(&intr_table_lock);
+			return (piclist[idx].base + pin);
+		}
+	}
+
+	/*
+	 * XXX we should never encounter an unregistered PIC, but that
+	 * can only be done when we properly support bus enumeration
+	 * using multiple passes. Until then, fake an entry and give it
+	 * some adhoc maximum number of IRQs and IPIs.
+	 */
+	piclist[idx].dev = NULL;
+	piclist[idx].node = node;
+	piclist[idx].irqs = 124;
+	piclist[idx].ipis = 4;
+	piclist[idx].base = nirqs;
+	nirqs += 128;
+	npics++;
+
+	mtx_unlock(&intr_table_lock);
+
+	return (piclist[idx].base + pin);
+}
+
+int
+powerpc_enable_intr(void)
+{
+	struct powerpc_intr *i;
+	int error, vector;
+#ifdef SMP
+	int n;
+#endif
+
+	if (npics == 0)
+		panic("no PIC detected\n");
+
+	if (root_pic == NULL)
+		root_pic = piclist[0].dev;
+
+#ifdef SMP
+	/* Install an IPI handler. */
+	if (mp_ncpus > 1) {
+		for (n = 0; n < npics; n++) {
+			if (piclist[n].dev != root_pic)
+				continue;
+
+			KASSERT(piclist[n].ipis != 0,
+			    ("%s: SMP root PIC does not supply any IPIs",
+			    __func__));
+			error = powerpc_setup_intr("IPI",
+			    MAP_IRQ(piclist[n].node, piclist[n].irqs),
+			    powerpc_ipi_handler, NULL, NULL,
+			    INTR_TYPE_MISC | INTR_EXCL, &ipi_cookie);
+			if (error) {
+				printf("unable to setup IPI handler\n");
+				return (error);
+			}
+
+			/*
+			 * Some subterfuge: disable late EOI and mark this
+			 * as an IPI to the dispatch layer.
+			 */
+			i = intr_lookup(MAP_IRQ(piclist[n].node,
+			    piclist[n].irqs));
+			i->event->ie_post_filter = NULL;
+			i->ipi = 1;
+		}
+	}
+#endif
+
+	for (vector = 0; vector < nvectors; vector++) {
+		i = powerpc_intrs[vector];
+		if (i == NULL)
+			continue;
+
+		error = powerpc_map_irq(i);
+		if (error)
+			continue;
+
+		if (i->trig == -1)
+			PIC_TRANSLATE_CODE(i->pic, i->intline, i->fwcode,
+			    &i->trig, &i->pol);
+		if (i->trig != INTR_TRIGGER_CONFORM ||
+		    i->pol != INTR_POLARITY_CONFORM)
+			PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
+
+		if (i->event != NULL)
+			PIC_ENABLE(i->pic, i->intline, vector);
+	}
+
+	return (0);
+}
+
+int
+powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter,
+    driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep)
+{
+	struct powerpc_intr *i;
+	int error, enable = 0;
+
+	i = intr_lookup(irq);
+	if (i == NULL)
+		return (ENOMEM);
+
+	if (i->event == NULL) {
+		error = intr_event_create(&i->event, (void *)i, 0, irq,
+		    powerpc_intr_pre_ithread, powerpc_intr_post_ithread,
+		    powerpc_intr_eoi, powerpc_assign_intr_cpu, "irq%u:", irq);
+		if (error)
+			return (error);
+
+		enable = 1;
+	}
+
+	error = intr_event_add_handler(i->event, name, filter, handler, arg,
+	    intr_priority(flags), flags, cookiep);
+
+	mtx_lock(&intr_table_lock);
+	intrcnt_setname(i->event->ie_fullname, i->cntindex);
+	mtx_unlock(&intr_table_lock);
+
+	if (!cold) {
+		error = powerpc_map_irq(i);
+
+		if (!error) {
+			if (i->trig == -1)
+				PIC_TRANSLATE_CODE(i->pic, i->intline,
+				    i->fwcode, &i->trig, &i->pol);
+	
+			if (i->trig != INTR_TRIGGER_CONFORM ||
+			    i->pol != INTR_POLARITY_CONFORM)
+				PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
+
+			if (i->pic == root_pic)
+				PIC_BIND(i->pic, i->intline, i->cpu);
+
+			if (enable)
+				PIC_ENABLE(i->pic, i->intline, i->vector);
+		}
+	}
+	return (error);
+}
+
+int
+powerpc_teardown_intr(void *cookie)
+{
+
+	return (intr_event_remove_handler(cookie));
+}
+
+#ifdef SMP
+int
+powerpc_bind_intr(u_int irq, u_char cpu)
+{
+	struct powerpc_intr *i;
+
+	i = intr_lookup(irq);
+	if (i == NULL)
+		return (ENOMEM);
+
+	return (intr_event_bind(i->event, cpu));
+}
+#endif
+
+int
+powerpc_fw_config_intr(int irq, int sense_code)
+{
+	struct powerpc_intr *i;
+
+	i = intr_lookup(irq);
+	if (i == NULL)
+		return (ENOMEM);
+
+	i->trig = -1;
+	i->pol = INTR_POLARITY_CONFORM;
+	i->fwcode = sense_code;
+
+	if (!cold && i->pic != NULL) {
+		PIC_TRANSLATE_CODE(i->pic, i->intline, i->fwcode, &i->trig,
+		    &i->pol);
+		PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
+	}
+
+	return (0);
+}
+
+int
+powerpc_config_intr(int irq, enum intr_trigger trig, enum intr_polarity pol)
+{
+	struct powerpc_intr *i;
+
+	i = intr_lookup(irq);
+	if (i == NULL)
+		return (ENOMEM);
+
+	i->trig = trig;
+	i->pol = pol;
+
+	if (!cold && i->pic != NULL)
+		PIC_CONFIG(i->pic, i->intline, trig, pol);
+
+	return (0);
+}
+
+void
+powerpc_dispatch_intr(u_int vector, struct trapframe *tf)
+{
+	struct powerpc_intr *i;
+	struct intr_event *ie;
+
+	i = powerpc_intrs[vector];
+	if (i == NULL)
+		goto stray;
+
+	(*i->cntp)++;
+
+	ie = i->event;
+	KASSERT(ie != NULL, ("%s: interrupt without an event", __func__));
+
+	/*
+	 * IPIs are magical and need to be EOI'ed before filtering.
+	 * This prevents races in IPI handling.
+	 */
+	if (i->ipi)
+		PIC_EOI(i->pic, i->intline);
+
+	if (intr_event_handle(ie, tf) != 0) {
+		goto stray;
+	}
+	return;
+
+stray:
+	stray_count++;
+	if (stray_count <= MAX_STRAY_LOG) {
+		printf("stray irq %d\n", i ? i->irq : -1);
+		if (stray_count >= MAX_STRAY_LOG) {
+			printf("got %d stray interrupts, not logging anymore\n",
+			    MAX_STRAY_LOG);
+		}
+	}
+	if (i != NULL)
+		PIC_MASK(i->pic, i->intline);
+}


Property changes on: trunk/sys/powerpc/powerpc/intr_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/iommu_if.m
===================================================================
--- trunk/sys/powerpc/powerpc/iommu_if.m	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/iommu_if.m	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,54 @@
+#-
+# Copyright (c) 2010 Nathan Whitehorn
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# from: src/sys/kern/bus_if.m,v 1.21 2002/04/21 11:16:10 markm Exp
+# $FreeBSD: stable/10/sys/powerpc/powerpc/iommu_if.m 232356 2012-03-01 19:58:34Z jhb $
+# $MidnightBSD$
+
+#include <machine/bus.h>
+
+#include <sys/bus.h>
+#include <sys/bus_dma.h>
+
+INTERFACE iommu;
+
+METHOD int map {
+	device_t	iommu;
+	bus_dma_segment_t *segs;
+	int		*nsegs;
+	bus_addr_t	lowaddr;
+	bus_addr_t	highaddr;
+	bus_size_t	alignment;
+	bus_addr_t	boundary;
+	void		*cookie;
+};
+
+METHOD int unmap {
+	device_t	iommu;
+	bus_dma_segment_t *segs;
+	int		nsegs;
+	void		*cookie;
+};
+


Property changes on: trunk/sys/powerpc/powerpc/iommu_if.m
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/mem.c
===================================================================
--- trunk/sys/powerpc/powerpc/mem.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/mem.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,321 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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, and code derived from software contributed to
+ * Berkeley by William Jolitz.
+ *
+ * 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.
+ * 4. 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.
+ *
+ *	from: Utah $Hdr: mem.c 1.13 89/10/08$
+ *	from: @(#)mem.c	7.2 (Berkeley) 5/9/91
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/mem.c 271113 2014-09-04 18:24:47Z nwhitehorn $");
+
+/*
+ * Memory special file
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/ioccom.h>
+#include <sys/malloc.h>
+#include <sys/memrange.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/msgbuf.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/uio.h>
+
+#include <machine/md_var.h>
+#include <machine/vmparam.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_page.h>
+
+#include <machine/memdev.h>
+
+static void ppc_mrinit(struct mem_range_softc *);
+static int ppc_mrset(struct mem_range_softc *, struct mem_range_desc *, int *);
+
+MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors");
+
+static struct mem_range_ops ppc_mem_range_ops = {
+	ppc_mrinit,
+	ppc_mrset,
+	NULL,
+	NULL
+};
+struct mem_range_softc mem_range_softc = {
+	&ppc_mem_range_ops,
+	0, 0, NULL
+}; 
+
+/* ARGSUSED */
+int
+memrw(struct cdev *dev, struct uio *uio, int flags)
+{
+	struct iovec *iov;
+	int error = 0;
+	vm_offset_t va, eva, off, v;
+	vm_prot_t prot;
+	struct vm_page m;
+	vm_page_t marr;
+	vm_size_t cnt;
+
+	cnt = 0;
+	error = 0;
+
+	GIANT_REQUIRED;
+
+	while (uio->uio_resid > 0 && !error) {
+		iov = uio->uio_iov;
+		if (iov->iov_len == 0) {
+			uio->uio_iov++;
+			uio->uio_iovcnt--;
+			if (uio->uio_iovcnt < 0)
+				panic("memrw");
+			continue;
+		}
+		if (dev2unit(dev) == CDEV_MINOR_MEM) {
+kmem_direct_mapped:	v = uio->uio_offset;
+
+			off = uio->uio_offset & PAGE_MASK;
+			cnt = PAGE_SIZE - ((vm_offset_t)iov->iov_base &
+			    PAGE_MASK);
+			cnt = min(cnt, PAGE_SIZE - off);
+			cnt = min(cnt, iov->iov_len);
+
+			if (mem_valid(v, cnt)) {
+				error = EFAULT;
+				break;
+			}
+	
+			if (!pmap_dev_direct_mapped(v, cnt)) {
+				error = uiomove((void *)v, cnt, uio);
+			} else {
+				m.phys_addr = trunc_page(v);
+				marr = &m;
+				error = uiomove_fromphys(&marr, off, cnt, uio);
+			}
+		}
+		else if (dev2unit(dev) == CDEV_MINOR_KMEM) {
+			va = uio->uio_offset;
+
+			if ((va < VM_MIN_KERNEL_ADDRESS) || (va > virtual_end))
+				goto kmem_direct_mapped;
+
+			va = trunc_page(uio->uio_offset);
+			eva = round_page(uio->uio_offset
+			    + iov->iov_len);
+
+			/* 
+			 * Make sure that all the pages are currently resident
+			 * so that we don't create any zero-fill pages.
+			 */
+
+			for (; va < eva; va += PAGE_SIZE)
+				if (pmap_extract(kernel_pmap, va) == 0)
+					return (EFAULT);
+
+			prot = (uio->uio_rw == UIO_READ)
+			    ? VM_PROT_READ : VM_PROT_WRITE;
+
+			va = uio->uio_offset;
+			if (kernacc((void *) va, iov->iov_len, prot)
+			    == FALSE)
+				return (EFAULT);
+
+			error = uiomove((void *)va, iov->iov_len, uio);
+
+			continue;
+		}
+	}
+
+	return (error);
+}
+
+/*
+ * allow user processes to MMAP some memory sections
+ * instead of going through read/write
+ */
+int
+memmmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
+    int prot, vm_memattr_t *memattr)
+{
+	int i;
+
+	if (dev2unit(dev) == CDEV_MINOR_MEM)
+		*paddr = offset;
+	else if (dev2unit(dev) == CDEV_MINOR_KMEM)
+		*paddr = vtophys(offset);
+	else
+		return (EFAULT);
+
+	for (i = 0; i < mem_range_softc.mr_ndesc; i++) {
+		if (!(mem_range_softc.mr_desc[i].mr_flags & MDF_ACTIVE))
+			continue;
+
+		if (offset >= mem_range_softc.mr_desc[i].mr_base &&
+		    offset < mem_range_softc.mr_desc[i].mr_base +
+		    mem_range_softc.mr_desc[i].mr_len) {
+			switch (mem_range_softc.mr_desc[i].mr_flags &
+			    MDF_ATTRMASK) {
+			case MDF_WRITEBACK:
+				*memattr = VM_MEMATTR_WRITE_BACK;
+				break;
+			case MDF_WRITECOMBINE:
+				*memattr = VM_MEMATTR_WRITE_COMBINING;
+				break;
+			case MDF_UNCACHEABLE:
+				*memattr = VM_MEMATTR_UNCACHEABLE;
+				break;
+			case MDF_WRITETHROUGH:
+				*memattr = VM_MEMATTR_WRITE_THROUGH;
+				break;
+			}
+
+			break;
+		}
+	}
+
+	return (0);
+}
+
+static void
+ppc_mrinit(struct mem_range_softc *sc)
+{
+	sc->mr_cap = 0;
+	sc->mr_ndesc = 8; /* XXX: Should be dynamically expandable */
+	sc->mr_desc = malloc(sc->mr_ndesc * sizeof(struct mem_range_desc),
+	    M_MEMDESC, M_WAITOK | M_ZERO);
+}
+
+static int
+ppc_mrset(struct mem_range_softc *sc, struct mem_range_desc *desc, int *arg)
+{
+	int i;
+
+	switch(*arg) {
+	case MEMRANGE_SET_UPDATE:
+		for (i = 0; i < sc->mr_ndesc; i++) {
+			if (!sc->mr_desc[i].mr_len) {
+				sc->mr_desc[i] = *desc;
+				sc->mr_desc[i].mr_flags |= MDF_ACTIVE;
+				return (0);
+			}
+			if (sc->mr_desc[i].mr_base == desc->mr_base &&
+			    sc->mr_desc[i].mr_len == desc->mr_len)
+				return (EEXIST);
+		}
+		return (ENOSPC);
+	case MEMRANGE_SET_REMOVE:
+		for (i = 0; i < sc->mr_ndesc; i++)
+			if (sc->mr_desc[i].mr_base == desc->mr_base &&
+			    sc->mr_desc[i].mr_len == desc->mr_len) {
+				bzero(&sc->mr_desc[i], sizeof(sc->mr_desc[i]));
+				return (0);
+			}
+		return (ENOENT);
+	default:
+		return (EOPNOTSUPP);
+	}
+
+	return (0);
+}
+
+/*
+ * Operations for changing memory attributes.
+ *
+ * This is basically just an ioctl shim for mem_range_attr_get
+ * and mem_range_attr_set.
+ */
+/* ARGSUSED */
+int 
+memioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, int flags,
+    struct thread *td)
+{
+	int nd, error = 0;
+	struct mem_range_op *mo = (struct mem_range_op *)data;
+	struct mem_range_desc *md;
+	
+	/* is this for us? */
+	if ((cmd != MEMRANGE_GET) &&
+	    (cmd != MEMRANGE_SET))
+		return (ENOTTY);
+
+	/* any chance we can handle this? */
+	if (mem_range_softc.mr_op == NULL)
+		return (EOPNOTSUPP);
+
+	/* do we have any descriptors? */
+	if (mem_range_softc.mr_ndesc == 0)
+		return (ENXIO);
+
+	switch (cmd) {
+	case MEMRANGE_GET:
+		nd = imin(mo->mo_arg[0], mem_range_softc.mr_ndesc);
+		if (nd > 0) {
+			md = (struct mem_range_desc *)
+				malloc(nd * sizeof(struct mem_range_desc),
+				       M_MEMDESC, M_WAITOK);
+			error = mem_range_attr_get(md, &nd);
+			if (!error)
+				error = copyout(md, mo->mo_desc, 
+					nd * sizeof(struct mem_range_desc));
+			free(md, M_MEMDESC);
+		}
+		else
+			nd = mem_range_softc.mr_ndesc;
+		mo->mo_arg[0] = nd;
+		break;
+		
+	case MEMRANGE_SET:
+		md = (struct mem_range_desc *)malloc(sizeof(struct mem_range_desc),
+						    M_MEMDESC, M_WAITOK);
+		error = copyin(mo->mo_desc, md, sizeof(struct mem_range_desc));
+		/* clamp description string */
+		md->mr_owner[sizeof(md->mr_owner) - 1] = 0;
+		if (error == 0)
+			error = mem_range_attr_set(md, &mo->mo_arg[0]);
+		free(md, M_MEMDESC);
+		break;
+	}
+	return (error);
+}
+


Property changes on: trunk/sys/powerpc/powerpc/mem.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/mmu_if.m
===================================================================
--- trunk/sys/powerpc/powerpc/mmu_if.m	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/mmu_if.m	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,950 @@
+#-
+# Copyright (c) 2005 Peter Grehan
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD: stable/10/sys/powerpc/powerpc/mmu_if.m 270920 2014-09-01 07:58:15Z kib $
+# $MidnightBSD$
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+#include <machine/mmuvar.h>
+
+/**
+ * @defgroup MMU mmu - KObj methods for PowerPC MMU implementations
+ * @brief A set of methods required by all MMU implementations. These
+ * are basically direct call-thru's from the pmap machine-dependent
+ * code.
+ * Thanks to Bruce M Simpson's pmap man pages for routine descriptions.
+ *@{
+ */
+
+INTERFACE mmu;
+
+#
+# Default implementations of some methods
+#
+CODE {
+	static void mmu_null_copy(mmu_t mmu, pmap_t dst_pmap, pmap_t src_pmap,
+	    vm_offset_t dst_addr, vm_size_t len, vm_offset_t src_addr)
+	{
+		return;
+	}
+
+	static void mmu_null_growkernel(mmu_t mmu, vm_offset_t addr)
+	{
+		return;
+	}
+
+	static void mmu_null_init(mmu_t mmu)
+	{
+		return;
+	}
+
+	static boolean_t mmu_null_is_prefaultable(mmu_t mmu, pmap_t pmap,
+	    vm_offset_t va)
+	{
+		return (FALSE);
+	}
+
+	static void mmu_null_object_init_pt(mmu_t mmu, pmap_t pmap,
+	    vm_offset_t addr, vm_object_t object, vm_pindex_t index,
+	    vm_size_t size)
+	{
+		return;
+	}
+
+	static void mmu_null_page_init(mmu_t mmu, vm_page_t m)
+	{
+		return;
+	}
+
+	static void mmu_null_remove_pages(mmu_t mmu, pmap_t pmap)
+	{
+		return;
+	}
+
+	static int mmu_null_mincore(mmu_t mmu, pmap_t pmap, vm_offset_t addr,
+	    vm_paddr_t *locked_pa)
+	{
+		return (0);
+	}
+
+	static void mmu_null_deactivate(struct thread *td)
+	{
+		return;
+	}
+
+	static void mmu_null_align_superpage(mmu_t mmu, vm_object_t object,
+	    vm_ooffset_t offset, vm_offset_t *addr, vm_size_t size)
+	{
+		return;
+	}
+
+	static struct pmap_md *mmu_null_scan_md(mmu_t mmu, struct pmap_md *p)
+	{
+		return (NULL);
+	}
+
+	static void *mmu_null_mapdev_attr(mmu_t mmu, vm_offset_t pa,
+	    vm_size_t size, vm_memattr_t ma)
+	{
+		return MMU_MAPDEV(mmu, pa, size);
+	}
+
+	static void mmu_null_kenter_attr(mmu_t mmu, vm_offset_t va,
+	    vm_offset_t pa, vm_memattr_t ma)
+	{
+		MMU_KENTER(mmu, va, pa);
+	}
+
+	static void mmu_null_page_set_memattr(mmu_t mmu, vm_page_t m,
+	    vm_memattr_t ma)
+	{
+		return;
+	}
+};
+
+
+/**
+ * @brief Apply the given advice to the specified range of addresses within
+ * the given pmap.  Depending on the advice, clear the referenced and/or
+ * modified flags in each mapping and set the mapped page's dirty field.
+ *
+ * @param _pmap		physical map
+ * @param _start	virtual range start
+ * @param _end		virtual range end
+ * @param _advice	advice to apply
+ */
+METHOD void advise {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_offset_t	_start;
+	vm_offset_t	_end;
+	int		_advice;
+};
+
+
+/**
+ * @brief Clear the 'modified' bit on the given physical page
+ *
+ * @param _pg		physical page
+ */
+METHOD void clear_modify {
+	mmu_t		_mmu;
+	vm_page_t	_pg;
+};
+
+
+/**
+ * @brief Clear the write and modified bits in each of the given
+ * physical page's mappings
+ *
+ * @param _pg		physical page
+ */
+METHOD void remove_write {
+	mmu_t		_mmu;
+	vm_page_t	_pg;
+};
+
+
+/**
+ * @brief Copy the address range given by the source physical map, virtual
+ * address and length to the destination physical map and virtual address.
+ * This routine is optional (xxx default null implementation ?)
+ *
+ * @param _dst_pmap	destination physical map
+ * @param _src_pmap	source physical map
+ * @param _dst_addr	destination virtual address
+ * @param _len		size of range
+ * @param _src_addr	source virtual address
+ */
+METHOD void copy {
+	mmu_t		_mmu;
+	pmap_t		_dst_pmap;
+	pmap_t		_src_pmap;
+	vm_offset_t	_dst_addr;
+	vm_size_t	_len;
+	vm_offset_t	_src_addr;
+} DEFAULT mmu_null_copy;
+
+
+/**
+ * @brief Copy the source physical page to the destination physical page
+ *
+ * @param _src		source physical page
+ * @param _dst		destination physical page
+ */
+METHOD void copy_page {
+	mmu_t		_mmu;
+	vm_page_t	_src;
+	vm_page_t	_dst;
+};
+
+METHOD void copy_pages {
+	mmu_t		_mmu;
+	vm_page_t	*_ma;
+	vm_offset_t	_a_offset;
+	vm_page_t	*_mb;
+	vm_offset_t	_b_offset;
+	int		_xfersize;
+};
+
+/**
+ * @brief Create a mapping between a virtual/physical address pair in the
+ * passed physical map with the specified protection and wiring
+ *
+ * @param _pmap		physical map
+ * @param _va		mapping virtual address
+ * @param _p		mapping physical page
+ * @param _prot		mapping page protection
+ * @param _flags	pmap_enter flags
+ * @param _psind	superpage size index
+ */
+METHOD int enter {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_offset_t	_va;
+	vm_page_t	_p;
+	vm_prot_t	_prot;
+	u_int		_flags;
+	int8_t		_psind;
+};
+
+
+/**
+ * @brief Maps a sequence of resident pages belonging to the same object.
+ *
+ * @param _pmap		physical map
+ * @param _start	virtual range start
+ * @param _end		virtual range end
+ * @param _m_start	physical page mapped at start
+ * @param _prot		mapping page protection
+ */
+METHOD void enter_object {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_offset_t	_start;
+	vm_offset_t	_end;
+	vm_page_t	_m_start;
+	vm_prot_t	_prot;
+};
+
+
+/**
+ * @brief A faster entry point for page mapping where it is possible
+ * to short-circuit some of the tests in pmap_enter.
+ *
+ * @param _pmap		physical map (and also currently active pmap)
+ * @param _va		mapping virtual address
+ * @param _pg		mapping physical page
+ * @param _prot		new page protection - used to see if page is exec.
+ */
+METHOD void enter_quick {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_offset_t	_va;
+	vm_page_t	_pg;
+	vm_prot_t	_prot;
+};
+
+
+/**
+ * @brief Reverse map the given virtual address, returning the physical
+ * page associated with the address if a mapping exists.
+ *
+ * @param _pmap		physical map
+ * @param _va		mapping virtual address
+ *
+ * @retval 0		No mapping found
+ * @retval addr		The mapping physical address
+ */
+METHOD vm_paddr_t extract {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_offset_t	_va;
+};
+
+
+/**
+ * @brief Reverse map the given virtual address, returning the
+ * physical page if found. The page must be held (by calling
+ * vm_page_hold) if the page protection matches the given protection
+ *
+ * @param _pmap		physical map
+ * @param _va		mapping virtual address
+ * @param _prot		protection used to determine if physical page
+ *			should be locked
+ *
+ * @retval NULL		No mapping found
+ * @retval page		Pointer to physical page. Held if protections match
+ */
+METHOD vm_page_t extract_and_hold {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_offset_t	_va;
+	vm_prot_t	_prot;
+};
+
+
+/**
+ * @brief Increase kernel virtual address space to the given virtual address.
+ * Not really required for PowerPC, so optional unless the MMU implementation
+ * can use it.
+ *
+ * @param _va		new upper limit for kernel virtual address space
+ */
+METHOD void growkernel {
+	mmu_t		_mmu;
+	vm_offset_t	_va;
+} DEFAULT mmu_null_growkernel;
+
+
+/**
+ * @brief Called from vm_mem_init. Zone allocation is available at
+ * this stage so a convenient time to create zones. This routine is
+ * for MMU-implementation convenience and is optional.
+ */
+METHOD void init {
+	mmu_t		_mmu;
+} DEFAULT mmu_null_init;
+
+
+/**
+ * @brief Return if the page has been marked by MMU hardware to have been
+ * modified
+ *
+ * @param _pg		physical page to test
+ *
+ * @retval boolean	TRUE if page has been modified
+ */
+METHOD boolean_t is_modified {
+	mmu_t		_mmu;
+	vm_page_t	_pg;
+};
+
+
+/**
+ * @brief Return whether the specified virtual address is a candidate to be
+ * prefaulted in. This routine is optional.
+ *
+ * @param _pmap		physical map
+ * @param _va		virtual address to test
+ *
+ * @retval boolean	TRUE if the address is a candidate.
+ */
+METHOD boolean_t is_prefaultable {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_offset_t	_va;
+} DEFAULT mmu_null_is_prefaultable;
+
+
+/**
+ * @brief Return whether or not the specified physical page was referenced
+ * in any physical maps.
+ *
+ * @params _pg		physical page
+ *
+ * @retval boolean	TRUE if page has been referenced
+ */
+METHOD boolean_t is_referenced {
+	mmu_t		_mmu;
+	vm_page_t	_pg;
+};
+
+
+/**
+ * @brief Return a count of referenced bits for a page, clearing those bits.
+ * Not all referenced bits need to be cleared, but it is necessary that 0
+ * only be returned when there are none set.
+ *
+ * @params _m		physical page
+ *
+ * @retval int		count of referenced bits
+ */
+METHOD int ts_referenced {
+	mmu_t		_mmu;
+	vm_page_t	_pg;
+};
+
+
+/**
+ * @brief Map the requested physical address range into kernel virtual
+ * address space. The value in _virt is taken as a hint. The virtual
+ * address of the range is returned, or NULL if the mapping could not
+ * be created. The range can be direct-mapped if that is supported.
+ *
+ * @param *_virt	Hint for start virtual address, and also return
+ *			value
+ * @param _start	physical address range start
+ * @param _end		physical address range end
+ * @param _prot		protection of range (currently ignored)
+ *
+ * @retval NULL		could not map the area
+ * @retval addr, *_virt	mapping start virtual address
+ */
+METHOD vm_offset_t map {
+	mmu_t		_mmu;
+	vm_offset_t	*_virt;
+	vm_paddr_t	_start;
+	vm_paddr_t	_end;
+	int		_prot;
+};
+
+
+/**
+ * @brief Used to create a contiguous set of read-only mappings for a
+ * given object to try and eliminate a cascade of on-demand faults as
+ * the object is accessed sequentially. This routine is optional.
+ *
+ * @param _pmap		physical map
+ * @param _addr		mapping start virtual address
+ * @param _object	device-backed V.M. object to be mapped
+ * @param _pindex	page-index within object of mapping start
+ * @param _size		size in bytes of mapping
+ */
+METHOD void object_init_pt {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_offset_t	_addr;
+	vm_object_t	_object;
+	vm_pindex_t	_pindex;
+	vm_size_t	_size;
+} DEFAULT mmu_null_object_init_pt;
+
+
+/**
+ * @brief Used to determine if the specified page has a mapping for the
+ * given physical map, by scanning the list of reverse-mappings from the
+ * page. The list is scanned to a maximum of 16 entries.
+ *
+ * @param _pmap		physical map
+ * @param _pg		physical page
+ *
+ * @retval bool		TRUE if the physical map was found in the first 16
+ *			reverse-map list entries off the physical page.
+ */
+METHOD boolean_t page_exists_quick {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_page_t	_pg;
+};
+
+
+/**
+ * @brief Initialise the machine-dependent section of the physical page
+ * data structure. This routine is optional.
+ *
+ * @param _pg		physical page
+ */
+METHOD void page_init {
+	mmu_t		_mmu;
+	vm_page_t	_pg;
+} DEFAULT mmu_null_page_init;
+
+
+/**
+ * @brief Count the number of managed mappings to the given physical
+ * page that are wired.
+ *
+ * @param _pg		physical page
+ *
+ * @retval int		the number of wired, managed mappings to the
+ *			given physical page
+ */
+METHOD int page_wired_mappings {
+	mmu_t		_mmu;
+	vm_page_t	_pg;
+};
+
+
+/**
+ * @brief Initialise a physical map data structure
+ *
+ * @param _pmap		physical map
+ */
+METHOD void pinit {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+};
+
+
+/**
+ * @brief Initialise the physical map for process 0, the initial process
+ * in the system.
+ * XXX default to pinit ?
+ *
+ * @param _pmap		physical map
+ */
+METHOD void pinit0 {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+};
+
+
+/**
+ * @brief Set the protection for physical pages in the given virtual address
+ * range to the given value.
+ *
+ * @param _pmap		physical map
+ * @param _start	virtual range start
+ * @param _end		virtual range end
+ * @param _prot		new page protection
+ */
+METHOD void protect {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_offset_t	_start;
+	vm_offset_t	_end;
+	vm_prot_t	_prot;
+};
+
+
+/**
+ * @brief Create a mapping in kernel virtual address space for the given array
+ * of wired physical pages.
+ *
+ * @param _start	mapping virtual address start
+ * @param *_m		array of physical page pointers
+ * @param _count	array elements
+ */
+METHOD void qenter {
+	mmu_t		_mmu;
+	vm_offset_t	_start;
+	vm_page_t	*_pg;
+	int		_count;
+};
+
+
+/**
+ * @brief Remove the temporary mappings created by qenter.
+ *
+ * @param _start	mapping virtual address start
+ * @param _count	number of pages in mapping
+ */
+METHOD void qremove {
+	mmu_t		_mmu;
+	vm_offset_t	_start;
+	int		_count;
+};
+
+
+/**
+ * @brief Release per-pmap resources, e.g. mutexes, allocated memory etc. There
+ * should be no existing mappings for the physical map at this point
+ *
+ * @param _pmap		physical map
+ */
+METHOD void release {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+};
+
+
+/**
+ * @brief Remove all mappings in the given physical map for the start/end
+ * virtual address range. The range will be page-aligned.
+ *
+ * @param _pmap		physical map
+ * @param _start	mapping virtual address start
+ * @param _end		mapping virtual address end
+ */
+METHOD void remove {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_offset_t	_start;
+	vm_offset_t	_end;
+};
+
+
+/**
+ * @brief Traverse the reverse-map list off the given physical page and
+ * remove all mappings. Clear the PGA_WRITEABLE attribute from the page.
+ *
+ * @param _pg		physical page
+ */
+METHOD void remove_all {
+	mmu_t		_mmu;
+	vm_page_t	_pg;
+};
+
+
+/**
+ * @brief Remove all mappings in the given start/end virtual address range
+ * for the given physical map. Similar to the remove method, but it used
+ * when tearing down all mappings in an address space. This method is
+ * optional, since pmap_remove will be called for each valid vm_map in
+ * the address space later.
+ *
+ * @param _pmap		physical map
+ * @param _start	mapping virtual address start
+ * @param _end		mapping virtual address end
+ */
+METHOD void remove_pages {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+} DEFAULT mmu_null_remove_pages;
+
+
+/**
+ * @brief Clear the wired attribute from the mappings for the specified range
+ * of addresses in the given pmap.
+ *
+ * @param _pmap		physical map
+ * @param _start	virtual range start
+ * @param _end		virtual range end
+ */
+METHOD void unwire {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_offset_t	_start;
+	vm_offset_t	_end;
+};
+
+
+/**
+ * @brief Zero a physical page. It is not assumed that the page is mapped,
+ * so a temporary (or direct) mapping may need to be used.
+ *
+ * @param _pg		physical page
+ */
+METHOD void zero_page {
+	mmu_t		_mmu;
+	vm_page_t	_pg;
+};
+
+
+/**
+ * @brief Zero a portion of a physical page, starting at a given offset and
+ * for a given size (multiples of 512 bytes for 4k pages).
+ *
+ * @param _pg		physical page
+ * @param _off		byte offset from start of page
+ * @param _size		size of area to zero
+ */
+METHOD void zero_page_area {
+	mmu_t		_mmu;
+	vm_page_t	_pg;
+	int		_off;
+	int		_size;
+};
+
+
+/**
+ * @brief Called from the idle loop to zero pages. XXX I think locking
+ * constraints might be different here compared to zero_page.
+ *
+ * @param _pg		physical page
+ */
+METHOD void zero_page_idle {
+	mmu_t		_mmu;
+	vm_page_t	_pg;
+};
+
+
+/**
+ * @brief Extract mincore(2) information from a mapping.
+ *
+ * @param _pmap		physical map
+ * @param _addr		page virtual address
+ * @param _locked_pa	page physical address
+ *
+ * @retval 0		no result
+ * @retval non-zero	mincore(2) flag values
+ */
+METHOD int mincore {
+	mmu_t		_mmu;
+	pmap_t		_pmap;
+	vm_offset_t	_addr;
+	vm_paddr_t	*_locked_pa;
+} DEFAULT mmu_null_mincore;
+
+
+/**
+ * @brief Perform any operations required to allow a physical map to be used
+ * before it's address space is accessed.
+ *
+ * @param _td		thread associated with physical map
+ */
+METHOD void activate {
+	mmu_t		_mmu;
+	struct thread	*_td;
+};
+
+/**
+ * @brief Perform any operations required to deactivate a physical map,
+ * for instance as it is context-switched out.
+ *
+ * @param _td		thread associated with physical map
+ */
+METHOD void deactivate {
+	mmu_t		_mmu;
+	struct thread	*_td;
+} DEFAULT mmu_null_deactivate;
+
+/**
+ * @brief Return a hint for the best virtual address to map a tentative
+ * virtual address range in a given VM object. The default is to just
+ * return the given tentative start address.
+ *
+ * @param _obj		VM backing object
+ * @param _offset	starting offset with the VM object
+ * @param _addr		initial guess at virtual address
+ * @param _size		size of virtual address range
+ */
+METHOD void align_superpage {
+	mmu_t		_mmu;
+	vm_object_t	_obj;
+	vm_ooffset_t	_offset;
+	vm_offset_t	*_addr;
+	vm_size_t	_size;
+} DEFAULT mmu_null_align_superpage;
+
+
+
+
+/**
+ * INTERNAL INTERFACES
+ */
+
+/**
+ * @brief Bootstrap the VM system. At the completion of this routine, the
+ * kernel will be running in it's own address space with full control over
+ * paging.
+ *
+ * @param _start	start of reserved memory (obsolete ???)
+ * @param _end		end of reserved memory (obsolete ???)
+ *			XXX I think the intent of these was to allow
+ *			the memory used by kernel text+data+bss and
+ *			loader variables/load-time kld's to be carved out
+ *			of available physical mem.
+ *
+ */
+METHOD void bootstrap {
+	mmu_t		_mmu;
+	vm_offset_t	_start;
+	vm_offset_t	_end;
+};
+
+/**
+ * @brief Set up the MMU on the current CPU. Only called by the PMAP layer
+ * for alternate CPUs on SMP systems.
+ *
+ * @param _ap		Set to 1 if the CPU being set up is an AP
+ *
+ */
+METHOD void cpu_bootstrap {
+	mmu_t		_mmu;
+	int		_ap;
+};
+
+
+/**
+ * @brief Create a kernel mapping for a given physical address range.
+ * Called by bus code on behalf of device drivers. The mapping does not
+ * have to be a virtual address: it can be a direct-mapped physical address
+ * if that is supported by the MMU.
+ *
+ * @param _pa		start physical address
+ * @param _size		size in bytes of mapping
+ *
+ * @retval addr		address of mapping.
+ */
+METHOD void * mapdev {
+	mmu_t		_mmu;
+	vm_paddr_t	_pa;
+	vm_size_t	_size;
+};
+
+/**
+ * @brief Create a kernel mapping for a given physical address range.
+ * Called by bus code on behalf of device drivers. The mapping does not
+ * have to be a virtual address: it can be a direct-mapped physical address
+ * if that is supported by the MMU.
+ *
+ * @param _pa		start physical address
+ * @param _size		size in bytes of mapping
+ * @param _attr		cache attributes
+ *
+ * @retval addr		address of mapping.
+ */
+METHOD void * mapdev_attr {
+	mmu_t		_mmu;
+	vm_offset_t	_pa;
+	vm_size_t	_size;
+	vm_memattr_t	_attr;
+} DEFAULT mmu_null_mapdev_attr;
+
+/**
+ * @brief Change cache control attributes for a page. Should modify all
+ * mappings for that page.
+ *
+ * @param _m		page to modify
+ * @param _ma		new cache control attributes
+ */
+METHOD void page_set_memattr {
+	mmu_t		_mmu;
+	vm_page_t	_pg;
+	vm_memattr_t	_ma;
+} DEFAULT mmu_null_page_set_memattr;
+
+/**
+ * @brief Remove the mapping created by mapdev. Called when a driver
+ * is unloaded.
+ *
+ * @param _va		Mapping address returned from mapdev
+ * @param _size		size in bytes of mapping
+ */
+METHOD void unmapdev {
+	mmu_t		_mmu;
+	vm_offset_t	_va;
+	vm_size_t	_size;
+};
+
+
+/**
+ * @brief Reverse-map a kernel virtual address
+ *
+ * @param _va		kernel virtual address to reverse-map
+ *
+ * @retval pa		physical address corresponding to mapping
+ */
+METHOD vm_paddr_t kextract {
+	mmu_t		_mmu;
+	vm_offset_t	_va;
+};
+
+
+/**
+ * @brief Map a wired page into kernel virtual address space
+ *
+ * @param _va		mapping virtual address
+ * @param _pa		mapping physical address
+ */
+METHOD void kenter {
+	mmu_t		_mmu;
+	vm_offset_t	_va;
+	vm_paddr_t	_pa;
+};
+
+/**
+ * @brief Map a wired page into kernel virtual address space
+ *
+ * @param _va		mapping virtual address
+ * @param _pa		mapping physical address
+ * @param _ma		mapping cache control attributes
+ */
+METHOD void kenter_attr {
+	mmu_t		_mmu;
+	vm_offset_t	_va;
+	vm_offset_t	_pa;
+	vm_memattr_t	_ma;
+} DEFAULT mmu_null_kenter_attr;
+
+/**
+ * @brief Determine if the given physical address range has been direct-mapped.
+ *
+ * @param _pa		physical address start
+ * @param _size		physical address range size
+ *
+ * @retval bool		TRUE if the range is direct-mapped.
+ */
+METHOD boolean_t dev_direct_mapped {
+	mmu_t		_mmu;
+	vm_paddr_t	_pa;
+	vm_size_t	_size;
+};
+
+
+/**
+ * @brief Enforce instruction cache coherency. Typically called after a
+ * region of memory has been modified and before execution of or within
+ * that region is attempted. Setting breakpoints in a process through
+ * ptrace(2) is one example of when the instruction cache needs to be
+ * made coherent.
+ *
+ * @param _pm		the physical map of the virtual address
+ * @param _va		the virtual address of the modified region
+ * @param _sz		the size of the modified region
+ */
+METHOD void sync_icache {
+	mmu_t		_mmu;
+	pmap_t		_pm;
+	vm_offset_t	_va;
+	vm_size_t	_sz;
+};
+
+
+/**
+ * @brief Create temporary memory mapping for use by dumpsys().
+ *
+ * @param _md		The memory chunk in which the mapping lies.
+ * @param _ofs		The offset within the chunk of the mapping.
+ * @param _sz		The requested size of the mapping.
+ *
+ * @retval vm_offset_t	The virtual address of the mapping.
+ *			
+ * The sz argument is modified to reflect the actual size of the
+ * mapping.
+ */
+METHOD vm_offset_t dumpsys_map {
+	mmu_t		_mmu;
+	struct pmap_md	*_md;
+	vm_size_t	_ofs;
+	vm_size_t	*_sz;
+};
+
+
+/**
+ * @brief Remove temporary dumpsys() mapping.
+ *
+ * @param _md		The memory chunk in which the mapping lies.
+ * @param _ofs		The offset within the chunk of the mapping.
+ * @param _va		The virtual address of the mapping.
+ */
+METHOD void dumpsys_unmap {
+	mmu_t		_mmu;
+	struct pmap_md	*_md;
+	vm_size_t	_ofs;
+	vm_offset_t	_va;
+};
+
+
+/**
+ * @brief Scan/iterate memory chunks.
+ *
+ * @param _prev		The previously returned chunk or NULL.
+ *
+ * @retval		The next (or first when _prev is NULL) chunk.
+ */
+METHOD struct pmap_md * scan_md {
+	mmu_t		_mmu;
+	struct pmap_md	*_prev;
+} DEFAULT mmu_null_scan_md;


Property changes on: trunk/sys/powerpc/powerpc/mmu_if.m
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/mp_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/mp_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/mp_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,376 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Marcel Moolenaar
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/mp_machdep.c 266676 2014-05-26 01:37:43Z nwhitehorn $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/bus.h>
+#include <sys/cpuset.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr_machdep.h>
+#include <machine/pcb.h>
+#include <machine/platform.h>
+#include <machine/md_var.h>
+#include <machine/setjmp.h>
+#include <machine/smp.h>
+
+#include "pic_if.h"
+
+extern struct pcpu __pcpu[MAXCPU];
+
+volatile static int ap_awake;
+volatile static u_int ap_letgo;
+volatile static u_quad_t ap_timebase;
+static u_int ipi_msg_cnt[32];
+static struct mtx ap_boot_mtx;
+struct pcb stoppcbs[MAXCPU];
+int longfault(faultbuf, int);
+
+void
+machdep_ap_bootstrap(void)
+{
+
+	/* Set PIR */
+	PCPU_SET(pir, mfspr(SPR_PIR));
+	PCPU_SET(awake, 1);
+	__asm __volatile("msync; isync");
+
+	while (ap_letgo == 0)
+		;
+
+	/* Initialize DEC and TB, sync with the BSP values */
+#ifdef __powerpc64__
+	/* Writing to the time base register is hypervisor-privileged */
+	if (mfmsr() & PSL_HV)
+		mttb(ap_timebase);
+#else
+	mttb(ap_timebase);
+#endif
+	decr_ap_init();
+
+	/* Give platform code a chance to do anything necessary */
+	platform_smp_ap_init();
+
+	/* Serialize console output and AP count increment */
+	mtx_lock_spin(&ap_boot_mtx);
+	ap_awake++;
+	printf("SMP: AP CPU #%d launched\n", PCPU_GET(cpuid));
+	mtx_unlock_spin(&ap_boot_mtx);
+
+	/* Start per-CPU event timers. */
+	cpu_initclocks_ap();
+
+	/* Announce ourselves awake, and enter the scheduler */
+	sched_throw(NULL);
+}
+
+void
+cpu_mp_setmaxid(void)
+{
+	struct cpuref cpuref;
+	int error;
+
+	mp_ncpus = 0;
+	error = platform_smp_first_cpu(&cpuref);
+	while (!error) {
+		mp_ncpus++;
+		error = platform_smp_next_cpu(&cpuref);
+	}
+	/* Sanity. */
+	if (mp_ncpus == 0)
+		mp_ncpus = 1;
+
+	/*
+	 * Set the largest cpuid we're going to use. This is necessary
+	 * for VM initialization.
+	 */
+	mp_maxid = min(mp_ncpus, MAXCPU) - 1;
+}
+
+int
+cpu_mp_probe(void)
+{
+
+	/*
+	 * We're not going to enable SMP if there's only 1 processor.
+	 */
+	return (mp_ncpus > 1);
+}
+
+void
+cpu_mp_start(void)
+{
+	struct cpuref bsp, cpu;
+	struct pcpu *pc;
+	int error;
+
+	error = platform_smp_get_bsp(&bsp);
+	KASSERT(error == 0, ("Don't know BSP"));
+	KASSERT(bsp.cr_cpuid == 0, ("%s: cpuid != 0", __func__));
+
+	error = platform_smp_first_cpu(&cpu);
+	while (!error) {
+		if (cpu.cr_cpuid >= MAXCPU) {
+			printf("SMP: cpu%d: skipped -- ID out of range\n",
+			    cpu.cr_cpuid);
+			goto next;
+		}
+		if (CPU_ISSET(cpu.cr_cpuid, &all_cpus)) {
+			printf("SMP: cpu%d: skipped - duplicate ID\n",
+			    cpu.cr_cpuid);
+			goto next;
+		}
+		if (cpu.cr_cpuid != bsp.cr_cpuid) {
+			void *dpcpu;
+
+			pc = &__pcpu[cpu.cr_cpuid];
+			dpcpu = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE,
+			    M_WAITOK | M_ZERO);
+			pcpu_init(pc, cpu.cr_cpuid, sizeof(*pc));
+			dpcpu_init(dpcpu, cpu.cr_cpuid);
+		} else {
+			pc = pcpup;
+			pc->pc_cpuid = bsp.cr_cpuid;
+			pc->pc_bsp = 1;
+		}
+		pc->pc_hwref = cpu.cr_hwref;
+		CPU_SET(pc->pc_cpuid, &all_cpus);
+next:
+		error = platform_smp_next_cpu(&cpu);
+	}
+}
+
+void
+cpu_mp_announce(void)
+{
+	struct pcpu *pc;
+	int i;
+
+	for (i = 0; i <= mp_maxid; i++) {
+		pc = pcpu_find(i);
+		if (pc == NULL)
+			continue;
+		printf("cpu%d: dev=%x", i, (int)pc->pc_hwref);
+		if (pc->pc_bsp)
+			printf(" (BSP)");
+		printf("\n");
+	}
+}
+
+static void
+cpu_mp_unleash(void *dummy)
+{
+	struct pcpu *pc;
+	int cpus, timeout;
+
+	if (mp_ncpus <= 1)
+		return;
+
+	mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN);
+
+	cpus = 0;
+	smp_cpus = 0;
+	STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
+		cpus++;
+		if (!pc->pc_bsp) {
+			if (bootverbose)
+				printf("Waking up CPU %d (dev=%x)\n",
+				    pc->pc_cpuid, (int)pc->pc_hwref);
+
+			platform_smp_start_cpu(pc);
+			
+			timeout = 2000;	/* wait 2sec for the AP */
+			while (!pc->pc_awake && --timeout > 0)
+				DELAY(1000);
+
+		} else {
+			PCPU_SET(pir, mfspr(SPR_PIR));
+			pc->pc_awake = 1;
+		}
+		if (pc->pc_awake) {
+			if (bootverbose)
+				printf("Adding CPU %d, pir=%x, awake=%x\n",
+				    pc->pc_cpuid, pc->pc_pir, pc->pc_awake);
+			smp_cpus++;
+		} else
+			CPU_SET(pc->pc_cpuid, &stopped_cpus);
+	}
+
+	ap_awake = 1;
+
+	/* Provide our current DEC and TB values for APs */
+	ap_timebase = mftb() + 10;
+	__asm __volatile("msync; isync");
+	
+	/* Let APs continue */
+	atomic_store_rel_int(&ap_letgo, 1);
+
+#ifdef __powerpc64__
+	/* Writing to the time base register is hypervisor-privileged */
+	if (mfmsr() & PSL_HV)
+		mttb(ap_timebase);
+#else
+	mttb(ap_timebase);
+#endif
+
+	while (ap_awake < smp_cpus)
+		;
+
+	if (smp_cpus != cpus || cpus != mp_ncpus) {
+		printf("SMP: %d CPUs found; %d CPUs usable; %d CPUs woken\n",
+		    mp_ncpus, cpus, smp_cpus);
+	}
+
+	/* Let the APs get into the scheduler */
+	DELAY(10000);
+
+	/* XXX Atomic set operation? */
+	smp_started = 1;
+}
+
+SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL);
+
+int
+powerpc_ipi_handler(void *arg)
+{
+	u_int cpuid;
+	uint32_t ipimask;
+	int msg;
+
+	CTR2(KTR_SMP, "%s: MSR 0x%08x", __func__, mfmsr());
+
+	ipimask = atomic_readandclear_32(&(pcpup->pc_ipimask));
+	if (ipimask == 0)
+		return (FILTER_STRAY);
+	while ((msg = ffs(ipimask) - 1) != -1) {
+		ipimask &= ~(1u << msg);
+		ipi_msg_cnt[msg]++;
+		switch (msg) {
+		case IPI_AST:
+			CTR1(KTR_SMP, "%s: IPI_AST", __func__);
+			break;
+		case IPI_PREEMPT:
+			CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__);
+			sched_preempt(curthread);
+			break;
+		case IPI_RENDEZVOUS:
+			CTR1(KTR_SMP, "%s: IPI_RENDEZVOUS", __func__);
+			smp_rendezvous_action();
+			break;
+		case IPI_STOP:
+
+			/*
+			 * IPI_STOP_HARD is mapped to IPI_STOP so it is not
+			 * necessary to add such case in the switch.
+			 */
+			CTR1(KTR_SMP, "%s: IPI_STOP or IPI_STOP_HARD (stop)",
+			    __func__);
+			cpuid = PCPU_GET(cpuid);
+			savectx(&stoppcbs[cpuid]);
+			savectx(PCPU_GET(curpcb));
+			CPU_SET_ATOMIC(cpuid, &stopped_cpus);
+			while (!CPU_ISSET(cpuid, &started_cpus))
+				cpu_spinwait();
+			CPU_CLR_ATOMIC(cpuid, &stopped_cpus);
+			CPU_CLR_ATOMIC(cpuid, &started_cpus);
+			CTR1(KTR_SMP, "%s: IPI_STOP (restart)", __func__);
+			break;
+		case IPI_HARDCLOCK:
+			CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__);
+			hardclockintr();
+			break;
+		}
+	}
+
+	return (FILTER_HANDLED);
+}
+
+static void
+ipi_send(struct pcpu *pc, int ipi)
+{
+
+	CTR4(KTR_SMP, "%s: pc=%p, targetcpu=%d, IPI=%d", __func__,
+	    pc, pc->pc_cpuid, ipi);
+
+	atomic_set_32(&pc->pc_ipimask, (1 << ipi));
+	powerpc_sync();
+	PIC_IPI(root_pic, pc->pc_cpuid);
+
+	CTR1(KTR_SMP, "%s: sent", __func__);
+}
+
+/* Send an IPI to a set of cpus. */
+void
+ipi_selected(cpuset_t cpus, int ipi)
+{
+	struct pcpu *pc;
+
+	STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
+		if (CPU_ISSET(pc->pc_cpuid, &cpus))
+			ipi_send(pc, ipi);
+	}
+}
+
+/* Send an IPI to a specific CPU. */
+void
+ipi_cpu(int cpu, u_int ipi)
+{
+
+	ipi_send(cpuid_to_pcpu[cpu], ipi);
+}
+
+/* Send an IPI to all CPUs EXCEPT myself. */
+void
+ipi_all_but_self(int ipi)
+{
+	struct pcpu *pc;
+
+	STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
+		if (pc != pcpup)
+			ipi_send(pc, ipi);
+	}
+}


Property changes on: trunk/sys/powerpc/powerpc/mp_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/nexus.c
===================================================================
--- trunk/sys/powerpc/powerpc/nexus.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/nexus.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,228 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 1998 Massachusetts Institute of Technology
+ * Copyright 2001 by Thomas Moestl <tmm at FreeBSD.org>.
+ * Copyright 2006 by Marius Strobl <marius at FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ *
+ * 	from: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/nexus.c 266160 2014-05-15 17:30:16Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/pcpu.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/resource.h>
+
+/*
+ * The nexus handles root-level resource allocation requests and interrupt
+ * mapping. All direct subdevices of nexus are attached by DEVICE_IDENTIFY().
+ */
+
+static device_probe_t nexus_probe;
+static device_attach_t nexus_attach;
+static bus_setup_intr_t nexus_setup_intr;
+static bus_teardown_intr_t nexus_teardown_intr;
+static bus_activate_resource_t nexus_activate_resource;
+static bus_deactivate_resource_t nexus_deactivate_resource;
+#ifdef SMP
+static bus_bind_intr_t nexus_bind_intr;
+#endif
+static bus_config_intr_t nexus_config_intr;
+static ofw_bus_map_intr_t nexus_ofw_map_intr;
+
+static device_method_t nexus_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		nexus_probe),
+	DEVMETHOD(device_attach,	nexus_attach),
+
+	/* Bus interface */
+	DEVMETHOD(bus_add_child,	bus_generic_add_child),
+	DEVMETHOD(bus_activate_resource,	nexus_activate_resource),
+	DEVMETHOD(bus_deactivate_resource,	nexus_deactivate_resource),
+	DEVMETHOD(bus_setup_intr,	nexus_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	nexus_teardown_intr),
+#ifdef SMP
+	DEVMETHOD(bus_bind_intr,	nexus_bind_intr),
+#endif
+	DEVMETHOD(bus_config_intr,	nexus_config_intr),
+
+	/* ofw_bus interface */
+	DEVMETHOD(ofw_bus_map_intr,	nexus_ofw_map_intr),
+
+	DEVMETHOD_END
+};
+
+static devclass_t nexus_devclass;
+
+DEFINE_CLASS_0(nexus, nexus_driver, nexus_methods, 1);
+EARLY_DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0,
+    BUS_PASS_BUS);
+MODULE_VERSION(nexus, 1);
+
+static int
+nexus_probe(device_t dev)
+{
+        
+	device_quiet(dev);	/* suppress attach message for neatness */
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+nexus_attach(device_t dev)
+{
+
+	bus_generic_probe(dev);
+	bus_generic_attach(dev);
+
+	return (0);
+}
+
+static int
+nexus_setup_intr(device_t bus __unused, device_t child, struct resource *r,
+    int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
+    void **cookiep)
+{
+	int error;
+
+	if (r == NULL)
+		panic("%s: NULL interrupt resource!", __func__);
+
+	if ((rman_get_flags(r) & RF_SHAREABLE) == 0)
+		flags |= INTR_EXCL;
+
+	/* We depend here on rman_activate_resource() being idempotent. */
+	error = rman_activate_resource(r);
+	if (error)
+		return (error);
+
+	error = powerpc_setup_intr(device_get_nameunit(child),
+	    rman_get_start(r), filt, intr, arg, flags, cookiep);
+
+	return (error);
+}
+
+static int
+nexus_teardown_intr(device_t bus __unused, device_t child __unused,
+    struct resource *r, void *ih)
+{
+        
+	if (r == NULL)
+		return (EINVAL);
+
+	return (powerpc_teardown_intr(ih));
+}
+
+#ifdef SMP
+static int
+nexus_bind_intr(device_t bus __unused, device_t child __unused,
+    struct resource *r, int cpu)
+{
+
+	return (powerpc_bind_intr(rman_get_start(r), cpu));
+}
+#endif
+
+static int
+nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
+    enum intr_polarity pol)
+{
+ 
+	return (powerpc_config_intr(irq, trig, pol));
+} 
+
+static int
+nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
+    pcell_t *irq)
+{
+	u_int intr = MAP_IRQ(iparent, irq[0]);
+	if (icells > 1)
+		powerpc_fw_config_intr(intr, irq[1]);
+	return (intr);
+}
+
+static int
+nexus_activate_resource(device_t bus __unused, device_t child __unused,
+    int type, int rid __unused, struct resource *r)
+{
+
+	if (type == SYS_RES_MEMORY) {
+		vm_offset_t start;
+		void *p;
+
+		start = (vm_offset_t) rman_get_start(r);
+		if (bootverbose)
+			printf("nexus mapdev: start %zx, len %ld\n", start,
+			    rman_get_size(r));
+
+		p = pmap_mapdev(start, (vm_size_t) rman_get_size(r));
+		if (p == NULL)
+			return (ENOMEM);
+		rman_set_virtual(r, p);
+		rman_set_bustag(r, &bs_be_tag);
+		rman_set_bushandle(r, (u_long)p);
+	}
+	return (rman_activate_resource(r));
+}
+
+static int
+nexus_deactivate_resource(device_t bus __unused, device_t child __unused,
+    int type __unused, int rid __unused, struct resource *r)
+{
+
+	/*
+	 * If this is a memory resource, unmap it.
+	 */
+	if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
+		bus_size_t psize;
+
+		psize = rman_get_size(r);
+		pmap_unmapdev((vm_offset_t)rman_get_virtual(r), psize);
+	}
+
+	return (rman_deactivate_resource(r));
+}
+


Property changes on: trunk/sys/powerpc/powerpc/nexus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/openpic.c
===================================================================
--- trunk/sys/powerpc/powerpc/openpic.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/openpic.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,383 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2002 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/powerpc/openpic.c 222813 2011-06-07 08:46:13Z attilio $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/rman.h>
+#include <sys/sched.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/openpicreg.h>
+#include <machine/openpicvar.h>
+
+#include "pic_if.h"
+
+devclass_t openpic_devclass;
+
+/*
+ * Local routines
+ */
+static int openpic_intr(void *arg);
+
+static __inline uint32_t
+openpic_read(struct openpic_softc *sc, u_int reg)
+{
+	return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg));
+}
+
+static __inline void
+openpic_write(struct openpic_softc *sc, u_int reg, uint32_t val)
+{
+	bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val);
+}
+
+static __inline void
+openpic_set_priority(struct openpic_softc *sc, int pri)
+{
+	u_int tpr;
+	uint32_t x;
+
+	sched_pin();
+	tpr = OPENPIC_PCPU_TPR((sc->sc_dev == root_pic) ? PCPU_GET(cpuid) : 0);
+	x = openpic_read(sc, tpr);
+	x &= ~OPENPIC_TPR_MASK;
+	x |= pri;
+	openpic_write(sc, tpr, x);
+	sched_unpin();
+}
+
+int
+openpic_common_attach(device_t dev, uint32_t node)
+{
+	struct openpic_softc *sc;
+	u_int     cpu, ipi, irq;
+	u_int32_t x;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+
+	sc->sc_rid = 0;
+	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
+	    RF_ACTIVE);
+
+	if (sc->sc_memr == NULL) {
+		device_printf(dev, "Could not alloc mem resource!\n");
+		return (ENXIO);
+	}
+
+	sc->sc_bt = rman_get_bustag(sc->sc_memr);
+	sc->sc_bh = rman_get_bushandle(sc->sc_memr);
+
+	/* Reset the PIC */
+	x = openpic_read(sc, OPENPIC_CONFIG);
+	x |= OPENPIC_CONFIG_RESET;
+	openpic_write(sc, OPENPIC_CONFIG, x);
+
+	while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) {
+		powerpc_sync();
+		DELAY(100);
+	}
+
+	/* Check if this is a cascaded PIC */
+	sc->sc_irq = 0;
+	sc->sc_intr = NULL;
+	do {
+		struct resource_list *rl;
+
+		rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
+		if (rl == NULL)
+			break;
+		if (resource_list_find(rl, SYS_RES_IRQ, 0) == NULL)
+			break;
+
+		sc->sc_intr = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+		    &sc->sc_irq, RF_ACTIVE);
+
+		/* XXX Cascaded PICs pass NULL trapframes! */
+		bus_setup_intr(dev, sc->sc_intr, INTR_TYPE_MISC | INTR_MPSAFE,
+		    openpic_intr, NULL, dev, &sc->sc_icookie);
+	} while (0);
+
+	/* Reset the PIC */
+	x = openpic_read(sc, OPENPIC_CONFIG);
+	x |= OPENPIC_CONFIG_RESET;
+	openpic_write(sc, OPENPIC_CONFIG, x);
+
+	while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) {
+		powerpc_sync();
+		DELAY(100);
+	}
+
+	x = openpic_read(sc, OPENPIC_FEATURE);
+	switch (x & OPENPIC_FEATURE_VERSION_MASK) {
+	case 1:
+		sc->sc_version = "1.0";
+		break;
+	case 2:
+		sc->sc_version = "1.2";
+		break;
+	case 3:
+		sc->sc_version = "1.3";
+		break;
+	default:
+		sc->sc_version = "unknown";
+		break;
+	}
+
+	sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >>
+	    OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1;
+	sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >>
+	    OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1;
+
+	/*
+	 * PSIM seems to report 1 too many IRQs and CPUs
+	 */
+	if (sc->sc_psim) {
+		sc->sc_nirq--;
+		sc->sc_ncpu--;
+	}
+
+	if (bootverbose)
+		device_printf(dev,
+		    "Version %s, supports %d CPUs and %d irqs\n",
+		    sc->sc_version, sc->sc_ncpu, sc->sc_nirq);
+
+	for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
+		openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 15);
+
+	/* Reset and disable all interrupts. */
+	for (irq = 0; irq < sc->sc_nirq; irq++) {
+		x = irq;                /* irq == vector. */
+		x |= OPENPIC_IMASK;
+		x |= OPENPIC_POLARITY_NEGATIVE;
+		x |= OPENPIC_SENSE_LEVEL;
+		x |= 8 << OPENPIC_PRIORITY_SHIFT;
+		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+	}
+
+	/* Reset and disable all IPIs. */
+	for (ipi = 0; ipi < 4; ipi++) {
+		x = sc->sc_nirq + ipi;
+		x |= OPENPIC_IMASK;
+		x |= 15 << OPENPIC_PRIORITY_SHIFT;
+		openpic_write(sc, OPENPIC_IPI_VECTOR(ipi), x);
+	}
+
+	/* we don't need 8259 passthrough mode */
+	x = openpic_read(sc, OPENPIC_CONFIG);
+	x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
+	openpic_write(sc, OPENPIC_CONFIG, x);
+
+	/* send all interrupts to cpu 0 */
+	for (irq = 0; irq < sc->sc_nirq; irq++)
+		openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0);
+
+	/* clear all pending interrupts from cpu 0 */
+	for (irq = 0; irq < sc->sc_nirq; irq++) {
+		(void)openpic_read(sc, OPENPIC_PCPU_IACK(0));
+		openpic_write(sc, OPENPIC_PCPU_EOI(0), 0);
+	}
+
+	for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
+		openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 0);
+
+	powerpc_register_pic(dev, node, sc->sc_nirq, 4, FALSE);
+
+	/* If this is not a cascaded PIC, it must be the root PIC */
+	if (sc->sc_intr == NULL)
+		root_pic = dev;
+
+	return (0);
+}
+
+/*
+ * PIC I/F methods
+ */
+
+void
+openpic_bind(device_t dev, u_int irq, cpuset_t cpumask)
+{
+	struct openpic_softc *sc;
+
+	/* If we aren't directly connected to the CPU, this won't work */
+	if (dev != root_pic)
+		return;
+
+	sc = device_get_softc(dev);
+
+	/*
+	 * XXX: openpic_write() is very special and just needs a 32 bits mask.
+	 * For the moment, just play dirty and get the first half word.
+	 */
+	openpic_write(sc, OPENPIC_IDEST(irq), cpumask.__bits[0] & 0xffffffff);
+}
+
+void
+openpic_config(device_t dev, u_int irq, enum intr_trigger trig,
+    enum intr_polarity pol)
+{
+	struct openpic_softc *sc;
+	uint32_t x;
+
+	sc = device_get_softc(dev);
+	x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
+	if (pol == INTR_POLARITY_LOW)
+		x &= ~OPENPIC_POLARITY_POSITIVE;
+	else
+		x |= OPENPIC_POLARITY_POSITIVE;
+	if (trig == INTR_TRIGGER_EDGE)
+		x &= ~OPENPIC_SENSE_LEVEL;
+	else
+		x |= OPENPIC_SENSE_LEVEL;
+	openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+}
+
+static int
+openpic_intr(void *arg)
+{
+	device_t dev = (device_t)(arg);
+
+	/* XXX Cascaded PICs do not pass non-NULL trapframes! */
+	openpic_dispatch(dev, NULL);
+
+	return (FILTER_HANDLED);
+}
+
+void
+openpic_dispatch(device_t dev, struct trapframe *tf)
+{
+	struct openpic_softc *sc;
+	u_int cpuid, vector;
+
+	CTR1(KTR_INTR, "%s: got interrupt", __func__);
+
+	cpuid = (dev == root_pic) ? PCPU_GET(cpuid) : 0;
+
+	sc = device_get_softc(dev);
+	while (1) {
+		vector = openpic_read(sc, OPENPIC_PCPU_IACK(cpuid));
+		vector &= OPENPIC_VECTOR_MASK;
+		if (vector == 255)
+			break;
+		powerpc_dispatch_intr(vector, tf);
+	}
+}
+
+void
+openpic_enable(device_t dev, u_int irq, u_int vector)
+{
+	struct openpic_softc *sc;
+	uint32_t x;
+
+	sc = device_get_softc(dev);
+	if (irq < sc->sc_nirq) {
+		x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
+		x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
+		x |= vector;
+		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+	} else {
+		x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
+		x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
+		x |= vector;
+		openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
+	}
+}
+
+void
+openpic_eoi(device_t dev, u_int irq __unused)
+{
+	struct openpic_softc *sc;
+	u_int cpuid;
+
+	cpuid = (dev == root_pic) ? PCPU_GET(cpuid) : 0;
+
+	sc = device_get_softc(dev);
+	openpic_write(sc, OPENPIC_PCPU_EOI(cpuid), 0);
+}
+
+void
+openpic_ipi(device_t dev, u_int cpu)
+{
+	struct openpic_softc *sc;
+
+	KASSERT(dev == root_pic, ("Cannot send IPIs from non-root OpenPIC"));
+
+	sc = device_get_softc(dev);
+	sched_pin();
+	openpic_write(sc, OPENPIC_PCPU_IPI_DISPATCH(PCPU_GET(cpuid), 0),
+	    1u << cpu);
+	sched_unpin();
+}
+
+void
+openpic_mask(device_t dev, u_int irq)
+{
+	struct openpic_softc *sc;
+	uint32_t x;
+
+	sc = device_get_softc(dev);
+	if (irq < sc->sc_nirq) {
+		x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
+		x |= OPENPIC_IMASK;
+		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+	} else {
+		x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
+		x |= OPENPIC_IMASK;
+		openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
+	}
+}
+
+void
+openpic_unmask(device_t dev, u_int irq)
+{
+	struct openpic_softc *sc;
+	uint32_t x;
+
+	sc = device_get_softc(dev);
+	if (irq < sc->sc_nirq) {
+		x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
+		x &= ~OPENPIC_IMASK;
+		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+	} else {
+		x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
+		x &= ~OPENPIC_IMASK;
+		openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
+	}
+}


Property changes on: trunk/sys/powerpc/powerpc/openpic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/pic_if.m
===================================================================
--- trunk/sys/powerpc/powerpc/pic_if.m	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/pic_if.m	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,98 @@
+#-
+# Copyright (c) 1998 Doug Rabson
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# from: src/sys/kern/bus_if.m,v 1.21 2002/04/21 11:16:10 markm Exp
+# $FreeBSD: stable/10/sys/powerpc/powerpc/pic_if.m 265969 2014-05-13 18:06:26Z ian $
+# $MidnightBSD$
+
+#include <sys/bus.h>
+#include <sys/cpuset.h>
+#include <machine/frame.h>
+
+INTERFACE pic;
+
+CODE {
+	static pic_translate_code_t pic_translate_code_default;
+
+	static void pic_translate_code_default(device_t dev, u_int irq,
+	    int code, enum intr_trigger *trig, enum intr_polarity *pol)
+	{
+		*trig = INTR_TRIGGER_CONFORM;
+		*pol = INTR_POLARITY_CONFORM;
+	}
+};
+
+METHOD void bind {
+	device_t	dev;
+	u_int		irq;
+	cpuset_t	cpumask;
+};
+
+METHOD void translate_code {
+	device_t	dev;
+	u_int		irq;
+	int		code;
+	enum intr_trigger *trig;
+	enum intr_polarity *pol;
+} DEFAULT pic_translate_code_default;
+
+METHOD void config {
+	device_t	dev;
+	u_int		irq;
+	enum intr_trigger trig;
+	enum intr_polarity pol;
+};
+
+METHOD void dispatch {
+	device_t	dev;
+	struct trapframe *tf;
+};
+
+METHOD void enable {
+	device_t	dev;
+	u_int		irq;
+	u_int		vector;
+};
+
+METHOD void eoi {
+	device_t	dev;
+	u_int		irq;
+};
+
+METHOD void ipi {
+	device_t	dev;
+	u_int		cpu;
+};
+
+METHOD void mask {
+	device_t	dev;
+	u_int		irq;
+};
+
+METHOD void unmask {
+	device_t	dev;
+	u_int		irq;
+};
+


Property changes on: trunk/sys/powerpc/powerpc/pic_if.m
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/platform.c
===================================================================
--- trunk/sys/powerpc/powerpc/platform.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/platform.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,326 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Peter Grehan
+ * Copyright (c) 2009 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/platform.c 266020 2014-05-14 14:17:51Z ian $");
+
+/*
+ * Dispatch platform calls to the appropriate platform implementation
+ * through a previously registered kernel object.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/ktr.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <sys/smp.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+#include <machine/platform.h>
+#include <machine/platformvar.h>
+#include <machine/smp.h>
+
+#include "platform_if.h"
+
+static platform_def_t	*plat_def_impl;
+static platform_t	plat_obj;
+static struct kobj_ops	plat_kernel_kops;
+static struct platform_kobj	plat_kernel_obj;
+
+static char plat_name[64] = "";
+SYSCTL_STRING(_hw, OID_AUTO, platform, CTLFLAG_RD | CTLFLAG_TUN,
+    plat_name, 0, "Platform currently in use");
+
+static struct mem_region pregions[PHYS_AVAIL_SZ];
+static struct mem_region aregions[PHYS_AVAIL_SZ];
+static int npregions, naregions;
+
+/*
+ * Memory region utilities: determine if two regions overlap,
+ * and merge two overlapping regions into one
+ */
+static int
+memr_overlap(struct mem_region *r1, struct mem_region *r2)
+{
+	if ((r1->mr_start + r1->mr_size) < r2->mr_start ||
+	    (r2->mr_start + r2->mr_size) < r1->mr_start)
+		return (FALSE);
+
+	return (TRUE);
+}
+
+static void
+memr_merge(struct mem_region *from, struct mem_region *to)
+{
+	vm_offset_t end;
+	end = ulmax(to->mr_start + to->mr_size, from->mr_start + from->mr_size);
+	to->mr_start = ulmin(from->mr_start, to->mr_start);
+	to->mr_size = end - to->mr_start;
+}
+
+/*
+ * Quick sort callout for comparing memory regions.
+ */
+static int
+mr_cmp(const void *a, const void *b)
+{
+	const struct mem_region *regiona, *regionb;
+
+	regiona = a;
+	regionb = b;
+	if (regiona->mr_start < regionb->mr_start)
+		return (-1);
+	else if (regiona->mr_start > regionb->mr_start)
+		return (1);
+	else
+		return (0);
+}
+
+void
+mem_regions(struct mem_region **phys, int *physsz, struct mem_region **avail,
+    int *availsz)
+{
+	int i, j, still_merging;
+
+	if (npregions == 0) {
+		PLATFORM_MEM_REGIONS(plat_obj, &pregions[0], &npregions,
+		    aregions, &naregions);
+		qsort(pregions, npregions, sizeof(*pregions), mr_cmp);
+		qsort(aregions, naregions, sizeof(*aregions), mr_cmp);
+
+		/* Remove overlapping available regions */
+		do {
+			still_merging = FALSE;
+			for (i = 0; i < naregions; i++) {
+				if (aregions[i].mr_size == 0)
+					continue;
+				for (j = i+1; j < naregions; j++) {
+					if (aregions[j].mr_size == 0)
+						continue;
+					if (!memr_overlap(&aregions[j],
+					    &aregions[i]))
+						continue;
+
+					memr_merge(&aregions[j], &aregions[i]);
+					/* mark inactive */
+					aregions[j].mr_size = 0;
+					still_merging = TRUE;
+				}
+			}
+		} while (still_merging == TRUE);
+
+		/* Collapse zero-length available regions */
+		for (i = 0; i < naregions; i++) {
+			if (aregions[i].mr_size == 0) {
+				memcpy(&aregions[i], &aregions[i+1],
+				    (naregions - i - 1)*sizeof(*aregions));
+				naregions--;
+			}
+		}
+	}
+
+	*phys = pregions;
+	*avail = aregions;
+	*physsz = npregions;
+	*availsz = naregions;
+}
+
+int
+mem_valid(vm_offset_t addr, int len)
+{
+	int i;
+
+	if (npregions == 0) {
+		struct mem_region *p, *a;
+		int na, np;
+		mem_regions(&p, &np, &a, &na);
+	}
+
+	for (i = 0; i < npregions; i++)
+		if ((addr >= pregions[i].mr_start)
+		   && (addr + len <= pregions[i].mr_start + pregions[i].mr_size))
+			return (0);
+
+	return (EFAULT);
+}
+
+vm_offset_t
+platform_real_maxaddr(void)
+{
+	return (PLATFORM_REAL_MAXADDR(plat_obj));
+}
+
+const char *
+installed_platform()
+{
+	return (plat_def_impl->name);
+}
+
+u_long
+platform_timebase_freq(struct cpuref *cpu)
+{
+	return (PLATFORM_TIMEBASE_FREQ(plat_obj, cpu));
+}
+
+/*
+ * Put the current CPU, as last step in suspend, to sleep
+ */
+void
+platform_sleep()
+{
+        PLATFORM_SLEEP(plat_obj);
+}
+
+int
+platform_smp_first_cpu(struct cpuref *cpu)
+{
+	return (PLATFORM_SMP_FIRST_CPU(plat_obj, cpu));
+}
+
+int
+platform_smp_next_cpu(struct cpuref *cpu)
+{
+	return (PLATFORM_SMP_NEXT_CPU(plat_obj, cpu));
+}
+
+int
+platform_smp_get_bsp(struct cpuref *cpu)
+{
+	return (PLATFORM_SMP_GET_BSP(plat_obj, cpu));
+}
+
+int
+platform_smp_start_cpu(struct pcpu *cpu)
+{
+	return (PLATFORM_SMP_START_CPU(plat_obj, cpu));
+}
+
+void
+platform_smp_ap_init()
+{
+	PLATFORM_SMP_AP_INIT(plat_obj);
+}
+
+#ifdef SMP
+struct cpu_group *
+cpu_topo(void)
+{
+        return (PLATFORM_SMP_TOPO(plat_obj));
+}
+#endif
+
+/*
+ * Reset back to firmware.
+ */
+void
+cpu_reset()
+{
+        PLATFORM_RESET(plat_obj);
+}
+
+/*
+ * Platform install routines. Highest priority wins, using the same
+ * algorithm as bus attachment.
+ */
+SET_DECLARE(platform_set, platform_def_t);
+
+void
+platform_probe_and_attach()
+{
+	platform_def_t	**platpp, *platp;
+	int		prio, best_prio;
+
+	plat_obj = &plat_kernel_obj;
+	best_prio = 0;
+
+	/*
+	 * Try to locate the best platform kobj
+	 */
+	SET_FOREACH(platpp, platform_set) {
+		platp = *platpp;
+
+		/*
+		 * Take care of compiling the selected class, and
+		 * then statically initialise the MMU object
+		 */
+		kobj_class_compile_static(platp, &plat_kernel_kops);
+		kobj_init_static((kobj_t)plat_obj, platp);
+
+		prio = PLATFORM_PROBE(plat_obj);
+
+		/* Check for errors */
+		if (prio > 0)
+			continue;
+
+		/*
+		 * Check if this module was specifically requested through
+		 * the loader tunable we provide.
+		 */
+		if (strcmp(platp->name,plat_name) == 0) {
+			plat_def_impl = platp;
+			break;
+		}
+
+		/* Otherwise, see if it is better than our current best */
+		if (plat_def_impl == NULL || prio > best_prio) {
+			best_prio = prio;
+			plat_def_impl = platp;
+		}
+
+		/*
+		 * We can't free the KOBJ, since it is static. Reset the ops
+		 * member of this class so that we can come back later.
+		 */
+		platp->ops = NULL;
+	}
+
+	if (plat_def_impl == NULL)
+		panic("No platform module found!");
+
+	/*
+	 * Recompile to make sure we ended with the
+	 * correct one, and then attach.
+	 */
+
+	kobj_class_compile_static(plat_def_impl, &plat_kernel_kops);
+	kobj_init_static((kobj_t)plat_obj, plat_def_impl);
+
+	strlcpy(plat_name,plat_def_impl->name,sizeof(plat_name));
+
+	PLATFORM_ATTACH(plat_obj);
+}
+


Property changes on: trunk/sys/powerpc/powerpc/platform.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/platform_if.m
===================================================================
--- trunk/sys/powerpc/powerpc/platform_if.m	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/platform_if.m	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,219 @@
+#-
+# Copyright (c) 2009 Nathan Whitehorn
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD: stable/10/sys/powerpc/powerpc/platform_if.m 266020 2014-05-14 14:17:51Z ian $
+# $MidnightBSD$
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <sys/smp.h>
+
+#include <machine/platform.h>
+#include <machine/platformvar.h>
+#include <machine/smp.h>
+#include <machine/vmparam.h>
+
+/**
+ * @defgroup PLATFORM platform - KObj methods for PowerPC platform
+ * implementations
+ * @brief A set of methods required by all platform implementations.
+ * These are used to bring up secondary CPUs, supply the physical memory
+ * map, etc.
+ *@{
+ */
+
+INTERFACE platform;
+
+#
+# Default implementations
+#
+CODE {
+	static void platform_null_attach(platform_t plat)
+	{
+		return;
+	}
+	static int platform_null_smp_first_cpu(platform_t plat,
+	    struct cpuref  *cpuref)
+	{
+		cpuref->cr_hwref = -1;
+		cpuref->cr_cpuid = 0;
+		return (0);
+	}
+	static int platform_null_smp_next_cpu(platform_t plat,
+	    struct cpuref  *_cpuref)
+	{
+		return (ENOENT);
+	}
+	static struct cpu_group *platform_null_smp_topo(platform_t plat)
+	{
+#ifdef SMP
+		return (smp_topo_none());
+#else
+		return (NULL);
+#endif
+	}
+	static vm_offset_t platform_null_real_maxaddr(platform_t plat)
+	{
+		return (VM_MAX_ADDRESS);
+	}
+	static void platform_null_smp_ap_init(platform_t plat)
+	{
+		return;
+	}
+};
+
+/**
+ * @brief Probe for whether we are on this platform, returning the standard
+ * newbus probe codes. If we have Open Firmware or a flattened device tree,
+ * it is guaranteed to be available at this point.
+ */
+METHOD int probe {
+	platform_t	_plat;
+};
+
+
+/**
+ * @brief Attach this platform module. This happens before the MMU is online,
+ * so the platform module can install its own high-priority MMU module at
+ * this point.
+ */
+METHOD int attach {
+	platform_t	_plat;
+} DEFAULT platform_null_attach;
+
+
+/**
+ * @brief Return the system's physical memory map.
+ * 
+ * It shall provide the total and the available regions of RAM.
+ * The available regions need not take the kernel into account.
+ *
+ * @param _memp		Array of physical memory chunks
+ * @param _memsz	Number of physical memory chunks
+ * @param _availp	Array of available physical memory chunks
+ * @param _availsz	Number of available physical memory chunks
+ */
+
+METHOD void mem_regions {
+	platform_t	    _plat;
+	struct mem_region  *_memp;
+	int		   *_memsz;
+	struct mem_region  *_availp;
+	int		   *_availsz;
+};
+
+/**
+ * @brief Return the maximum address accessible in real mode
+ *   (for use with hypervisors)
+ */
+METHOD vm_offset_t real_maxaddr {
+	platform_t	_plat;
+} DEFAULT platform_null_real_maxaddr;
+
+
+/**
+ * @brief Get the CPU's timebase frequency, in ticks per second.
+ *
+ * @param _cpu		CPU whose timebase to query
+ */
+
+METHOD u_long timebase_freq {
+	platform_t	_plat;
+	struct cpuref  *_cpu;
+};
+
+# SMP bits 
+
+/**
+ * @brief Fill the first CPU's cpuref
+ *
+ * @param _cpuref	CPU
+ */
+METHOD int smp_first_cpu {
+	platform_t	_plat;
+	struct cpuref  *_cpuref;
+} DEFAULT platform_null_smp_first_cpu;
+
+/**
+ * @brief Fill the next CPU's cpuref
+ *
+ * @param _cpuref	CPU
+ */
+METHOD int smp_next_cpu {
+	platform_t	_plat;
+	struct cpuref  *_cpuref;
+} DEFAULT platform_null_smp_next_cpu;
+
+/**
+ * @brief Find the boot processor
+ *
+ * @param _cpuref	CPU
+ */
+METHOD int smp_get_bsp {
+	platform_t	_plat;
+	struct cpuref  *_cpuref;
+} DEFAULT platform_null_smp_first_cpu;
+
+/**
+ * @brief Start a CPU
+ *
+ * @param _cpuref	CPU
+ */
+METHOD int smp_start_cpu {
+	platform_t	_plat;
+	struct pcpu	*_cpu;
+};
+
+/**
+ * @brief Start a CPU
+ *
+ */
+METHOD void smp_ap_init {
+	platform_t	_plat;
+} DEFAULT platform_null_smp_ap_init;
+
+/**
+ * @brief Return SMP topology
+ */
+METHOD cpu_group_t smp_topo {
+	platform_t	_plat;
+} DEFAULT platform_null_smp_topo;
+
+/**
+ * @brief Reset system
+ */
+METHOD void reset {
+	platform_t	_plat;
+};
+
+/**
+ * @brief Suspend the CPU
+ */
+METHOD void sleep {
+	platform_t	_plat;
+};
+


Property changes on: trunk/sys/powerpc/powerpc/platform_if.m
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/pmap_dispatch.c
===================================================================
--- trunk/sys/powerpc/powerpc/pmap_dispatch.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/pmap_dispatch.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,580 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Peter Grehan
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/pmap_dispatch.c 270920 2014-09-01 07:58:15Z kib $");
+
+/*
+ * Dispatch MI pmap calls to the appropriate MMU implementation
+ * through a previously registered kernel object.
+ *
+ * Before pmap_bootstrap() can be called, a CPU module must have
+ * called pmap_mmu_install(). This may be called multiple times:
+ * the highest priority call will be installed as the default
+ * MMU handler when pmap_bootstrap() is called.
+ *
+ * It is required that mutex_init() be called before pmap_bootstrap(), 
+ * as the PMAP layer makes extensive use of mutexes.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/ktr.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+#include <machine/mmuvar.h>
+#include <machine/smp.h>
+
+#include "mmu_if.h"
+
+static mmu_def_t	*mmu_def_impl;
+static mmu_t		mmu_obj;
+static struct mmu_kobj	mmu_kernel_obj;
+static struct kobj_ops	mmu_kernel_kops;
+
+/*
+ * pmap globals
+ */
+struct pmap kernel_pmap_store;
+
+struct msgbuf *msgbufp;
+vm_offset_t    msgbuf_phys;
+
+vm_offset_t kernel_vm_end;
+vm_offset_t phys_avail[PHYS_AVAIL_SZ];
+vm_offset_t virtual_avail;
+vm_offset_t virtual_end;
+
+int pmap_bootstrapped;
+
+#ifdef AIM
+int
+pvo_vaddr_compare(struct pvo_entry *a, struct pvo_entry *b)
+{
+	if (PVO_VADDR(a) < PVO_VADDR(b))
+		return (-1);
+	else if (PVO_VADDR(a) > PVO_VADDR(b))
+		return (1);
+	return (0);
+}
+RB_GENERATE(pvo_tree, pvo_entry, pvo_plink, pvo_vaddr_compare);
+#endif
+	
+
+void
+pmap_advise(pmap_t pmap, vm_offset_t start, vm_offset_t end, int advice)
+{
+
+	CTR5(KTR_PMAP, "%s(%p, %#x, %#x, %d)", __func__, pmap, start, end,
+	    advice);
+	MMU_ADVISE(mmu_obj, pmap, start, end, advice);
+}
+
+void
+pmap_clear_modify(vm_page_t m)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, m);
+	MMU_CLEAR_MODIFY(mmu_obj, m);
+}
+
+void
+pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr,
+    vm_size_t len, vm_offset_t src_addr)
+{
+
+	CTR6(KTR_PMAP, "%s(%p, %p, %#x, %#x, %#x)", __func__, dst_pmap,
+	    src_pmap, dst_addr, len, src_addr);
+	MMU_COPY(mmu_obj, dst_pmap, src_pmap, dst_addr, len, src_addr);
+}
+
+void
+pmap_copy_page(vm_page_t src, vm_page_t dst)
+{
+
+	CTR3(KTR_PMAP, "%s(%p, %p)", __func__, src, dst);
+	MMU_COPY_PAGE(mmu_obj, src, dst);
+}
+
+void
+pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
+    vm_offset_t b_offset, int xfersize)
+{
+
+	CTR6(KTR_PMAP, "%s(%p, %#x, %p, %#x, %#x)", __func__, ma,
+	    a_offset, mb, b_offset, xfersize);
+	MMU_COPY_PAGES(mmu_obj, ma, a_offset, mb, b_offset, xfersize);
+}
+
+int
+pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t p, vm_prot_t prot,
+    u_int flags, int8_t psind)
+{
+
+	CTR6(KTR_PMAP, "pmap_enter(%p, %#x, %p, %#x, %x, %d)", pmap, va,
+	    p, prot, flags, psind);
+	return (MMU_ENTER(mmu_obj, pmap, va, p, prot, flags, psind));
+}
+
+void
+pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
+    vm_page_t m_start, vm_prot_t prot)
+{
+
+	CTR6(KTR_PMAP, "%s(%p, %#x, %#x, %p, %#x)", __func__, pmap, start,
+	    end, m_start, prot);
+	MMU_ENTER_OBJECT(mmu_obj, pmap, start, end, m_start, prot);
+}
+
+void
+pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
+{
+
+	CTR5(KTR_PMAP, "%s(%p, %#x, %p, %#x)", __func__, pmap, va, m, prot);
+	MMU_ENTER_QUICK(mmu_obj, pmap, va, m, prot);
+}
+
+vm_paddr_t
+pmap_extract(pmap_t pmap, vm_offset_t va)
+{
+
+	CTR3(KTR_PMAP, "%s(%p, %#x)", __func__, pmap, va);
+	return (MMU_EXTRACT(mmu_obj, pmap, va));
+}
+
+vm_page_t
+pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
+{
+
+	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, pmap, va, prot);
+	return (MMU_EXTRACT_AND_HOLD(mmu_obj, pmap, va, prot));
+}
+
+void
+pmap_growkernel(vm_offset_t va)
+{
+
+	CTR2(KTR_PMAP, "%s(%#x)", __func__, va);
+	MMU_GROWKERNEL(mmu_obj, va);
+}
+
+void
+pmap_init(void)
+{
+
+	CTR1(KTR_PMAP, "%s()", __func__);
+	MMU_INIT(mmu_obj);
+}
+
+boolean_t
+pmap_is_modified(vm_page_t m)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, m);
+	return (MMU_IS_MODIFIED(mmu_obj, m));
+}
+
+boolean_t
+pmap_is_prefaultable(pmap_t pmap, vm_offset_t va)
+{
+
+	CTR3(KTR_PMAP, "%s(%p, %#x)", __func__, pmap, va);
+	return (MMU_IS_PREFAULTABLE(mmu_obj, pmap, va));
+}
+
+boolean_t
+pmap_is_referenced(vm_page_t m)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, m);
+	return (MMU_IS_REFERENCED(mmu_obj, m));
+}
+
+boolean_t
+pmap_ts_referenced(vm_page_t m)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, m);
+	return (MMU_TS_REFERENCED(mmu_obj, m));
+}
+
+vm_offset_t
+pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot)
+{
+
+	CTR5(KTR_PMAP, "%s(%p, %#x, %#x, %#x)", __func__, virt, start, end,
+	    prot);
+	return (MMU_MAP(mmu_obj, virt, start, end, prot));
+}
+
+void
+pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object,
+    vm_pindex_t pindex, vm_size_t size)
+{
+
+	CTR6(KTR_PMAP, "%s(%p, %#x, %p, %u, %#x)", __func__, pmap, addr,
+	    object, pindex, size);
+	MMU_OBJECT_INIT_PT(mmu_obj, pmap, addr, object, pindex, size);
+}
+
+boolean_t
+pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
+{
+
+	CTR3(KTR_PMAP, "%s(%p, %p)", __func__, pmap, m);
+	return (MMU_PAGE_EXISTS_QUICK(mmu_obj, pmap, m));
+}
+
+void
+pmap_page_init(vm_page_t m)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, m);
+	MMU_PAGE_INIT(mmu_obj, m);
+}
+
+int
+pmap_page_wired_mappings(vm_page_t m)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, m);
+	return (MMU_PAGE_WIRED_MAPPINGS(mmu_obj, m));
+}
+
+int
+pmap_pinit(pmap_t pmap)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, pmap);
+	MMU_PINIT(mmu_obj, pmap);
+	return (1);
+}
+
+void
+pmap_pinit0(pmap_t pmap)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, pmap);
+	MMU_PINIT0(mmu_obj, pmap);
+}
+
+void
+pmap_protect(pmap_t pmap, vm_offset_t start, vm_offset_t end, vm_prot_t prot)
+{
+
+	CTR5(KTR_PMAP, "%s(%p, %#x, %#x, %#x)", __func__, pmap, start, end,
+	    prot);
+	MMU_PROTECT(mmu_obj, pmap, start, end, prot);
+}
+
+void
+pmap_qenter(vm_offset_t start, vm_page_t *m, int count)
+{
+
+	CTR4(KTR_PMAP, "%s(%#x, %p, %d)", __func__, start, m, count);
+	MMU_QENTER(mmu_obj, start, m, count);
+}
+
+void
+pmap_qremove(vm_offset_t start, int count)
+{
+
+	CTR3(KTR_PMAP, "%s(%#x, %d)", __func__, start, count);
+	MMU_QREMOVE(mmu_obj, start, count);
+}
+
+void
+pmap_release(pmap_t pmap)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, pmap);
+	MMU_RELEASE(mmu_obj, pmap);
+}
+
+void
+pmap_remove(pmap_t pmap, vm_offset_t start, vm_offset_t end)
+{
+
+	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, pmap, start, end);
+	MMU_REMOVE(mmu_obj, pmap, start, end);
+}
+
+void
+pmap_remove_all(vm_page_t m)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, m);
+	MMU_REMOVE_ALL(mmu_obj, m);
+}
+
+void
+pmap_remove_pages(pmap_t pmap)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, pmap);
+	MMU_REMOVE_PAGES(mmu_obj, pmap);
+}
+
+void
+pmap_remove_write(vm_page_t m)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, m);
+	MMU_REMOVE_WRITE(mmu_obj, m);
+}
+
+void
+pmap_unwire(pmap_t pmap, vm_offset_t start, vm_offset_t end)
+{
+
+	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, pmap, start, end);
+	MMU_UNWIRE(mmu_obj, pmap, start, end);
+}
+
+void
+pmap_zero_page(vm_page_t m)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, m);
+	MMU_ZERO_PAGE(mmu_obj, m);
+}
+
+void
+pmap_zero_page_area(vm_page_t m, int off, int size)
+{
+
+	CTR4(KTR_PMAP, "%s(%p, %d, %d)", __func__, m, off, size);
+	MMU_ZERO_PAGE_AREA(mmu_obj, m, off, size);
+}
+
+void
+pmap_zero_page_idle(vm_page_t m)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, m);
+	MMU_ZERO_PAGE_IDLE(mmu_obj, m);
+}
+
+int
+pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa)
+{
+
+	CTR3(KTR_PMAP, "%s(%p, %#x)", __func__, pmap, addr);
+	return (MMU_MINCORE(mmu_obj, pmap, addr, locked_pa));
+}
+
+void
+pmap_activate(struct thread *td)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, td);
+	MMU_ACTIVATE(mmu_obj, td);
+}
+
+void
+pmap_deactivate(struct thread *td)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, td);
+	MMU_DEACTIVATE(mmu_obj, td);
+}
+
+/*
+ *	Increase the starting virtual address of the given mapping if a
+ *	different alignment might result in more superpage mappings.
+ */
+void
+pmap_align_superpage(vm_object_t object, vm_ooffset_t offset,
+    vm_offset_t *addr, vm_size_t size)
+{
+
+	CTR5(KTR_PMAP, "%s(%p, %#x, %p, %#x)", __func__, object, offset, addr,
+	    size);
+	MMU_ALIGN_SUPERPAGE(mmu_obj, object, offset, addr, size);
+}
+
+/*
+ * Routines used in machine-dependent code
+ */
+void
+pmap_bootstrap(vm_offset_t start, vm_offset_t end)
+{
+	mmu_obj = &mmu_kernel_obj;
+
+	/*
+	 * Take care of compiling the selected class, and
+	 * then statically initialise the MMU object
+	 */
+	kobj_class_compile_static(mmu_def_impl, &mmu_kernel_kops);
+	kobj_init_static((kobj_t)mmu_obj, mmu_def_impl);
+
+	MMU_BOOTSTRAP(mmu_obj, start, end);
+}
+
+void
+pmap_cpu_bootstrap(int ap)
+{
+	/*
+	 * No KTR here because our console probably doesn't work yet
+	 */
+
+	return (MMU_CPU_BOOTSTRAP(mmu_obj, ap));
+}
+
+void *
+pmap_mapdev(vm_paddr_t pa, vm_size_t size)
+{
+
+	CTR3(KTR_PMAP, "%s(%#x, %#x)", __func__, pa, size);
+	return (MMU_MAPDEV(mmu_obj, pa, size));
+}
+
+void *
+pmap_mapdev_attr(vm_offset_t pa, vm_size_t size, vm_memattr_t attr)
+{
+
+	CTR4(KTR_PMAP, "%s(%#x, %#x, %#x)", __func__, pa, size, attr);
+	return (MMU_MAPDEV_ATTR(mmu_obj, pa, size, attr));
+}
+
+void
+pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma)
+{
+
+	CTR3(KTR_PMAP, "%s(%p, %#x)", __func__, m, ma);
+	return (MMU_PAGE_SET_MEMATTR(mmu_obj, m, ma));
+}
+
+void
+pmap_unmapdev(vm_offset_t va, vm_size_t size)
+{
+
+	CTR3(KTR_PMAP, "%s(%#x, %#x)", __func__, va, size);
+	MMU_UNMAPDEV(mmu_obj, va, size);
+}
+
+vm_paddr_t
+pmap_kextract(vm_offset_t va)
+{
+
+	CTR2(KTR_PMAP, "%s(%#x)", __func__, va);
+	return (MMU_KEXTRACT(mmu_obj, va));
+}
+
+void
+pmap_kenter(vm_offset_t va, vm_paddr_t pa)
+{
+
+	CTR3(KTR_PMAP, "%s(%#x, %#x)", __func__, va, pa);
+	MMU_KENTER(mmu_obj, va, pa);
+}
+
+void
+pmap_kenter_attr(vm_offset_t va, vm_offset_t pa, vm_memattr_t ma)
+{
+
+	CTR4(KTR_PMAP, "%s(%#x, %#x, %#x)", __func__, va, pa, ma);
+	MMU_KENTER_ATTR(mmu_obj, va, pa, ma);
+}
+
+boolean_t
+pmap_dev_direct_mapped(vm_paddr_t pa, vm_size_t size)
+{
+
+	CTR3(KTR_PMAP, "%s(%#x, %#x)", __func__, pa, size);
+	return (MMU_DEV_DIRECT_MAPPED(mmu_obj, pa, size));
+}
+
+void
+pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz)
+{
+ 
+	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, pm, va, sz);
+	return (MMU_SYNC_ICACHE(mmu_obj, pm, va, sz));
+}
+
+vm_offset_t
+pmap_dumpsys_map(struct pmap_md *md, vm_size_t ofs, vm_size_t *sz)
+{
+
+	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, md, ofs, *sz);
+	return (MMU_DUMPSYS_MAP(mmu_obj, md, ofs, sz));
+}
+
+void
+pmap_dumpsys_unmap(struct pmap_md *md, vm_size_t ofs, vm_offset_t va)
+{
+
+	CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, md, ofs, va);
+	return (MMU_DUMPSYS_UNMAP(mmu_obj, md, ofs, va));
+}
+
+struct pmap_md *
+pmap_scan_md(struct pmap_md *prev)
+{
+
+	CTR2(KTR_PMAP, "%s(%p)", __func__, prev);
+	return (MMU_SCAN_MD(mmu_obj, prev));
+}
+
+/*
+ * MMU install routines. Highest priority wins, equal priority also
+ * overrides allowing last-set to win.
+ */
+SET_DECLARE(mmu_set, mmu_def_t);
+
+boolean_t
+pmap_mmu_install(char *name, int prio)
+{
+	mmu_def_t	**mmupp, *mmup;
+	static int	curr_prio = 0;
+
+	/*
+	 * Try and locate the MMU kobj corresponding to the name
+	 */
+	SET_FOREACH(mmupp, mmu_set) {
+		mmup = *mmupp;
+
+		if (mmup->name &&
+		    !strcmp(mmup->name, name) &&
+		    (prio >= curr_prio || mmu_def_impl == NULL)) {
+			curr_prio = prio;
+			mmu_def_impl = mmup;
+			return (TRUE);
+		}
+	}
+
+	return (FALSE);
+}
+
+int unmapped_buf_allowed;


Property changes on: trunk/sys/powerpc/powerpc/pmap_dispatch.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/sc_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/sc_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/sc_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,91 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Jake Burkholder.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/sc_machdep.c 124771 2004-01-21 05:16:23Z grehan $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <sys/kbio.h>
+#include <sys/consio.h>
+#include <sys/sysctl.h>
+
+#include <dev/syscons/syscons.h>
+
+static sc_softc_t sc_softcs[8];
+
+int
+sc_get_cons_priority(int *unit, int *flags)
+{
+
+	*unit = 0;
+	*flags = 0;
+	return (CN_INTERNAL);
+}
+
+int
+sc_max_unit(void)
+{
+	return (1);
+}
+
+sc_softc_t *
+sc_get_softc(int unit, int flags)
+{
+	sc_softc_t *sc;
+
+	if (unit < 0)
+		return (NULL);
+	sc = &sc_softcs[unit];
+	sc->unit = unit;
+	if ((sc->flags & SC_INIT_DONE) == 0) {
+		sc->keyboard = -1;
+		sc->adapter = -1;
+		sc->cursor_char = SC_CURSOR_CHAR;
+		sc->mouse_char = SC_MOUSE_CHAR;
+	}
+	return (sc);
+}
+
+void
+sc_get_bios_values(bios_values_t *values)
+{
+	values->cursor_start = 0;
+	values->cursor_end = 32;
+	values->shift_state = 0;
+}
+
+int
+sc_tone(int hz)
+{
+	return (0);
+}


Property changes on: trunk/sys/powerpc/powerpc/sc_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/setjmp.S
===================================================================
--- trunk/sys/powerpc/powerpc/setjmp.S	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/setjmp.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,116 @@
+/* $MidnightBSD$ */
+/*	$FreeBSD: stable/10/sys/powerpc/powerpc/setjmp.S 230400 2012-01-20 22:34:19Z andreast $  */
+/*	from:	NetBSD: setjmp.S,v 1.1 1998/01/27 15:13:12 sakamoto Exp $  */
+/*	from:	OpenBSD: setjmp.S,v 1.2 1996/12/28 06:22:18 rahnds Exp 	*/
+/* kernel version of this file, does not have signal goop */
+/* int setjmp(jmp_buf env) */
+
+#include <machine/asm.h>
+
+#ifdef __powerpc64__
+#define LD_REG	ld
+#define	ST_REG	std
+#define	REGWIDTH 8
+#else
+#define	LD_REG	lwz
+#define	ST_REG	stw
+#define	REGWIDTH 4
+#endif
+
+#define JMP_r1	1*REGWIDTH
+#define JMP_r2	2*REGWIDTH
+#define JMP_r14	3*REGWIDTH
+#define JMP_r15 4*REGWIDTH
+#define JMP_r16 5*REGWIDTH
+#define JMP_r17 6*REGWIDTH
+#define JMP_r18 7*REGWIDTH
+#define JMP_r19 8*REGWIDTH
+#define JMP_r20 9*REGWIDTH
+#define JMP_r21 10*REGWIDTH
+#define JMP_r22 11*REGWIDTH
+#define JMP_r23 12*REGWIDTH
+#define JMP_r24 13*REGWIDTH
+#define JMP_r25 14*REGWIDTH
+#define JMP_r26 15*REGWIDTH
+#define JMP_r27 16*REGWIDTH
+#define JMP_r28 17*REGWIDTH
+#define JMP_r29 18*REGWIDTH
+#define JMP_r30 19*REGWIDTH
+#define JMP_r31 20*REGWIDTH
+#define JMP_lr 	21*REGWIDTH
+#define JMP_cr	22*REGWIDTH
+#define JMP_ctr	23*REGWIDTH
+#define JMP_xer	24*REGWIDTH
+#define JMP_sig	25*REGWIDTH
+
+ASENTRY_NOPROF(setjmp)
+	ST_REG 31, JMP_r31(3)
+	/* r1, r2, r14-r30 */
+	ST_REG 1,  JMP_r1 (3)
+	ST_REG 2,  JMP_r2 (3)
+	ST_REG 14, JMP_r14(3)
+	ST_REG 15, JMP_r15(3)
+	ST_REG 16, JMP_r16(3)
+	ST_REG 17, JMP_r17(3)
+	ST_REG 18, JMP_r18(3)
+	ST_REG 19, JMP_r19(3)
+	ST_REG 20, JMP_r20(3)
+	ST_REG 21, JMP_r21(3)
+	ST_REG 22, JMP_r22(3)
+	ST_REG 23, JMP_r23(3)
+	ST_REG 24, JMP_r24(3)
+	ST_REG 25, JMP_r25(3)
+	ST_REG 26, JMP_r26(3)
+	ST_REG 27, JMP_r27(3)
+	ST_REG 28, JMP_r28(3)
+	ST_REG 29, JMP_r29(3)
+	ST_REG 30, JMP_r30(3)
+	/* cr, lr, ctr, xer */
+	mfcr 0
+	ST_REG 0, JMP_cr(3)
+	mflr 0
+	ST_REG 0, JMP_lr(3)
+	mfctr 0
+	ST_REG 0, JMP_ctr(3)
+	mfxer 0
+	ST_REG 0, JMP_xer(3)
+	/* f14-f31, fpscr */
+	li 3, 0
+	blr
+
+
+.extern sigsetmask
+ASENTRY_NOPROF(longjmp)
+	LD_REG 31, JMP_r31(3)
+	/* r1, r2, r14-r30 */
+	LD_REG 1,  JMP_r1 (3)
+	LD_REG 2,  JMP_r2 (3)
+	LD_REG 14, JMP_r14(3)
+	LD_REG 15, JMP_r15(3)
+	LD_REG 16, JMP_r16(3)
+	LD_REG 17, JMP_r17(3)
+	LD_REG 18, JMP_r18(3)
+	LD_REG 19, JMP_r19(3)
+	LD_REG 20, JMP_r20(3)
+	LD_REG 21, JMP_r21(3)
+	LD_REG 22, JMP_r22(3)
+	LD_REG 23, JMP_r23(3)
+	LD_REG 24, JMP_r24(3)
+	LD_REG 25, JMP_r25(3)
+	LD_REG 26, JMP_r26(3)
+	LD_REG 27, JMP_r27(3)
+	LD_REG 28, JMP_r28(3)
+	LD_REG 29, JMP_r29(3)
+	LD_REG 30, JMP_r30(3)
+	/* cr, lr, ctr, xer */
+	LD_REG 0, JMP_cr(3)
+	mtcr 0
+	LD_REG 0, JMP_lr(3)
+	mtlr 0
+	LD_REG 0, JMP_ctr(3)
+	mtctr 0
+	LD_REG 0, JMP_xer(3)
+	mtxer 0
+	/* f14-f31, fpscr */
+	mr 3, 4
+	blr


Property changes on: trunk/sys/powerpc/powerpc/setjmp.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/sigcode32.S
===================================================================
--- trunk/sys/powerpc/powerpc/sigcode32.S	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/sigcode32.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,60 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/powerpc/sigcode32.S 297630 2016-04-07 00:37:46Z jhibbits $ */
+/* $NetBSD: sigcode.S,v 1.1 1999/11/17 14:56:11 kleink 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 <machine/asm.h>
+#include <sys/syscall.h>
+#include "assym.s"
+
+/*
+ * The following code gets copied to the top of the user stack on process
+ * execution.  It does signal trampolining on signal delivery.
+ *
+ * On entry r1 points to a struct sigframe at bottom of current stack.
+ * All other registers are unchanged.
+ */
+	.globl	CNAME(sigcode32),CNAME(szsigcode32)
+CNAME(sigcode32):
+	addi	1,1,-32			/* reserved space for callee */
+	blrl
+	addi	3,1,32+SF_UC		/* restore sp, and get &frame->sf_uc */
+	li	0,SYS_sigreturn
+	sc				/* sigreturn(scp) */
+	li	0,SYS_exit
+	sc				/* exit(errno) */
+endsigcode32:
+	
+	.data
+CNAME(szsigcode32):
+	.long	endsigcode32 - CNAME(sigcode32)


Property changes on: trunk/sys/powerpc/powerpc/sigcode32.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/sigcode64.S
===================================================================
--- trunk/sys/powerpc/powerpc/sigcode64.S	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/sigcode64.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,67 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/powerpc/sigcode64.S 267040 2014-06-04 06:21:54Z nwhitehorn $ */
+/* $NetBSD: sigcode.S,v 1.1 1999/11/17 14:56:11 kleink 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 <machine/asm.h>
+#include <sys/syscall.h>
+#include "assym.s"
+
+/*
+ * The following code gets copied to the top of the user stack on process
+ * execution.  It does signal trampolining on signal delivery.
+ *
+ * On entry r1 points to a struct sigframe at bottom of current stack.
+ * All other registers are unchanged.
+ */
+	.globl	CNAME(sigcode64),CNAME(szsigcode64)
+CNAME(sigcode64):
+	addi	1,1,-112		/* reserved space for callee */
+	mflr	2			/* resolve function descriptor */
+	ld	0,0(2)			
+	ld	2,8(2)
+	mtlr	0
+
+	blrl
+
+	addi	3,1,112+SF_UC		/* restore sp, and get &frame->sf_uc */
+	li	0,SYS_sigreturn
+	sc				/* sigreturn(scp) */
+	li	0,SYS_exit
+	sc				/* exit(errno) */
+	nop				/* align to doubleword */
+endsigcode64:
+	
+	.data
+CNAME(szsigcode64):
+	.long	endsigcode64 - CNAME(sigcode64)


Property changes on: trunk/sys/powerpc/powerpc/sigcode64.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/stack_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/stack_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/stack_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,109 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2005 Antoine Brodin
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/stack_machdep.c 209975 2010-07-13 05:32:19Z nwhitehorn $");
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/stack.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+
+#include <machine/db_machdep.h>
+#include <machine/pcb.h>
+#include <machine/spr.h>
+#include <machine/stack.h>
+#include <machine/trap.h>
+
+#ifdef __powerpc64__
+#define CALLOFFSET 8 /* Account for the TOC reload slot */
+#else
+#define CALLOFFSET 4
+#endif
+
+static void
+stack_capture(struct stack *st, vm_offset_t frame)
+{
+	vm_offset_t callpc;
+
+	stack_zero(st);
+	if (frame < PAGE_SIZE)
+		return;
+	while (1) {
+		frame = *(vm_offset_t *)frame;
+		if (frame < PAGE_SIZE)
+			break;
+
+	    #ifdef __powerpc64__
+		callpc = *(vm_offset_t *)(frame + 16) - 4;
+	    #else
+		callpc = *(vm_offset_t *)(frame + 4) - 4;
+	    #endif
+		if ((callpc & 3) || (callpc < 0x100))
+			break;
+
+		/*
+		 * Don't bother traversing trap-frames - there should
+		 * be enough info down to the frame to work out where
+		 * things are going wrong. Plus, prevents this shortened
+		 * version of code from accessing user-space frames
+		 */
+		if (callpc + CALLOFFSET == (vm_offset_t) &trapexit ||
+		    callpc + CALLOFFSET == (vm_offset_t) &asttrapexit)
+			break;
+
+		if (stack_put(st, callpc) == -1)
+			break;
+	}
+}
+
+void
+stack_save_td(struct stack *st, struct thread *td)
+{
+	vm_offset_t frame;
+
+	if (TD_IS_SWAPPED(td))
+		panic("stack_save_td: swapped");
+	if (TD_IS_RUNNING(td))
+		panic("stack_save_td: running");
+
+	frame = td->td_pcb->pcb_sp;
+	stack_capture(st, frame);
+}
+
+void
+stack_save(struct stack *st)
+{
+	register_t frame;
+
+	frame = (register_t)__builtin_frame_address(1);
+	stack_capture(st, frame);
+}


Property changes on: trunk/sys/powerpc/powerpc/stack_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/suswintr.c
===================================================================
--- trunk/sys/powerpc/powerpc/suswintr.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/suswintr.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,52 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 1994 Wolfgang Solfrank.
+ * Copyright (C) 1994 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.
+ *
+ * $NetBSD: suswintr.c,v 1.2 2000/06/09 14:05:48 kleink Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/suswintr.c 125689 2004-02-11 07:48:19Z grehan $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/resourcevar.h>
+
+/*
+ * Emulate suswintr
+ *
+ * Simply return fault for all cases
+ */
+int
+suswintr(void *addr, int s)
+{
+
+	return -1;
+}


Property changes on: trunk/sys/powerpc/powerpc/suswintr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/swtch32.S
===================================================================
--- trunk/sys/powerpc/powerpc/swtch32.S	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/swtch32.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,210 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/powerpc/swtch32.S 266004 2014-05-14 04:42:38Z ian $ */
+/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */
+
+/*-
+ * Copyright (C) 2001 Benno Rice
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+*/
+/*-
+ * 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 "assym.s"
+#include "opt_sched.h"
+
+#include <sys/syscall.h>
+
+#include <machine/trap.h>
+#include <machine/param.h>
+#include <machine/asm.h>
+#include <machine/spr.h>
+
+/*
+ * void cpu_throw(struct thread *old, struct thread *new)
+ */
+ENTRY(cpu_throw)
+	mr	%r2, %r4
+	b	cpu_switchin
+
+/*
+ * void cpu_switch(struct thread *old,
+ *		   struct thread *new,
+ *		   struct mutex *mtx); 
+ *
+ * Switch to a new thread saving the current state in the old thread.
+ */
+ENTRY(cpu_switch)
+	lwz	%r6,TD_PCB(%r3)		/* Get the old thread's PCB ptr */
+	stmw	%r12,PCB_CONTEXT(%r6)	/* Save the non-volatile GP regs.
+					   These can now be used for scratch */
+
+	mfcr	%r16			/* Save the condition register */
+	stw	%r16,PCB_CR(%r6)
+	mflr	%r16			/* Save the link register */
+	stw	%r16,PCB_LR(%r6)
+#ifdef BOOKE
+	mfspr	%r16,SPR_DBCR0
+	stw	%r16,PCB_BOOKE_DBCR0(%r6)
+#endif
+	stw	%r1,PCB_SP(%r6)		/* Save the stack pointer */
+
+	mr	%r14,%r3		/* Copy the old thread ptr... */
+	mr	%r2,%r4			/* and the new thread ptr in curthread */
+	mr	%r16,%r5		/* and the new lock */
+	mr	%r17,%r6		/* and the PCB */
+	
+	lwz	%r7,PCB_FLAGS(%r17)
+	/* Save FPU context if needed */
+	andi.	%r7, %r7, PCB_FPU
+	beq	.L1
+	bl	save_fpu
+
+.L1:
+	mr	%r3,%r14		/* restore old thread ptr */
+	lwz	%r7,PCB_FLAGS(%r17)
+	/* Save Altivec context if needed */
+	andi.	%r7, %r7, PCB_VEC
+	beq	.L2
+	bl	save_vec
+	
+.L2:
+	mr	%r3,%r14		/* restore old thread ptr */
+	bl	pmap_deactivate		/* Deactivate the current pmap */
+
+	sync				/* Make sure all of that finished */
+	stw	%r16,TD_LOCK(%r14)	/* ULE:	update old thread's lock */
+
+cpu_switchin:
+#if defined(SMP) && defined(SCHED_ULE)
+	/* Wait for the new thread to become unblocked */
+	lis	%r6,blocked_lock at ha
+	addi	%r6,%r6,blocked_lock at l
+blocked_loop:
+	lwz	%r7,TD_LOCK(%r2)
+	cmpw	%r6,%r7 
+	beq-	blocked_loop
+	isync
+#endif
+
+	mfsprg	%r7,0			/* Get the pcpu pointer */
+	stw	%r2,PC_CURTHREAD(%r7)	/* Store new current thread */
+	lwz	%r17,TD_PCB(%r2)	/* Store new current PCB */
+	stw	%r17,PC_CURPCB(%r7)
+
+	mr	%r3,%r2			/* Get new thread ptr */
+	bl	pmap_activate		/* Activate the new address space */
+
+	lwz	%r6, PCB_FLAGS(%r17)
+	/* Restore FPU context if needed */
+	andi.	%r6, %r6, PCB_FPU
+	beq	.L3
+	mr	%r3,%r2			/* Pass curthread to enable_fpu */
+	bl	enable_fpu
+
+.L3:
+	lwz	%r6, PCB_FLAGS(%r17)
+	/* Restore Altivec context if needed */
+	andi.	%r6, %r6, PCB_VEC
+	beq	.L4
+	mr	%r3,%r2			/* Pass curthread to enable_vec */
+	bl	enable_vec
+
+.L4:
+	/* thread to restore is in r3 */
+	mr	%r3,%r17		/* Recover PCB ptr */
+	lmw	%r12,PCB_CONTEXT(%r3)	/* Load the non-volatile GP regs */
+	lwz	%r5,PCB_CR(%r3)		/* Load the condition register */
+	mtcr	%r5
+	lwz	%r5,PCB_LR(%r3)		/* Load the link register */
+	mtlr	%r5
+#ifdef AIM
+	lwz	%r5,PCB_AIM_USR_VSID(%r3) /* Load the USER_SR segment reg */
+	isync
+	mtsr	USER_SR,%r5
+	isync
+#endif
+#ifdef BOOKE
+	lwz	%r5,PCB_BOOKE_DBCR0(%r3)
+	mtspr	SPR_DBCR0,%r5
+#endif
+	lwz	%r1,PCB_SP(%r3)		/* Load the stack pointer */
+	/*
+	 * Perform a dummy stwcx. to clear any reservations we may have
+	 * inherited from the previous thread. It doesn't matter if the
+	 * stwcx succeeds or not. pcb_context[0] can be clobbered.
+	 */
+	stwcx.	%r1, 0, %r3
+	blr
+
+/*
+ * savectx(pcb)
+ * Update pcb, saving current processor state
+ */
+ENTRY(savectx)
+	stmw	%r12,PCB_CONTEXT(%r3)	/* Save the non-volatile GP regs */
+	mfcr	%r4			/* Save the condition register */
+	stw	%r4,PCB_CR(%r3)
+	blr
+
+/*
+ * fork_trampoline()
+ * Set up the return from cpu_fork()
+ */
+ENTRY(fork_trampoline)
+	lwz	%r3,CF_FUNC(%r1)
+	lwz	%r4,CF_ARG0(%r1)
+	lwz	%r5,CF_ARG1(%r1)
+	bl	fork_exit
+	addi	%r1,%r1,CF_SIZE-FSP	/* Allow 8 bytes in front of
+					   trapframe to simulate FRAME_SETUP
+					   does when allocating space for
+					   a frame pointer/saved LR */
+	b	trapexit


Property changes on: trunk/sys/powerpc/powerpc/swtch32.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/swtch64.S
===================================================================
--- trunk/sys/powerpc/powerpc/swtch64.S	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/swtch64.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,288 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/powerpc/swtch64.S 266001 2014-05-14 03:09:37Z ian $ */
+/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */
+
+/*-
+ * Copyright (C) 2001 Benno Rice
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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.
+*/
+/*-
+ * 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 "assym.s"
+#include "opt_sched.h"
+
+#include <sys/syscall.h>
+
+#include <machine/trap.h>
+#include <machine/param.h>
+#include <machine/asm.h>
+
+/*
+ * void cpu_throw(struct thread *old, struct thread *new)
+ */
+ENTRY(cpu_throw)
+	mr	%r13, %r4
+	b	cpu_switchin
+
+/*
+ * void cpu_switch(struct thread *old,
+ *		   struct thread *new,
+ *		   struct mutex *mtx); 
+ *
+ * Switch to a new thread saving the current state in the old thread.
+ */
+ENTRY(cpu_switch)
+	ld	%r6,TD_PCB(%r3)		/* Get the old thread's PCB ptr */
+	std	%r12,PCB_CONTEXT(%r6)	/* Save the non-volatile GP regs.
+					   These can now be used for scratch */
+	std	%r14,PCB_CONTEXT+2*8(%r6)	
+	std	%r15,PCB_CONTEXT+3*8(%r6)	
+	std	%r16,PCB_CONTEXT+4*8(%r6)	
+	std	%r17,PCB_CONTEXT+5*8(%r6)	
+	std	%r18,PCB_CONTEXT+6*8(%r6)	
+	std	%r19,PCB_CONTEXT+7*8(%r6)	
+	std	%r20,PCB_CONTEXT+8*8(%r6)	
+	std	%r21,PCB_CONTEXT+9*8(%r6)	
+	std	%r22,PCB_CONTEXT+10*8(%r6)	
+	std	%r23,PCB_CONTEXT+11*8(%r6)	
+	std	%r24,PCB_CONTEXT+12*8(%r6)	
+	std	%r25,PCB_CONTEXT+13*8(%r6)	
+	std	%r26,PCB_CONTEXT+14*8(%r6)	
+	std	%r27,PCB_CONTEXT+15*8(%r6)	
+	std	%r28,PCB_CONTEXT+16*8(%r6)	
+	std	%r29,PCB_CONTEXT+17*8(%r6)	
+	std	%r30,PCB_CONTEXT+18*8(%r6)	
+	std	%r31,PCB_CONTEXT+19*8(%r6)	
+
+	mfcr	%r16			/* Save the condition register */
+	std	%r16,PCB_CR(%r6)
+	mflr	%r16			/* Save the link register */
+	std	%r16,PCB_LR(%r6)
+	std	%r1,PCB_SP(%r6)		/* Save the stack pointer */
+	std	%r2,PCB_TOC(%r6)	/* Save the TOC pointer */
+	
+	mr	%r14,%r3		/* Copy the old thread ptr... */
+	mr	%r13,%r4		/* and the new thread ptr in curthread*/
+	mr	%r16,%r5		/* and the new lock */
+	mr	%r17,%r6		/* and the PCB */
+	
+	stdu	%r1,-48(%r1)
+
+	lwz	%r7,PCB_FLAGS(%r17)
+	/* Save FPU context if needed */
+	andi.	%r7, %r7, PCB_FPU
+	beq	.L1
+	bl	save_fpu
+	nop
+
+.L1:
+	mr	%r3,%r14		/* restore old thread ptr */
+	lwz	%r7,PCB_FLAGS(%r17)
+	/* Save Altivec context if needed */
+	andi.	%r7, %r7, PCB_VEC
+	beq	.L2
+	bl	save_vec
+	nop
+	
+.L2:
+	mr	%r3,%r14		/* restore old thread ptr */
+	bl	pmap_deactivate	/* Deactivate the current pmap */
+	nop
+
+	addi	%r1,%r1,48
+
+	sync				/* Make sure all of that finished */
+	std	%r16,TD_LOCK(%r14)	/* ULE:	update old thread's lock */
+
+cpu_switchin:
+#if defined(SMP) && defined(SCHED_ULE)
+	/* Wait for the new thread to become unblocked */
+	lis	%r6,blocked_lock at ha
+	addi	%r6,%r6,blocked_lock at l
+blocked_loop:
+	ld	%r7,TD_LOCK(%r13)
+	cmpd	%r6,%r7 
+	beq-	blocked_loop
+	isync
+#endif
+
+	mfsprg	%r7,0			/* Get the pcpu pointer */
+	std	%r13,PC_CURTHREAD(%r7)	/* Store new current thread */
+	ld	%r17,TD_PCB(%r13)	/* Store new current PCB */
+	std	%r17,PC_CURPCB(%r7)
+
+	stdu	%r1,-48(%r1)
+
+	mr	%r3,%r13		/* Get new thread ptr */
+	bl	pmap_activate		/* Activate the new address space */
+	nop
+
+	lwz	%r6, PCB_FLAGS(%r17)
+	/* Restore FPU context if needed */
+	andi.	%r6, %r6, PCB_FPU
+	beq	.L3
+	mr	%r3,%r13		/* Pass curthread to enable_fpu */
+	bl	enable_fpu
+	nop
+
+.L3:
+	lwz	%r6, PCB_FLAGS(%r17)
+	/* Restore Altivec context if needed */
+	andi.	%r6, %r6, PCB_VEC
+	beq	.L4
+	mr	%r3,%r13		/* Pass curthread to enable_vec */
+	bl	enable_vec
+	nop
+
+	/* thread to restore is in r3 */
+.L4:
+	addi	%r1,%r1,48
+	mr	%r3,%r17		/* Recover PCB ptr */
+	ld	%r12,PCB_CONTEXT(%r3)	/* Load the non-volatile GP regs. */
+	ld	%r14,PCB_CONTEXT+2*8(%r3)	
+	ld	%r15,PCB_CONTEXT+3*8(%r3)	
+	ld	%r16,PCB_CONTEXT+4*8(%r3)	
+	ld	%r17,PCB_CONTEXT+5*8(%r3)	
+	ld	%r18,PCB_CONTEXT+6*8(%r3)	
+	ld	%r19,PCB_CONTEXT+7*8(%r3)	
+	ld	%r20,PCB_CONTEXT+8*8(%r3)	
+	ld	%r21,PCB_CONTEXT+9*8(%r3)	
+	ld	%r22,PCB_CONTEXT+10*8(%r3)	
+	ld	%r23,PCB_CONTEXT+11*8(%r3)	
+	ld	%r24,PCB_CONTEXT+12*8(%r3)	
+	ld	%r25,PCB_CONTEXT+13*8(%r3)	
+	ld	%r26,PCB_CONTEXT+14*8(%r3)	
+	ld	%r27,PCB_CONTEXT+15*8(%r3)	
+	ld	%r28,PCB_CONTEXT+16*8(%r3)
+	ld	%r29,PCB_CONTEXT+17*8(%r3)	
+	ld	%r30,PCB_CONTEXT+18*8(%r3)	
+	ld	%r31,PCB_CONTEXT+19*8(%r3)	
+	ld	%r5,PCB_CR(%r3)		/* Load the condition register */
+	mtcr	%r5
+	ld	%r5,PCB_LR(%r3)		/* Load the link register */
+	mtlr	%r5
+	ld	%r1,PCB_SP(%r3)		/* Load the stack pointer */
+	ld	%r2,PCB_TOC(%r3)	/* Load the TOC pointer */
+
+	lis	%r5,USER_ADDR at highesta	/* Load the copyin/out segment reg */
+	ori	%r5,%r5,USER_ADDR at highera
+	sldi	%r5,%r5,32
+	oris	%r5,%r5,USER_ADDR at ha
+	isync
+	slbie	%r5
+	lis	%r6,USER_SLB_SLBE at highesta
+	ori	%r6,%r6,USER_SLB_SLBE at highera
+	sldi	%r6,%r6,32
+	oris	%r6,%r6,USER_SLB_SLBE at ha
+	ori	%r6,%r6,USER_SLB_SLBE at l
+	ld	%r5,PCB_AIM_USR_VSID(%r3)
+	slbmte	%r5,%r6
+	isync
+
+	/*
+	 * Perform a dummy stdcx. to clear any reservations we may have
+	 * inherited from the previous thread. It doesn't matter if the
+	 * stdcx succeeds or not. pcb_context[0] can be clobbered.
+	 */
+	stdcx.	%r1, 0, %r3
+	blr
+
+/*
+ * savectx(pcb)
+ * Update pcb, saving current processor state
+ */
+ENTRY(savectx)
+	std	%r12,PCB_CONTEXT(%r3)	/* Save the non-volatile GP regs. */
+	std	%r13,PCB_CONTEXT+1*8(%r3)	
+	std	%r14,PCB_CONTEXT+2*8(%r3)	
+	std	%r15,PCB_CONTEXT+3*8(%r3)	
+	std	%r16,PCB_CONTEXT+4*8(%r3)	
+	std	%r17,PCB_CONTEXT+5*8(%r3)	
+	std	%r18,PCB_CONTEXT+6*8(%r3)	
+	std	%r19,PCB_CONTEXT+7*8(%r3)	
+	std	%r20,PCB_CONTEXT+8*8(%r3)	
+	std	%r21,PCB_CONTEXT+9*8(%r3)	
+	std	%r22,PCB_CONTEXT+10*8(%r3)	
+	std	%r23,PCB_CONTEXT+11*8(%r3)	
+	std	%r24,PCB_CONTEXT+12*8(%r3)	
+	std	%r25,PCB_CONTEXT+13*8(%r3)	
+	std	%r26,PCB_CONTEXT+14*8(%r3)	
+	std	%r27,PCB_CONTEXT+15*8(%r3)	
+	std	%r28,PCB_CONTEXT+16*8(%r3)
+	std	%r29,PCB_CONTEXT+17*8(%r3)	
+	std	%r30,PCB_CONTEXT+18*8(%r3)	
+	std	%r31,PCB_CONTEXT+19*8(%r3)	
+
+	mfcr	%r4			/* Save the condition register */
+	std	%r4,PCB_CR(%r3)
+	std	%r2,PCB_TOC(%r3)	/* Save the TOC pointer */
+	blr
+
+/*
+ * fork_trampoline()
+ * Set up the return from cpu_fork()
+ */
+
+ENTRY_NOPROF(fork_trampoline)
+	ld	%r3,CF_FUNC(%r1)
+	ld	%r4,CF_ARG0(%r1)
+	ld	%r5,CF_ARG1(%r1)
+
+	stdu	%r1,-48(%r1)
+	bl	fork_exit
+	nop
+	addi	%r1,%r1,48+CF_SIZE-FSP	/* Allow 8 bytes in front of
+					   trapframe to simulate FRAME_SETUP
+					   does when allocating space for
+					   a frame pointer/saved LR */
+	b	trapexit
+	nop


Property changes on: trunk/sys/powerpc/powerpc/swtch64.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/syncicache.c
===================================================================
--- trunk/sys/powerpc/powerpc/syncicache.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/syncicache.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,73 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 1995-1997, 1999 Wolfgang Solfrank.
+ * Copyright (C) 1995-1997, 1999 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.
+ *
+ * $NetBSD: syncicache.c,v 1.2 1999/05/05 12:36:40 tsubai Exp $
+ */
+
+#ifndef lint
+static const char rcsid[] =
+  "$FreeBSD: stable/10/sys/powerpc/powerpc/syncicache.c 209975 2010-07-13 05:32:19Z nwhitehorn $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#if	defined(_KERNEL) || defined(_STANDALONE)
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <vm/vm.h>
+#endif
+#include <sys/sysctl.h>
+
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+
+void
+__syncicache(void *from, int len)
+{
+	register_t l, off;
+	char	*p;
+
+	off = (uintptr_t)from & (cacheline_size - 1);
+	l = len += off;
+	p = (char *)from - off;
+
+	do {
+		__asm __volatile ("dcbst 0,%0" :: "r"(p));
+		p += cacheline_size;
+	} while ((l -= cacheline_size) > 0);
+	__asm __volatile ("sync");
+	p = (char *)from - off;
+	do {
+		__asm __volatile ("icbi 0,%0" :: "r"(p));
+		p += cacheline_size;
+	} while ((len -= cacheline_size) > 0);
+	__asm __volatile ("sync; isync");
+}
+


Property changes on: trunk/sys/powerpc/powerpc/syncicache.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/sys_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/sys_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/sys_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,54 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2001 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/sys_machdep.c 209975 2010-07-13 05:32:19Z nwhitehorn $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/sysproto.h>
+
+#include "opt_compat.h"
+
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32_proto.h>
+
+int
+freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
+{
+
+	return (EINVAL);
+}
+#endif
+
+int
+sysarch(struct thread *td, struct sysarch_args *uap)
+{
+
+	return (EINVAL);
+}
+


Property changes on: trunk/sys/powerpc/powerpc/sys_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/uio_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/uio_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/uio_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,132 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2004 Alan L. Cox <alc at cs.rice.edu>
+ * Copyright (c) 1982, 1986, 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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.
+ *
+ *	@(#)kern_subr.c	8.3 (Berkeley) 1/21/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/powerpc/uio_machdep.c 266312 2014-05-17 13:59:11Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/sf_buf.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+#include <machine/cpu.h>
+#include <machine/vmparam.h>
+#include <machine/md_var.h>
+
+/*
+ * Implement uiomove(9) from physical memory using sf_bufs to
+ * avoid the creation and destruction of ephemeral mappings.
+ */
+int
+uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
+{
+	struct thread *td = curthread;
+	struct iovec *iov;
+	void *cp;
+	vm_offset_t page_offset;
+	vm_page_t m;
+	size_t cnt;
+	int error = 0;
+	int save = 0;
+	struct sf_buf *sf;
+
+	KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
+	    ("uiomove_fromphys: mode"));
+	KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
+	    ("uiomove_fromphys proc"));
+
+	save = td->td_pflags & TDP_DEADLKTREAT;
+	td->td_pflags |= TDP_DEADLKTREAT;
+	while (n > 0 && uio->uio_resid) {
+		iov = uio->uio_iov;
+		cnt = iov->iov_len;
+		if (cnt == 0) {
+			uio->uio_iov++;
+			uio->uio_iovcnt--;
+			continue;
+		}
+		if (cnt > n)
+			cnt = n;
+		page_offset = offset & PAGE_MASK;
+		cnt = min(cnt, PAGE_SIZE - page_offset);
+
+		m = ma[offset >> PAGE_SHIFT];
+		sf = sf_buf_alloc(m, 0);
+		cp = (char*)sf_buf_kva(sf) + page_offset;
+
+		switch (uio->uio_segflg) {
+			case UIO_USERSPACE:
+				maybe_yield();
+				if (uio->uio_rw == UIO_READ)
+					error = copyout(cp, iov->iov_base, cnt);
+				else
+					error = copyin(iov->iov_base, cp, cnt);
+				if (error) {
+					sf_buf_free(sf);
+					goto out;
+				}
+				break;
+			case UIO_SYSSPACE:
+				if (uio->uio_rw == UIO_READ)
+					bcopy(cp, iov->iov_base, cnt);
+				else
+					bcopy(iov->iov_base, cp, cnt);
+				break;
+			case UIO_NOCOPY:
+				break;
+		}
+		sf_buf_free(sf);
+		iov->iov_base = (char *)iov->iov_base + cnt;
+		iov->iov_len -= cnt;
+		uio->uio_resid -= cnt;
+		uio->uio_offset += cnt;
+		offset += cnt;
+		n -= cnt;
+	}
+out:
+	if (save == 0)
+		td->td_pflags &= ~TDP_DEADLKTREAT;
+	return (error);
+}


Property changes on: trunk/sys/powerpc/powerpc/uio_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/powerpc/vm_machdep.c
===================================================================
--- trunk/sys/powerpc/powerpc/vm_machdep.c	                        (rev 0)
+++ trunk/sys/powerpc/powerpc/vm_machdep.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,411 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 1982, 1986 The Regents of the University of California.
+ * Copyright (c) 1989, 1990 William Jolitz
+ * Copyright (c) 1994 John Dyson
+ * 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, and William Jolitz.
+ *
+ * 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 University of
+ *	California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ *	from: @(#)vm_machdep.c	7.3 (Berkeley) 5/13/91
+ *	Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
+ * $FreeBSD: stable/10/sys/powerpc/powerpc/vm_machdep.c 265952 2014-05-13 16:50:10Z ian $
+ */
+/*-
+ * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution at CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/vnode.h>
+#include <sys/vmmeter.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/sf_buf.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/unistd.h>
+
+#include <machine/cpu.h>
+#include <machine/fpu.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+
+/*
+ * On systems without a direct mapped region (e.g. PPC64),
+ * we use the same code as the Book E implementation. Since
+ * we need to have runtime detection of this, define some machinery
+ * for sf_bufs in this case, and ignore it on systems with direct maps.
+ */
+
+#ifndef NSFBUFS
+#define NSFBUFS		(512 + maxusers * 16)
+#endif
+
+static int nsfbufs;
+static int nsfbufspeak;
+static int nsfbufsused;
+
+SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufs, CTLFLAG_RDTUN, &nsfbufs, 0,
+    "Maximum number of sendfile(2) sf_bufs available");
+SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufspeak, CTLFLAG_RD, &nsfbufspeak, 0,
+    "Number of sendfile(2) sf_bufs at peak usage");
+SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsused, CTLFLAG_RD, &nsfbufsused, 0,
+    "Number of sendfile(2) sf_bufs in use");
+
+static void sf_buf_init(void *arg);
+SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL);
+ 
+LIST_HEAD(sf_head, sf_buf);
+ 
+/* A hash table of active sendfile(2) buffers */
+static struct sf_head *sf_buf_active;
+static u_long sf_buf_hashmask;
+
+#define SF_BUF_HASH(m)  (((m) - vm_page_array) & sf_buf_hashmask)
+
+static TAILQ_HEAD(, sf_buf) sf_buf_freelist;
+static u_int sf_buf_alloc_want;
+
+/*
+ * A lock used to synchronize access to the hash table and free list
+ */
+static struct mtx sf_buf_lock;
+
+#ifdef __powerpc64__
+extern uintptr_t tocbase;
+#endif
+
+
+/*
+ * Finish a fork operation, with process p2 nearly set up.
+ * Copy and update the pcb, set up the stack so that the child
+ * ready to run and return to user mode.
+ */
+void
+cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
+{
+	struct	trapframe *tf;
+	struct	callframe *cf;
+	struct	pcb *pcb;
+
+	KASSERT(td1 == curthread || td1 == &thread0,
+	    ("cpu_fork: p1 not curproc and not proc0"));
+	CTR3(KTR_PROC, "cpu_fork: called td1=%p p2=%p flags=%x",
+	    td1, p2, flags);
+
+	if ((flags & RFPROC) == 0)
+		return;
+
+	pcb = (struct pcb *)((td2->td_kstack +
+	    td2->td_kstack_pages * PAGE_SIZE - sizeof(struct pcb)) & ~0x2fUL);
+	td2->td_pcb = pcb;
+
+	/* Copy the pcb */
+	bcopy(td1->td_pcb, pcb, sizeof(struct pcb));
+
+	/*
+	 * Create a fresh stack for the new process.
+	 * Copy the trap frame for the return to user mode as if from a
+	 * syscall.  This copies most of the user mode register values.
+	 */
+	tf = (struct trapframe *)pcb - 1;
+	bcopy(td1->td_frame, tf, sizeof(*tf));
+
+	/* Set up trap frame. */
+	tf->fixreg[FIRSTARG] = 0;
+	tf->fixreg[FIRSTARG + 1] = 0;
+	tf->cr &= ~0x10000000;
+
+	td2->td_frame = tf;
+
+	cf = (struct callframe *)tf - 1;
+	memset(cf, 0, sizeof(struct callframe));
+	#ifdef __powerpc64__
+	cf->cf_toc = tocbase;
+	#endif
+	cf->cf_func = (register_t)fork_return;
+	cf->cf_arg0 = (register_t)td2;
+	cf->cf_arg1 = (register_t)tf;
+
+	pcb->pcb_sp = (register_t)cf;
+	KASSERT(pcb->pcb_sp % 16 == 0, ("stack misaligned"));
+	#ifdef __powerpc64__
+	pcb->pcb_lr = ((register_t *)fork_trampoline)[0];
+	pcb->pcb_toc = ((register_t *)fork_trampoline)[1];
+	#else
+	pcb->pcb_lr = (register_t)fork_trampoline;
+	#endif
+	#ifdef AIM
+	pcb->pcb_cpu.aim.usr_vsid = 0;
+	#endif
+
+	/* Setup to release spin count in fork_exit(). */
+	td2->td_md.md_spinlock_count = 1;
+	td2->td_md.md_saved_msr = PSL_KERNSET;
+
+	/*
+ 	 * Now cpu_switch() can schedule the new process.
+	 */
+}
+
+/*
+ * Intercept the return address from a freshly forked process that has NOT
+ * been scheduled yet.
+ *
+ * This is needed to make kernel threads stay in kernel mode.
+ */
+void
+cpu_set_fork_handler(struct thread *td, void (*func)(void *), void *arg)
+{
+	struct callframe *cf;
+
+	CTR4(KTR_PROC, "%s called with td=%p func=%p arg=%p",
+	    __func__, td, func, arg);
+
+	cf = (struct callframe *)td->td_pcb->pcb_sp;
+
+	cf->cf_func = (register_t)func;
+	cf->cf_arg0 = (register_t)arg;
+}
+
+void
+cpu_exit(struct thread *td)
+{
+
+}
+
+/*
+ * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-))
+ */
+static void
+sf_buf_init(void *arg)
+{
+	struct sf_buf *sf_bufs;
+	vm_offset_t sf_base;
+	int i;
+
+	/* Don't bother on systems with a direct map */
+	if (hw_direct_map)
+		return;
+
+	nsfbufs = NSFBUFS;
+	TUNABLE_INT_FETCH("kern.ipc.nsfbufs", &nsfbufs);
+
+	sf_buf_active = hashinit(nsfbufs, M_TEMP, &sf_buf_hashmask);
+	TAILQ_INIT(&sf_buf_freelist);
+	sf_base = kva_alloc(nsfbufs * PAGE_SIZE);
+	sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP,
+	    M_NOWAIT | M_ZERO);
+
+	for (i = 0; i < nsfbufs; i++) {
+		sf_bufs[i].kva = sf_base + i * PAGE_SIZE;
+		TAILQ_INSERT_TAIL(&sf_buf_freelist, &sf_bufs[i], free_entry);
+	}
+	sf_buf_alloc_want = 0;
+	mtx_init(&sf_buf_lock, "sf_buf", NULL, MTX_DEF);
+}
+
+/*
+ * Get an sf_buf from the freelist. Will block if none are available.
+ */
+struct sf_buf *
+sf_buf_alloc(struct vm_page *m, int flags)
+{
+	struct sf_head *hash_list;
+	struct sf_buf *sf;
+	int error;
+
+	if (hw_direct_map) {
+		/* Shortcut the direct mapped case */
+		return ((struct sf_buf *)m);
+	}
+
+	hash_list = &sf_buf_active[SF_BUF_HASH(m)];
+	mtx_lock(&sf_buf_lock);
+	LIST_FOREACH(sf, hash_list, list_entry) {
+		if (sf->m == m) {
+			sf->ref_count++;
+			if (sf->ref_count == 1) {
+				TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry);
+				nsfbufsused++;
+				nsfbufspeak = imax(nsfbufspeak, nsfbufsused);
+			}
+			goto done;
+		}
+	}
+
+	while ((sf = TAILQ_FIRST(&sf_buf_freelist)) == NULL) {
+		if (flags & SFB_NOWAIT)
+			goto done;
+
+		sf_buf_alloc_want++;
+		SFSTAT_INC(sf_allocwait);
+		error = msleep(&sf_buf_freelist, &sf_buf_lock,
+		    (flags & SFB_CATCH) ? PCATCH | PVM : PVM, "sfbufa", 0);
+		sf_buf_alloc_want--;
+
+		/*
+		 * If we got a signal, don't risk going back to sleep.
+		 */
+		if (error)
+			goto done;
+	}
+
+	TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry);
+	if (sf->m != NULL)
+		LIST_REMOVE(sf, list_entry);
+
+	LIST_INSERT_HEAD(hash_list, sf, list_entry);
+	sf->ref_count = 1;
+	sf->m = m;
+	nsfbufsused++;
+	nsfbufspeak = imax(nsfbufspeak, nsfbufsused);
+	pmap_qenter(sf->kva, &sf->m, 1);
+done:
+	mtx_unlock(&sf_buf_lock);
+	return (sf);
+}
+
+/*
+ * Detach mapped page and release resources back to the system.
+ *
+ * Remove a reference from the given sf_buf, adding it to the free
+ * list when its reference count reaches zero. A freed sf_buf still,
+ * however, retains its virtual-to-physical mapping until it is
+ * recycled or reactivated by sf_buf_alloc(9).
+ */
+void
+sf_buf_free(struct sf_buf *sf)
+{
+	if (hw_direct_map)
+		return;
+
+	mtx_lock(&sf_buf_lock);
+	sf->ref_count--;
+	if (sf->ref_count == 0) {
+		TAILQ_INSERT_TAIL(&sf_buf_freelist, sf, free_entry);
+		nsfbufsused--;
+
+		if (sf_buf_alloc_want > 0)
+			wakeup(&sf_buf_freelist);
+	}
+	mtx_unlock(&sf_buf_lock);
+}
+
+/*
+ * Software interrupt handler for queued VM system processing.
+ */
+void
+swi_vm(void *dummy)
+{
+
+	if (busdma_swi_pending != 0)
+		busdma_swi();
+}
+
+/*
+ * Tell whether this address is in some physical memory region.
+ * Currently used by the kernel coredump code in order to avoid
+ * dumping the ``ISA memory hole'' which could cause indefinite hangs,
+ * or other unpredictable behaviour.
+ */
+int
+is_physical_memory(vm_offset_t addr)
+{
+
+	/*
+	 * stuff other tests for known memory-mapped devices (PCI?)
+	 * here
+	 */
+	return (1);
+}
+
+/*
+ * CPU threading functions related to the VM layer. These could be used
+ * to map the SLB bits required for the kernel stack instead of forcing a
+ * fixed-size KVA.
+ */
+
+void
+cpu_thread_swapin(struct thread *td)
+{
+
+}
+
+void
+cpu_thread_swapout(struct thread *td)
+{
+
+}
+


Property changes on: trunk/sys/powerpc/powerpc/vm_machdep.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ehci_ps3.c
===================================================================
--- trunk/sys/powerpc/ps3/ehci_ps3.c	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ehci_ps3.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,174 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2010 Nathan Whitehorn
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ps3/ehci_ps3.c 278278 2015-02-05 20:03:02Z hselasky $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ps3/ehci_ps3.c 278278 2015-02-05 20:03:02Z hselasky $");
+
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+
+#include <sys/rman.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ehci.h>
+#include <dev/usb/controller/ehcireg.h>
+
+#include "ps3bus.h"
+
+struct ps3_ehci_softc {
+	ehci_softc_t            base;
+	struct bus_space         tag;
+};
+
+static int
+ehci_ps3_probe(device_t dev)
+{
+	if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_SYSBUS ||
+	    ps3bus_get_devtype(dev) != PS3_DEVTYPE_USB)
+		return (ENXIO);
+
+	device_set_desc(dev, "Playstation 3 USB 2.0 controller");
+	return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+ehci_ps3_attach(device_t dev)
+{
+	ehci_softc_t *sc = device_get_softc(dev);
+	int rid, err;
+
+	sc->sc_bus.parent = dev;
+	sc->sc_bus.devices = sc->sc_devices;
+	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+	sc->sc_bus.dma_bits = 32;
+
+	/* get all DMA memory */
+	if (usb_bus_mem_alloc_all(&sc->sc_bus,
+	    USB_GET_DMA_TAG(dev), &ehci_iterate_hw_softc))
+		return (ENOMEM);
+
+	rid = 1;
+	sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &rid, RF_ACTIVE);
+
+	if (!sc->sc_io_res) {
+		device_printf(dev, "Could not map memory\n");
+		goto error;
+	}
+
+	sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
+	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
+	sc->sc_io_size = rman_get_size(sc->sc_io_res);
+
+	rid = 1;
+	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+	    RF_SHAREABLE | RF_ACTIVE);
+
+	if (sc->sc_irq_res == NULL) {
+		device_printf(dev, "Could not allocate irq\n");
+		return (ENXIO);
+	}
+
+	sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
+	if (!sc->sc_bus.bdev) {
+		device_printf(dev, "Could not add USB device\n");
+		return (ENXIO);
+	}
+
+	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+
+	sprintf(sc->sc_vendor, "Sony");
+
+	err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+	    NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
+	if (err) {
+		device_printf(dev, "Could not setup error irq, %d\n", err);
+		goto error;
+	}
+
+	sc->sc_flags |= EHCI_SCFLG_BIGEMMIO;
+	err = ehci_init(sc);
+	if (err) {
+		device_printf(dev, "USB init failed err=%d\n", err);
+		goto error;
+	}
+
+	err = device_probe_and_attach(sc->sc_bus.bdev);
+	if (err == 0)
+		return (0);
+
+error:
+	return (ENXIO);
+}
+
+static device_method_t ehci_ps3_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe, ehci_ps3_probe),
+	DEVMETHOD(device_attach, ehci_ps3_attach),
+	DEVMETHOD(device_resume, bus_generic_resume),
+	DEVMETHOD(device_suspend, bus_generic_suspend),
+	DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+	DEVMETHOD_END
+};
+
+static driver_t ehci_ps3_driver = {
+	.name = "ehci",
+	.methods = ehci_ps3_methods,
+	.size = sizeof(ehci_softc_t),
+};
+
+static devclass_t ehci_ps3_devclass;
+
+DRIVER_MODULE(ehci_ps3, ps3bus, ehci_ps3_driver, ehci_ps3_devclass, 0, 0);
+MODULE_DEPEND(ehci_ps3, usb, 1, 1, 1);


Property changes on: trunk/sys/powerpc/ps3/ehci_ps3.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/if_glc.c
===================================================================
--- trunk/sys/powerpc/ps3/if_glc.c	                        (rev 0)
+++ trunk/sys/powerpc/ps3/if_glc.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,961 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2010 Nathan Whitehorn
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ps3/if_glc.c 243882 2012-12-05 08:04:20Z glebius $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/endian.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+
+#include <machine/pio.h>
+#include <machine/bus.h>
+#include <machine/platform.h>
+#include <machine/pmap.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include "ps3bus.h"
+#include "ps3-hvcall.h"
+#include "if_glcreg.h"
+
+static int	glc_probe(device_t);
+static int	glc_attach(device_t);
+static void	glc_init(void *xsc);
+static void	glc_start(struct ifnet *ifp);
+static int	glc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
+static void	glc_set_multicast(struct glc_softc *sc);
+static int	glc_add_rxbuf(struct glc_softc *sc, int idx);
+static int	glc_add_rxbuf_dma(struct glc_softc *sc, int idx);
+static int	glc_encap(struct glc_softc *sc, struct mbuf **m_head,
+		    bus_addr_t *pktdesc);
+static int	glc_intr_filter(void *xsc);
+static void	glc_intr(void *xsc);
+static void	glc_tick(void *xsc);
+static void	glc_media_status(struct ifnet *ifp, struct ifmediareq *ifmr);
+static int	glc_media_change(struct ifnet *ifp);
+
+static MALLOC_DEFINE(M_GLC, "gelic", "PS3 GELIC ethernet");
+
+static device_method_t glc_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		glc_probe),
+	DEVMETHOD(device_attach,	glc_attach),
+
+	{ 0, 0 }
+};
+
+static driver_t glc_driver = {
+	"glc",
+	glc_methods,
+	sizeof(struct glc_softc)
+};
+
+static devclass_t glc_devclass;
+
+DRIVER_MODULE(glc, ps3bus, glc_driver, glc_devclass, 0, 0);
+
+static int 
+glc_probe(device_t dev) 
+{
+
+	if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_SYSBUS ||
+	    ps3bus_get_devtype(dev) != PS3_DEVTYPE_GELIC)
+		return (ENXIO);
+
+	device_set_desc(dev, "Playstation 3 GELIC Network Controller");
+	return (BUS_PROBE_SPECIFIC);
+}
+
+static void
+glc_getphys(void *xaddr, bus_dma_segment_t *segs, int nsegs, int error)
+{
+	if (error != 0)
+		return;
+
+	*(bus_addr_t *)xaddr = segs[0].ds_addr;
+}
+
+static int 
+glc_attach(device_t dev) 
+{
+	struct glc_softc *sc;
+	struct glc_txsoft *txs;
+	uint64_t mac64, val, junk;
+	int i, err;
+
+	sc = device_get_softc(dev);
+
+	sc->sc_bus = ps3bus_get_bus(dev);
+	sc->sc_dev = ps3bus_get_device(dev);
+	sc->sc_self = dev;
+
+	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+	    MTX_DEF);
+	callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0);
+	sc->next_txdma_slot = 0;
+	sc->bsy_txdma_slots = 0;
+	sc->sc_next_rxdma_slot = 0;
+	sc->first_used_txdma_slot = -1;
+
+	/*
+	 * Shut down existing tasks.
+	 */
+
+	lv1_net_stop_tx_dma(sc->sc_bus, sc->sc_dev, 0);
+	lv1_net_stop_rx_dma(sc->sc_bus, sc->sc_dev, 0);
+
+	sc->sc_ifp = if_alloc(IFT_ETHER);
+	sc->sc_ifp->if_softc = sc;
+
+	/*
+	 * Get MAC address and VLAN id
+	 */
+
+	lv1_net_control(sc->sc_bus, sc->sc_dev, GELIC_GET_MAC_ADDRESS,
+	    0, 0, 0, &mac64, &junk);
+	memcpy(sc->sc_enaddr, &((uint8_t *)&mac64)[2], sizeof(sc->sc_enaddr));
+	sc->sc_tx_vlan = sc->sc_rx_vlan = -1;
+	err = lv1_net_control(sc->sc_bus, sc->sc_dev, GELIC_GET_VLAN_ID,
+	    GELIC_VLAN_TX_ETHERNET, 0, 0, &val, &junk);
+	if (err == 0)
+		sc->sc_tx_vlan = val;
+	err = lv1_net_control(sc->sc_bus, sc->sc_dev, GELIC_GET_VLAN_ID,
+	    GELIC_VLAN_RX_ETHERNET, 0, 0, &val, &junk);
+	if (err == 0)
+		sc->sc_rx_vlan = val;
+
+	/*
+	 * Set up interrupt handler
+	 */
+	sc->sc_irqid = 0;
+	sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid,
+	    RF_ACTIVE);
+	if (sc->sc_irq == NULL) {
+		device_printf(dev, "Could not allocate IRQ!\n");
+		mtx_destroy(&sc->sc_mtx);
+		return (ENXIO);
+	}
+
+	bus_setup_intr(dev, sc->sc_irq,
+	    INTR_TYPE_NET | INTR_MPSAFE | INTR_ENTROPY,
+	    glc_intr_filter, glc_intr, sc, &sc->sc_irqctx);
+	sc->sc_hwirq_status = (uint64_t *)contigmalloc(8, M_GLC, M_ZERO, 0,
+	    BUS_SPACE_MAXADDR_32BIT, 8, PAGE_SIZE);
+	lv1_net_set_interrupt_status_indicator(sc->sc_bus, sc->sc_dev,
+	    vtophys(sc->sc_hwirq_status), 0);
+	lv1_net_set_interrupt_mask(sc->sc_bus, sc->sc_dev,
+	    GELIC_INT_RXDONE | GELIC_INT_RXFRAME | GELIC_INT_PHY |
+	    GELIC_INT_TX_CHAIN_END, 0);
+
+	/*
+	 * Set up DMA.
+	 */
+
+	err = bus_dma_tag_create(bus_get_dma_tag(dev), 32, 0,
+	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+	    129*sizeof(struct glc_dmadesc), 1, 128*sizeof(struct glc_dmadesc),
+	    0, NULL,NULL, &sc->sc_dmadesc_tag);
+
+	err = bus_dmamem_alloc(sc->sc_dmadesc_tag, (void **)&sc->sc_txdmadesc,
+	    BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO,
+	    &sc->sc_txdmadesc_map);
+	err = bus_dmamap_load(sc->sc_dmadesc_tag, sc->sc_txdmadesc_map,
+	    sc->sc_txdmadesc, 128*sizeof(struct glc_dmadesc), glc_getphys,
+	    &sc->sc_txdmadesc_phys, 0);
+	err = bus_dmamem_alloc(sc->sc_dmadesc_tag, (void **)&sc->sc_rxdmadesc,
+	    BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO,
+	    &sc->sc_rxdmadesc_map);
+	err = bus_dmamap_load(sc->sc_dmadesc_tag, sc->sc_rxdmadesc_map,
+	    sc->sc_rxdmadesc, 128*sizeof(struct glc_dmadesc), glc_getphys,
+	    &sc->sc_rxdmadesc_phys, 0);
+
+	err = bus_dma_tag_create(bus_get_dma_tag(dev), 128, 0,
+	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+	    BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0, NULL,NULL,
+	    &sc->sc_rxdma_tag);
+	err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
+	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+	    BUS_SPACE_MAXSIZE_32BIT, 16, BUS_SPACE_MAXSIZE_32BIT, 0, NULL,NULL,
+	    &sc->sc_txdma_tag);
+
+	/* init transmit descriptors */
+	STAILQ_INIT(&sc->sc_txfreeq);
+	STAILQ_INIT(&sc->sc_txdirtyq);
+
+	/* create TX DMA maps */
+	err = ENOMEM;
+	for (i = 0; i < GLC_MAX_TX_PACKETS; i++) {
+		txs = &sc->sc_txsoft[i];
+		txs->txs_mbuf = NULL;
+		err = bus_dmamap_create(sc->sc_txdma_tag, 0, &txs->txs_dmamap);
+		if (err) {
+			device_printf(dev,
+			    "unable to create TX DMA map %d, error = %d\n",
+			    i, err);
+		}
+		STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
+	}
+
+	/* Create the receive buffer DMA maps. */
+	for (i = 0; i < GLC_MAX_RX_PACKETS; i++) {
+		err = bus_dmamap_create(sc->sc_rxdma_tag, 0,
+		    &sc->sc_rxsoft[i].rxs_dmamap);
+		if (err) {
+			device_printf(dev,
+			    "unable to create RX DMA map %d, error = %d\n",
+			    i, err);
+		}
+		sc->sc_rxsoft[i].rxs_mbuf = NULL;
+	}
+
+	/*
+	 * Attach to network stack
+	 */
+
+	if_initname(sc->sc_ifp, device_get_name(dev), device_get_unit(dev));
+	sc->sc_ifp->if_mtu = ETHERMTU;
+	sc->sc_ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+	sc->sc_ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
+	sc->sc_ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_RXCSUM;
+	sc->sc_ifp->if_capenable = IFCAP_HWCSUM | IFCAP_RXCSUM;
+	sc->sc_ifp->if_start = glc_start;
+	sc->sc_ifp->if_ioctl = glc_ioctl;
+	sc->sc_ifp->if_init = glc_init;
+
+	ifmedia_init(&sc->sc_media, IFM_IMASK, glc_media_change,
+	    glc_media_status);
+	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_10_T, 0, NULL);
+	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL);
+	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_100_TX, 0, NULL);
+	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL);
+	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL);
+	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
+	ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
+
+	IFQ_SET_MAXLEN(&sc->sc_ifp->if_snd, GLC_MAX_TX_PACKETS);
+	sc->sc_ifp->if_snd.ifq_drv_maxlen = GLC_MAX_TX_PACKETS;
+	IFQ_SET_READY(&sc->sc_ifp->if_snd);
+
+	ether_ifattach(sc->sc_ifp, sc->sc_enaddr);
+	sc->sc_ifp->if_hwassist = 0;
+
+	return (0);
+
+	mtx_destroy(&sc->sc_mtx);
+	if_free(sc->sc_ifp);
+	return (ENXIO);
+}
+
+static void
+glc_init_locked(struct glc_softc *sc)
+{
+	int i, error;
+	struct glc_rxsoft *rxs;
+	struct glc_txsoft *txs;
+
+	mtx_assert(&sc->sc_mtx, MA_OWNED);
+
+	lv1_net_stop_tx_dma(sc->sc_bus, sc->sc_dev, 0);
+	lv1_net_stop_rx_dma(sc->sc_bus, sc->sc_dev, 0);
+
+	glc_set_multicast(sc);
+
+	for (i = 0; i < GLC_MAX_RX_PACKETS; i++) {
+		rxs = &sc->sc_rxsoft[i];
+		rxs->rxs_desc_slot = i;
+
+		if (rxs->rxs_mbuf == NULL) {
+			glc_add_rxbuf(sc, i);
+
+			if (rxs->rxs_mbuf == NULL) {
+				rxs->rxs_desc_slot = -1;
+				break;
+			}
+		}
+
+		glc_add_rxbuf_dma(sc, i);
+		bus_dmamap_sync(sc->sc_dmadesc_tag, sc->sc_rxdmadesc_map,
+		    BUS_DMASYNC_PREREAD);
+	}
+
+	/* Clear TX dirty queue */
+	while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
+		STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
+		bus_dmamap_unload(sc->sc_txdma_tag, txs->txs_dmamap);
+
+		if (txs->txs_mbuf != NULL) {
+			m_freem(txs->txs_mbuf);
+			txs->txs_mbuf = NULL;
+		}
+
+		STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
+	}
+	sc->first_used_txdma_slot = -1;
+	sc->bsy_txdma_slots = 0;
+
+	error = lv1_net_start_rx_dma(sc->sc_bus, sc->sc_dev,
+	    sc->sc_rxsoft[0].rxs_desc, 0);
+	if (error != 0)
+		device_printf(sc->sc_self,
+		    "lv1_net_start_rx_dma error: %d\n", error);
+
+	sc->sc_ifp->if_drv_flags |= IFF_DRV_RUNNING;
+	sc->sc_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+	sc->sc_ifpflags = sc->sc_ifp->if_flags;
+
+	sc->sc_wdog_timer = 0;
+	callout_reset(&sc->sc_tick_ch, hz, glc_tick, sc);
+}
+
+static void
+glc_stop(void *xsc)
+{
+	struct glc_softc *sc = xsc;
+
+	mtx_assert(&sc->sc_mtx, MA_OWNED);
+
+	lv1_net_stop_tx_dma(sc->sc_bus, sc->sc_dev, 0);
+	lv1_net_stop_rx_dma(sc->sc_bus, sc->sc_dev, 0);
+}
+
+static void
+glc_init(void *xsc)
+{
+	struct glc_softc *sc = xsc;
+
+	mtx_lock(&sc->sc_mtx);
+	glc_init_locked(sc);
+	mtx_unlock(&sc->sc_mtx);
+}
+
+static void
+glc_tick(void *xsc)
+{
+	struct glc_softc *sc = xsc;
+
+	mtx_assert(&sc->sc_mtx, MA_OWNED);
+
+	/*
+	 * XXX: Sometimes the RX queue gets stuck. Poke it periodically until
+	 * we figure out why. This will fail harmlessly if the RX queue is
+	 * already running.
+	 */
+	lv1_net_start_rx_dma(sc->sc_bus, sc->sc_dev,
+	    sc->sc_rxsoft[sc->sc_next_rxdma_slot].rxs_desc, 0);
+
+	if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) {
+		callout_reset(&sc->sc_tick_ch, hz, glc_tick, sc);
+		return;
+	}
+
+	/* Problems */
+	device_printf(sc->sc_self, "device timeout\n");
+
+	glc_init_locked(sc);
+}
+
+static void
+glc_start_locked(struct ifnet *ifp)
+{
+	struct glc_softc *sc = ifp->if_softc;
+	bus_addr_t first, pktdesc;
+	int kickstart = 0;
+	int error;
+	struct mbuf *mb_head;
+
+	mtx_assert(&sc->sc_mtx, MA_OWNED);
+	first = 0;
+
+	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+	    IFF_DRV_RUNNING)
+		return;
+
+	if (STAILQ_EMPTY(&sc->sc_txdirtyq))
+		kickstart = 1;
+
+	while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+		IFQ_DRV_DEQUEUE(&ifp->if_snd, mb_head);
+
+		if (mb_head == NULL)
+			break;
+
+		/* Check if the ring buffer is full */
+		if (sc->bsy_txdma_slots > 125) {
+			/* Put the packet back and stop */
+			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+			IFQ_DRV_PREPEND(&ifp->if_snd, mb_head);
+			break;
+		}
+
+		BPF_MTAP(ifp, mb_head);
+
+		if (sc->sc_tx_vlan >= 0)
+			mb_head = ether_vlanencap(mb_head, sc->sc_tx_vlan);
+
+		if (glc_encap(sc, &mb_head, &pktdesc)) {
+			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+			break;
+		}
+
+		if (first == 0)
+			first = pktdesc;
+	}
+
+	if (kickstart && first != 0) {
+		error = lv1_net_start_tx_dma(sc->sc_bus, sc->sc_dev, first, 0);
+		if (error != 0)
+			device_printf(sc->sc_self,
+			    "lv1_net_start_tx_dma error: %d\n", error);
+		sc->sc_wdog_timer = 5;
+	}
+}
+
+static void
+glc_start(struct ifnet *ifp)
+{
+	struct glc_softc *sc = ifp->if_softc;
+
+	mtx_lock(&sc->sc_mtx);
+	glc_start_locked(ifp);
+	mtx_unlock(&sc->sc_mtx);
+}
+
+static int
+glc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+	struct glc_softc *sc = ifp->if_softc;
+	struct ifreq *ifr = (struct ifreq *)data;
+	int err = 0;
+
+	switch (cmd) {
+	case SIOCSIFFLAGS:
+                mtx_lock(&sc->sc_mtx);
+		if ((ifp->if_flags & IFF_UP) != 0) {
+			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
+			   ((ifp->if_flags ^ sc->sc_ifpflags) &
+			    (IFF_ALLMULTI | IFF_PROMISC)) != 0)
+				glc_set_multicast(sc);
+			else
+				glc_init_locked(sc);
+		}
+		else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+			glc_stop(sc);
+		sc->sc_ifpflags = ifp->if_flags;
+		mtx_unlock(&sc->sc_mtx);
+		break;
+	case SIOCADDMULTI:
+	case SIOCDELMULTI:
+                mtx_lock(&sc->sc_mtx);
+		glc_set_multicast(sc);
+                mtx_unlock(&sc->sc_mtx);
+		break;
+	case SIOCGIFMEDIA:
+	case SIOCSIFMEDIA:
+		err = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
+		break;
+	default:
+		err = ether_ioctl(ifp, cmd, data);
+		break;
+	}
+
+	return (err);
+}
+
+static void
+glc_set_multicast(struct glc_softc *sc)
+{
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ifmultiaddr *inm;
+	uint64_t addr;
+	int naddrs;
+
+	/* Clear multicast filter */
+	lv1_net_remove_multicast_address(sc->sc_bus, sc->sc_dev, 0, 1);
+
+	/* Add broadcast */
+	lv1_net_add_multicast_address(sc->sc_bus, sc->sc_dev,
+	    0xffffffffffffL, 0);
+
+	if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
+		lv1_net_add_multicast_address(sc->sc_bus, sc->sc_dev, 0, 1);
+	} else {
+		if_maddr_rlock(ifp);
+		naddrs = 1; /* Include broadcast */
+		TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) {
+			if (inm->ifma_addr->sa_family != AF_LINK)
+				continue;
+			addr = 0;
+			memcpy(&((uint8_t *)(&addr))[2],
+			    LLADDR((struct sockaddr_dl *)inm->ifma_addr),
+			    ETHER_ADDR_LEN);
+
+			lv1_net_add_multicast_address(sc->sc_bus, sc->sc_dev,
+			    addr, 0);
+
+			/*
+			 * Filter can only hold 32 addresses, so fall back to
+			 * the IFF_ALLMULTI case if we have too many.
+			 */
+			if (++naddrs >= 32) {
+				lv1_net_add_multicast_address(sc->sc_bus,
+				    sc->sc_dev, 0, 1);
+				break;
+			}
+		}
+		if_maddr_runlock(ifp);
+	}
+}
+
+static int
+glc_add_rxbuf(struct glc_softc *sc, int idx)
+{
+	struct glc_rxsoft *rxs = &sc->sc_rxsoft[idx];
+	struct mbuf *m;
+	bus_dma_segment_t segs[1];
+	int error, nsegs;
+			
+	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+	if (m == NULL)
+		return (ENOBUFS);
+	m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
+
+	if (rxs->rxs_mbuf != NULL) {
+		bus_dmamap_sync(sc->sc_rxdma_tag, rxs->rxs_dmamap,
+		    BUS_DMASYNC_POSTREAD);
+		bus_dmamap_unload(sc->sc_rxdma_tag, rxs->rxs_dmamap);
+	}
+
+	error = bus_dmamap_load_mbuf_sg(sc->sc_rxdma_tag, rxs->rxs_dmamap, m,
+	    segs, &nsegs, BUS_DMA_NOWAIT);
+	if (error != 0) {
+		device_printf(sc->sc_self,
+		    "cannot load RS DMA map %d, error = %d\n", idx, error);
+		m_freem(m);
+		return (error);
+	}
+	/* If nsegs is wrong then the stack is corrupt. */
+	KASSERT(nsegs == 1,
+	    ("%s: too many DMA segments (%d)", __func__, nsegs));
+	rxs->rxs_mbuf = m;
+	rxs->segment = segs[0];
+
+	bus_dmamap_sync(sc->sc_rxdma_tag, rxs->rxs_dmamap, BUS_DMASYNC_PREREAD);
+
+	return (0);
+}
+
+static int
+glc_add_rxbuf_dma(struct glc_softc *sc, int idx)
+{
+	struct glc_rxsoft *rxs = &sc->sc_rxsoft[idx];
+	
+	bzero(&sc->sc_rxdmadesc[idx], sizeof(sc->sc_rxdmadesc[idx]));
+	sc->sc_rxdmadesc[idx].paddr = rxs->segment.ds_addr;
+	sc->sc_rxdmadesc[idx].len = rxs->segment.ds_len;
+	sc->sc_rxdmadesc[idx].next = sc->sc_rxdmadesc_phys +
+	    ((idx + 1) % GLC_MAX_RX_PACKETS)*sizeof(sc->sc_rxdmadesc[idx]);
+	sc->sc_rxdmadesc[idx].cmd_stat = GELIC_DESCR_OWNED;
+
+	rxs->rxs_desc_slot = idx;
+	rxs->rxs_desc = sc->sc_rxdmadesc_phys + idx*sizeof(struct glc_dmadesc);
+
+        return (0);
+}
+
+static int
+glc_encap(struct glc_softc *sc, struct mbuf **m_head, bus_addr_t *pktdesc)
+{
+	bus_dma_segment_t segs[16];
+	struct glc_txsoft *txs;
+	struct mbuf *m;
+	bus_addr_t firstslotphys;
+	int i, idx, nsegs, nsegs_max;
+	int err = 0;
+
+	/* Max number of segments is the number of free DMA slots */
+	nsegs_max = 128 - sc->bsy_txdma_slots;
+
+	if (nsegs_max > 16 || sc->first_used_txdma_slot < 0)
+		nsegs_max = 16;
+
+	/* Get a work queue entry. */
+	if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) {
+		/* Ran out of descriptors. */
+		return (ENOBUFS);
+	}
+
+	nsegs = 0;
+	for (m = *m_head; m != NULL; m = m->m_next)
+		nsegs++;
+
+	if (nsegs > nsegs_max) {
+		m = m_collapse(*m_head, M_NOWAIT, nsegs_max);
+		if (m == NULL) {
+			m_freem(*m_head);
+			*m_head = NULL;
+			return (ENOBUFS);
+		}
+		*m_head = m;
+	}
+	
+	err = bus_dmamap_load_mbuf_sg(sc->sc_txdma_tag, txs->txs_dmamap,
+	    *m_head, segs, &nsegs, BUS_DMA_NOWAIT);
+	if (err != 0) {
+		m_freem(*m_head);
+		*m_head = NULL;
+		return (err);
+	}
+
+	KASSERT(nsegs <= 128 - sc->bsy_txdma_slots,
+	    ("GLC: Mapped too many (%d) DMA segments with %d available",
+	    nsegs, 128 - sc->bsy_txdma_slots));
+
+	if (nsegs == 0) {
+		m_freem(*m_head);
+		*m_head = NULL;
+		return (EIO);
+	}
+
+	txs->txs_ndescs = nsegs;
+	txs->txs_firstdesc = sc->next_txdma_slot;
+
+	idx = txs->txs_firstdesc;
+	firstslotphys = sc->sc_txdmadesc_phys +
+	    txs->txs_firstdesc*sizeof(struct glc_dmadesc);
+
+	for (i = 0; i < nsegs; i++) {
+		bzero(&sc->sc_txdmadesc[idx], sizeof(sc->sc_txdmadesc[idx]));
+		sc->sc_txdmadesc[idx].paddr = segs[i].ds_addr;
+		sc->sc_txdmadesc[idx].len = segs[i].ds_len;
+		sc->sc_txdmadesc[idx].next = sc->sc_txdmadesc_phys +
+		    ((idx + 1) % GLC_MAX_TX_PACKETS)*sizeof(struct glc_dmadesc);
+		sc->sc_txdmadesc[idx].cmd_stat |= GELIC_CMDSTAT_NOIPSEC;
+
+		if (i+1 == nsegs) {
+			txs->txs_lastdesc = idx;
+			sc->sc_txdmadesc[idx].next = 0;
+			sc->sc_txdmadesc[idx].cmd_stat |= GELIC_CMDSTAT_LAST;
+		}
+
+		if ((*m_head)->m_pkthdr.csum_flags & CSUM_TCP)
+			sc->sc_txdmadesc[idx].cmd_stat |= GELIC_CMDSTAT_CSUM_TCP;
+		if ((*m_head)->m_pkthdr.csum_flags & CSUM_UDP)
+			sc->sc_txdmadesc[idx].cmd_stat |= GELIC_CMDSTAT_CSUM_UDP;
+		sc->sc_txdmadesc[idx].cmd_stat |= GELIC_DESCR_OWNED;
+
+		idx = (idx + 1) % GLC_MAX_TX_PACKETS;
+	}
+	sc->next_txdma_slot = idx;
+	sc->bsy_txdma_slots += nsegs;
+	if (txs->txs_firstdesc != 0)
+		idx = txs->txs_firstdesc - 1;
+	else
+		idx = GLC_MAX_TX_PACKETS - 1;
+
+	if (sc->first_used_txdma_slot < 0)
+		sc->first_used_txdma_slot = txs->txs_firstdesc;
+
+	bus_dmamap_sync(sc->sc_txdma_tag, txs->txs_dmamap,
+	    BUS_DMASYNC_PREWRITE);
+	sc->sc_txdmadesc[idx].next = firstslotphys;
+
+	STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q);
+	STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q);
+	txs->txs_mbuf = *m_head;
+	*pktdesc = firstslotphys;
+
+	return (0);
+}
+
+static void
+glc_rxintr(struct glc_softc *sc)
+{
+	int i, restart_rxdma, error;
+	struct mbuf *m;
+	struct ifnet *ifp = sc->sc_ifp;
+
+	bus_dmamap_sync(sc->sc_dmadesc_tag, sc->sc_rxdmadesc_map,
+	    BUS_DMASYNC_POSTREAD);
+
+	restart_rxdma = 0;
+	while ((sc->sc_rxdmadesc[sc->sc_next_rxdma_slot].cmd_stat &
+	   GELIC_DESCR_OWNED) == 0) {
+		i = sc->sc_next_rxdma_slot;
+		sc->sc_next_rxdma_slot++;
+		if (sc->sc_next_rxdma_slot >= GLC_MAX_RX_PACKETS)
+			sc->sc_next_rxdma_slot = 0;
+
+		if (sc->sc_rxdmadesc[i].cmd_stat & GELIC_CMDSTAT_CHAIN_END)
+			restart_rxdma = 1;
+
+		if (sc->sc_rxdmadesc[i].rxerror & GELIC_RXERRORS) {
+			ifp->if_ierrors++;
+			goto requeue;
+		}
+
+		m = sc->sc_rxsoft[i].rxs_mbuf;
+		if (sc->sc_rxdmadesc[i].data_stat & GELIC_RX_IPCSUM) {
+			m->m_pkthdr.csum_flags |=
+			    CSUM_IP_CHECKED | CSUM_IP_VALID;
+		}
+		if (sc->sc_rxdmadesc[i].data_stat & GELIC_RX_TCPUDPCSUM) {
+			m->m_pkthdr.csum_flags |=
+			    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+			m->m_pkthdr.csum_data = 0xffff;
+		}
+
+		if (glc_add_rxbuf(sc, i)) {
+			ifp->if_ierrors++;
+			goto requeue;
+		}
+
+		ifp->if_ipackets++;
+		m->m_pkthdr.rcvif = ifp;
+		m->m_len = sc->sc_rxdmadesc[i].valid_size;
+		m->m_pkthdr.len = m->m_len;
+
+		/*
+		 * Remove VLAN tag. Even on early firmwares that do not allow
+		 * multiple VLANs, the VLAN tag is still in place here.
+		 */
+		m_adj(m, 2);
+
+		mtx_unlock(&sc->sc_mtx);
+		(*ifp->if_input)(ifp, m);
+		mtx_lock(&sc->sc_mtx);
+
+	    requeue:
+		glc_add_rxbuf_dma(sc, i);	
+	}
+
+	bus_dmamap_sync(sc->sc_dmadesc_tag, sc->sc_rxdmadesc_map,
+	    BUS_DMASYNC_PREWRITE);
+
+	if (restart_rxdma) {
+		error = lv1_net_start_rx_dma(sc->sc_bus, sc->sc_dev,
+		    sc->sc_rxsoft[sc->sc_next_rxdma_slot].rxs_desc, 0);
+		if (error != 0)
+			device_printf(sc->sc_self,
+			    "lv1_net_start_rx_dma error: %d\n", error);
+	}
+}
+
+static void
+glc_txintr(struct glc_softc *sc)
+{
+	struct ifnet *ifp = sc->sc_ifp;
+	struct glc_txsoft *txs;
+	int progress = 0, kickstart = 0, error;
+
+	bus_dmamap_sync(sc->sc_dmadesc_tag, sc->sc_txdmadesc_map,
+	    BUS_DMASYNC_POSTREAD);
+
+	while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
+		if (sc->sc_txdmadesc[txs->txs_lastdesc].cmd_stat
+		    & GELIC_DESCR_OWNED)
+			break;
+
+		STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
+		bus_dmamap_unload(sc->sc_txdma_tag, txs->txs_dmamap);
+		sc->bsy_txdma_slots -= txs->txs_ndescs;
+
+		if (txs->txs_mbuf != NULL) {
+			m_freem(txs->txs_mbuf);
+			txs->txs_mbuf = NULL;
+		}
+
+		if ((sc->sc_txdmadesc[txs->txs_lastdesc].cmd_stat & 0xf0000000)
+		    != 0) {
+			lv1_net_stop_tx_dma(sc->sc_bus, sc->sc_dev, 0);
+			kickstart = 1;
+			ifp->if_oerrors++;
+		}
+
+		if (sc->sc_txdmadesc[txs->txs_lastdesc].cmd_stat &
+		    GELIC_CMDSTAT_CHAIN_END)
+			kickstart = 1;
+
+		STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
+		ifp->if_opackets++;
+		progress = 1;
+	}
+
+	if (txs != NULL)
+		sc->first_used_txdma_slot = txs->txs_firstdesc;
+	else
+		sc->first_used_txdma_slot = -1;
+
+	if (kickstart || txs != NULL) {
+		/* Speculatively (or necessarily) start the TX queue again */
+		error = lv1_net_start_tx_dma(sc->sc_bus, sc->sc_dev,
+		    sc->sc_txdmadesc_phys +
+		    txs->txs_firstdesc*sizeof(struct glc_dmadesc), 0);
+		if (error != 0)
+			device_printf(sc->sc_self,
+			    "lv1_net_start_tx_dma error: %d\n", error);
+	}
+
+	if (progress) {
+		/*
+		 * We freed some descriptors, so reset IFF_DRV_OACTIVE
+		 * and restart.
+		 */
+		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+		sc->sc_wdog_timer = STAILQ_EMPTY(&sc->sc_txdirtyq) ? 0 : 5;
+
+		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) &&
+		    !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+			glc_start_locked(ifp);
+	}
+}
+
+static int
+glc_intr_filter(void *xsc)
+{
+	struct glc_softc *sc = xsc; 
+
+	powerpc_sync();
+	atomic_set_64(&sc->sc_interrupt_status, *sc->sc_hwirq_status);
+	return (FILTER_SCHEDULE_THREAD);
+}
+
+static void
+glc_intr(void *xsc)
+{
+	struct glc_softc *sc = xsc; 
+	uint64_t status, linkstat, junk;
+
+	mtx_lock(&sc->sc_mtx);
+
+	status = atomic_readandclear_64(&sc->sc_interrupt_status);
+
+	if (status == 0) {
+		mtx_unlock(&sc->sc_mtx);
+		return;
+	}
+
+	if (status & (GELIC_INT_RXDONE | GELIC_INT_RXFRAME))
+		glc_rxintr(sc);
+
+	if (status & (GELIC_INT_TXDONE | GELIC_INT_TX_CHAIN_END))
+		glc_txintr(sc);
+
+	if (status & GELIC_INT_PHY) {
+		lv1_net_control(sc->sc_bus, sc->sc_dev, GELIC_GET_LINK_STATUS,
+		    GELIC_VLAN_TX_ETHERNET, 0, 0, &linkstat, &junk);
+
+		linkstat = (linkstat & GELIC_LINK_UP) ?
+		    LINK_STATE_UP : LINK_STATE_DOWN;
+		if (linkstat != sc->sc_ifp->if_link_state)
+			if_link_state_change(sc->sc_ifp, linkstat);
+	}
+
+	mtx_unlock(&sc->sc_mtx);
+}
+
+static void
+glc_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+	struct glc_softc *sc = ifp->if_softc; 
+	uint64_t status, junk;
+
+	ifmr->ifm_status = IFM_AVALID;
+	ifmr->ifm_active = IFM_ETHER;
+
+	lv1_net_control(sc->sc_bus, sc->sc_dev, GELIC_GET_LINK_STATUS,
+	    GELIC_VLAN_TX_ETHERNET, 0, 0, &status, &junk);
+
+	if (status & GELIC_LINK_UP)
+		ifmr->ifm_status |= IFM_ACTIVE;
+
+	if (status & GELIC_SPEED_10)
+		ifmr->ifm_active |= IFM_10_T;
+	else if (status & GELIC_SPEED_100)
+		ifmr->ifm_active |= IFM_100_TX;
+	else if (status & GELIC_SPEED_1000)
+		ifmr->ifm_active |= IFM_1000_T;
+
+	if (status & GELIC_FULL_DUPLEX)
+		ifmr->ifm_active |= IFM_FDX;
+	else
+		ifmr->ifm_active |= IFM_HDX;
+}
+
+static int
+glc_media_change(struct ifnet *ifp)
+{
+	struct glc_softc *sc = ifp->if_softc; 
+	uint64_t mode, junk;
+	int result;
+
+	if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_ETHER)
+		return (EINVAL);
+
+	switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) {
+	case IFM_AUTO:
+		mode = GELIC_AUTO_NEG;
+		break;
+	case IFM_10_T:
+		mode = GELIC_SPEED_10;
+		break;
+	case IFM_100_TX:
+		mode = GELIC_SPEED_100;
+		break;
+	case IFM_1000_T:
+		mode = GELIC_SPEED_1000 | GELIC_FULL_DUPLEX;
+		break;
+	default:
+		return (EINVAL);
+	}
+
+	if (IFM_OPTIONS(sc->sc_media.ifm_media) & IFM_FDX)
+		mode |= GELIC_FULL_DUPLEX;
+
+	result = lv1_net_control(sc->sc_bus, sc->sc_dev, GELIC_SET_LINK_MODE,
+	    GELIC_VLAN_TX_ETHERNET, mode, 0, &junk, &junk);
+
+	return (result ? EIO : 0);
+}
+


Property changes on: trunk/sys/powerpc/ps3/if_glc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/if_glcreg.h
===================================================================
--- trunk/sys/powerpc/ps3/if_glcreg.h	                        (rev 0)
+++ trunk/sys/powerpc/ps3/if_glcreg.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,161 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2010 Nathan Whitehorn
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ps3/if_glcreg.h 217044 2011-01-06 04:12:29Z nwhitehorn $
+ */
+
+#ifndef _POWERPC_PS3_IF_GLCREG_H
+#define _POWERPC_PS3_IF_GLCREG_H
+
+#define GLC_MAX_TX_PACKETS	128
+#define GLC_MAX_RX_PACKETS	128
+
+struct glc_dmadesc;
+
+/*
+ * software state for transmit job mbufs (may be elements of mbuf chains)
+ */
+ 
+struct glc_txsoft {
+	struct mbuf *txs_mbuf;		/* head of our mbuf chain */
+	bus_dmamap_t txs_dmamap;	/* our DMA map */
+	int txs_firstdesc;		/* first descriptor in packet */
+	int txs_lastdesc;		/* last descriptor in packet */
+
+	int txs_ndescs;			/* number of descriptors */
+	STAILQ_ENTRY(glc_txsoft) txs_q;
+};
+
+STAILQ_HEAD(glc_txsq, glc_txsoft);
+
+/*
+ * software state for receive jobs
+ */
+struct glc_rxsoft {
+	struct mbuf *rxs_mbuf;		/* head of our mbuf chain */
+	bus_dmamap_t rxs_dmamap;	/* our DMA map */
+
+	int rxs_desc_slot;		/* DMA descriptor for this packet */
+	bus_addr_t rxs_desc;
+
+	bus_dma_segment_t segment;
+};
+
+struct glc_softc {
+	struct ifnet	*sc_ifp;
+	device_t	sc_self;
+	struct mtx	sc_mtx;
+	u_char		sc_enaddr[ETHER_ADDR_LEN];
+	int		sc_tx_vlan, sc_rx_vlan;
+	int		sc_ifpflags;
+
+	uint64_t	sc_dma_base[5];
+	bus_dma_tag_t	sc_dmadesc_tag;
+
+	int		sc_irqid;
+	struct resource	*sc_irq;
+	void		*sc_irqctx;
+	uint64_t	*sc_hwirq_status;
+	volatile uint64_t sc_interrupt_status;
+
+	struct ifmedia	sc_media;
+
+	/* Transmission */
+
+	bus_dma_tag_t	sc_txdma_tag;
+	struct glc_txsoft sc_txsoft[GLC_MAX_TX_PACKETS];
+	struct glc_dmadesc *sc_txdmadesc;
+	int		next_txdma_slot, first_used_txdma_slot, bsy_txdma_slots;
+	bus_dmamap_t	sc_txdmadesc_map;
+	bus_addr_t	sc_txdmadesc_phys;
+
+	struct glc_txsq	sc_txfreeq;
+	struct glc_txsq	sc_txdirtyq;
+
+	/* Reception */
+	
+	bus_dma_tag_t	sc_rxdma_tag;
+	struct glc_rxsoft sc_rxsoft[GLC_MAX_RX_PACKETS];
+	struct glc_dmadesc *sc_rxdmadesc;
+	int		sc_next_rxdma_slot;
+	bus_dmamap_t	sc_rxdmadesc_map;
+	bus_addr_t	sc_rxdmadesc_phys;
+
+	int		sc_bus, sc_dev;
+	int		sc_wdog_timer;
+	struct callout	sc_tick_ch;
+};
+
+#define GELIC_GET_MAC_ADDRESS   0x0001
+#define GELIC_GET_LINK_STATUS   0x0002
+#define GELIC_SET_LINK_MODE     0x0003
+#define  GELIC_LINK_UP          0x0001
+#define  GELIC_FULL_DUPLEX      0x0002
+#define  GELIC_AUTO_NEG         0x0004
+#define  GELIC_SPEED_10         0x0010
+#define  GELIC_SPEED_100        0x0020
+#define  GELIC_SPEED_1000       0x0040
+#define GELIC_GET_VLAN_ID       0x0004
+#define  GELIC_VLAN_TX_ETHERNET	0x0002
+#define  GELIC_VLAN_RX_ETHERNET	0x0012
+#define  GELIC_VLAN_TX_WIRELESS	0x0003
+#define  GELIC_VLAN_RX_WIRELESS	0x0013
+
+/* Command status code */
+#define	GELIC_DESCR_OWNED	0xa0000000
+#define	GELIC_CMDSTAT_DMA_DONE	0x00000000
+#define	GELIC_CMDSTAT_CHAIN_END	0x00000002
+#define GELIC_CMDSTAT_CSUM_TCP	0x00020000
+#define GELIC_CMDSTAT_CSUM_UDP	0x00030000
+#define GELIC_CMDSTAT_NOIPSEC	0x00080000
+#define GELIC_CMDSTAT_LAST	0x00040000
+#define GELIC_RXERRORS		0x7def8000
+
+/* RX Data Status codes */
+#define GELIC_RX_IPCSUM		0x20000000
+#define GELIC_RX_TCPUDPCSUM	0x10000000
+
+/* Interrupt options */
+#define GELIC_INT_RXDONE	0x0000000000004000UL
+#define GELIC_INT_RXFRAME	0x1000000000000000UL
+#define GELIC_INT_TXDONE	0x0080000000000000UL
+#define GELIC_INT_TX_CHAIN_END	0x0100000000000000UL
+#define GELIC_INT_PHY		0x0000000020000000UL
+
+/* Hardware DMA descriptor. Must be 32-byte aligned */
+
+struct glc_dmadesc {
+	uint32_t paddr;	/* Must be 128 byte aligned for receive */
+	uint32_t len;
+	uint32_t next;
+	uint32_t cmd_stat;
+	uint32_t result_size;
+	uint32_t valid_size;
+	uint32_t data_stat;
+	uint32_t rxerror;
+};
+
+#endif /* _POWERPC_PS3_IF_GLCREG_H */
+


Property changes on: trunk/sys/powerpc/ps3/if_glcreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/mmu_ps3.c
===================================================================
--- trunk/sys/powerpc/ps3/mmu_ps3.c	                        (rev 0)
+++ trunk/sys/powerpc/ps3/mmu_ps3.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,311 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2010 Nathan Whitehorn
+ * 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.
+ *
+ * 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 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ps3/mmu_ps3.c 247297 2013-02-26 01:00:11Z attilio $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/msgbuf.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/vmmeter.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_pageout.h>
+#include <vm/uma.h>
+
+#include <powerpc/aim/mmu_oea64.h>
+
+#include "mmu_if.h"
+#include "moea64_if.h"
+#include "ps3-hvcall.h"
+
+#define VSID_HASH_MASK		0x0000007fffffffffUL
+#define PTESYNC()		__asm __volatile("ptesync")
+
+extern int ps3fb_remap(void);
+
+static uint64_t mps3_vas_id;
+
+/*
+ * Kernel MMU interface
+ */
+
+static void	mps3_bootstrap(mmu_t mmup, vm_offset_t kernelstart,
+		    vm_offset_t kernelend);
+static void	mps3_cpu_bootstrap(mmu_t mmup, int ap);
+static void	mps3_pte_synch(mmu_t, uintptr_t pt, struct lpte *pvo_pt);
+static void	mps3_pte_clear(mmu_t, uintptr_t pt, struct lpte *pvo_pt,
+		    uint64_t vpn, uint64_t ptebit);
+static void	mps3_pte_unset(mmu_t, uintptr_t pt, struct lpte *pvo_pt,
+		    uint64_t vpn);
+static void	mps3_pte_change(mmu_t, uintptr_t pt, struct lpte *pvo_pt,
+		    uint64_t vpn);
+static int	mps3_pte_insert(mmu_t, u_int ptegidx, struct lpte *pvo_pt);
+static uintptr_t mps3_pvo_to_pte(mmu_t, const struct pvo_entry *pvo);
+
+
+static mmu_method_t mps3_methods[] = {
+        MMUMETHOD(mmu_bootstrap,	mps3_bootstrap),
+        MMUMETHOD(mmu_cpu_bootstrap,	mps3_cpu_bootstrap),
+
+	MMUMETHOD(moea64_pte_synch,	mps3_pte_synch),
+	MMUMETHOD(moea64_pte_clear,	mps3_pte_clear),
+	MMUMETHOD(moea64_pte_unset,	mps3_pte_unset),
+	MMUMETHOD(moea64_pte_change,	mps3_pte_change),
+	MMUMETHOD(moea64_pte_insert,	mps3_pte_insert),
+	MMUMETHOD(moea64_pvo_to_pte,	mps3_pvo_to_pte),
+
+        { 0, 0 }
+};
+
+MMU_DEF_INHERIT(ps3_mmu, "mmu_ps3", mps3_methods, 0, oea64_mmu);
+
+static void
+mps3_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
+{
+	uint64_t final_pteg_count;
+
+	moea64_early_bootstrap(mmup, kernelstart, kernelend);
+
+	lv1_construct_virtual_address_space(
+	    20 /* log_2(moea64_pteg_count) */, 2 /* n page sizes */,
+	    (24UL << 56) | (16UL << 48) /* page sizes 16 MB + 64 KB */,
+	    &mps3_vas_id, &final_pteg_count
+	);
+
+	moea64_pteg_count = final_pteg_count / sizeof(struct lpteg);
+
+	moea64_mid_bootstrap(mmup, kernelstart, kernelend);
+	moea64_late_bootstrap(mmup, kernelstart, kernelend);
+}
+
+static void
+mps3_cpu_bootstrap(mmu_t mmup, int ap)
+{
+	struct slb *slb = PCPU_GET(slb);
+	register_t seg0;
+	int i;
+
+	mtmsr(mfmsr() & ~PSL_DR & ~PSL_IR);
+
+	/*
+	 * Destroy the loader's address space if we are coming up for
+	 * the first time, and redo the FB mapping so we can continue
+	 * having a console.
+	 */
+
+	if (!ap)
+		lv1_destruct_virtual_address_space(0);
+
+	lv1_select_virtual_address_space(mps3_vas_id);
+
+	if (!ap)
+		ps3fb_remap();
+
+	/*
+	 * Install kernel SLB entries
+	 */
+
+        __asm __volatile ("slbia");
+        __asm __volatile ("slbmfee %0,%1; slbie %0;" : "=r"(seg0) : "r"(0));
+	for (i = 0; i < 64; i++) {
+		if (!(slb[i].slbe & SLBE_VALID))
+			continue;
+
+		__asm __volatile ("slbmte %0, %1" ::
+		    "r"(slb[i].slbv), "r"(slb[i].slbe));
+	}
+}
+
+static void
+mps3_pte_synch(mmu_t mmu, uintptr_t slot, struct lpte *pvo_pt)
+{
+	uint64_t halfbucket[4], rcbits;
+	
+	PTESYNC();
+	lv1_read_htab_entries(mps3_vas_id, slot & ~0x3UL, &halfbucket[0],
+	    &halfbucket[1], &halfbucket[2], &halfbucket[3], &rcbits);
+
+	/*
+	 * rcbits contains the low 12 bits of each PTEs 2nd part,
+	 * spaced at 16-bit intervals
+	 */
+
+	KASSERT((halfbucket[slot & 0x3] & LPTE_AVPN_MASK) ==
+	    (pvo_pt->pte_hi & LPTE_AVPN_MASK),
+	    ("PTE upper word %#lx != %#lx\n",
+	    halfbucket[slot & 0x3], pvo_pt->pte_hi));
+
+ 	pvo_pt->pte_lo |= (rcbits >> ((3 - (slot & 0x3))*16)) &
+	    (LPTE_CHG | LPTE_REF);
+}
+
+static void
+mps3_pte_clear(mmu_t mmu, uintptr_t slot, struct lpte *pvo_pt, uint64_t vpn,
+    u_int64_t ptebit)
+{
+
+	lv1_write_htab_entry(mps3_vas_id, slot, pvo_pt->pte_hi,
+	    pvo_pt->pte_lo & ~ptebit);
+}
+
+static void
+mps3_pte_unset(mmu_t mmu, uintptr_t slot, struct lpte *pvo_pt, uint64_t vpn)
+{
+
+	mps3_pte_synch(mmu, slot, pvo_pt);
+	pvo_pt->pte_hi &= ~LPTE_VALID;
+	lv1_write_htab_entry(mps3_vas_id, slot, 0, 0);
+	moea64_pte_valid--;
+}
+
+static void
+mps3_pte_change(mmu_t mmu, uintptr_t slot, struct lpte *pvo_pt, uint64_t vpn)
+{
+ 
+	mps3_pte_synch(mmu, slot, pvo_pt);
+	lv1_write_htab_entry(mps3_vas_id, slot, pvo_pt->pte_hi,
+	    pvo_pt->pte_lo);
+}
+
+static int
+mps3_pte_insert(mmu_t mmu, u_int ptegidx, struct lpte *pvo_pt)
+{
+	int result;
+	struct lpte evicted;
+	struct pvo_entry *pvo;
+	uint64_t index;
+
+	pvo_pt->pte_hi |= LPTE_VALID;
+	pvo_pt->pte_hi &= ~LPTE_HID;
+	evicted.pte_hi = 0;
+	PTESYNC();
+	result = lv1_insert_htab_entry(mps3_vas_id, ptegidx << 3,
+	    pvo_pt->pte_hi, pvo_pt->pte_lo, LPTE_LOCKED | LPTE_WIRED, 0,
+	    &index, &evicted.pte_hi, &evicted.pte_lo);
+
+	if (result != 0) {
+		/* No freeable slots in either PTEG? We're hosed. */
+		panic("mps3_pte_insert: overflow (%d)", result);
+		return (-1);
+	}
+
+	/*
+	 * See where we ended up.
+	 */
+	if (index >> 3 != ptegidx)
+		pvo_pt->pte_hi |= LPTE_HID;
+
+	moea64_pte_valid++;
+
+	if (!evicted.pte_hi)
+		return (index & 0x7);
+
+	/*
+	 * Synchronize the sacrifice PTE with its PVO, then mark both
+	 * invalid. The PVO will be reused when/if the VM system comes
+	 * here after a fault.
+	 */
+
+	ptegidx = index >> 3; /* Where the sacrifice PTE was found */
+	if (evicted.pte_hi & LPTE_HID)
+		ptegidx ^= moea64_pteg_mask; /* PTEs indexed by primary */
+
+	KASSERT((evicted.pte_hi & (LPTE_WIRED | LPTE_LOCKED)) == 0,
+	    ("Evicted a wired PTE"));
+
+	result = 0;
+	LIST_FOREACH(pvo, &moea64_pvo_table[ptegidx], pvo_olink) {
+		if (!PVO_PTEGIDX_ISSET(pvo))
+			continue;
+
+		if (pvo->pvo_pte.lpte.pte_hi == (evicted.pte_hi | LPTE_VALID)) {
+			KASSERT(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID,
+			    ("Invalid PVO for valid PTE!"));
+			pvo->pvo_pte.lpte.pte_hi &= ~LPTE_VALID;
+			pvo->pvo_pte.lpte.pte_lo |=
+			    evicted.pte_lo & (LPTE_REF | LPTE_CHG);
+			PVO_PTEGIDX_CLR(pvo);
+			moea64_pte_valid--;
+			moea64_pte_overflow++;
+			result = 1;
+			break;
+		}
+	}
+
+	KASSERT(result == 1, ("PVO for sacrifice PTE not found"));
+
+	return (index & 0x7);
+}
+
+static __inline u_int
+va_to_pteg(uint64_t vsid, vm_offset_t addr, int large)
+{
+	uint64_t hash;
+	int shift;
+
+	shift = large ? moea64_large_page_shift : ADDR_PIDX_SHFT;
+	hash = (vsid & VSID_HASH_MASK) ^ (((uint64_t)addr & ADDR_PIDX) >>
+	    shift);
+	return (hash & moea64_pteg_mask);
+}
+
+uintptr_t
+mps3_pvo_to_pte(mmu_t mmu, const struct pvo_entry *pvo)
+{
+	uint64_t vsid;
+	u_int ptegidx;
+
+	/* If the PTEG index is not set, then there is no page table entry */
+	if (!PVO_PTEGIDX_ISSET(pvo))
+		return (-1);
+
+	vsid = PVO_VSID(pvo);
+	ptegidx = va_to_pteg(vsid, PVO_VADDR(pvo), pvo->pvo_vaddr & PVO_LARGE);
+
+	/*
+	 * We can find the actual pte entry without searching by grabbing
+	 * the PTEG index from 3 unused bits in pvo_vaddr and by
+	 * noticing the HID bit.
+	 */
+	if (pvo->pvo_pte.lpte.pte_hi & LPTE_HID)
+		ptegidx ^= moea64_pteg_mask;
+
+	return ((ptegidx << 3) | PVO_PTEGIDX_GET(pvo));
+}
+


Property changes on: trunk/sys/powerpc/ps3/mmu_ps3.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ohci_ps3.c
===================================================================
--- trunk/sys/powerpc/ps3/ohci_ps3.c	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ohci_ps3.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,173 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2010 Nathan Whitehorn
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ps3/ohci_ps3.c 278278 2015-02-05 20:03:02Z hselasky $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ps3/ohci_ps3.c 278278 2015-02-05 20:03:02Z hselasky $");
+
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/linker_set.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+
+#include <sys/rman.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ohci.h>
+#include <dev/usb/controller/ohcireg.h>
+
+#include "ps3bus.h"
+
+static int
+ohci_ps3_probe(device_t dev)
+{
+	if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_SYSBUS ||
+	    ps3bus_get_devtype(dev) != PS3_DEVTYPE_USB)
+		return (ENXIO);
+
+	device_set_desc(dev, "Playstation 3 USB 2.0 controller");
+	return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+ohci_ps3_attach(device_t dev)
+{
+	ohci_softc_t *sc = device_get_softc(dev);
+	int rid, err;
+
+	sc->sc_bus.parent = dev;
+	sc->sc_bus.devices = sc->sc_devices;
+	sc->sc_bus.devices_max = OHCI_MAX_DEVICES;
+	sc->sc_bus.dma_bits = 32;
+
+	/* get all DMA memory */
+	if (usb_bus_mem_alloc_all(&sc->sc_bus,
+	    USB_GET_DMA_TAG(dev), &ohci_iterate_hw_softc))
+		return (ENOMEM);
+
+	rid = 0;
+	sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &rid, RF_ACTIVE);
+
+	if (!sc->sc_io_res) {
+		device_printf(dev, "Could not map memory\n");
+		goto error;
+	}
+
+	sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
+	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
+	sc->sc_io_size = rman_get_size(sc->sc_io_res);
+
+	rid = 0;
+	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+	    RF_SHAREABLE | RF_ACTIVE);
+
+	if (sc->sc_irq_res == NULL) {
+		device_printf(dev, "Could not allocate irq\n");
+		return (ENXIO);
+	}
+
+	sc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
+	if (!sc->sc_bus.bdev) {
+		device_printf(dev, "Could not add USB device\n");
+		return (ENXIO);
+	}
+
+	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+
+	sprintf(sc->sc_vendor, "Sony");
+
+	err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+	    NULL, (driver_intr_t *)ohci_interrupt, sc, &sc->sc_intr_hdl);
+	if (err) {
+		device_printf(dev, "Could not setup error irq, %d\n", err);
+		goto error;
+	}
+
+	//sc->sc_flags |= EHCI_SCFLG_BIGEMMIO;
+	bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl,
+	    OHCI_CONTROL, 0);
+	err = ohci_init(sc);
+	if (err) {
+		device_printf(dev, "USB init failed err=%d\n", err);
+		goto error;
+	}
+
+	err = device_probe_and_attach(sc->sc_bus.bdev);
+	if (err == 0)
+		return (0);
+
+error:
+	return (ENXIO);
+}
+
+static device_method_t ohci_ps3_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe, ohci_ps3_probe),
+	DEVMETHOD(device_attach, ohci_ps3_attach),
+	DEVMETHOD(device_resume, bus_generic_resume),
+	DEVMETHOD(device_suspend, bus_generic_suspend),
+	DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+	DEVMETHOD_END
+};
+
+static driver_t ohci_ps3_driver = {
+	.name = "ohci",
+	.methods = ohci_ps3_methods,
+	.size = sizeof(ohci_softc_t),
+};
+
+static devclass_t ohci_ps3_devclass;
+
+DRIVER_MODULE(ohci_ps3, ps3bus, ohci_ps3_driver, ohci_ps3_devclass, 0, 0);
+MODULE_DEPEND(ohci_ps3, usb, 1, 1, 1);
+


Property changes on: trunk/sys/powerpc/ps3/ohci_ps3.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/platform_ps3.c
===================================================================
--- trunk/sys/powerpc/ps3/platform_ps3.c	                        (rev 0)
+++ trunk/sys/powerpc/ps3/platform_ps3.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,260 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2010 Nathan Whitehorn
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ps3/platform_ps3.c 271114 2014-09-04 18:28:30Z nwhitehorn $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/hid.h>
+#include <machine/platform.h>
+#include <machine/platformvar.h>
+#include <machine/pmap.h>
+#include <machine/smp.h>
+#include <machine/spr.h>
+#include <machine/vmparam.h>
+
+#include "platform_if.h"
+#include "ps3-hvcall.h"
+
+#ifdef SMP
+extern void *ap_pcpu;
+#endif
+
+static int ps3_probe(platform_t);
+static int ps3_attach(platform_t);
+static void ps3_mem_regions(platform_t, struct mem_region *phys, int *physsz,
+    struct mem_region *avail, int *availsz);
+static vm_offset_t ps3_real_maxaddr(platform_t);
+static u_long ps3_timebase_freq(platform_t, struct cpuref *cpuref);
+#ifdef SMP
+static int ps3_smp_first_cpu(platform_t, struct cpuref *cpuref);
+static int ps3_smp_next_cpu(platform_t, struct cpuref *cpuref);
+static int ps3_smp_get_bsp(platform_t, struct cpuref *cpuref);
+static int ps3_smp_start_cpu(platform_t, struct pcpu *cpu);
+static struct cpu_group *ps3_smp_topo(platform_t);
+#endif
+static void ps3_reset(platform_t);
+static void ps3_cpu_idle(sbintime_t);
+
+static platform_method_t ps3_methods[] = {
+	PLATFORMMETHOD(platform_probe, 		ps3_probe),
+	PLATFORMMETHOD(platform_attach,		ps3_attach),
+	PLATFORMMETHOD(platform_mem_regions,	ps3_mem_regions),
+	PLATFORMMETHOD(platform_real_maxaddr,	ps3_real_maxaddr),
+	PLATFORMMETHOD(platform_timebase_freq,	ps3_timebase_freq),
+
+#ifdef SMP
+	PLATFORMMETHOD(platform_smp_first_cpu,	ps3_smp_first_cpu),
+	PLATFORMMETHOD(platform_smp_next_cpu,	ps3_smp_next_cpu),
+	PLATFORMMETHOD(platform_smp_get_bsp,	ps3_smp_get_bsp),
+	PLATFORMMETHOD(platform_smp_start_cpu,	ps3_smp_start_cpu),
+	PLATFORMMETHOD(platform_smp_topo,	ps3_smp_topo),
+#endif
+
+	PLATFORMMETHOD(platform_reset,		ps3_reset),
+
+	PLATFORMMETHOD_END
+};
+
+static platform_def_t ps3_platform = {
+	"ps3",
+	ps3_methods,
+	0
+};
+
+PLATFORM_DEF(ps3_platform);
+
+static int
+ps3_probe(platform_t plat)
+{
+
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+ps3_attach(platform_t plat)
+{
+
+	pmap_mmu_install("mmu_ps3", BUS_PROBE_SPECIFIC);
+	cpu_idle_hook = ps3_cpu_idle;
+
+	/* Set a breakpoint to make NULL an invalid address */
+	lv1_set_dabr(0x7 /* read and write, MMU on */, 2 /* kernel accesses */);
+
+	return (0);
+}
+
+void
+ps3_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
+    struct mem_region *avail_regions, int *availsz)
+{
+	uint64_t lpar_id, junk, ppe_id;
+
+	/* Get real mode memory region */
+	avail_regions[0].mr_start = 0;
+	lv1_get_logical_partition_id(&lpar_id);
+	lv1_get_logical_ppe_id(&ppe_id);
+	lv1_get_repository_node_value(lpar_id,
+	    lv1_repository_string("bi") >> 32, lv1_repository_string("pu"),
+	    ppe_id, lv1_repository_string("rm_size"),
+	    &avail_regions[0].mr_size, &junk);
+
+	/* Now get extended memory region */
+	lv1_get_repository_node_value(lpar_id,
+	    lv1_repository_string("bi") >> 32,
+	    lv1_repository_string("rgntotal"), 0, 0,
+	    &avail_regions[1].mr_size, &junk);
+
+	/* Convert to maximum amount we can allocate in 16 MB pages */
+	avail_regions[1].mr_size -= avail_regions[0].mr_size;
+	avail_regions[1].mr_size -= avail_regions[1].mr_size % (16*1024*1024);
+
+	/* Allocate extended memory region */
+	lv1_allocate_memory(avail_regions[1].mr_size, 24 /* 16 MB pages */,
+	    0, 0x04 /* any address */, &avail_regions[1].mr_start, &junk);
+
+	*availsz = 2;
+
+	if (phys != NULL) {
+		memcpy(phys, avail_regions, sizeof(*phys)*2);
+		*physsz = 2;
+	}
+}
+
+static u_long
+ps3_timebase_freq(platform_t plat, struct cpuref *cpuref)
+{
+	uint64_t ticks, node_id, junk;
+
+	lv1_get_repository_node_value(PS3_LPAR_ID_PME, 
+	    lv1_repository_string("be") >> 32, 0, 0, 0, &node_id, &junk);
+	lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+	    lv1_repository_string("be") >> 32, node_id,
+	    lv1_repository_string("clock"), 0, &ticks, &junk);
+
+	return (ticks);
+}
+
+#ifdef SMP
+static int
+ps3_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
+{
+
+	cpuref->cr_cpuid = 0;
+	cpuref->cr_hwref = cpuref->cr_cpuid;
+
+	return (0);
+}
+
+static int
+ps3_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
+{
+
+	if (cpuref->cr_cpuid >= 1)
+		return (ENOENT);
+
+	cpuref->cr_cpuid++;
+	cpuref->cr_hwref = cpuref->cr_cpuid;
+
+	return (0);
+}
+
+static int
+ps3_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
+{
+
+	cpuref->cr_cpuid = 0;
+	cpuref->cr_hwref = cpuref->cr_cpuid;
+
+	return (0);
+}
+
+static int
+ps3_smp_start_cpu(platform_t plat, struct pcpu *pc)
+{
+	/* loader(8) is spinning on 0x40 == 0 right now */
+	uint32_t *secondary_spin_sem = (uint32_t *)(0x40);
+	int timeout;
+
+	if (pc->pc_hwref != 1)
+		return (ENXIO);
+
+	ap_pcpu = pc;
+	*secondary_spin_sem = 1;
+	powerpc_sync();
+	DELAY(1);
+
+	timeout = 10000;
+	while (!pc->pc_awake && timeout--)
+		DELAY(100);
+
+	return ((pc->pc_awake) ? 0 : EBUSY);
+}
+
+static struct cpu_group *
+ps3_smp_topo(platform_t plat)
+{
+	return (smp_topo_1level(CG_SHARE_L1, 2, CG_FLAG_SMT));
+}
+#endif
+
+static void
+ps3_reset(platform_t plat)
+{
+	lv1_panic(1);
+}
+
+static vm_offset_t
+ps3_real_maxaddr(platform_t plat)
+{
+	struct mem_region *phys, *avail;
+	int nphys, navail;
+
+	mem_regions(&phys, &nphys, &avail, &navail);
+
+	return (phys[0].mr_start + phys[0].mr_size);
+}
+
+static void
+ps3_cpu_idle(sbintime_t sbt)
+{
+	lv1_pause(0);
+}
+


Property changes on: trunk/sys/powerpc/ps3/platform_ps3.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ps3-hv-asm.awk
===================================================================
--- trunk/sys/powerpc/ps3/ps3-hv-asm.awk	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ps3-hv-asm.awk	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,54 @@
+# This script generates the PS3 hypervisor call stubs from an HV
+# interface definition file. The PS3 HV calling convention is very
+# similar to the PAPR one, except that the function token is passed in
+# r11 instead of r3.
+#
+# Invoke like so: awk -f ps3-hv-asm.awk < ps3-hvcall.master > ps3-hvcall.S
+#
+
+# $FreeBSD: stable/10/sys/powerpc/ps3/ps3-hv-asm.awk 228688 2011-12-18 16:53:03Z nwhitehorn $
+# $MidnightBSD$
+
+BEGIN {
+	printf("/* $MidnightBSD$ */\n\n");
+	printf("#include <machine/asm.h>\n\n");
+	printf("#define hc .long 0x44000022\n\n");
+}
+
+/HVCALL.*/ {
+	code = $2;
+	ins = split($4, a, ",")
+	outs = split($5, a, ",")
+	
+	printf("ASENTRY(%s)\n",$3);
+	printf("\tmflr	%%r0\n");
+	printf("\tstd	%%r0,16(%%r1)\n");
+	printf("\tstdu	%%r1,-%d(%%r1)\n", 48+8*outs);
+
+	if ($4 == "UNUSED")
+		ins = 0
+	
+	# Save output reg addresses to the stack
+	for (i = 0; i < outs; i++) {
+		if (ins+i >= 8) {
+		   printf("\tld	%%r11,%d(%%r1)\n", 48+8*outs + 48 + 8*(i+ins));
+		   printf("\tstd	%%r11,%d(%%r1)\n", 48+8*i);
+		} else {
+		   printf("\tstd	%%r%d,%d(%%r1)\n", 3+ins+i, 48+8*i);
+		}
+	}
+
+	printf("\tli	%%r11,%d\n", code);
+	printf("\thc\n");
+	printf("\textsw	%%r3,%%r3\n");
+		
+	for (i = 0; i < outs; i++) {
+		printf("\tld	%%r11,%d(%%r1)\n", 48+8*i);
+		printf("\tstd	%%r%d,0(%%r11)\n", 4+i);
+	}
+
+	printf("\tld	%%r1,0(%%r1)\n");
+	printf("\tld	%%r0,16(%%r1)\n");
+	printf("\tmtlr	%%r0\n");
+	printf("\tblr\n\n");
+}


Property changes on: trunk/sys/powerpc/ps3/ps3-hv-asm.awk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ps3-hv-header.awk
===================================================================
--- trunk/sys/powerpc/ps3/ps3-hv-header.awk	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ps3-hv-header.awk	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,43 @@
+# This script generates the PS3 hypervisor call header from a hypervisor
+# interface definition file. All lines that do not begin with HVCALL
+# or a bare # for comments are copied to the output header so that
+# enums, constant, C comments and the like can be passed through into the
+# header.
+#
+# Invoke like so: awk -f ps3-hv-header.awk < ps3-hvcall.master > ps3-hv.h
+#
+
+# $FreeBSD: stable/10/sys/powerpc/ps3/ps3-hv-header.awk 217044 2011-01-06 04:12:29Z nwhitehorn $
+# $MidnightBSD$
+
+!/HVCALL.*/ && (!/#.*/ || /#define.*/ || /#include.*/) {
+	print($0);
+}
+
+/HVCALL.*/ {
+	split($5, outs, ",")
+	if ($4 == "UNUSED")
+		split("", ins, ",")
+	else
+		split($4, ins, ",")
+
+	printf("int %s(",$3);
+	for (i = 1; i <= length(ins); i++) {
+		printf("uint64_t %s", ins[i]);
+		if (i < length(ins)) printf(", ");
+	}
+
+	if (length(outs) > 0 && length(ins) > 0)
+		printf(", ");
+
+	for (i = 1; i <= length(outs); i++) {
+		printf("uint64_t *%s", outs[i]);
+		if (i < length(outs)) printf(", ");
+	}
+
+	if (length(outs) == 0 && length(ins) == 0)
+		printf("void");
+
+	printf(");\n");
+}
+	


Property changes on: trunk/sys/powerpc/ps3/ps3-hv-header.awk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ps3-hvcall.S
===================================================================
--- trunk/sys/powerpc/ps3/ps3-hvcall.S	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ps3-hvcall.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,1279 @@
+/* $MidnightBSD$ */
+/* $FreeBSD: stable/10/sys/powerpc/ps3/ps3-hvcall.S 228689 2011-12-18 16:53:21Z nwhitehorn $ */
+
+#include <machine/asm.h>
+
+#define hc .long 0x44000022
+
+ASENTRY(lv1_allocate_memory)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-64(%r1)
+	std	%r7,48(%r1)
+	std	%r8,56(%r1)
+	li	%r11,0
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_write_htab_entry)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,1
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_construct_virtual_address_space)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-64(%r1)
+	std	%r6,48(%r1)
+	std	%r7,56(%r1)
+	li	%r11,2
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_get_virtual_address_space_id_of_ppe)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r4,48(%r1)
+	li	%r11,4
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_query_logical_partition_address_region_info)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-88(%r1)
+	std	%r4,48(%r1)
+	std	%r5,56(%r1)
+	std	%r6,64(%r1)
+	std	%r7,72(%r1)
+	std	%r8,80(%r1)
+	li	%r11,6
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r11,64(%r1)
+	std	%r6,0(%r11)
+	ld	%r11,72(%r1)
+	std	%r7,0(%r11)
+	ld	%r11,80(%r1)
+	std	%r8,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_select_virtual_address_space)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,7
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_pause)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,9
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_destruct_virtual_address_space)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,10
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_configure_irq_state_bitmap)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,11
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_connect_irq_plug_ext)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,12
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_release_memory)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,13
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_put_iopte)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,15
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_disconnect_irq_plug_ext)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,17
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_construct_event_receive_port)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r3,48(%r1)
+	li	%r11,18
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_destruct_event_receive_port)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,19
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_send_event_locally)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,24
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_end_of_interrupt)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,27
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_connect_irq_plug)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,28
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_disconnect_irq_plus)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,29
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_end_of_interrupt_ext)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,30
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_did_update_interrupt_mask)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,31
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_shutdown_logical_partition)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,44
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_destruct_logical_spe)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,54
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_construct_logical_spe)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-96(%r1)
+	std	%r10,48(%r1)
+	ld	%r11,208(%r1)
+	std	%r11,56(%r1)
+	ld	%r11,216(%r1)
+	std	%r11,64(%r1)
+	ld	%r11,224(%r1)
+	std	%r11,72(%r1)
+	ld	%r11,232(%r1)
+	std	%r11,80(%r1)
+	ld	%r11,240(%r1)
+	std	%r11,88(%r1)
+	li	%r11,57
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r11,64(%r1)
+	std	%r6,0(%r11)
+	ld	%r11,72(%r1)
+	std	%r7,0(%r11)
+	ld	%r11,80(%r1)
+	std	%r8,0(%r11)
+	ld	%r11,88(%r1)
+	std	%r9,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_set_spe_interrupt_mask)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,61
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_disable_logical_spe)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,65
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_clear_spe_interrupt_status)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,66
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_get_spe_interrupt_status)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r5,48(%r1)
+	li	%r11,67
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_get_logical_ppe_id)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r3,48(%r1)
+	li	%r11,69
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_get_logical_partition_id)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r3,48(%r1)
+	li	%r11,74
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_get_spe_irq_outlet)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r5,48(%r1)
+	li	%r11,78
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_set_spe_privilege_state_area_1_register)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,79
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_get_repository_node_value)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-64(%r1)
+	std	%r8,48(%r1)
+	std	%r9,56(%r1)
+	li	%r11,91
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_read_htab_entries)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-88(%r1)
+	std	%r5,48(%r1)
+	std	%r6,56(%r1)
+	std	%r7,64(%r1)
+	std	%r8,72(%r1)
+	std	%r9,80(%r1)
+	li	%r11,95
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r11,64(%r1)
+	std	%r6,0(%r11)
+	ld	%r11,72(%r1)
+	std	%r7,0(%r11)
+	ld	%r11,80(%r1)
+	std	%r8,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_set_dabr)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,96
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_allocate_io_segment)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r6,48(%r1)
+	li	%r11,116
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_release_io_segment)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,117
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_construct_io_irq_outlet)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r4,48(%r1)
+	li	%r11,120
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_destruct_io_irq_outlet)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,121
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_map_htab)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r4,48(%r1)
+	li	%r11,122
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_unmap_htab)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,123
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_get_version_info)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r3,48(%r1)
+	li	%r11,127
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_insert_htab_entry)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-72(%r1)
+	std	%r9,48(%r1)
+	std	%r10,56(%r1)
+	ld	%r11,184(%r1)
+	std	%r11,64(%r1)
+	li	%r11,158
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r11,64(%r1)
+	std	%r6,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_read_virtual_uart)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r6,48(%r1)
+	li	%r11,162
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_write_virtual_uart)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r6,48(%r1)
+	li	%r11,163
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_set_virtual_uart_param)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,164
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_get_virtual_uart_param)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r5,48(%r1)
+	li	%r11,165
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_configure_virtual_uart)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r4,48(%r1)
+	li	%r11,166
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_open_device)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,170
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_close_device)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,171
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_map_device_mmio_region)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r8,48(%r1)
+	li	%r11,172
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_unmap_device_mmio_region)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,173
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_allocate_device_dma_region)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r8,48(%r1)
+	li	%r11,174
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_free_device_dma_region)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,175
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_map_device_dma_region)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,176
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_unmap_device_dma_region)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,177
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_read_pci_config)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r9,48(%r1)
+	li	%r11,178
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_write_pci_config)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,179
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_net_add_multicast_address)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,185
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_net_remove_multicast_address)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,186
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_net_start_tx_dma)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,187
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_net_stop_tx_dma)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,188
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_net_start_rx_dma)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,189
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_net_stop_rx_dma)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,190
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_net_set_interrupt_status_indicator)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,191
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_net_set_interrupt_mask)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,193
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_net_control)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-64(%r1)
+	std	%r9,48(%r1)
+	std	%r10,56(%r1)
+	li	%r11,194
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_connect_interrupt_event_receive_port)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,197
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_disconnect_interrupt_event_receive_port)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,198
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_deconfigure_virtual_uart_irq)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,202
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_enable_logical_spe)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,207
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_gpu_open)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,210
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_gpu_close)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,211
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_gpu_device_map)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-64(%r1)
+	std	%r4,48(%r1)
+	std	%r5,56(%r1)
+	li	%r11,212
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_gpu_device_unmap)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,213
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_gpu_memory_allocate)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-64(%r1)
+	std	%r8,48(%r1)
+	std	%r9,56(%r1)
+	li	%r11,214
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_gpu_memory_free)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,216
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_gpu_context_allocate)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-88(%r1)
+	std	%r5,48(%r1)
+	std	%r6,56(%r1)
+	std	%r7,64(%r1)
+	std	%r8,72(%r1)
+	std	%r9,80(%r1)
+	li	%r11,217
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r11,64(%r1)
+	std	%r6,0(%r11)
+	ld	%r11,72(%r1)
+	std	%r7,0(%r11)
+	ld	%r11,80(%r1)
+	std	%r8,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_gpu_context_free)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,218
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_gpu_context_iomap)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,221
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_gpu_context_attribute)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,225
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_gpu_context_intr)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r4,48(%r1)
+	li	%r11,227
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_gpu_attribute)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,228
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_get_rtc)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-64(%r1)
+	std	%r3,48(%r1)
+	std	%r4,56(%r1)
+	li	%r11,232
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_storage_read)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r9,48(%r1)
+	li	%r11,245
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_storage_write)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r9,48(%r1)
+	li	%r11,246
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_storage_send_device_command)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r9,48(%r1)
+	li	%r11,248
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_storage_get_async_status)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-64(%r1)
+	std	%r4,48(%r1)
+	std	%r5,56(%r1)
+	li	%r11,249
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_storage_check_async_status)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-56(%r1)
+	std	%r5,48(%r1)
+	li	%r11,254
+	hc
+	extsw	%r3,%r3
+	ld	%r11,48(%r1)
+	std	%r4,0(%r11)
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+
+ASENTRY(lv1_panic)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-48(%r1)
+	li	%r11,255
+	hc
+	extsw	%r3,%r3
+	ld	%r1,0(%r1)
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr
+


Property changes on: trunk/sys/powerpc/ps3/ps3-hvcall.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ps3-hvcall.h
===================================================================
--- trunk/sys/powerpc/ps3/ps3-hvcall.h	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ps3-hvcall.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,140 @@
+/* $MidnightBSD$ */
+/*
+ * Playstation 3 LV1 hypercall interface
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ps3/ps3-hvcall.h 228689 2011-12-18 16:53:21Z nwhitehorn $
+ */
+
+#include <sys/types.h>
+
+enum lpar_id {
+	PS3_LPAR_ID_CURRENT	= 0x00,
+	PS3_LPAR_ID_PME		= 0x01,
+};
+
+/* Return codes from hypercalls */
+#define LV1_SUCCESS			0
+#define LV1_RESOURCE_SHORTAGE		-2
+#define LV1_NO_PRIVILEGE		-3
+#define LV1_DENIED_BY_POLICY		-4
+#define LV1_ACCESS_VIOLATION		-5
+#define LV1_NO_ENTRY			-6
+#define LV1_DUPLICATE_ENTRY		-7
+#define LV1_TYPE_MISMATCH		-8
+#define LV1_BUSY			-9
+#define LV1_EMPTY			-10
+#define LV1_WRONG_STATE			-11
+#define LV1_NO_MATCH			-13
+#define LV1_ALREADY_CONNECTED		-14
+#define LV1_UNSUPPORTED_PARAMETER_VALUE	-15
+#define LV1_CONDITION_NOT_SATISFIED	-16
+#define LV1_ILLEGAL_PARAMETER_VALUE	-17
+#define LV1_BAD_OPTION			-18
+#define LV1_IMPLEMENTATION_LIMITATION	-19
+#define LV1_NOT_IMPLEMENTED		-20
+#define LV1_INVALID_CLASS_ID		-21
+#define LV1_CONSTRAINT_NOT_SATISFIED	-22
+#define LV1_ALIGNMENT_ERROR		-23
+#define LV1_HARDWARE_ERROR		-24
+#define LV1_INVALID_DATA_FORMAT		-25
+#define LV1_INVALID_OPERATION		-26
+#define LV1_INTERNAL_ERROR		-32768
+
+static inline uint64_t
+lv1_repository_string(const char *str)
+{
+	uint64_t ret = 0;
+	strncpy((char *)&ret, str, sizeof(ret));
+	return (ret);
+}
+
+int lv1_allocate_memory(uint64_t size, uint64_t log_page_size, uint64_t zero, uint64_t flags, uint64_t *base_addr, uint64_t *muid);
+int lv1_write_htab_entry(uint64_t vas_id, uint64_t slot, uint64_t pte_hi, uint64_t pte_lo);
+int lv1_construct_virtual_address_space(uint64_t log_pteg_count, uint64_t n_sizes, uint64_t page_sizes, uint64_t *vas_id, uint64_t *hv_pteg_count);
+int lv1_get_virtual_address_space_id_of_ppe(uint64_t ppe_id, uint64_t *vas_id);
+int lv1_query_logical_partition_address_region_info(uint64_t lpar_id, uint64_t *base_addr, uint64_t *size, uint64_t *access_right, uint64_t *max_page_size, uint64_t *flags);
+int lv1_select_virtual_address_space(uint64_t vas_id);
+int lv1_pause(uint64_t mode);
+int lv1_destruct_virtual_address_space(uint64_t vas_id);
+int lv1_configure_irq_state_bitmap(uint64_t ppe_id, uint64_t cpu_id, uint64_t bitmap_addr);
+int lv1_connect_irq_plug_ext(uint64_t ppe_id, uint64_t cpu_id, uint64_t virq, uint64_t outlet, uint64_t zero);
+int lv1_release_memory(uint64_t base_addr);
+int lv1_put_iopte(uint64_t ioas_id, uint64_t ioif_addr, uint64_t lpar_addr, uint64_t io_id, uint64_t flags);
+int lv1_disconnect_irq_plug_ext(uint64_t ppe_id, uint64_t cpu_id, uint64_t virq);
+int lv1_construct_event_receive_port(uint64_t *outlet);
+int lv1_destruct_event_receive_port(uint64_t outlet);
+int lv1_send_event_locally(uint64_t outlet);
+int lv1_end_of_interrupt(uint64_t irq);
+int lv1_connect_irq_plug(uint64_t virq, uint64_t irq);
+int lv1_disconnect_irq_plus(uint64_t virq);
+int lv1_end_of_interrupt_ext(uint64_t ppe_id, uint64_t cpu_id, uint64_t virq);
+int lv1_did_update_interrupt_mask(uint64_t ppe_id, uint64_t cpu_id);
+int lv1_shutdown_logical_partition(uint64_t cmd);
+int lv1_destruct_logical_spe(uint64_t spe_id);
+int lv1_construct_logical_spe(uint64_t pshift1, uint64_t pshift2, uint64_t pshift3, uint64_t pshift4, uint64_t pshift5, uint64_t vas_id, uint64_t spe_type, uint64_t *priv2_addr, uint64_t *problem_phys, uint64_t *local_store_phys, uint64_t *unused, uint64_t *shadow_addr, uint64_t *spe_id);
+int lv1_set_spe_interrupt_mask(uint64_t spe_id, uint64_t class, uint64_t mask);
+int lv1_disable_logical_spe(uint64_t spe_id, uint64_t zero);
+int lv1_clear_spe_interrupt_status(uint64_t spe_id, uint64_t class, uint64_t stat, uint64_t zero);
+int lv1_get_spe_interrupt_status(uint64_t spe_id, uint64_t class, uint64_t *stat);
+int lv1_get_logical_ppe_id(uint64_t *ppe_id);
+int lv1_get_logical_partition_id(uint64_t *lpar_id);
+int lv1_get_spe_irq_outlet(uint64_t spe_id, uint64_t class, uint64_t *outlet);
+int lv1_set_spe_privilege_state_area_1_register(uint64_t spe_id, uint64_t offset, uint64_t value);
+int lv1_get_repository_node_value(uint64_t lpar_id, uint64_t n1, uint64_t n2, uint64_t n3, uint64_t n4, uint64_t *v1, uint64_t *v2);
+int lv1_read_htab_entries(uint64_t vas_id, uint64_t slot, uint64_t *hi1, uint64_t *hi2, uint64_t *hi3, uint64_t *hi4, uint64_t *rcbits);
+int lv1_set_dabr(uint64_t dabr, uint64_t flags);
+int lv1_allocate_io_segment(uint64_t ioas_id, uint64_t seg_size, uint64_t io_pagesize, uint64_t *ioif_addr);
+int lv1_release_io_segment(uint64_t ioas_id, uint64_t ioif_addr);
+int lv1_construct_io_irq_outlet(uint64_t interrupt_id, uint64_t *outlet);
+int lv1_destruct_io_irq_outlet(uint64_t outlet);
+int lv1_map_htab(uint64_t lpar_id, uint64_t *htab_addr);
+int lv1_unmap_htab(uint64_t htab_addr);
+int lv1_get_version_info(uint64_t *firm_vers);
+int lv1_insert_htab_entry(uint64_t vas_id, uint64_t pteg, uint64_t pte_hi, uint64_t pte_lo, uint64_t lockflags, uint64_t flags, uint64_t *index, uint64_t *evicted_hi, uint64_t *evicted_lo);
+int lv1_read_virtual_uart(uint64_t port, uint64_t buffer, uint64_t bytes, uint64_t *bytes_read);
+int lv1_write_virtual_uart(uint64_t port, uint64_t buffer, uint64_t bytes, uint64_t *bytes_written);
+int lv1_set_virtual_uart_param(uint64_t port, uint64_t param, uint64_t value);
+int lv1_get_virtual_uart_param(uint64_t port, uint64_t param, uint64_t *value);
+int lv1_configure_virtual_uart(uint64_t lpar_addr, uint64_t *outlet);
+int lv1_open_device(uint64_t bus, uint64_t dev, uint64_t zero);
+int lv1_close_device(uint64_t bus, uint64_t dev);
+int lv1_map_device_mmio_region(uint64_t bus, uint64_t dev, uint64_t bus_addr, uint64_t size, uint64_t page_size, uint64_t *lpar_addr);
+int lv1_unmap_device_mmio_region(uint64_t bus, uint64_t dev, uint64_t lpar_addr);
+int lv1_allocate_device_dma_region(uint64_t bus, uint64_t dev, uint64_t io_size, uint64_t io_pagesize, uint64_t flag, uint64_t *dma_region);
+int lv1_free_device_dma_region(uint64_t bus, uint64_t dev, uint64_t dma_region);
+int lv1_map_device_dma_region(uint64_t bus, uint64_t dev, uint64_t lpar_addr, uint64_t dma_region, uint64_t size, uint64_t flags);
+int lv1_unmap_device_dma_region(uint64_t bus, uint64_t dev, uint64_t dma_region, uint64_t size);
+int lv1_read_pci_config(uint64_t ps3bus, uint64_t bus, uint64_t dev, uint64_t func, uint64_t offset, uint64_t size, uint64_t *result);
+int lv1_write_pci_config(uint64_t ps3bus, uint64_t bus, uint64_t dev, uint64_t func, uint64_t offset, uint64_t size, uint64_t data);
+int lv1_net_add_multicast_address(uint64_t bus, uint64_t dev, uint64_t addr, uint64_t flags);
+int lv1_net_remove_multicast_address(uint64_t bus, uint64_t dev, uint64_t zero, uint64_t one);
+int lv1_net_start_tx_dma(uint64_t bus, uint64_t dev, uint64_t bus_addr, uint64_t zero);
+int lv1_net_stop_tx_dma(uint64_t bus, uint64_t dev, uint64_t zero);
+int lv1_net_start_rx_dma(uint64_t bus, uint64_t dev, uint64_t bus_addr, uint64_t zero);
+int lv1_net_stop_rx_dma(uint64_t bus, uint64_t dev, uint64_t zero);
+int lv1_net_set_interrupt_status_indicator(uint64_t bus, uint64_t dev, uint64_t irq_status_addr, uint64_t zero);
+int lv1_net_set_interrupt_mask(uint64_t bus, uint64_t dev, uint64_t mask, uint64_t zero);
+int lv1_net_control(uint64_t bus, uint64_t dev, uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t *v1, uint64_t *v2);
+int lv1_connect_interrupt_event_receive_port(uint64_t bus, uint64_t dev, uint64_t outlet, uint64_t irq);
+int lv1_disconnect_interrupt_event_receive_port(uint64_t bus, uint64_t dev, uint64_t outlet, uint64_t irq);
+int lv1_deconfigure_virtual_uart_irq(void);
+int lv1_enable_logical_spe(uint64_t spe_id, uint64_t resource_id);
+int lv1_gpu_open(uint64_t zero);
+int lv1_gpu_close(void);
+int lv1_gpu_device_map(uint64_t dev, uint64_t *lpar_addr, uint64_t *lpar_size);
+int lv1_gpu_device_unmap(uint64_t dev);
+int lv1_gpu_memory_allocate(uint64_t ddr_size, uint64_t zero1, uint64_t zero2, uint64_t zero3, uint64_t zero4, uint64_t *handle, uint64_t *ddr_lpar);
+int lv1_gpu_memory_free(uint64_t handle);
+int lv1_gpu_context_allocate(uint64_t handle, uint64_t flags, uint64_t *chandle, uint64_t *lpar_dma_control, uint64_t *lpar_driver_info, uint64_t *lpar_reports, uint64_t *lpar_reports_size);
+int lv1_gpu_context_free(uint64_t chandle);
+int lv1_gpu_context_iomap(uint64_t changle, uint64_t gpu_ioif, uint64_t xdr_lpar, uint64_t fbsize, uint64_t ioflags);
+int lv1_gpu_context_attribute(uint64_t chandle, uint64_t op, uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4);
+int lv1_gpu_context_intr(uint64_t chandle, uint64_t *v1);
+int lv1_gpu_attribute(uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t p5);
+int lv1_get_rtc(uint64_t *rtc_val, uint64_t *timebase);
+int lv1_storage_read(uint64_t dev, uint64_t region, uint64_t sector, uint64_t nsectors, uint64_t flags, uint64_t buf, uint64_t *dma_tag);
+int lv1_storage_write(uint64_t dev, uint64_t region, uint64_t sector, uint64_t nsectors, uint64_t flags, uint64_t buf, uint64_t *dma_tag);
+int lv1_storage_send_device_command(uint64_t dev, uint64_t cmd_id, uint64_t cmd_block, uint64_t cmd_size, uint64_t data_buf, uint64_t blocks, uint64_t *dma_tag);
+int lv1_storage_get_async_status(uint64_t dev, uint64_t *dma_tag, uint64_t *status);
+int lv1_storage_check_async_status(uint64_t dev, uint64_t dma_tag, uint64_t *status);
+int lv1_panic(uint64_t howto);


Property changes on: trunk/sys/powerpc/ps3/ps3-hvcall.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ps3-hvcall.master
===================================================================
--- trunk/sys/powerpc/ps3/ps3-hvcall.master	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ps3-hvcall.master	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,141 @@
+/*
+ * Playstation 3 LV1 hypercall interface
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ps3/ps3-hvcall.master 228689 2011-12-18 16:53:21Z nwhitehorn $
+ * $MidnightBSD$
+ */
+
+#include <sys/types.h>
+
+enum lpar_id {
+	PS3_LPAR_ID_CURRENT	= 0x00,
+	PS3_LPAR_ID_PME		= 0x01,
+};
+
+/* Return codes from hypercalls */
+#define LV1_SUCCESS			0
+#define LV1_RESOURCE_SHORTAGE		-2
+#define LV1_NO_PRIVILEGE		-3
+#define LV1_DENIED_BY_POLICY		-4
+#define LV1_ACCESS_VIOLATION		-5
+#define LV1_NO_ENTRY			-6
+#define LV1_DUPLICATE_ENTRY		-7
+#define LV1_TYPE_MISMATCH		-8
+#define LV1_BUSY			-9
+#define LV1_EMPTY			-10
+#define LV1_WRONG_STATE			-11
+#define LV1_NO_MATCH			-13
+#define LV1_ALREADY_CONNECTED		-14
+#define LV1_UNSUPPORTED_PARAMETER_VALUE	-15
+#define LV1_CONDITION_NOT_SATISFIED	-16
+#define LV1_ILLEGAL_PARAMETER_VALUE	-17
+#define LV1_BAD_OPTION			-18
+#define LV1_IMPLEMENTATION_LIMITATION	-19
+#define LV1_NOT_IMPLEMENTED		-20
+#define LV1_INVALID_CLASS_ID		-21
+#define LV1_CONSTRAINT_NOT_SATISFIED	-22
+#define LV1_ALIGNMENT_ERROR		-23
+#define LV1_HARDWARE_ERROR		-24
+#define LV1_INVALID_DATA_FORMAT		-25
+#define LV1_INVALID_OPERATION		-26
+#define LV1_INTERNAL_ERROR		-32768
+
+static inline uint64_t
+lv1_repository_string(const char *str)
+{
+	uint64_t ret = 0;
+	strncpy((char *)&ret, str, sizeof(ret));
+	return (ret);
+}
+
+#	Code	Name					Inputs				Outputs
+HVCALL	0	lv1_allocate_memory			size,log_page_size,zero,flags	base_addr,muid
+HVCALL	1	lv1_write_htab_entry			vas_id,slot,pte_hi,pte_lo
+HVCALL	2	lv1_construct_virtual_address_space	log_pteg_count,n_sizes,page_sizes vas_id,hv_pteg_count
+HVCALL	4	lv1_get_virtual_address_space_id_of_ppe	ppe_id				vas_id
+HVCALL	6	lv1_query_logical_partition_address_region_info	lpar_id			base_addr,size,access_right,max_page_size,flags
+HVCALL	7	lv1_select_virtual_address_space	vas_id
+HVCALL	9	lv1_pause				mode
+HVCALL	10	lv1_destruct_virtual_address_space	vas_id
+HVCALL	11	lv1_configure_irq_state_bitmap		ppe_id,cpu_id,bitmap_addr
+HVCALL	12	lv1_connect_irq_plug_ext		ppe_id,cpu_id,virq,outlet,zero
+HVCALL	13	lv1_release_memory			base_addr
+HVCALL	15	lv1_put_iopte				ioas_id,ioif_addr,lpar_addr,io_id,flags
+HVCALL	17	lv1_disconnect_irq_plug_ext		ppe_id,cpu_id,virq
+HVCALL	18	lv1_construct_event_receive_port	UNUSED				outlet
+HVCALL	19	lv1_destruct_event_receive_port		outlet
+HVCALL	24	lv1_send_event_locally			outlet
+HVCALL	27	lv1_end_of_interrupt			irq
+HVCALL	28	lv1_connect_irq_plug			virq,irq
+HVCALL	29	lv1_disconnect_irq_plus			virq
+HVCALL	30	lv1_end_of_interrupt_ext		ppe_id,cpu_id,virq
+HVCALL	31	lv1_did_update_interrupt_mask		ppe_id,cpu_id
+HVCALL	44	lv1_shutdown_logical_partition		cmd
+HVCALL	54	lv1_destruct_logical_spe		spe_id
+HVCALL	57	lv1_construct_logical_spe		pshift1,pshift2,pshift3,pshift4,pshift5,vas_id,spe_type	priv2_addr,problem_phys,local_store_phys,unused,shadow_addr,spe_id
+HVCALL	61	lv1_set_spe_interrupt_mask		spe_id,class,mask
+HVCALL	65	lv1_disable_logical_spe			spe_id,zero
+HVCALL	66	lv1_clear_spe_interrupt_status		spe_id,class,stat,zero
+HVCALL	67	lv1_get_spe_interrupt_status		spe_id,class			stat
+HVCALL	69	lv1_get_logical_ppe_id			UNUSED				ppe_id
+HVCALL	74	lv1_get_logical_partition_id		UNUSED				lpar_id
+HVCALL	78	lv1_get_spe_irq_outlet			spe_id,class			outlet
+HVCALL	79	lv1_set_spe_privilege_state_area_1_register	spe_id,offset,value
+HVCALL	91	lv1_get_repository_node_value		lpar_id,n1,n2,n3,n4		v1,v2
+HVCALL	95	lv1_read_htab_entries			vas_id,slot	hi1,hi2,hi3,hi4,rcbits
+HVCALL	96	lv1_set_dabr				dabr,flags
+HVCALL	116	lv1_allocate_io_segment			ioas_id,seg_size,io_pagesize	ioif_addr
+HVCALL	117	lv1_release_io_segment			ioas_id,ioif_addr
+HVCALL	120	lv1_construct_io_irq_outlet		interrupt_id			outlet
+HVCALL	121	lv1_destruct_io_irq_outlet		outlet
+HVCALL	122	lv1_map_htab				lpar_id				htab_addr
+HVCALL	123	lv1_unmap_htab				htab_addr
+HVCALL	127	lv1_get_version_info			UNUSED				firm_vers
+HVCALL	158	lv1_insert_htab_entry			vas_id,pteg,pte_hi,pte_lo,lockflags,flags	index,evicted_hi,evicted_lo
+HVCALL	162	lv1_read_virtual_uart			port,buffer,bytes		bytes_read
+HVCALL	163	lv1_write_virtual_uart			port,buffer,bytes		bytes_written
+HVCALL	164	lv1_set_virtual_uart_param		port,param,value
+HVCALL	165	lv1_get_virtual_uart_param		port,param			value
+HVCALL	166	lv1_configure_virtual_uart		lpar_addr			outlet
+HVCALL	170	lv1_open_device				bus,dev,zero
+HVCALL	171	lv1_close_device			bus,dev
+HVCALL	172	lv1_map_device_mmio_region		bus,dev,bus_addr,size,page_size	lpar_addr
+HVCALL	173	lv1_unmap_device_mmio_region		bus,dev,lpar_addr
+HVCALL	174	lv1_allocate_device_dma_region		bus,dev,io_size,io_pagesize,flag	dma_region
+HVCALL	175	lv1_free_device_dma_region		bus,dev,dma_region
+HVCALL	176	lv1_map_device_dma_region		bus,dev,lpar_addr,dma_region,size,flags
+HVCALL	177	lv1_unmap_device_dma_region		bus,dev,dma_region,size
+HVCALL	178	lv1_read_pci_config			ps3bus,bus,dev,func,offset,size	result
+HVCALL	179	lv1_write_pci_config			ps3bus,bus,dev,func,offset,size,data
+HVCALL	185	lv1_net_add_multicast_address		bus,dev,addr,flags
+HVCALL	186	lv1_net_remove_multicast_address	bus,dev,zero,one
+HVCALL	187	lv1_net_start_tx_dma			bus,dev,bus_addr,zero
+HVCALL	188	lv1_net_stop_tx_dma			bus,dev,zero
+HVCALL	189	lv1_net_start_rx_dma			bus,dev,bus_addr,zero
+HVCALL	190	lv1_net_stop_rx_dma			bus,dev,zero
+HVCALL	191	lv1_net_set_interrupt_status_indicator	bus,dev,irq_status_addr,zero
+HVCALL	193	lv1_net_set_interrupt_mask		bus,dev,mask,zero
+HVCALL	194	lv1_net_control				bus,dev,p1,p2,p3,p4		v1,v2
+HVCALL	197	lv1_connect_interrupt_event_receive_port	bus,dev,outlet,irq
+HVCALL	198	lv1_disconnect_interrupt_event_receive_port	bus,dev,outlet,irq
+HVCALL	202	lv1_deconfigure_virtual_uart_irq
+HVCALL	207	lv1_enable_logical_spe			spe_id,resource_id
+HVCALL	210	lv1_gpu_open				zero
+HVCALL	211	lv1_gpu_close
+HVCALL	212	lv1_gpu_device_map			dev				lpar_addr,lpar_size
+HVCALL	213	lv1_gpu_device_unmap			dev
+HVCALL	214	lv1_gpu_memory_allocate			ddr_size,zero1,zero2,zero3,zero4	handle,ddr_lpar
+HVCALL	216	lv1_gpu_memory_free			handle
+HVCALL	217	lv1_gpu_context_allocate		handle,flags			chandle,lpar_dma_control,lpar_driver_info,lpar_reports,lpar_reports_size
+HVCALL	218	lv1_gpu_context_free			chandle
+HVCALL	221	lv1_gpu_context_iomap			changle,gpu_ioif,xdr_lpar,fbsize,ioflags
+HVCALL	225	lv1_gpu_context_attribute		chandle,op,p1,p2,p3,p4
+HVCALL	227	lv1_gpu_context_intr			chandle				v1
+HVCALL	228	lv1_gpu_attribute			p1,p2,p3,p4,p5
+HVCALL	232	lv1_get_rtc				UNUSED				rtc_val,timebase
+HVCALL	245	lv1_storage_read			dev,region,sector,nsectors,flags,buf	dma_tag
+HVCALL	246	lv1_storage_write			dev,region,sector,nsectors,flags,buf	dma_tag
+HVCALL	248	lv1_storage_send_device_command		dev,cmd_id,cmd_block,cmd_size,data_buf,blocks	dma_tag
+HVCALL	249	lv1_storage_get_async_status		dev				dma_tag,status
+HVCALL	254	lv1_storage_check_async_status		dev,dma_tag			status
+HVCALL	255	lv1_panic				howto


Property changes on: trunk/sys/powerpc/ps3/ps3-hvcall.master
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ps3_syscons.c
===================================================================
--- trunk/sys/powerpc/ps3/ps3_syscons.c	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ps3_syscons.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,199 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011-2014 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ps3/ps3_syscons.c 271769 2014-09-18 14:38:18Z dumbbell $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/limits.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/fbio.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/platform.h>
+#include <machine/pmap.h>
+
+#include <dev/vt/vt.h>
+#include <dev/vt/hw/fb/vt_fb.h>
+#include <dev/vt/colors/vt_termcolors.h>
+
+#include "ps3-hvcall.h"
+
+#define PS3FB_SIZE (4*1024*1024)
+
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET	0x0100
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC		0x0101
+#define  L1GPU_DISPLAY_SYNC_HSYNC			1
+#define  L1GPU_DISPLAY_SYNC_VSYNC			2
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP		0x0102
+
+static vd_init_t ps3fb_init;
+static vd_probe_t ps3fb_probe;
+void ps3fb_remap(void);
+
+struct ps3fb_softc {
+	struct fb_info	fb_info;
+
+	uint64_t	sc_fbhandle;
+	uint64_t	sc_fbcontext;
+	uint64_t	sc_dma_control;
+	uint64_t	sc_driver_info;
+	uint64_t	sc_reports;
+	uint64_t	sc_reports_size;
+};
+
+static struct vt_driver vt_ps3fb_driver = {
+	.vd_name = "ps3fb",
+	.vd_probe = ps3fb_probe,
+	.vd_init = ps3fb_init,
+	.vd_blank = vt_fb_blank,
+	.vd_bitblt_text = vt_fb_bitblt_text,
+	.vd_bitblt_bmp = vt_fb_bitblt_bitmap,
+	.vd_drawrect = vt_fb_drawrect,
+	.vd_setpixel = vt_fb_setpixel,
+	.vd_fb_ioctl = vt_fb_ioctl,
+	.vd_fb_mmap = vt_fb_mmap,
+	/* Better than VGA, but still generic driver. */
+	.vd_priority = VD_PRIORITY_GENERIC + 1,
+};
+
+VT_DRIVER_DECLARE(vt_ps3fb, vt_ps3fb_driver);
+static struct ps3fb_softc ps3fb_softc;
+
+static int
+ps3fb_probe(struct vt_device *vd)
+{
+	struct ps3fb_softc *sc;
+	int disable;
+	char compatible[64];
+#if 0
+	phandle_t root;
+#endif
+
+	disable = 0;
+	TUNABLE_INT_FETCH("hw.syscons.disable", &disable);
+	if (disable != 0)
+		return (0);
+
+	sc = &ps3fb_softc;
+
+#if 0
+	root = OF_finddevice("/");
+	if (OF_getprop(root, "compatible", compatible, sizeof(compatible)) <= 0)
+                return (0);
+	
+	if (strncmp(compatible, "sony,ps3", sizeof(compatible)) != 0)
+		return (0);
+#else
+	TUNABLE_STR_FETCH("hw.platform", compatible, sizeof(compatible));
+	if (strcmp(compatible, "ps3") != 0)
+		return (CN_DEAD);
+#endif
+
+	return (CN_INTERNAL);
+}
+
+void
+ps3fb_remap(void)
+{
+	struct ps3fb_softc *sc;
+	vm_offset_t va, fb_paddr;
+
+	sc = &ps3fb_softc;
+
+	lv1_gpu_close();
+	lv1_gpu_open(0);
+
+	lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET,
+	    0,0,0,0);
+	lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_MODE_SET,
+	    0,0,1,0);
+	lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+	    0,L1GPU_DISPLAY_SYNC_VSYNC,0,0);
+	lv1_gpu_context_attribute(0, L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+	    1,L1GPU_DISPLAY_SYNC_VSYNC,0,0);
+	lv1_gpu_memory_allocate(PS3FB_SIZE, 0, 0, 0, 0, &sc->sc_fbhandle,
+	    &fb_paddr);
+	lv1_gpu_context_allocate(sc->sc_fbhandle, 0, &sc->sc_fbcontext,
+	    &sc->sc_dma_control, &sc->sc_driver_info, &sc->sc_reports,
+	    &sc->sc_reports_size);
+
+	lv1_gpu_context_attribute(sc->sc_fbcontext,
+	    L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 0, 0, 0, 0);
+	lv1_gpu_context_attribute(sc->sc_fbcontext,
+	    L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 1, 0, 0, 0);
+
+	sc->fb_info.fb_pbase = fb_paddr;
+	for (va = 0; va < PS3FB_SIZE; va += PAGE_SIZE)
+		pmap_kenter_attr(0x10000000 + va, fb_paddr + va,
+		    VM_MEMATTR_WRITE_COMBINING); 
+}
+
+static int
+ps3fb_init(struct vt_device *vd)
+{
+	struct ps3fb_softc *sc;
+
+	/* Init softc */
+	vd->vd_softc = sc = &ps3fb_softc;
+
+	/* XXX: get from HV repository */
+	sc->fb_info.fb_depth = 32;
+	sc->fb_info.fb_height = 480;
+	sc->fb_info.fb_width = 720;
+	sc->fb_info.fb_stride = sc->fb_info.fb_width*4;
+	sc->fb_info.fb_size = sc->fb_info.fb_height * sc->fb_info.fb_stride;
+	sc->fb_info.fb_bpp = sc->fb_info.fb_stride / sc->fb_info.fb_width * 8;
+
+	/*
+	 * The loader puts the FB at 0x10000000, so use that for now.
+	 */
+
+	sc->fb_info.fb_vbase = 0x10000000;
+
+	/* 32-bit VGA palette */
+	vt_generate_cons_palette(sc->fb_info.fb_cmap, COLOR_FORMAT_RGB,
+	    255, 0, 255, 8, 255, 16);
+
+	/* Set correct graphics context */
+	lv1_gpu_context_attribute(sc->sc_fbcontext,
+	    L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 0, 0, 0, 0);
+	lv1_gpu_context_attribute(sc->sc_fbcontext,
+	    L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, 1, 0, 0, 0);
+
+	vt_fb_init(vd);
+	sc->fb_info.fb_flags &= ~FB_FLAG_NOMMAP; /* Set wrongly by vt_fb_init */
+
+	return (CN_INTERNAL);
+}
+


Property changes on: trunk/sys/powerpc/ps3/ps3_syscons.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ps3bus.c
===================================================================
--- trunk/sys/powerpc/ps3/ps3bus.c	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ps3bus.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,765 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2010 Nathan Whitehorn
+ * Copyright (C) 2011 glevand (geoffrey.levand at mail.ru)
+ * 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.
+ *
+ * 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 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ps3/ps3bus.c 271114 2014-09-04 18:28:30Z nwhitehorn $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/cpu.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/platform.h>
+#include <machine/pmap.h>
+#include <machine/resource.h>
+
+#include "ps3bus.h"
+#include "ps3-hvcall.h"
+#include "iommu_if.h"
+#include "clock_if.h"
+
+static void	ps3bus_identify(driver_t *, device_t);
+static int	ps3bus_probe(device_t);
+static int	ps3bus_attach(device_t);
+static int	ps3bus_print_child(device_t dev, device_t child);
+static int	ps3bus_read_ivar(device_t bus, device_t child, int which,
+		    uintptr_t *result);
+static struct resource *ps3bus_alloc_resource(device_t bus, device_t child,
+		    int type, int *rid, u_long start, u_long end,
+		    u_long count, u_int flags);
+static int	ps3bus_activate_resource(device_t bus, device_t child, int type,
+		    int rid, struct resource *res);
+static bus_dma_tag_t ps3bus_get_dma_tag(device_t dev, device_t child);
+static int	ps3_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs,		    bus_addr_t min, bus_addr_t max, bus_size_t alignment,
+		    bus_addr_t boundary, void *cookie);
+static int	ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs,
+		    int nsegs, void *cookie);
+static int	ps3_gettime(device_t dev, struct timespec *ts);
+static int	ps3_settime(device_t dev, struct timespec *ts);
+
+struct ps3bus_devinfo {
+	int bus;
+	int dev;
+	uint64_t bustype;
+	uint64_t devtype;
+	int busidx;
+	int devidx;
+
+	struct resource_list resources;
+	bus_dma_tag_t dma_tag;
+
+	struct mtx iommu_mtx;
+	bus_addr_t dma_base[4];
+};
+
+static MALLOC_DEFINE(M_PS3BUS, "ps3bus", "PS3 system bus device information");
+
+enum ps3bus_irq_type {
+	SB_IRQ = 2,
+	OHCI_IRQ = 3,
+	EHCI_IRQ = 4,
+};
+
+enum ps3bus_reg_type {
+	OHCI_REG = 3,
+	EHCI_REG = 4,
+};
+
+static device_method_t ps3bus_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_identify,	ps3bus_identify),
+	DEVMETHOD(device_probe,		ps3bus_probe),
+	DEVMETHOD(device_attach,	ps3bus_attach),
+
+	/* Bus interface */
+	DEVMETHOD(bus_add_child,	bus_generic_add_child),
+	DEVMETHOD(bus_get_dma_tag,	ps3bus_get_dma_tag),
+	DEVMETHOD(bus_print_child,	ps3bus_print_child),
+	DEVMETHOD(bus_read_ivar,	ps3bus_read_ivar),
+	DEVMETHOD(bus_alloc_resource,	ps3bus_alloc_resource),
+	DEVMETHOD(bus_activate_resource, ps3bus_activate_resource),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+
+	/* IOMMU interface */
+	DEVMETHOD(iommu_map,		ps3_iommu_map),
+	DEVMETHOD(iommu_unmap,		ps3_iommu_unmap),
+
+	/* Clock interface */
+	DEVMETHOD(clock_gettime,	ps3_gettime),
+	DEVMETHOD(clock_settime,	ps3_settime),
+
+	DEVMETHOD_END
+};
+
+struct ps3bus_softc {
+	struct rman sc_mem_rman;
+	struct rman sc_intr_rman;
+	struct mem_region *regions;
+	int rcount;
+};
+
+static driver_t ps3bus_driver = {
+	"ps3bus",
+	ps3bus_methods,
+	sizeof(struct ps3bus_softc)
+};
+
+static devclass_t ps3bus_devclass;
+
+DRIVER_MODULE(ps3bus, nexus, ps3bus_driver, ps3bus_devclass, 0, 0);
+
+static void
+ps3bus_identify(driver_t *driver, device_t parent)
+{
+	if (strcmp(installed_platform(), "ps3") != 0)
+		return;
+
+	if (device_find_child(parent, "ps3bus", -1) == NULL)
+		BUS_ADD_CHILD(parent, 0, "ps3bus", 0);
+}
+
+static int 
+ps3bus_probe(device_t dev) 
+{
+	/* Do not attach to any OF nodes that may be present */
+	
+	device_set_desc(dev, "Playstation 3 System Bus");
+
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static void
+ps3bus_resources_init(struct rman *rm, int bus_index, int dev_index,
+    struct ps3bus_devinfo *dinfo)
+{
+	uint64_t irq_type, irq, outlet;
+	uint64_t reg_type, paddr, len;
+	uint64_t ppe, junk;
+	int i, result;
+	int thread;
+
+	resource_list_init(&dinfo->resources);
+
+	lv1_get_logical_ppe_id(&ppe);
+	thread = 32 - fls(mfctrl());
+
+	/* Scan for interrupts */
+	for (i = 0; i < 10; i++) {
+		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("dev") | dev_index,
+		    lv1_repository_string("intr") | i, 0, &irq_type, &irq);
+
+		if (result != 0)
+			break;
+
+		switch (irq_type) {
+		case SB_IRQ:
+			lv1_construct_event_receive_port(&outlet);
+			lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
+			    0);
+			lv1_connect_interrupt_event_receive_port(dinfo->bus,
+			    dinfo->dev, outlet, irq);
+			break;
+		case OHCI_IRQ:
+		case EHCI_IRQ:
+			lv1_construct_io_irq_outlet(irq, &outlet);
+			lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
+			    0);
+			break;
+		default:
+			printf("Unknown IRQ type %ld for device %d.%d\n",
+			    irq_type, dinfo->bus, dinfo->dev);
+			break;
+		}
+
+		resource_list_add(&dinfo->resources, SYS_RES_IRQ, i,
+		    outlet, outlet, 1);
+	}
+
+	/* Scan for registers */
+	for (i = 0; i < 10; i++) {
+		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("dev") | dev_index,
+		    lv1_repository_string("reg") | i, 
+		    lv1_repository_string("type"), &reg_type, &junk);
+
+		if (result != 0)
+			break;
+
+		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("dev") | dev_index,
+		    lv1_repository_string("reg") | i, 
+		    lv1_repository_string("data"), &paddr, &len);
+
+		result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev,
+		    paddr, len, 12 /* log_2(4 KB) */, &paddr);
+
+		if (result != 0) {
+			printf("Mapping registers failed for device "
+			    "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev,
+			    dinfo->bustype, dinfo->devtype, result);
+			continue;
+		}
+
+		rman_manage_region(rm, paddr, paddr + len - 1);
+		resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i,
+		    paddr, paddr + len, len);
+	}
+}
+
+static void
+ps3bus_resources_init_by_type(struct rman *rm, int bus_index, int dev_index,
+    uint64_t irq_type, uint64_t reg_type, struct ps3bus_devinfo *dinfo)
+{
+	uint64_t _irq_type, irq, outlet;
+	uint64_t _reg_type, paddr, len;
+	uint64_t ppe, junk;
+	int i, result;
+	int thread;
+
+	resource_list_init(&dinfo->resources);
+
+	lv1_get_logical_ppe_id(&ppe);
+	thread = 32 - fls(mfctrl());
+
+	/* Scan for interrupts */
+	for (i = 0; i < 10; i++) {
+		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("dev") | dev_index,
+		    lv1_repository_string("intr") | i, 0, &_irq_type, &irq);
+
+		if (result != 0)
+			break;
+
+		if (_irq_type != irq_type)
+			continue;
+
+		lv1_construct_io_irq_outlet(irq, &outlet);
+		lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
+		    0);
+		resource_list_add(&dinfo->resources, SYS_RES_IRQ, i,
+		    outlet, outlet, 1);
+	}
+
+	/* Scan for registers */
+	for (i = 0; i < 10; i++) {
+		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("dev") | dev_index,
+		    lv1_repository_string("reg") | i, 
+		    lv1_repository_string("type"), &_reg_type, &junk);
+
+		if (result != 0)
+			break;
+
+		if (_reg_type != reg_type)
+			continue;
+
+		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("dev") | dev_index,
+		    lv1_repository_string("reg") | i, 
+		    lv1_repository_string("data"), &paddr, &len);
+
+		result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev,
+		    paddr, len, 12 /* log_2(4 KB) */, &paddr);
+
+		if (result != 0) {
+			printf("Mapping registers failed for device "
+			    "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev,
+			    dinfo->bustype, dinfo->devtype, result);
+			break;
+		}
+
+		rman_manage_region(rm, paddr, paddr + len - 1);
+		resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i,
+		    paddr, paddr + len, len);
+	}
+}
+
+static int 
+ps3bus_attach(device_t self) 
+{
+	struct ps3bus_softc *sc;
+	struct ps3bus_devinfo *dinfo;
+	int bus_index, dev_index, result;
+	uint64_t bustype, bus, devs;
+	uint64_t dev, devtype;
+	uint64_t junk;
+	device_t cdev;
+
+	sc = device_get_softc(self);
+	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+	sc->sc_mem_rman.rm_descr = "PS3Bus Memory Mapped I/O";
+	sc->sc_intr_rman.rm_type = RMAN_ARRAY;
+	sc->sc_intr_rman.rm_descr = "PS3Bus Interrupts";
+	rman_init(&sc->sc_mem_rman);
+	rman_init(&sc->sc_intr_rman);
+	rman_manage_region(&sc->sc_intr_rman, 0, ~0);
+
+	/* Get memory regions for DMA */
+	mem_regions(&sc->regions, &sc->rcount, &sc->regions, &sc->rcount);
+
+	/*
+	 * Probe all the PS3's buses.
+	 */
+
+	for (bus_index = 0; bus_index < 5; bus_index++) {
+		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("type"), 0, 0, &bustype, &junk);
+
+		if (result != 0)
+			continue;
+
+		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("id"), 0, 0, &bus, &junk);
+
+		if (result != 0)
+			continue;
+
+		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("num_dev"), 0, 0, &devs, &junk);
+
+		for (dev_index = 0; dev_index < devs; dev_index++) {
+			result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+			    (lv1_repository_string("bus") >> 32) | bus_index,
+			    lv1_repository_string("dev") | dev_index,
+			    lv1_repository_string("type"), 0, &devtype, &junk);
+
+			if (result != 0)
+				continue;
+
+			result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+			    (lv1_repository_string("bus") >> 32) | bus_index,
+			    lv1_repository_string("dev") | dev_index,
+			    lv1_repository_string("id"), 0, &dev, &junk);
+
+			if (result != 0)
+				continue;
+			
+			switch (devtype) {
+			case PS3_DEVTYPE_USB:
+				/* USB device has OHCI and EHCI USB host controllers */
+
+				lv1_open_device(bus, dev, 0);
+
+				/* OHCI host controller */
+
+				dinfo = malloc(sizeof(*dinfo), M_PS3BUS,
+				    M_WAITOK | M_ZERO);
+
+				dinfo->bus = bus;
+				dinfo->dev = dev;
+				dinfo->bustype = bustype;
+				dinfo->devtype = devtype;
+				dinfo->busidx = bus_index;
+				dinfo->devidx = dev_index;
+
+				ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index,
+				    dev_index, OHCI_IRQ, OHCI_REG, dinfo);
+
+				cdev = device_add_child(self, "ohci", -1);
+				if (cdev == NULL) {
+					device_printf(self,
+					    "device_add_child failed\n");
+					free(dinfo, M_PS3BUS);
+					continue;
+				}
+
+				mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF);
+				device_set_ivars(cdev, dinfo);
+
+				/* EHCI host controller */
+
+				dinfo = malloc(sizeof(*dinfo), M_PS3BUS,
+				    M_WAITOK | M_ZERO);
+
+				dinfo->bus = bus;
+				dinfo->dev = dev;
+				dinfo->bustype = bustype;
+				dinfo->devtype = devtype;
+				dinfo->busidx = bus_index;
+				dinfo->devidx = dev_index;
+
+				ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index,
+				    dev_index, EHCI_IRQ, EHCI_REG, dinfo);
+
+				cdev = device_add_child(self, "ehci", -1);
+				if (cdev == NULL) {
+					device_printf(self,
+					    "device_add_child failed\n");
+					free(dinfo, M_PS3BUS);
+					continue;
+				}
+
+				mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF);
+				device_set_ivars(cdev, dinfo);
+				break;
+			default:
+				dinfo = malloc(sizeof(*dinfo), M_PS3BUS,
+				    M_WAITOK | M_ZERO);
+
+				dinfo->bus = bus;
+				dinfo->dev = dev;
+				dinfo->bustype = bustype;
+				dinfo->devtype = devtype;
+				dinfo->busidx = bus_index;
+				dinfo->devidx = dev_index;
+
+				if (dinfo->bustype == PS3_BUSTYPE_SYSBUS ||
+				    dinfo->bustype == PS3_BUSTYPE_STORAGE)
+					lv1_open_device(bus, dev, 0);
+
+				ps3bus_resources_init(&sc->sc_mem_rman, bus_index,
+				    dev_index, dinfo);
+
+				cdev = device_add_child(self, NULL, -1);
+				if (cdev == NULL) {
+					device_printf(self,
+					    "device_add_child failed\n");
+					free(dinfo, M_PS3BUS);
+					continue;
+				}
+
+				mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF);
+				device_set_ivars(cdev, dinfo);
+			}
+		}
+	}
+	
+	clock_register(self, 1000);
+
+	return (bus_generic_attach(self));
+}
+
+static int
+ps3bus_print_child(device_t dev, device_t child)
+{
+	struct ps3bus_devinfo *dinfo = device_get_ivars(child);
+	int retval = 0;
+
+	retval += bus_print_child_header(dev, child);
+	retval += resource_list_print_type(&dinfo->resources, "mem",
+	    SYS_RES_MEMORY, "%#lx");
+	retval += resource_list_print_type(&dinfo->resources, "irq",
+	    SYS_RES_IRQ, "%ld");
+
+	retval += bus_print_child_footer(dev, child);
+
+	return (retval);
+}
+
+static int
+ps3bus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
+{
+	struct ps3bus_devinfo *dinfo = device_get_ivars(child);
+
+	switch (which) {
+	case PS3BUS_IVAR_BUS:
+		*result = dinfo->bus;
+		break;
+	case PS3BUS_IVAR_DEVICE:
+		*result = dinfo->dev;
+		break;
+	case PS3BUS_IVAR_BUSTYPE:
+		*result = dinfo->bustype;
+		break;
+	case PS3BUS_IVAR_DEVTYPE:
+		*result = dinfo->devtype;
+		break;
+	case PS3BUS_IVAR_BUSIDX:
+		*result = dinfo->busidx;
+		break;
+	case PS3BUS_IVAR_DEVIDX:
+		*result = dinfo->devidx;
+		break;
+	default:
+		return (EINVAL);
+	}
+
+	return (0);
+}
+
+static struct resource *
+ps3bus_alloc_resource(device_t bus, device_t child, int type, int *rid,
+    u_long start, u_long end, u_long count, u_int flags)
+{
+	struct	ps3bus_devinfo *dinfo;
+	struct	ps3bus_softc *sc;
+	int	needactivate;
+        struct	resource *rv;
+        struct	rman *rm;
+        u_long	adjstart, adjend, adjcount;
+        struct	resource_list_entry *rle;
+
+	sc = device_get_softc(bus);
+	dinfo = device_get_ivars(child);
+	needactivate = flags & RF_ACTIVE;
+	flags &= ~RF_ACTIVE;
+
+	switch (type) {
+	case SYS_RES_MEMORY:
+		rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY,
+		    *rid);
+		if (rle == NULL) {
+			device_printf(bus, "no rle for %s memory %d\n",
+				      device_get_nameunit(child), *rid);
+			return (NULL);
+		}
+
+		if (start < rle->start)
+			adjstart = rle->start;
+		else if (start > rle->end)
+			adjstart = rle->end;
+		else
+			adjstart = start;
+
+		if (end < rle->start)
+			adjend = rle->start;
+		else if (end > rle->end)
+			adjend = rle->end;
+		else
+			adjend = end;
+
+		adjcount = adjend - adjstart;
+
+		rm = &sc->sc_mem_rman;
+		break;
+	case SYS_RES_IRQ:
+		rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ,
+		    *rid);
+		rm = &sc->sc_intr_rman;
+		adjstart = rle->start;
+		adjcount = ulmax(count, rle->count);
+		adjend = ulmax(rle->end, rle->start + adjcount - 1);
+		break;
+	default:
+		device_printf(bus, "unknown resource request from %s\n",
+			      device_get_nameunit(child));
+		return (NULL);
+        }
+
+	rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags,
+	    child);
+	if (rv == NULL) {
+		device_printf(bus,
+			"failed to reserve resource %#lx - %#lx (%#lx)"
+			" for %s\n", adjstart, adjend, adjcount,
+			device_get_nameunit(child));
+		return (NULL);
+	}
+
+	rman_set_rid(rv, *rid);
+
+	if (needactivate) {
+		if (bus_activate_resource(child, type, *rid, rv) != 0) {
+			device_printf(bus,
+				"failed to activate resource for %s\n",
+				device_get_nameunit(child));
+				rman_release_resource(rv);
+			return (NULL);
+		}
+	}
+
+	return (rv);
+}
+
+static int
+ps3bus_activate_resource(device_t bus, device_t child, int type, int rid,
+    struct resource *res)
+{
+	void *p;
+
+	if (type == SYS_RES_IRQ)
+		return (bus_activate_resource(bus, type, rid, res));
+
+	if (type == SYS_RES_MEMORY) {
+		vm_offset_t start;
+
+		start = (vm_offset_t) rman_get_start(res);
+
+		if (bootverbose)
+			printf("ps3 mapdev: start %zx, len %ld\n", start,
+			       rman_get_size(res));
+
+		p = pmap_mapdev(start, (vm_size_t) rman_get_size(res));
+		if (p == NULL)
+			return (ENOMEM);
+		rman_set_virtual(res, p);
+		rman_set_bustag(res, &bs_be_tag);
+		rman_set_bushandle(res, (u_long)p);
+	}
+
+	return (rman_activate_resource(res));
+}
+
+static bus_dma_tag_t
+ps3bus_get_dma_tag(device_t dev, device_t child)
+{
+	struct ps3bus_devinfo *dinfo = device_get_ivars(child);
+	struct ps3bus_softc *sc = device_get_softc(dev);
+	int i, err, flags, pagesize;
+
+	if (dinfo->bustype != PS3_BUSTYPE_SYSBUS &&
+	    dinfo->bustype != PS3_BUSTYPE_STORAGE)
+		return (bus_get_dma_tag(dev));
+
+	mtx_lock(&dinfo->iommu_mtx);
+	if (dinfo->dma_tag != NULL) {
+		mtx_unlock(&dinfo->iommu_mtx);
+		return (dinfo->dma_tag);
+	}
+
+	flags = 0; /* 32-bit mode */
+	if (dinfo->bustype == PS3_BUSTYPE_SYSBUS &&
+	    dinfo->devtype == PS3_DEVTYPE_USB)
+		flags = 2; /* 8-bit mode */
+
+	pagesize = 24; /* log_2(16 MB) */
+	if (dinfo->bustype == PS3_BUSTYPE_STORAGE)
+		pagesize = 12; /* 4 KB */
+
+	for (i = 0; i < sc->rcount; i++) {
+		err = lv1_allocate_device_dma_region(dinfo->bus, dinfo->dev,
+		    sc->regions[i].mr_size, pagesize, flags,
+		    &dinfo->dma_base[i]);
+		if (err != 0) {
+			device_printf(child,
+			    "could not allocate DMA region %d: %d\n", i, err);
+			goto fail;
+		}
+
+		err = lv1_map_device_dma_region(dinfo->bus, dinfo->dev,
+		    sc->regions[i].mr_start, dinfo->dma_base[i],
+		    sc->regions[i].mr_size,
+		    0xf800000000000800UL /* Cell Handbook Figure 7.3.4.1 */);
+		if (err != 0) {
+			device_printf(child,
+			    "could not map DMA region %d: %d\n", i, err);
+			goto fail;
+		}
+	}
+
+	err = bus_dma_tag_create(bus_get_dma_tag(dev),
+	    1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
+	    NULL, NULL, BUS_SPACE_MAXSIZE, 0, BUS_SPACE_MAXSIZE,
+	    0, NULL, NULL, &dinfo->dma_tag);
+
+	/*
+	 * Note: storage devices have IOMMU mappings set up by the hypervisor,
+	 * but use physical, non-translated addresses. The above IOMMU
+	 * initialization is necessary for the hypervisor to be able to set up
+	 * the mappings, but actual DMA mappings should not use the IOMMU
+	 * routines.
+	 */
+	if (dinfo->bustype != PS3_BUSTYPE_STORAGE)
+		bus_dma_tag_set_iommu(dinfo->dma_tag, dev, dinfo);
+
+fail:
+	mtx_unlock(&dinfo->iommu_mtx);
+
+	if (err)
+		return (NULL);
+
+	return (dinfo->dma_tag);
+}
+
+static int
+ps3_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs,
+    bus_addr_t min, bus_addr_t max, bus_size_t alignment, bus_addr_t boundary,
+    void *cookie)
+{
+	struct ps3bus_devinfo *dinfo = cookie;
+	struct ps3bus_softc *sc = device_get_softc(dev);
+	int i, j;
+
+	for (i = 0; i < *nsegs; i++) {
+		for (j = 0; j < sc->rcount; j++) {
+			if (segs[i].ds_addr >= sc->regions[j].mr_start &&
+			    segs[i].ds_addr < sc->regions[j].mr_start +
+			      sc->regions[j].mr_size)
+				break;
+		}
+		KASSERT(j < sc->rcount,
+		    ("Trying to map address %#lx not in physical memory",
+		    segs[i].ds_addr));
+
+		segs[i].ds_addr = dinfo->dma_base[j] +
+		    (segs[i].ds_addr - sc->regions[j].mr_start);
+	}
+
+	return (0);
+}
+
+static int
+ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs, int nsegs, void *cookie)
+{
+
+	return (0);
+}
+
+#define Y2K 946684800
+
+static int
+ps3_gettime(device_t dev, struct timespec *ts)
+{
+	uint64_t rtc, tb;
+	int result;
+
+	result = lv1_get_rtc(&rtc, &tb);
+	if (result)
+		return (result);
+
+	ts->tv_sec = rtc + Y2K;
+	ts->tv_nsec = 0;
+	return (0);
+}
+	
+static int
+ps3_settime(device_t dev, struct timespec *ts)
+{
+	return (-1);
+}
+


Property changes on: trunk/sys/powerpc/ps3/ps3bus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ps3bus.h
===================================================================
--- trunk/sys/powerpc/ps3/ps3bus.h	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ps3bus.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,70 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2010 Nathan Whitehorn
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ps3/ps3bus.h 223313 2011-06-20 00:17:44Z nwhitehorn $
+ */
+
+#ifndef _POWERPC_PS3_PS3BUS_H
+#define _POWERPC_PS3_PS3BUS_H
+
+enum {
+	PS3BUS_IVAR_BUS,
+	PS3BUS_IVAR_DEVICE,
+	PS3BUS_IVAR_BUSTYPE,
+	PS3BUS_IVAR_DEVTYPE,
+	PS3BUS_IVAR_BUSIDX,
+	PS3BUS_IVAR_DEVIDX,
+};
+
+#define PS3BUS_ACCESSOR(A, B, T) \
+	__BUS_ACCESSOR(ps3bus, A, PS3BUS, B, T)
+
+PS3BUS_ACCESSOR(bus,		BUS,		int)
+PS3BUS_ACCESSOR(device,		DEVICE,		int)
+PS3BUS_ACCESSOR(bustype,	BUSTYPE,	uint64_t)
+PS3BUS_ACCESSOR(devtype,	DEVTYPE,	uint64_t)
+PS3BUS_ACCESSOR(busidx,		BUSIDX,		int)
+PS3BUS_ACCESSOR(devidx,		DEVIDX,		int)
+
+/* Bus types */
+enum {
+	PS3_BUSTYPE_SYSBUS = 4,
+	PS3_BUSTYPE_STORAGE = 5,
+};
+
+/* Device types */
+enum {
+	/* System bus devices */
+	PS3_DEVTYPE_GELIC = 3,
+	PS3_DEVTYPE_USB = 4,
+	PS3_DEVTYPE_GPIO = 6,
+
+	/* Storage bus devices */
+	PS3_DEVTYPE_DISK = 0,
+	PS3_DEVTYPE_CDROM = 5,
+	PS3_DEVTYPE_FLASH = 14,
+};
+
+#endif /* _POWERPC_PS3_PS3BUS_H */


Property changes on: trunk/sys/powerpc/ps3/ps3bus.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ps3cdrom.c
===================================================================
--- trunk/sys/powerpc/ps3/ps3cdrom.c	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ps3cdrom.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,711 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2010 Nathan Whitehorn
+ * Copyright (C) 2011 glevand <geoffrey.levand at mail.ru>
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ps3/ps3cdrom.c 315813 2017-03-23 06:41:13Z mav $");
+
+#include <sys/param.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/ata.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/pio.h>
+#include <machine/bus.h>
+#include <machine/platform.h>
+#include <machine/pmap.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_sim.h>
+#include <cam/cam_xpt_sim.h>
+#include <cam/cam_debug.h>
+#include <cam/scsi/scsi_all.h>
+
+#include "ps3bus.h"
+#include "ps3-hvcall.h"
+
+#define PS3CDROM_LOCK_INIT(_sc)		\
+	mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), "ps3cdrom", \
+	    MTX_DEF)
+#define PS3CDROM_LOCK_DESTROY(_sc)	mtx_destroy(&_sc->sc_mtx);
+#define PS3CDROM_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
+#define	PS3CDROM_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
+#define PS3CDROM_ASSERT_LOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define PS3CDROM_ASSERT_UNLOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+#define PS3CDROM_MAX_XFERS		3
+
+#define	LV1_STORAGE_SEND_ATAPI_COMMAND	0x01
+
+struct ps3cdrom_softc;
+
+struct ps3cdrom_xfer {
+	TAILQ_ENTRY(ps3cdrom_xfer) x_queue;
+	struct ps3cdrom_softc *x_sc;
+	union ccb *x_ccb;
+	bus_dmamap_t x_dmamap;
+	uint64_t x_tag;
+};
+
+TAILQ_HEAD(ps3cdrom_xferq, ps3cdrom_xfer);
+
+struct ps3cdrom_softc {
+	device_t sc_dev;
+
+	struct mtx sc_mtx;
+
+	uint64_t sc_blksize;
+	uint64_t sc_nblocks;
+
+	int sc_irqid;
+	struct resource	*sc_irq;
+	void *sc_irqctx;
+
+	bus_dma_tag_t sc_dmatag;
+
+	struct cam_sim *sc_sim;
+	struct cam_path *sc_path;
+
+	struct ps3cdrom_xfer sc_xfer[PS3CDROM_MAX_XFERS];
+	struct ps3cdrom_xferq sc_active_xferq;
+	struct ps3cdrom_xferq sc_free_xferq;
+};
+
+enum lv1_ata_proto {
+	NON_DATA_PROTO		= 0x00,
+	PIO_DATA_IN_PROTO	= 0x01,
+	PIO_DATA_OUT_PROTO	= 0x02,
+	DMA_PROTO		= 0x03
+};
+
+enum lv1_ata_in_out {
+	DIR_WRITE		= 0x00,
+	DIR_READ		= 0x01
+};
+
+struct lv1_atapi_cmd {
+	uint8_t pkt[32];
+	uint32_t pktlen;
+	uint32_t nblocks;
+	uint32_t blksize;
+	uint32_t proto;		/* enum lv1_ata_proto */
+	uint32_t in_out;	/* enum lv1_ata_in_out */
+	uint64_t buf;
+	uint32_t arglen;
+};
+
+static void ps3cdrom_action(struct cam_sim *sim, union ccb *ccb);
+static void ps3cdrom_poll(struct cam_sim *sim);
+static void ps3cdrom_async(void *callback_arg, u_int32_t code,
+    struct cam_path* path, void *arg);
+
+static void ps3cdrom_intr(void *arg);
+
+static void ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs,
+    int error);
+
+static int ps3cdrom_decode_lv1_status(uint64_t status,
+	u_int8_t *sense_key, u_int8_t *asc, u_int8_t *ascq);
+
+static int
+ps3cdrom_probe(device_t dev)
+{
+	if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_STORAGE ||
+	    ps3bus_get_devtype(dev) != PS3_DEVTYPE_CDROM)
+		return (ENXIO);
+
+	device_set_desc(dev, "Playstation 3 CDROM");
+
+	return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+ps3cdrom_attach(device_t dev)
+{
+	struct ps3cdrom_softc *sc = device_get_softc(dev);
+	struct cam_devq *devq;
+	struct ps3cdrom_xfer *xp;
+	struct ccb_setasync csa;
+	int i, err;
+
+	sc->sc_dev = dev;
+
+	PS3CDROM_LOCK_INIT(sc);
+
+	/* Setup interrupt handler */
+
+	sc->sc_irqid = 0;
+	sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid,
+	    RF_ACTIVE);
+	if (!sc->sc_irq) {
+		device_printf(dev, "Could not allocate IRQ\n");
+		err = ENXIO;
+		goto fail_destroy_lock;
+	}
+
+	err = bus_setup_intr(dev, sc->sc_irq,
+	    INTR_TYPE_CAM | INTR_MPSAFE | INTR_ENTROPY,
+	    NULL, ps3cdrom_intr, sc, &sc->sc_irqctx);
+	if (err) {
+		device_printf(dev, "Could not setup IRQ\n");
+		err = ENXIO;
+		goto fail_release_intr;
+	}
+
+	/* Setup DMA */
+
+	err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0,
+	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+	    BUS_SPACE_UNRESTRICTED, 1, PAGE_SIZE, 0,
+	    busdma_lock_mutex, &sc->sc_mtx, &sc->sc_dmatag);
+	if (err) {
+		device_printf(dev, "Could not create DMA tag\n");
+		err = ENXIO;
+		goto fail_teardown_intr;
+	}
+
+	/* Setup transfer queues */
+
+	TAILQ_INIT(&sc->sc_active_xferq);
+	TAILQ_INIT(&sc->sc_free_xferq);
+
+	for (i = 0; i < PS3CDROM_MAX_XFERS; i++) {
+		xp = &sc->sc_xfer[i];
+		xp->x_sc = sc;
+
+		err = bus_dmamap_create(sc->sc_dmatag, BUS_DMA_COHERENT,
+		    &xp->x_dmamap);
+		if (err) {
+			device_printf(dev, "Could not create DMA map (%d)\n",
+			    err);
+			goto fail_destroy_dmamap;
+		}
+
+		TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
+	}
+
+	/* Setup CAM */
+
+	devq = cam_simq_alloc(PS3CDROM_MAX_XFERS - 1);
+	if (!devq) {
+		device_printf(dev, "Could not allocate SIM queue\n");
+		err = ENOMEM;
+		goto fail_destroy_dmatag;
+	}
+
+	sc->sc_sim = cam_sim_alloc(ps3cdrom_action, ps3cdrom_poll, "ps3cdrom",
+	    sc, device_get_unit(dev), &sc->sc_mtx, PS3CDROM_MAX_XFERS - 1, 0,
+	    devq);
+	if (!sc->sc_sim) {
+		device_printf(dev, "Could not allocate SIM\n");
+		cam_simq_free(devq);
+		err = ENOMEM;
+		goto fail_destroy_dmatag;
+	}
+
+	/* Setup XPT */
+
+	PS3CDROM_LOCK(sc);
+
+	err = xpt_bus_register(sc->sc_sim, dev, 0);
+	if (err != CAM_SUCCESS) {
+		device_printf(dev, "Could not register XPT bus\n");
+		err = ENXIO;
+		PS3CDROM_UNLOCK(sc);
+		goto fail_free_sim;
+	}
+
+	err = xpt_create_path(&sc->sc_path, NULL, cam_sim_path(sc->sc_sim),
+	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
+	if (err != CAM_REQ_CMP) {
+		device_printf(dev, "Could not create XPT path\n");
+		err = ENOMEM;
+		PS3CDROM_UNLOCK(sc);
+		goto fail_unregister_xpt_bus;
+	}
+
+	xpt_setup_ccb(&csa.ccb_h, sc->sc_path, 5);
+	csa.ccb_h.func_code = XPT_SASYNC_CB;
+	csa.event_enable = AC_LOST_DEVICE;
+	csa.callback = ps3cdrom_async;
+	csa.callback_arg = sc->sc_sim;
+	xpt_action((union ccb *) &csa);
+
+	CAM_DEBUG(sc->sc_path, CAM_DEBUG_TRACE,
+	    ("registered SIM for ps3cdrom%d\n", device_get_unit(dev)));
+
+	PS3CDROM_UNLOCK(sc);
+
+	return (BUS_PROBE_SPECIFIC);
+
+fail_unregister_xpt_bus:
+
+	xpt_bus_deregister(cam_sim_path(sc->sc_sim));
+
+fail_free_sim:
+
+	cam_sim_free(sc->sc_sim, TRUE);
+
+fail_destroy_dmamap:
+
+	while ((xp = TAILQ_FIRST(&sc->sc_free_xferq))) {
+		TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue);
+		bus_dmamap_destroy(sc->sc_dmatag, xp->x_dmamap);
+	}
+
+fail_destroy_dmatag:
+
+	bus_dma_tag_destroy(sc->sc_dmatag);
+
+fail_teardown_intr:
+
+	bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
+
+fail_release_intr:
+
+	bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
+
+fail_destroy_lock:
+
+	PS3CDROM_LOCK_DESTROY(sc);
+
+	return (err);
+}
+
+static int
+ps3cdrom_detach(device_t dev)
+{
+	struct ps3cdrom_softc *sc = device_get_softc(dev);
+	int i;
+
+	xpt_async(AC_LOST_DEVICE, sc->sc_path, NULL);
+	xpt_free_path(sc->sc_path);
+	xpt_bus_deregister(cam_sim_path(sc->sc_sim));
+	cam_sim_free(sc->sc_sim, TRUE);
+
+	for (i = 0; i < PS3CDROM_MAX_XFERS; i++)
+		bus_dmamap_destroy(sc->sc_dmatag, sc->sc_xfer[i].x_dmamap);
+
+	bus_dma_tag_destroy(sc->sc_dmatag);
+
+	bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
+	bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
+
+	PS3CDROM_LOCK_DESTROY(sc);
+
+	return (0);
+}
+
+static void
+ps3cdrom_action(struct cam_sim *sim, union ccb *ccb)
+{
+	struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *)cam_sim_softc(sim);
+	device_t dev = sc->sc_dev;
+	struct ps3cdrom_xfer *xp;
+	int err;
+
+	PS3CDROM_ASSERT_LOCKED(sc);
+
+	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
+	   ("function code 0x%02x\n", ccb->ccb_h.func_code));
+
+	switch (ccb->ccb_h.func_code) {
+	case XPT_SCSI_IO:
+		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG)
+			break;
+
+		if(ccb->ccb_h.target_id > 0) {
+			ccb->ccb_h.status = CAM_TID_INVALID;
+			break;
+		}
+
+		if(ccb->ccb_h.target_lun > 0) {
+			ccb->ccb_h.status = CAM_LUN_INVALID;
+			break;
+		}
+
+		xp = TAILQ_FIRST(&sc->sc_free_xferq);
+		
+		KASSERT(xp != NULL, ("no free transfers"));
+
+		xp->x_ccb = ccb;
+
+		TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue);
+
+		err = bus_dmamap_load_ccb(sc->sc_dmatag, xp->x_dmamap,
+		    ccb, ps3cdrom_transfer, xp, 0);
+		if (err && err != EINPROGRESS) {
+			device_printf(dev, "Could not load DMA map (%d)\n",
+			    err);
+
+			xp->x_ccb = NULL;
+			TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
+			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+			break;
+		}
+		return;
+	case XPT_SET_TRAN_SETTINGS:
+		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
+		break;
+	case XPT_GET_TRAN_SETTINGS:
+	{
+		struct ccb_trans_settings *cts = &ccb->cts;
+
+		cts->protocol = PROTO_SCSI;
+		cts->protocol_version = SCSI_REV_2;
+		cts->transport = XPORT_SPI;
+		cts->transport_version = 2;
+		cts->proto_specific.valid = 0;
+		cts->xport_specific.valid = 0;
+		ccb->ccb_h.status = CAM_REQ_CMP;
+		break;
+	}
+	case XPT_RESET_BUS:
+	case XPT_RESET_DEV:
+		ccb->ccb_h.status = CAM_REQ_CMP;
+		break;
+	case XPT_CALC_GEOMETRY:
+		cam_calc_geometry(&ccb->ccg, 1);
+		break;
+	case XPT_PATH_INQ:
+	{
+		struct ccb_pathinq *cpi = &ccb->cpi;
+
+		cpi->version_num = 1;
+		cpi->hba_inquiry = 0;
+		cpi->target_sprt = 0;
+		cpi->hba_inquiry = PI_SDTR_ABLE;
+		cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN | PIM_NO_6_BYTE;
+		cpi->hba_eng_cnt = 0;
+		bzero(cpi->vuhba_flags, sizeof(cpi->vuhba_flags));
+		cpi->max_target = 0;
+		cpi->max_lun = 0;
+		cpi->initiator_id = 7;
+		cpi->bus_id = cam_sim_bus(sim);
+		cpi->unit_number = cam_sim_unit(sim);
+		cpi->base_transfer_speed = 150000;
+		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
+		strlcpy(cpi->hba_vid, "Sony", HBA_IDLEN);
+		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+		cpi->transport = XPORT_SPI;
+		cpi->transport_version = 2;
+		cpi->protocol = PROTO_SCSI;
+		cpi->protocol_version = SCSI_REV_2;
+		cpi->maxio = PAGE_SIZE;
+		cpi->ccb_h.status = CAM_REQ_CMP;
+		break;
+	}
+	default:
+		CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
+		    ("unsupported function code 0x%02x\n",
+		    ccb->ccb_h.func_code));
+		ccb->ccb_h.status = CAM_REQ_INVALID;
+		break;
+	}
+
+	xpt_done(ccb);
+}
+
+static void
+ps3cdrom_poll(struct cam_sim *sim)
+{
+	ps3cdrom_intr(cam_sim_softc(sim));
+}
+
+static void
+ps3cdrom_async(void *callback_arg, u_int32_t code,
+	struct cam_path* path, void *arg)
+{
+	switch (code) {
+	case AC_LOST_DEVICE:
+		xpt_print_path(path);
+		break;
+	default:
+		break;
+	}
+}
+
+static void
+ps3cdrom_intr(void *arg)
+{
+	struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *) arg;
+	device_t dev = sc->sc_dev;
+	uint64_t devid = ps3bus_get_device(dev);
+	struct ps3cdrom_xfer *xp;
+	union ccb *ccb;
+	u_int8_t *cdb, sense_key, asc, ascq;
+	uint64_t tag, status;
+
+	if (lv1_storage_get_async_status(devid, &tag, &status) != 0)
+		return;
+
+	PS3CDROM_LOCK(sc);
+
+	/* Find transfer with the returned tag */
+
+	TAILQ_FOREACH(xp, &sc->sc_active_xferq, x_queue) {
+		if (xp->x_tag == tag)
+			break;
+	}
+
+	if (xp) {
+		ccb = xp->x_ccb;
+		cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
+			    ccb->csio.cdb_io.cdb_ptr :
+			    ccb->csio.cdb_io.cdb_bytes;
+
+		CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
+		   ("ATAPI command 0x%02x tag 0x%016lx completed (0x%016lx)\n",
+		    cdb[0], tag, status));
+
+		if (!status) {
+			ccb->csio.scsi_status = SCSI_STATUS_OK;
+			ccb->csio.resid = 0;
+			ccb->ccb_h.status = CAM_REQ_CMP;
+		} else {
+			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+
+			if (!ps3cdrom_decode_lv1_status(status, &sense_key,
+			    &asc, &ascq)) {
+
+				CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
+				   ("sense key 0x%02x asc 0x%02x ascq 0x%02x\n",
+				    sense_key, asc, ascq));
+
+				scsi_set_sense_data(&ccb->csio.sense_data,
+				    /*sense_format*/ SSD_TYPE_NONE,
+				    /*current_error*/ 1,
+				    sense_key,
+				    asc,
+				    ascq,
+				    SSD_ELEM_NONE);
+				ccb->csio.sense_len = SSD_FULL_SIZE;
+				ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR |
+				    CAM_AUTOSNS_VALID;
+			}
+
+			if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
+				ccb->csio.resid = ccb->csio.dxfer_len;
+		}
+
+		if (ccb->ccb_h.flags & CAM_DIR_IN)
+			bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
+			    BUS_DMASYNC_POSTREAD);
+
+		bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap);
+
+		xp->x_ccb = NULL;
+		TAILQ_REMOVE(&sc->sc_active_xferq, xp, x_queue);
+		TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
+
+		xpt_done(ccb);
+	} else {
+		device_printf(dev,
+		    "Could not find transfer with tag 0x%016lx\n",  tag);
+	}
+
+	PS3CDROM_UNLOCK(sc);
+}
+
+static void
+ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+	struct ps3cdrom_xfer *xp = (struct ps3cdrom_xfer *) arg;
+	struct ps3cdrom_softc *sc = xp->x_sc;
+	device_t dev = sc->sc_dev;
+	uint64_t devid = ps3bus_get_device(dev);
+	union ccb *ccb = xp->x_ccb;
+	u_int8_t *cdb;
+	uint64_t start_sector, block_count;
+	int err;
+
+	KASSERT(nsegs == 1 || nsegs == 0,
+	    ("ps3cdrom_transfer: invalid number of DMA segments %d", nsegs));
+	KASSERT(error == 0, ("ps3cdrom_transfer: DMA error %d", error));
+
+	PS3CDROM_ASSERT_LOCKED(sc);
+
+	if (error) {
+		device_printf(dev, "Could not load DMA map (%d)\n",  error);
+
+		xp->x_ccb = NULL;
+		TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
+		ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+		xpt_done(ccb);
+		return;
+	}
+
+	cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
+		    ccb->csio.cdb_io.cdb_ptr :
+		    ccb->csio.cdb_io.cdb_bytes;
+
+	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
+	   ("ATAPI command 0x%02x cdb_len %d dxfer_len %d\n ", cdb[0],
+	    ccb->csio.cdb_len, ccb->csio.dxfer_len));
+
+	switch (cdb[0]) {
+	case READ_10:
+		KASSERT(nsegs == 1, ("ps3cdrom_transfer: no data to read"));
+		start_sector = (cdb[2] << 24) | (cdb[3] << 16) |
+		    (cdb[4] << 8) | cdb[5];
+		block_count = (cdb[7] << 8) | cdb[8];
+
+		err = lv1_storage_read(devid, 0 /* region id */,
+		    start_sector, block_count, 0 /* flags */, segs[0].ds_addr,
+		    &xp->x_tag);
+		bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
+		    BUS_DMASYNC_POSTREAD);
+		break;
+	case WRITE_10:
+		KASSERT(nsegs == 1, ("ps3cdrom_transfer: no data to write"));
+		start_sector = (cdb[2] << 24) | (cdb[3] << 16) |
+		    (cdb[4] << 8) | cdb[5];
+		block_count = (cdb[7] << 8) | cdb[8];
+
+		bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
+		    BUS_DMASYNC_PREWRITE);
+		err = lv1_storage_write(devid, 0 /* region id */,
+		    start_sector, block_count, 0 /* flags */,
+		    segs[0].ds_addr, &xp->x_tag);
+		break;
+	default:
+		{
+		struct lv1_atapi_cmd atapi_cmd;
+
+		bzero(&atapi_cmd, sizeof(atapi_cmd));
+		atapi_cmd.pktlen = 12;
+		bcopy(cdb, atapi_cmd.pkt, ccb->csio.cdb_len);
+
+		if (ccb->ccb_h.flags & CAM_DIR_IN) {
+			atapi_cmd.in_out = DIR_READ;
+			atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ?
+			    DMA_PROTO : PIO_DATA_IN_PROTO;
+		} else if (ccb->ccb_h.flags & CAM_DIR_OUT) {
+			atapi_cmd.in_out = DIR_WRITE;
+			atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ?
+			    DMA_PROTO : PIO_DATA_OUT_PROTO;
+		} else {
+			atapi_cmd.proto = NON_DATA_PROTO;
+		}
+
+		atapi_cmd.nblocks = atapi_cmd.arglen =
+		    (nsegs == 0) ? 0 : segs[0].ds_len;
+		atapi_cmd.blksize = 1;
+		atapi_cmd.buf = (nsegs == 0) ? 0 : segs[0].ds_addr;
+
+		if (ccb->ccb_h.flags & CAM_DIR_OUT)
+			bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
+			    BUS_DMASYNC_PREWRITE);
+
+		err = lv1_storage_send_device_command(devid,
+		    LV1_STORAGE_SEND_ATAPI_COMMAND, vtophys(&atapi_cmd),
+		    sizeof(atapi_cmd), atapi_cmd.buf, atapi_cmd.arglen,
+		    &xp->x_tag);
+	
+		break;
+		}
+	}
+
+	if (err) {
+		device_printf(dev, "ATAPI command 0x%02x failed (%d)\n",
+		    cdb[0], err);
+
+		bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap);
+
+		xp->x_ccb = NULL;
+		TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
+
+		bzero(&ccb->csio.sense_data, sizeof(ccb->csio.sense_data));
+		/* Invalid field in parameter list */
+		scsi_set_sense_data(&ccb->csio.sense_data,
+				    /*sense_format*/ SSD_TYPE_NONE,
+				    /*current_error*/ 1,
+				    /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
+				    /*asc*/ 0x26,
+				    /*ascq*/ 0x00,
+				    SSD_ELEM_NONE);
+
+		ccb->csio.sense_len = SSD_FULL_SIZE;
+		ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+		ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
+		xpt_done(ccb);
+	} else {
+		CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
+		   ("ATAPI command 0x%02x tag 0x%016lx submitted\n ", cdb[0],
+		   xp->x_tag));
+
+		TAILQ_INSERT_TAIL(&sc->sc_active_xferq, xp, x_queue);
+		ccb->ccb_h.status |= CAM_SIM_QUEUED;
+	}
+}
+
+static int
+ps3cdrom_decode_lv1_status(uint64_t status, u_int8_t *sense_key, u_int8_t *asc,
+    u_int8_t *ascq)
+{
+	if (((status >> 24) & 0xff) != SCSI_STATUS_CHECK_COND)
+		return -1;
+
+	*sense_key = (status >> 16) & 0xff;
+	*asc = (status >> 8) & 0xff;
+	*ascq = status & 0xff;
+
+	return (0);
+}
+
+static device_method_t ps3cdrom_methods[] = {
+	DEVMETHOD(device_probe,		ps3cdrom_probe),
+	DEVMETHOD(device_attach,	ps3cdrom_attach),
+	DEVMETHOD(device_detach,	ps3cdrom_detach),
+	{0, 0},
+};
+
+static driver_t ps3cdrom_driver = {
+	"ps3cdrom",
+	ps3cdrom_methods,
+	sizeof(struct ps3cdrom_softc),
+};
+
+static devclass_t ps3cdrom_devclass;
+
+DRIVER_MODULE(ps3cdrom, ps3bus, ps3cdrom_driver, ps3cdrom_devclass, 0, 0);
+MODULE_DEPEND(ps3cdrom, cam, 1, 1, 1);


Property changes on: trunk/sys/powerpc/ps3/ps3cdrom.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ps3disk.c
===================================================================
--- trunk/sys/powerpc/ps3/ps3disk.c	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ps3disk.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,704 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2011 glevand (geoffrey.levand at mail.ru)
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/ps3/ps3disk.c 227309 2011-11-07 15:43:11Z ed $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/disk.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/pio.h>
+#include <machine/bus.h>
+#include <machine/platform.h>
+#include <machine/pmap.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <geom/geom_disk.h>
+
+#include "ps3bus.h"
+#include "ps3-hvcall.h"
+
+#define PS3DISK_LOCK_INIT(_sc)		\
+	mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), "ps3disk", MTX_DEF)
+#define PS3DISK_LOCK_DESTROY(_sc)	mtx_destroy(&_sc->sc_mtx);
+#define PS3DISK_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
+#define	PS3DISK_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
+#define PS3DISK_ASSERT_LOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define PS3DISK_ASSERT_UNLOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+#define LV1_STORAGE_ATA_HDDOUT 		0x23
+
+static SYSCTL_NODE(_hw, OID_AUTO, ps3disk, CTLFLAG_RD, 0,
+    "PS3 Disk driver parameters");
+
+#ifdef PS3DISK_DEBUG
+static int ps3disk_debug = 0;
+SYSCTL_INT(_hw_ps3disk, OID_AUTO, debug, CTLFLAG_RW, &ps3disk_debug,
+	0, "control debugging printfs");
+TUNABLE_INT("hw.ps3disk.debug", &ps3disk_debug);
+enum {
+	PS3DISK_DEBUG_INTR	= 0x00000001,
+	PS3DISK_DEBUG_TASK	= 0x00000002,
+	PS3DISK_DEBUG_READ	= 0x00000004,
+	PS3DISK_DEBUG_WRITE	= 0x00000008,
+	PS3DISK_DEBUG_FLUSH	= 0x00000010,
+	PS3DISK_DEBUG_ANY	= 0xffffffff
+};
+#define	DPRINTF(sc, m, fmt, ...)				\
+do {								\
+	if (sc->sc_debug & (m))					\
+		printf(fmt, __VA_ARGS__);			\
+} while (0)
+#else
+#define	DPRINTF(sc, m, fmt, ...)
+#endif
+
+struct ps3disk_region {
+	uint64_t r_id;
+	uint64_t r_start;
+	uint64_t r_size;
+	uint64_t r_flags;
+};
+
+struct ps3disk_softc {
+	device_t sc_dev;
+
+	struct mtx sc_mtx;
+
+	uint64_t sc_blksize;
+	uint64_t sc_nblocks;
+
+	uint64_t sc_nregs;
+	struct ps3disk_region *sc_reg;
+
+	int sc_irqid;
+	struct resource	*sc_irq;
+	void *sc_irqctx;
+
+	struct disk **sc_disk;
+
+	struct bio_queue_head sc_bioq;
+	struct bio_queue_head sc_deferredq;
+	struct proc *sc_task;	
+
+	bus_dma_tag_t sc_dmatag;
+
+	int sc_running;
+	int sc_debug;
+};
+
+static int ps3disk_open(struct disk *dp);
+static int ps3disk_close(struct disk *dp);
+static void ps3disk_strategy(struct bio *bp);
+
+static void ps3disk_task(void *arg);
+static void ps3disk_intr(void *arg);
+static int ps3disk_get_disk_geometry(struct ps3disk_softc *sc);
+static int ps3disk_enum_regions(struct ps3disk_softc *sc);
+static void ps3disk_transfer(void *arg, bus_dma_segment_t *segs, int nsegs,
+    int error);
+
+static void ps3disk_sysctlattach(struct ps3disk_softc *sc);
+
+static MALLOC_DEFINE(M_PS3DISK, "ps3disk", "PS3 Disk");
+
+static int
+ps3disk_probe(device_t dev)
+{
+	if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_STORAGE ||
+	    ps3bus_get_devtype(dev) != PS3_DEVTYPE_DISK)
+		return (ENXIO);
+
+	device_set_desc(dev, "Playstation 3 Disk");
+
+	return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+ps3disk_attach(device_t dev)
+{
+	struct ps3disk_softc *sc;
+	struct disk *d;
+	intmax_t mb;
+	uint64_t junk;
+	char unit;
+	int i, err;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+
+	PS3DISK_LOCK_INIT(sc);
+
+	err = ps3disk_get_disk_geometry(sc);
+	if (err) {
+		device_printf(dev, "Could not get disk geometry\n");
+		err = ENXIO;
+		goto fail_destroy_lock;
+	}
+
+	device_printf(dev, "block size %lu total blocks %lu\n",
+	    sc->sc_blksize, sc->sc_nblocks);
+
+	err = ps3disk_enum_regions(sc);
+	if (err) {
+		device_printf(dev, "Could not enumerate disk regions\n");
+		err = ENXIO;
+		goto fail_destroy_lock;
+	}
+
+	device_printf(dev, "Found %lu regions\n", sc->sc_nregs);
+
+	if (!sc->sc_nregs) {
+		err = ENXIO;
+		goto fail_destroy_lock;
+	}
+
+	/* Setup interrupt handler */
+	sc->sc_irqid = 0;
+	sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid,
+	    RF_ACTIVE);
+	if (!sc->sc_irq) {
+		device_printf(dev, "Could not allocate IRQ\n");
+		err = ENXIO;
+		goto fail_free_regions;
+	}
+
+	err = bus_setup_intr(dev, sc->sc_irq,
+	    INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY,
+	    NULL, ps3disk_intr, sc, &sc->sc_irqctx);
+	if (err) {
+		device_printf(dev, "Could not setup IRQ\n");
+		err = ENXIO;
+		goto fail_release_intr;
+	}
+
+	/* Setup DMA */
+	err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0,
+	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+	    BUS_SPACE_UNRESTRICTED, 1, PAGE_SIZE, 0,
+	    busdma_lock_mutex, &sc->sc_mtx, &sc->sc_dmatag);
+	if (err) {
+		device_printf(dev, "Could not create DMA tag\n");
+		err = ENXIO;
+		goto fail_teardown_intr;
+	}
+
+	/* Setup disks */
+
+	sc->sc_disk = malloc(sc->sc_nregs * sizeof(struct disk *),
+	    M_PS3DISK, M_ZERO | M_WAITOK);
+	if (!sc->sc_disk) {
+		device_printf(dev, "Could not allocate disk(s)\n");
+		err = ENOMEM;
+		goto fail_teardown_intr;
+	}
+
+	for (i = 0; i < sc->sc_nregs; i++) {
+		struct ps3disk_region *rp = &sc->sc_reg[i];
+
+		d = sc->sc_disk[i] = disk_alloc();
+		d->d_open = ps3disk_open;
+		d->d_close = ps3disk_close;
+		d->d_strategy = ps3disk_strategy;
+		d->d_name = "ps3disk";
+		d->d_drv1 = sc;
+		d->d_maxsize = PAGE_SIZE;
+		d->d_sectorsize = sc->sc_blksize;
+		d->d_unit = i;
+		d->d_mediasize = sc->sc_reg[i].r_size * sc->sc_blksize;
+		d->d_flags |= DISKFLAG_CANFLUSHCACHE;
+
+		mb = d->d_mediasize >> 20;
+		unit = 'M';
+		if (mb >= 10240) {
+			unit = 'G';
+			mb /= 1024;
+		}
+
+		/* Test to see if we can read this region */
+		err = lv1_storage_read(ps3bus_get_device(dev), d->d_unit,
+		    0, 0, rp->r_flags, 0, &junk);
+		device_printf(dev, "region %d %ju%cB%s\n", i, mb, unit,
+		    (err == LV1_DENIED_BY_POLICY) ?  " (hypervisor protected)"
+		    : "");
+
+		if (err != LV1_DENIED_BY_POLICY)
+			disk_create(d, DISK_VERSION);
+	}
+	err = 0;
+
+	bioq_init(&sc->sc_bioq);
+	bioq_init(&sc->sc_deferredq);
+	kproc_create(&ps3disk_task, sc, &sc->sc_task, 0, 0, "ps3disk");
+
+	ps3disk_sysctlattach(sc);
+	sc->sc_running = 1;
+	return (0);
+
+fail_teardown_intr:
+	bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
+fail_release_intr:
+	bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
+fail_free_regions:
+	free(sc->sc_reg, M_PS3DISK);
+fail_destroy_lock:
+	PS3DISK_LOCK_DESTROY(sc);
+	return (err);
+}
+
+static int
+ps3disk_detach(device_t dev)
+{
+	struct ps3disk_softc *sc = device_get_softc(dev);
+	int i;
+
+	for (i = 0; i < sc->sc_nregs; i++)
+		disk_destroy(sc->sc_disk[i]);
+
+	bus_dma_tag_destroy(sc->sc_dmatag);
+
+	bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
+	bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
+
+	free(sc->sc_disk, M_PS3DISK);
+	free(sc->sc_reg, M_PS3DISK);
+
+	PS3DISK_LOCK_DESTROY(sc);
+
+	return (0);
+}
+
+static int
+ps3disk_open(struct disk *dp)
+{
+	return (0);
+}
+
+static int
+ps3disk_close(struct disk *dp)
+{
+	return (0);
+}
+
+/* Process deferred blocks */
+static void
+ps3disk_task(void *arg)
+{
+	struct ps3disk_softc *sc = (struct ps3disk_softc *) arg;
+	struct bio *bp;
+
+	
+	while (1) {
+		kproc_suspend_check(sc->sc_task);
+		tsleep(&sc->sc_deferredq, PRIBIO, "ps3disk", 10);
+
+		PS3DISK_LOCK(sc);
+		bp = bioq_takefirst(&sc->sc_deferredq);
+		PS3DISK_UNLOCK(sc);
+
+		if (bp == NULL)
+			continue;
+
+		if (bp->bio_driver1 != NULL) {
+			bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t)
+			    bp->bio_driver1);
+			bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t)
+			    bp->bio_driver1);
+		}
+
+		ps3disk_strategy(bp);
+	}
+
+	kproc_exit(0);
+}
+
+static void
+ps3disk_strategy(struct bio *bp)
+{
+	struct ps3disk_softc *sc = (struct ps3disk_softc *)bp->bio_disk->d_drv1;
+	int err;
+
+	if (sc == NULL) {
+		bp->bio_flags |= BIO_ERROR;
+		bp->bio_error = EINVAL;
+		biodone(bp);
+		return;
+	}
+
+	PS3DISK_LOCK(sc);
+	bp->bio_resid = bp->bio_bcount;
+	bioq_insert_tail(&sc->sc_bioq, bp);
+
+	DPRINTF(sc, PS3DISK_DEBUG_TASK, "%s: bio_cmd 0x%02x\n",
+	    __func__, bp->bio_cmd);
+
+	err = 0;
+	if (bp->bio_cmd == BIO_FLUSH) {
+		bp->bio_driver1 = 0;
+		err = lv1_storage_send_device_command(
+		    ps3bus_get_device(sc->sc_dev), LV1_STORAGE_ATA_HDDOUT,
+		    0, 0, 0, 0, (uint64_t *)&bp->bio_driver2);
+		if (err == LV1_BUSY)
+			err = EAGAIN;
+	} else if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
+		if (bp->bio_bcount % sc->sc_blksize != 0) {
+			err = EINVAL;
+		} else {
+			bus_dmamap_create(sc->sc_dmatag, BUS_DMA_COHERENT,
+			    (bus_dmamap_t *)(&bp->bio_driver1));
+			err = bus_dmamap_load(sc->sc_dmatag,
+			    (bus_dmamap_t)(bp->bio_driver1), bp->bio_data,
+			    bp->bio_bcount, ps3disk_transfer, bp, 0);
+			if (err == EINPROGRESS)
+				err = 0;
+		}
+	} else {
+		err = EINVAL;
+	}
+
+	if (err == EAGAIN) {
+		bioq_remove(&sc->sc_bioq, bp);
+		bioq_insert_tail(&sc->sc_deferredq, bp);
+	} else if (err != 0) {
+		bp->bio_error = err;
+		bp->bio_flags |= BIO_ERROR;
+		bioq_remove(&sc->sc_bioq, bp);
+		disk_err(bp, "hard error", -1, 1);
+		biodone(bp);
+	}
+
+	PS3DISK_UNLOCK(sc);
+}
+
+static void
+ps3disk_intr(void *arg)
+{
+	struct ps3disk_softc *sc = (struct ps3disk_softc *) arg;
+	device_t dev = sc->sc_dev;
+	uint64_t devid = ps3bus_get_device(dev);
+	struct bio *bp;
+	uint64_t tag, status;
+
+	if (lv1_storage_get_async_status(devid, &tag, &status) != 0)
+		return;
+	
+	PS3DISK_LOCK(sc);
+
+	DPRINTF(sc, PS3DISK_DEBUG_INTR, "%s: tag 0x%016lx "
+	    "status 0x%016lx\n", __func__, tag, status);
+
+	/* Locate the matching request */
+	TAILQ_FOREACH(bp, &sc->sc_bioq.queue, bio_queue) {
+		if ((uint64_t)bp->bio_driver2 != tag)
+			continue;
+
+		if (status != 0) {
+			device_printf(sc->sc_dev, "%s error (%#lx)\n",
+			    (bp->bio_cmd == BIO_READ) ? "Read" : "Write",
+			    status);
+			bp->bio_error = EIO;
+			bp->bio_flags |= BIO_ERROR;
+		} else {
+			bp->bio_error = 0;
+			bp->bio_resid = 0;
+			bp->bio_flags |= BIO_DONE;
+		}
+
+		if (bp->bio_driver1 != NULL) {
+			if (bp->bio_cmd == BIO_READ)
+				bus_dmamap_sync(sc->sc_dmatag, (bus_dmamap_t)
+				    bp->bio_driver1, BUS_DMASYNC_POSTREAD);
+			bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t)
+			    bp->bio_driver1);
+			bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t)
+			    bp->bio_driver1);
+		}
+
+		bioq_remove(&sc->sc_bioq, bp);
+		biodone(bp);
+		break;
+	}
+
+	if (bioq_first(&sc->sc_deferredq) != NULL)
+		wakeup(&sc->sc_deferredq);
+
+	PS3DISK_UNLOCK(sc);
+}
+
+static int
+ps3disk_get_disk_geometry(struct ps3disk_softc *sc)
+{
+	device_t dev = sc->sc_dev;
+	uint64_t bus_index = ps3bus_get_busidx(dev);
+	uint64_t dev_index = ps3bus_get_devidx(dev);
+	uint64_t junk;
+	int err;
+
+	err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+	    (lv1_repository_string("bus") >> 32) | bus_index,
+	    lv1_repository_string("dev") | dev_index,
+	    lv1_repository_string("blk_size"), 0, &sc->sc_blksize, &junk);
+	if (err) {
+		device_printf(dev, "Could not get block size (0x%08x)\n", err);
+		return (ENXIO);
+	}
+
+	err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+	    (lv1_repository_string("bus") >> 32) | bus_index,
+	    lv1_repository_string("dev") | dev_index,
+	    lv1_repository_string("n_blocks"), 0, &sc->sc_nblocks, &junk);
+	if (err) {
+		device_printf(dev, "Could not get total number of blocks "
+		    "(0x%08x)\n", err);
+		err = ENXIO;
+	}
+
+	return (err);
+}
+
+static int
+ps3disk_enum_regions(struct ps3disk_softc *sc)
+{
+	device_t dev = sc->sc_dev;
+	uint64_t bus_index = ps3bus_get_busidx(dev);
+	uint64_t dev_index = ps3bus_get_devidx(dev);
+	uint64_t junk;
+	int i, err;
+
+	/* Read number of regions */
+
+	err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+	    (lv1_repository_string("bus") >> 32) | bus_index,
+	    lv1_repository_string("dev") | dev_index,
+	    lv1_repository_string("n_regs"), 0, &sc->sc_nregs, &junk);
+	if (err) {
+		device_printf(dev, "Could not get number of regions (0x%08x)\n",
+		    err);
+		err = ENXIO;
+		goto fail;
+	}
+
+	if (!sc->sc_nregs)
+		return 0;
+
+	sc->sc_reg = malloc(sc->sc_nregs * sizeof(struct ps3disk_region),
+	    M_PS3DISK, M_ZERO | M_WAITOK);
+	if (!sc->sc_reg) {
+		err = ENOMEM;
+		goto fail;
+	}
+
+	/* Setup regions */
+
+	for (i = 0; i < sc->sc_nregs; i++) {
+		err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("dev") | dev_index,
+		    lv1_repository_string("region") | i,
+		    lv1_repository_string("id"), &sc->sc_reg[i].r_id, &junk);
+		if (err) {
+			device_printf(dev, "Could not get region id (0x%08x)\n",
+			    err);
+			err = ENXIO;
+			goto fail;
+		}
+
+		err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("dev") | dev_index,
+		    lv1_repository_string("region") | i,
+		    lv1_repository_string("start"), &sc->sc_reg[i].r_start,
+		    &junk);
+		if (err) {
+			device_printf(dev, "Could not get region start "
+			    "(0x%08x)\n", err);
+			err = ENXIO;
+			goto fail;
+		}
+
+		err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("dev") | dev_index,
+		    lv1_repository_string("region") | i,
+		    lv1_repository_string("size"), &sc->sc_reg[i].r_size,
+		    &junk);
+		if (err) {
+			device_printf(dev, "Could not get region size "
+			    "(0x%08x)\n", err);
+			err = ENXIO;
+			goto fail;
+		}
+
+		if (i == 0)
+			sc->sc_reg[i].r_flags = 0x2;
+		else
+			sc->sc_reg[i].r_flags = 0;
+	}
+
+	return (0);
+
+fail:
+
+	sc->sc_nregs = 0;
+	if (sc->sc_reg)
+		free(sc->sc_reg, M_PS3DISK);
+
+	return (err);
+}
+
+static void
+ps3disk_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+	struct bio *bp = (struct bio *)(arg);
+	struct ps3disk_softc *sc = (struct ps3disk_softc *)bp->bio_disk->d_drv1;
+	struct ps3disk_region *rp = &sc->sc_reg[bp->bio_disk->d_unit];
+	uint64_t devid = ps3bus_get_device(sc->sc_dev);
+	uint64_t block;
+	int i, err;
+
+	/* Locks already held by busdma */
+	PS3DISK_ASSERT_LOCKED(sc);
+
+	if (error) {
+		bp->bio_error = error;
+		bp->bio_flags |= BIO_ERROR;
+		bioq_remove(&sc->sc_bioq, bp);
+		biodone(bp);
+		return;
+	}
+
+	block = bp->bio_pblkno;
+	for (i = 0; i < nsegs; i++) {
+		KASSERT((segs[i].ds_len % sc->sc_blksize) == 0,
+		    ("DMA fragments not blocksize multiples"));
+
+		if (bp->bio_cmd == BIO_READ) {
+			err = lv1_storage_read(devid, rp->r_id,
+			    block, segs[i].ds_len/sc->sc_blksize,
+			    rp->r_flags, segs[i].ds_addr,
+			    (uint64_t *)&bp->bio_driver2);
+		} else {
+			bus_dmamap_sync(sc->sc_dmatag,
+			    (bus_dmamap_t)bp->bio_driver1,
+			    BUS_DMASYNC_PREWRITE);
+			err = lv1_storage_write(devid, rp->r_id,
+			    block, segs[i].ds_len/sc->sc_blksize,
+			    rp->r_flags, segs[i].ds_addr,
+			    (uint64_t *)&bp->bio_driver2);
+		}
+
+		if (err) {
+			if (err == LV1_BUSY) {
+				bioq_remove(&sc->sc_bioq, bp);
+				bioq_insert_tail(&sc->sc_deferredq, bp);
+			} else {
+				bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t)
+				    bp->bio_driver1);
+				bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t)
+				    bp->bio_driver1);
+				device_printf(sc->sc_dev, "Could not read "
+				    "sectors (0x%08x)\n", err);
+				bp->bio_error = EINVAL;
+				bp->bio_flags |= BIO_ERROR;
+				bioq_remove(&sc->sc_bioq, bp);
+				biodone(bp);
+			}
+
+			break;
+		}
+
+		DPRINTF(sc, PS3DISK_DEBUG_READ, "%s: tag 0x%016lx\n",
+		    __func__, sc->sc_bounce_tag);
+	}
+}
+
+#ifdef PS3DISK_DEBUG
+static int
+ps3disk_sysctl_debug(SYSCTL_HANDLER_ARGS)
+{
+	struct ps3disk_softc *sc = arg1;
+	int debug, error;
+
+	debug = sc->sc_debug;
+
+	error = sysctl_handle_int(oidp, &debug, 0, req);
+	if (error || !req->newptr)
+		return error;
+
+	sc->sc_debug = debug;
+
+	return 0;
+}
+#endif
+
+static void
+ps3disk_sysctlattach(struct ps3disk_softc *sc)
+{
+#ifdef PS3DISK_DEBUG
+	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
+	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
+
+	sc->sc_debug = ps3disk_debug;
+
+	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+		"debug", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+		ps3disk_sysctl_debug, "I", "control debugging printfs");
+#endif
+}
+
+static device_method_t ps3disk_methods[] = {
+	DEVMETHOD(device_probe,		ps3disk_probe),
+	DEVMETHOD(device_attach,	ps3disk_attach),
+	DEVMETHOD(device_detach,	ps3disk_detach),
+	{0, 0},
+};
+
+static driver_t ps3disk_driver = {
+	"ps3disk",
+	ps3disk_methods,
+	sizeof(struct ps3disk_softc),
+};
+
+static devclass_t ps3disk_devclass;
+
+DRIVER_MODULE(ps3disk, ps3bus, ps3disk_driver, ps3disk_devclass, 0, 0);


Property changes on: trunk/sys/powerpc/ps3/ps3disk.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/ps3/ps3pic.c
===================================================================
--- trunk/sys/powerpc/ps3/ps3pic.c	                        (rev 0)
+++ trunk/sys/powerpc/ps3/ps3pic.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,249 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2010 Nathan Whitehorn
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/ps3/ps3pic.c 266676 2014-05-26 01:37:43Z nwhitehorn $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/platform.h>
+
+#include "ps3-hvcall.h"
+#include "pic_if.h"
+
+static void	ps3pic_identify(driver_t *driver, device_t parent);
+static int	ps3pic_probe(device_t);
+static int	ps3pic_attach(device_t);
+
+static void	ps3pic_dispatch(device_t, struct trapframe *);
+static void	ps3pic_enable(device_t, u_int, u_int);
+static void	ps3pic_eoi(device_t, u_int);
+static void	ps3pic_ipi(device_t, u_int);
+static void	ps3pic_mask(device_t, u_int);
+static void	ps3pic_unmask(device_t, u_int);
+
+struct ps3pic_softc {
+	volatile uint64_t *bitmap_thread0;
+	volatile uint64_t *mask_thread0;
+	volatile uint64_t *bitmap_thread1;
+	volatile uint64_t *mask_thread1;
+
+	uint64_t	sc_ipi_outlet[2];
+	uint64_t	sc_ipi_virq;
+	int		sc_vector[64];
+};
+
+static device_method_t  ps3pic_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_identify,	ps3pic_identify),
+	DEVMETHOD(device_probe,		ps3pic_probe),
+	DEVMETHOD(device_attach,	ps3pic_attach),
+
+	/* PIC interface */
+	DEVMETHOD(pic_dispatch,		ps3pic_dispatch),
+	DEVMETHOD(pic_enable,		ps3pic_enable),
+	DEVMETHOD(pic_eoi,		ps3pic_eoi),
+	DEVMETHOD(pic_ipi,		ps3pic_ipi),
+	DEVMETHOD(pic_mask,		ps3pic_mask),
+	DEVMETHOD(pic_unmask,		ps3pic_unmask),
+
+	{ 0, 0 },
+};
+
+static driver_t ps3pic_driver = {
+	"ps3pic",
+	ps3pic_methods,
+	sizeof(struct ps3pic_softc)
+};
+
+static devclass_t ps3pic_devclass;
+
+DRIVER_MODULE(ps3pic, nexus, ps3pic_driver, ps3pic_devclass, 0, 0);
+
+static MALLOC_DEFINE(M_PS3PIC, "ps3pic", "PS3 PIC");
+
+static void
+ps3pic_identify(driver_t *driver, device_t parent)
+{
+	if (strcmp(installed_platform(), "ps3") != 0)
+		return;
+
+	if (device_find_child(parent, "ps3pic", -1) == NULL)
+		BUS_ADD_CHILD(parent, 0, "ps3pic", 0);
+}
+
+static int
+ps3pic_probe(device_t dev)
+{
+	device_set_desc(dev, "Playstation 3 interrupt controller");
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+ps3pic_attach(device_t dev)
+{
+	struct ps3pic_softc *sc;
+	uint64_t ppe;
+	int thread;
+
+	sc = device_get_softc(dev);
+
+	sc->bitmap_thread0 = contigmalloc(128 /* 512 bits * 2 */, M_PS3PIC,
+	    M_NOWAIT | M_ZERO, 0, BUS_SPACE_MAXADDR, 64 /* alignment */,
+	    PAGE_SIZE /* boundary */);
+	sc->mask_thread0 = sc->bitmap_thread0 + 4;
+	sc->bitmap_thread1 = sc->bitmap_thread0 + 8;
+	sc->mask_thread1 = sc->bitmap_thread0 + 12;
+
+	lv1_get_logical_ppe_id(&ppe);
+	thread = 32 - fls(mfctrl());
+	lv1_configure_irq_state_bitmap(ppe, thread,
+	    vtophys(sc->bitmap_thread0));
+
+	sc->sc_ipi_virq = 63;
+
+#ifdef SMP
+	lv1_configure_irq_state_bitmap(ppe, !thread,
+	    vtophys(sc->bitmap_thread1));
+
+	/* Map both IPIs to the same VIRQ to avoid changes in intr_machdep */
+	lv1_construct_event_receive_port(&sc->sc_ipi_outlet[0]);
+	lv1_connect_irq_plug_ext(ppe, thread, sc->sc_ipi_virq,
+	    sc->sc_ipi_outlet[0], 0);
+	lv1_construct_event_receive_port(&sc->sc_ipi_outlet[1]);
+	lv1_connect_irq_plug_ext(ppe, !thread, sc->sc_ipi_virq,
+	    sc->sc_ipi_outlet[1], 0);
+#endif
+
+	powerpc_register_pic(dev, 0, sc->sc_ipi_virq, 1, FALSE);
+	return (0);
+}
+
+/*
+ * PIC I/F methods.
+ */
+
+static void
+ps3pic_dispatch(device_t dev, struct trapframe *tf)
+{
+	uint64_t bitmap, mask;
+	int irq;
+	struct ps3pic_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	if (PCPU_GET(cpuid) == 0) {
+		bitmap = atomic_readandclear_64(&sc->bitmap_thread0[0]);
+		mask = sc->mask_thread0[0];
+	} else {
+		bitmap = atomic_readandclear_64(&sc->bitmap_thread1[0]);
+		mask = sc->mask_thread1[0];
+	}
+	powerpc_sync();
+
+	while ((irq = ffsl(bitmap & mask) - 1) != -1) {
+		bitmap &= ~(1UL << irq);
+		powerpc_dispatch_intr(sc->sc_vector[63 - irq], tf);
+	}
+}
+
+static void
+ps3pic_enable(device_t dev, u_int irq, u_int vector)
+{
+	struct ps3pic_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->sc_vector[irq] = vector;
+
+	ps3pic_unmask(dev, irq);
+}
+
+static void
+ps3pic_eoi(device_t dev, u_int irq)
+{
+	uint64_t ppe;
+	int thread;
+
+	lv1_get_logical_ppe_id(&ppe);
+	thread = 32 - fls(mfctrl());
+
+	lv1_end_of_interrupt_ext(ppe, thread, irq);
+}
+
+static void
+ps3pic_ipi(device_t dev, u_int cpu)
+{
+	struct ps3pic_softc *sc;
+	sc = device_get_softc(dev);
+
+	lv1_send_event_locally(sc->sc_ipi_outlet[cpu]);
+}
+
+static void
+ps3pic_mask(device_t dev, u_int irq)
+{
+	struct ps3pic_softc *sc;
+	uint64_t ppe;
+
+	sc = device_get_softc(dev);
+
+	/* Do not mask IPIs! */
+	if (irq == sc->sc_ipi_virq)
+		return;
+
+	atomic_clear_64(&sc->mask_thread0[0], 1UL << (63 - irq));
+	atomic_clear_64(&sc->mask_thread1[0], 1UL << (63 - irq));
+
+	lv1_get_logical_ppe_id(&ppe);
+	lv1_did_update_interrupt_mask(ppe, 0);
+	lv1_did_update_interrupt_mask(ppe, 1);
+}
+
+static void
+ps3pic_unmask(device_t dev, u_int irq)
+{
+	struct ps3pic_softc *sc;
+	uint64_t ppe;
+
+	sc = device_get_softc(dev);
+	atomic_set_64(&sc->mask_thread0[0], 1UL << (63 - irq));
+	atomic_set_64(&sc->mask_thread1[0], 1UL << (63 - irq));
+
+	lv1_get_logical_ppe_id(&ppe);
+	lv1_did_update_interrupt_mask(ppe, 0);
+	lv1_did_update_interrupt_mask(ppe, 1);
+}


Property changes on: trunk/sys/powerpc/ps3/ps3pic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/mmu_phyp.c
===================================================================
--- trunk/sys/powerpc/pseries/mmu_phyp.c	                        (rev 0)
+++ trunk/sys/powerpc/pseries/mmu_phyp.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,433 @@
+/* $MidnightBSD$ */
+/*
+ * Copyright (C) 2010 Andreas Tobler
+ * 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.
+ *
+ * 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 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/pseries/mmu_phyp.c 259227 2013-12-11 20:56:23Z andreast $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/msgbuf.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/vmmeter.h>
+
+#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_pageout.h>
+#include <vm/uma.h>
+
+#include <powerpc/aim/mmu_oea64.h>
+
+#include "mmu_if.h"
+#include "moea64_if.h"
+
+#include "phyp-hvcall.h"
+
+extern int n_slbs;
+
+/*
+ * Kernel MMU interface
+ */
+
+static void	mphyp_bootstrap(mmu_t mmup, vm_offset_t kernelstart,
+		    vm_offset_t kernelend);
+static void	mphyp_cpu_bootstrap(mmu_t mmup, int ap);
+static void	mphyp_pte_synch(mmu_t, uintptr_t pt, struct lpte *pvo_pt);
+static void	mphyp_pte_clear(mmu_t, uintptr_t pt, struct lpte *pvo_pt,
+		    uint64_t vpn, u_int64_t ptebit);
+static void	mphyp_pte_unset(mmu_t, uintptr_t pt, struct lpte *pvo_pt,
+		    uint64_t vpn);
+static void	mphyp_pte_change(mmu_t, uintptr_t pt, struct lpte *pvo_pt,
+		    uint64_t vpn);
+static int	mphyp_pte_insert(mmu_t, u_int ptegidx, struct lpte *pvo_pt);
+static uintptr_t mphyp_pvo_to_pte(mmu_t, const struct pvo_entry *pvo);
+
+#define VSID_HASH_MASK		0x0000007fffffffffULL
+
+
+static mmu_method_t mphyp_methods[] = {
+        MMUMETHOD(mmu_bootstrap,        mphyp_bootstrap),
+        MMUMETHOD(mmu_cpu_bootstrap,    mphyp_cpu_bootstrap),
+
+	MMUMETHOD(moea64_pte_synch,     mphyp_pte_synch),
+        MMUMETHOD(moea64_pte_clear,     mphyp_pte_clear),
+        MMUMETHOD(moea64_pte_unset,     mphyp_pte_unset),
+        MMUMETHOD(moea64_pte_change,    mphyp_pte_change),
+        MMUMETHOD(moea64_pte_insert,    mphyp_pte_insert),
+        MMUMETHOD(moea64_pvo_to_pte,    mphyp_pvo_to_pte),
+
+        { 0, 0 }
+};
+
+MMU_DEF_INHERIT(pseries_mmu, "mmu_phyp", mphyp_methods, 0, oea64_mmu);
+
+static void
+mphyp_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
+{
+	uint64_t final_pteg_count = 0;
+	char buf[8];
+	uint32_t prop[2];
+	uint32_t nptlp, shift = 0, slb_encoding = 0;
+	phandle_t dev, node, root;
+	int idx, len, res;
+
+	moea64_early_bootstrap(mmup, kernelstart, kernelend);
+
+	root = OF_peer(0);
+
+        dev = OF_child(root);
+	while (dev != 0) {
+                res = OF_getprop(dev, "name", buf, sizeof(buf));
+                if (res > 0 && strcmp(buf, "cpus") == 0)
+                        break;
+                dev = OF_peer(dev);
+        }
+
+	node = OF_child(dev);
+
+	while (node != 0) {
+                res = OF_getprop(node, "device_type", buf, sizeof(buf));
+                if (res > 0 && strcmp(buf, "cpu") == 0)
+                        break;
+                node = OF_peer(node);
+        }
+
+	res = OF_getprop(node, "ibm,pft-size", prop, sizeof(prop));
+	if (res <= 0)
+		panic("mmu_phyp: unknown PFT size");
+	final_pteg_count = 1 << prop[1];
+	res = OF_getprop(node, "ibm,slb-size", prop, sizeof(prop[0]));
+	if (res > 0)
+		n_slbs = prop[0];
+
+	moea64_pteg_count = final_pteg_count / sizeof(struct lpteg);
+
+	/*
+	 * Scan the large page size property for PAPR compatible machines.
+	 * See PAPR D.5 Changes to Section 5.1.4, 'CPU Node Properties'
+	 * for the encoding of the property.
+	 */
+
+	len = OF_getproplen(node, "ibm,segment-page-sizes");
+	if (len > 0) {
+		/*
+		 * We have to use a variable length array on the stack
+		 * since we have very limited stack space.
+		 */
+		cell_t arr[len/sizeof(cell_t)];
+		res = OF_getprop(node, "ibm,segment-page-sizes", &arr,
+				 sizeof(arr));
+		len /= 4;
+		idx = 0;
+		while (len > 0) {
+			shift = arr[idx];
+			slb_encoding = arr[idx + 1];
+			nptlp = arr[idx + 2];
+			idx += 3;
+			len -= 3;
+			while (len > 0 && nptlp) {
+				idx += 2;
+				len -= 2;
+				nptlp--;
+			}
+		}
+
+		/* For now we allow shift only to be <= 0x18. */
+		if (shift >= 0x18)
+		    shift = 0x18;
+
+		moea64_large_page_shift = shift;
+		moea64_large_page_size = 1 << shift;
+	}
+
+	moea64_mid_bootstrap(mmup, kernelstart, kernelend);
+	moea64_late_bootstrap(mmup, kernelstart, kernelend);
+}
+
+static void
+mphyp_cpu_bootstrap(mmu_t mmup, int ap)
+{
+	struct slb *slb = PCPU_GET(slb);
+	register_t seg0;
+	int i;
+
+	/*
+	 * Install kernel SLB entries
+	 */
+
+        __asm __volatile ("slbia");
+        __asm __volatile ("slbmfee %0,%1; slbie %0;" : "=r"(seg0) : "r"(0));
+	for (i = 0; i < 64; i++) {
+		if (!(slb[i].slbe & SLBE_VALID))
+			continue;
+
+		__asm __volatile ("slbmte %0, %1" ::
+		    "r"(slb[i].slbv), "r"(slb[i].slbe));
+	}
+}
+
+static void
+mphyp_pte_synch(mmu_t mmu, uintptr_t slot, struct lpte *pvo_pt)
+{
+	struct lpte pte;
+	uint64_t junk;
+
+	__asm __volatile("ptesync");
+	phyp_pft_hcall(H_READ, 0, slot, 0, 0, &pte.pte_hi, &pte.pte_lo,
+	    &junk);
+
+	pvo_pt->pte_lo |= pte.pte_lo & (LPTE_CHG | LPTE_REF);
+}
+
+static void
+mphyp_pte_clear(mmu_t mmu, uintptr_t slot, struct lpte *pvo_pt, uint64_t vpn,
+    u_int64_t ptebit)
+{
+
+	if (ptebit & LPTE_CHG)
+		phyp_hcall(H_CLEAR_MOD, 0, slot);
+	if (ptebit & LPTE_REF)
+		phyp_hcall(H_CLEAR_REF, 0, slot);
+}
+
+static void
+mphyp_pte_unset(mmu_t mmu, uintptr_t slot, struct lpte *pvo_pt, uint64_t vpn)
+{
+	struct lpte pte;
+	uint64_t junk;
+	int err;
+
+	err = phyp_pft_hcall(H_REMOVE, 1UL << 31, slot,
+	    pvo_pt->pte_hi & LPTE_AVPN_MASK, 0, &pte.pte_hi, &pte.pte_lo,
+	    &junk);
+	KASSERT(err == H_SUCCESS, ("Error removing page: %d", err));
+
+	pvo_pt->pte_lo |= pte.pte_lo & (LPTE_CHG | LPTE_REF);
+}
+
+static void
+mphyp_pte_change(mmu_t mmu, uintptr_t slot, struct lpte *pvo_pt, uint64_t vpn)
+{
+	struct lpte evicted;
+	uint64_t index, junk;
+	int64_t result;
+
+	/*
+	 * NB: this is protected by the global table lock, so this two-step
+	 * is safe, except for the scratch-page case. No CPUs on which we run
+	 * this code should be using scratch pages.
+	 */
+	KASSERT(!(pvo_pt->pte_hi & LPTE_LOCKED),
+	    ("Locked pages not supported on PHYP"));
+
+	/* XXX: optimization using H_PROTECT for common case? */
+	mphyp_pte_unset(mmu, slot, pvo_pt, vpn);
+	result = phyp_pft_hcall(H_ENTER, H_EXACT, slot, pvo_pt->pte_hi,
+				pvo_pt->pte_lo, &index, &evicted.pte_lo, &junk);
+	if (result != H_SUCCESS)
+		panic("mphyp_pte_change() insertion failure: %ld\n", result);
+}
+
+static __inline int
+mphyp_pte_spillable_ident(u_int ptegidx, struct lpte *to_evict)
+{
+	uint64_t slot, junk, k;
+	struct lpte pt;
+	int     i, j;
+
+	/* Start at a random slot */
+	i = mftb() % 8;
+	k = -1;
+	for (j = 0; j < 8; j++) {
+		slot = (ptegidx << 3) + (i + j) % 8;
+		phyp_pft_hcall(H_READ, 0, slot, 0, 0, &pt.pte_hi, &pt.pte_lo,
+		    &junk);
+		
+		if (pt.pte_hi & LPTE_SWBITS)
+			continue;
+
+		/* This is a candidate, so remember it */
+		k = slot;
+
+		/* Try to get a page that has not been used lately */
+		if (!(pt.pte_lo & LPTE_REF)) {
+			memcpy(to_evict, &pt, sizeof(struct lpte));
+			return (k);
+		}
+	}
+
+	phyp_pft_hcall(H_READ, 0, slot, 0, 0, &to_evict->pte_hi,
+	    &to_evict->pte_lo, &junk);
+	return (k);
+}
+
+static int
+mphyp_pte_insert(mmu_t mmu, u_int ptegidx, struct lpte *pvo_pt)
+{
+	int64_t result;
+	struct lpte evicted;
+	struct pvo_entry *pvo;
+	uint64_t index, junk;
+	u_int pteg_bktidx;
+
+	/* Check for locked pages, which we can't support on this system */
+	KASSERT(!(pvo_pt->pte_hi & LPTE_LOCKED),
+	    ("Locked pages not supported on PHYP"));
+
+	/* Initialize PTE */
+	pvo_pt->pte_hi |= LPTE_VALID;
+	pvo_pt->pte_hi &= ~LPTE_HID;
+	evicted.pte_hi = 0;
+
+	/*
+	 * First try primary hash.
+	 */
+	pteg_bktidx = ptegidx;
+	result = phyp_pft_hcall(H_ENTER, 0, pteg_bktidx << 3, pvo_pt->pte_hi,
+	    pvo_pt->pte_lo, &index, &evicted.pte_lo, &junk);
+	if (result == H_SUCCESS)
+		return (index & 0x07);
+	KASSERT(result == H_PTEG_FULL, ("Page insertion error: %ld "
+	    "(ptegidx: %#x/%#x, PTE %#lx/%#lx", result, ptegidx,
+	    moea64_pteg_count, pvo_pt->pte_hi, pvo_pt->pte_lo));
+
+	/*
+	 * Next try secondary hash.
+	 */
+	pteg_bktidx ^= moea64_pteg_mask;
+	pvo_pt->pte_hi |= LPTE_HID;
+	result = phyp_pft_hcall(H_ENTER, 0, pteg_bktidx << 3,
+	    pvo_pt->pte_hi, pvo_pt->pte_lo, &index, &evicted.pte_lo, &junk);
+	if (result == H_SUCCESS)
+		return (index & 0x07);
+	KASSERT(result == H_PTEG_FULL, ("Secondary page insertion error: %ld",
+	    result));
+
+	/*
+	 * Out of luck. Find a PTE to sacrifice.
+	 */
+	pteg_bktidx = ptegidx;
+	index = mphyp_pte_spillable_ident(pteg_bktidx, &evicted);
+	if (index == -1L) {
+		pteg_bktidx ^= moea64_pteg_mask;
+		index = mphyp_pte_spillable_ident(pteg_bktidx, &evicted);
+	}
+
+	if (index == -1L) {
+		/* No freeable slots in either PTEG? We're hosed. */
+		panic("mphyp_pte_insert: overflow");
+		return (-1);
+	}
+
+	if (pteg_bktidx == ptegidx)
+                pvo_pt->pte_hi &= ~LPTE_HID;
+        else
+                pvo_pt->pte_hi |= LPTE_HID;
+
+	/*
+	 * Synchronize the sacrifice PTE with its PVO, then mark both
+	 * invalid. The PVO will be reused when/if the VM system comes
+	 * here after a fault.
+	 */
+
+	if (evicted.pte_hi & LPTE_HID)
+		pteg_bktidx ^= moea64_pteg_mask; /* PTEs indexed by primary */
+
+	LIST_FOREACH(pvo, &moea64_pvo_table[pteg_bktidx], pvo_olink) {
+		if (pvo->pvo_pte.lpte.pte_hi == evicted.pte_hi) {
+			KASSERT(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID,
+			    ("Invalid PVO for valid PTE!"));
+			mphyp_pte_unset(mmu, index, &pvo->pvo_pte.lpte,
+			    pvo->pvo_vpn);
+			PVO_PTEGIDX_CLR(pvo);
+			moea64_pte_overflow++;
+			break;
+		}
+	}
+
+	KASSERT(pvo->pvo_pte.lpte.pte_hi == evicted.pte_hi,
+	   ("Unable to find PVO for spilled PTE"));
+
+	/*
+	 * Set the new PTE.
+	 */
+	result = phyp_pft_hcall(H_ENTER, H_EXACT, index, pvo_pt->pte_hi,
+	    pvo_pt->pte_lo, &index, &evicted.pte_lo, &junk);
+	if (result == H_SUCCESS)
+		return (index & 0x07);
+
+	panic("Page replacement error: %ld", result);
+	return (-1);
+}
+
+static __inline u_int
+va_to_pteg(uint64_t vsid, vm_offset_t addr, int large)
+{
+	uint64_t hash;
+	int shift;
+
+	shift = large ? moea64_large_page_shift : ADDR_PIDX_SHFT;
+	hash = (vsid & VSID_HASH_MASK) ^ (((uint64_t)addr & ADDR_PIDX) >>
+	    shift);
+	return (hash & moea64_pteg_mask);
+}
+
+static uintptr_t
+mphyp_pvo_to_pte(mmu_t mmu, const struct pvo_entry *pvo)
+{
+	uint64_t vsid;
+	u_int ptegidx;
+
+	/* If the PTEG index is not set, then there is no page table entry */
+	if (!PVO_PTEGIDX_ISSET(pvo))
+		return (-1);
+
+	vsid = PVO_VSID(pvo);
+	ptegidx = va_to_pteg(vsid, PVO_VADDR(pvo), pvo->pvo_vaddr & PVO_LARGE);
+
+	/*
+	 * We can find the actual pte entry without searching by grabbing
+	 * the PTEG index from 3 unused bits in pvo_vaddr and by
+	 * noticing the HID bit.
+	 */
+	if (pvo->pvo_pte.lpte.pte_hi & LPTE_HID)
+		ptegidx ^= moea64_pteg_mask;
+
+	return ((ptegidx << 3) | PVO_PTEGIDX_GET(pvo));
+}
+


Property changes on: trunk/sys/powerpc/pseries/mmu_phyp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/phyp-hvcall.S
===================================================================
--- trunk/sys/powerpc/pseries/phyp-hvcall.S	                        (rev 0)
+++ trunk/sys/powerpc/pseries/phyp-hvcall.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,71 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2010 Andreas Tobler
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/pseries/phyp-hvcall.S 257292 2013-10-28 23:47:52Z nwhitehorn $
+ */
+#include <machine/asm.h>
+
+/* Hypervisor entry call. */
+#define  hc  .long 0x44000022
+
+/*
+ * Simple HV calls take the same arguments, with the same ABI, as this
+ * C function
+ */
+ASENTRY(phyp_hcall)
+	mflr	%r0
+	std	%r0,16(%r1)
+	ld	%r11,112(%r1)		/* Last couple args into volatile regs*/
+	ld	%r12,120(%r1)
+	hc				/* invoke the hypervisor */
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr				/* return r3 = status */
+
+/*
+ * PFT HV calls take a special ABI (see PAPR 14.5.4.1)
+ *
+ * r3-r7 arguments passed unchanged, r8-r10 are addresses of return values
+ * HV takes the same r3-r7, but returns values in r3, r4-r6
+ */
+ASENTRY(phyp_pft_hcall)
+	mflr	%r0
+	std	%r0,16(%r1)
+	stdu	%r1,-80(%r1)
+	std	%r8,48(%r1)		/* save arguments */
+	std	%r9,56(%r1)
+	std	%r10,64(%r1)
+	hc				/* invoke the hypervisor */
+	ld	%r11,48(%r1)		/* store results */
+	std	%r4,0(%r11)
+	ld	%r11,56(%r1)
+	std	%r5,0(%r11)
+	ld	%r11,64(%r1)
+	std	%r6,0(%r11)
+	ld	%r1,0(%r1)		/* exit */
+	ld	%r0,16(%r1)
+	mtlr	%r0
+	blr				/* return r3 = status */
+


Property changes on: trunk/sys/powerpc/pseries/phyp-hvcall.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/phyp-hvcall.h
===================================================================
--- trunk/sys/powerpc/pseries/phyp-hvcall.h	                        (rev 0)
+++ trunk/sys/powerpc/pseries/phyp-hvcall.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,306 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2010 Andreas Tobler
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/pseries/phyp-hvcall.h 255643 2013-09-17 17:37:04Z nwhitehorn $
+ */
+
+#ifndef	_PSERIES_PHYP_HVCALL_H_
+#define	_PSERIES_PHYP_HVCALL_H_
+
+/* Information taken from: Power.org PAPR, Version 2.4 (December 7, 2009). */
+
+#include <sys/types.h>
+
+/* Return codes. */
+
+#define H_SUCCESS       0
+#define H_BUSY          1  /* Hardware Busy -- Retry Later. */
+#define H_CLOSED        2  /* Virtual I/O connection is closed. */
+#define H_NOT_AVAILABLE 3
+#define H_CONSTRAINED   4  /* The request called for resources in excess of
+			      the maximum allowed. The resultant allocation
+			      was constrained to maximum allowed. */
+#define H_PARTIAL       5  /* The request completed only partially successful.
+			      Parameters were valid but some specific hcall
+			      function condition prevented fully completing the
+			      architected function, see the specific hcall
+			      definition for possible reasons. */
+#define H_IN_PROGRESS     14
+#define H_PAGE_REGISTERED 15
+#define H_PARTIAL_STORE   16
+#define H_PENDING         17
+#define H_CONTINUE        18
+
+#define H_LONG_BUSY_ORDER_1_MS   9900  /* This return code is identical to
+					  H_BUSY, but with the added bonus of a
+					  hint to the partition OS. If the
+					  partition OS can delay for 1
+					  millisecond, the hcall will likely
+					  succeed on a new hcall with no further
+					  busy return codes. If the partition OS
+					  cannot handle a delay, they are
+					  certainly free to immediately turn
+					  around and try again. */
+#define H_LONG_BUSY_ORDER_10_MS  9901  /* Similar to H_LONG_BUSY_ORDER_1_MS, but
+					  the hint is 10mSec wait this time. */
+
+#define H_LONG_BUSY_ORDER_100_MS 9902  /* Similar to H_LONG_BUSY_ORDER_1_MS, but
+					  the hint is 100mSec wait this time. */ 
+
+#define H_LONG_BUSY_ORDER_1_S    9903  /* Similar to H_LONG_BUSY_ORDER_1_MS, but
+					  the hint is 1Sec wait this time. */
+#define H_LONG_BUSY_ORDER_10_S   9904  /* Similar to H_LONG_BUSY_ORDER_1_MS, but
+					  the hint is 10Sec wait this time. */
+#define H_LONG_BUSY_ORDER_100_S  9905  /* Similar to H_LONG_BUSY_ORDER_1_MS, but
+					  the hint is 100Sec wait this time. */
+
+#define H_HARDWARE   -1  /* Error. */
+#define H_FUNCTION   -2  /* Not supported. */
+#define H_PRIVILEGE  -3  /* Caller not in privileged mode. */
+#define H_PARAMETER  -4  /* Outside valid range for partition or conflicting. */
+#define H_BAD_MODE   -5  /* Illegal MSR value. */
+#define H_PTEG_FULL  -6  /* The requested pteg was full. */
+#define H_NOT_FOUND  -7  /* The requested entitiy was not found. */
+#define H_RESERVED_DABR -8  /* The requested address is reserved by the
+			       hypervisor on this processor. */
+#define H_NOMEM      -9
+#define H_AUTHORITY -10  /* The caller did not have authority to perform the
+			    function. */
+#define H_PERMISSION -11  /* The mapping specified by the request does not
+			     allow for the requested transfer. */
+#define H_DROPPED   -12  /* One or more packets could not be delivered to
+			    their requested destinations. */
+#define H_S_PARM   -13  /* The source parameter is illegal. */
+#define H_D_PARM   -14  /* The destination parameter is illegal. */
+#define H_R_PARM   -15  /* The remote TCE mapping is illegal. */
+#define H_RESOURCE  -16  /* One or more required resources are in use. */
+#define H_ADAPTER_PARM -17  /* Invalid adapter. */
+#define H_RH_PARM  -18  /* Resource not valid or logical partition
+			   conflicting. */
+#define H_RCQ_PARM -19  /* RCQ not valid or logical partition conflicting. */
+#define H_SCQ_PARM -20  /* SCQ not valid or logical partition conflicting. */
+#define H_EQ_PARM -21  /* EQ not valid or logical partition conflicting. */
+#define H_RT_PARM -22  /* Invalid resource type. */
+#define H_ST_PARM -23  /* Invalid service type. */
+#define H_SIGT_PARM -24 /* Invalid signalling type. */
+#define H_TOKEN_PARM -25  /* Invalid token. */
+#define H_MLENGTH_PARM -27  /* Invalid memory length. */
+#define H_MEM_PARM -28  /* Invalid memory I/O virtual address. */
+#define H_MEM_ACCESS_PARM -29  /* Invalid memory access control. */
+#define H_ATTR_PARM -30  /* Invalid attribute value. */
+#define H_PORT_PARM -31  /* Invalid port number. */
+#define H_MCG_PARM -32  /* Invalid multicast group. */
+#define H_VL_PARM -33  /* Invalid virtual lane. */
+#define H_TSIZE_PARM -34  /* Invalid trace size. */
+#define H_TRACE_PARM -35  /* Invalid trace buffer. */
+#define H_MASK_PARM -37  /* Invalid mask value. */
+#define H_MCG_FULL -38  /* Multicast attachments exceeded. */
+#define H_ALIAS_EXIST -39  /* Alias QP already defined. */
+#define H_P_COUNTER -40  /* Invalid counter specification. */
+#define H_TABLE_FULL -41  /* Resource page table full. */
+#define H_ALT_TABLE -42  /* Alternate table already exists / alternate page
+			    table not available. */
+#define H_MR_CONDITION -43  /* Invalid memory region condition. */
+#define H_NOT_ENOUGH_RESOURCES -44  /* Insufficient resources. */
+#define H_R_STATE -45  /* Invalid resource state condition or sequencing
+			  error. */
+#define H_RESCINDED -46
+#define H_ABORTED -54
+#define H_P2 -55
+#define H_P3 -56
+#define H_P4 -57
+#define H_P5 -58
+#define H_P6 -59
+#define H_P7 -60
+#define H_P8 -61
+#define H_P9 -62
+#define H_NOOP -63
+#define H_TOO_BIG -64
+
+#define H_UNSUPPORTED -67  /* Parameter value outside of the range supported
+			      by this implementation. */
+
+/* Flags. */
+/* Table 168. Page Frame Table Access flags field definition. */
+#define H_EXACT                 (1UL<<(63-24))
+#define H_R_XLATE               (1UL<<(63-25))
+#define H_READ_4                (1UL<<(63-26))
+
+/* Table 178. CMO Page Usage State flags Definition. */
+#define H_PAGE_STATE_CHANGE     (1UL<<(63-28))
+#define H_PAGE_UNUSED           ((1UL<<(63-29)) | (1UL<<(63-30)))
+#define H_PAGE_SET_UNUSED       (H_PAGE_STATE_CHANGE | H_PAGE_UNUSED)
+#define H_PAGE_SET_LOANED       (H_PAGE_SET_UNUSED | (1UL<<(63-31)))
+#define H_PAGE_SET_ACTIVE       H_PAGE_STATE_CHANGE
+
+/* Table 168. Page Frame Table Access flags field definition. */
+#define H_AVPN                  (1UL<<(63-32))
+#define H_ANDCOND               (1UL<<(63-33))
+
+#define H_ICACHE_INVALIDATE     (1UL<<(63-40))
+#define H_ICACHE_SYNCHRONIZE    (1UL<<(63-41))
+
+#define H_ZERO_PAGE             (1UL<<(63-48))
+#define H_COPY_PAGE             (1UL<<(63-49))
+
+#define H_N (1UL<<(63-61))
+#define H_PP1 (1UL<<(63-62))
+#define H_PP2 (1UL<<(63-63))
+
+/* pSeries hypervisor opcodes. */
+#define H_REMOVE		0x04
+#define H_ENTER			0x08
+#define H_READ			0x0c
+#define H_CLEAR_MOD		0x10
+#define H_CLEAR_REF		0x14
+#define H_PROTECT		0x18
+#define H_GET_TCE		0x1c
+#define H_PUT_TCE		0x20
+#define H_SET_SPRG0		0x24
+#define H_SET_DABR		0x28
+#define H_PAGE_INIT		0x2c
+#define H_SET_ASR		0x30
+#define H_ASR_ON		0x34
+#define H_ASR_OFF		0x38
+#define H_LOGICAL_CI_LOAD	0x3c
+#define H_LOGICAL_CI_STORE	0x40
+#define H_LOGICAL_CACHE_LOAD	0x44
+#define H_LOGICAL_CACHE_STORE	0x48
+#define H_LOGICAL_ICBI		0x4c
+#define H_LOGICAL_DCBF		0x50
+#define H_GET_TERM_CHAR		0x54
+#define H_PUT_TERM_CHAR		0x58
+#define H_REAL_TO_LOGICAL	0x5c
+#define H_HYPERVISOR_DATA	0x60
+#define H_EOI			0x64
+#define H_CPPR			0x68
+#define H_IPI			0x6c
+#define H_IPOLL			0x70
+#define H_XIRR			0x74
+#define H_MIGRATE_DMA		0x78
+#define H_PERFMON		0x7c
+#define H_REGISTER_VPA		0xdc
+#define H_CEDE			0xe0
+#define H_CONFER		0xe4
+#define H_PROD			0xe8
+#define H_GET_PPP		0xec
+#define H_SET_PPP		0xf0
+#define H_PURR			0xf4
+#define H_PIC			0xf8
+#define H_REG_CRQ		0xfc
+#define H_FREE_CRQ		0x100
+#define H_VIO_SIGNAL		0x104
+#define H_SEND_CRQ		0x108
+#define H_PUT_RTCE              0x10c
+#define H_COPY_RDMA		0x110
+#define H_REGISTER_LOGICAL_LAN	0x114
+#define H_FREE_LOGICAL_LAN	0x118
+#define H_ADD_LOGICAL_LAN_BUFFER 0x11c
+#define H_SEND_LOGICAL_LAN	0x120
+#define H_BULK_REMOVE		0x124
+#define H_WRITE_RDMA            0x128
+#define H_READ_RDMA             0x12c
+#define H_MULTICAST_CTRL	0x130
+#define H_SET_XDABR		0x134
+#define H_STUFF_TCE		0x138
+#define H_PUT_TCE_INDIRECT	0x13c
+#define H_PUT_RTCE_INDIRECT	0x140
+#define H_CHANGE_LOGICAL_LAN_MAC 0x14c
+#define H_VTERM_PARTNER_INFO	0x150
+#define H_REGISTER_VTERM	0x154
+#define H_FREE_VTERM		0x158
+/* Reserved ....
+#define H_RESET_EVENTS          0x15c
+#define H_ALLOC_RESOURCE        0x160
+#define H_FREE_RESOURCE         0x164
+#define H_MODIFY_QP             0x168
+#define H_QUERY_QP              0x16c
+#define H_REREGISTER_PMR        0x170
+#define H_REGISTER_SMR          0x174
+#define H_QUERY_MR              0x178
+#define H_QUERY_MW              0x17c
+#define H_QUERY_HCA             0x180
+#define H_QUERY_PORT            0x184
+#define H_MODIFY_PORT           0x188
+#define H_DEFINE_AQP1           0x18c
+#define H_GET_TRACE_BUFFER      0x190
+#define H_DEFINE_AQP0           0x194
+#define H_RESIZE_MR             0x198
+#define H_ATTACH_MCQP           0x19c
+#define H_DETACH_MCQP           0x1a0
+#define H_CREATE_RPT            0x1a4
+#define H_REMOVE_RPT            0x1a8
+#define H_REGISTER_RPAGES       0x1ac
+#define H_DISABLE_AND_GETC      0x1b0
+#define H_ERROR_DATA            0x1b4
+#define H_GET_HCA_INFO          0x1b8
+#define H_GET_PERF_COUNT        0x1bc
+#define H_MANAGE_TRACE          0x1c0
+.... */
+#define H_FREE_LOGICAL_LAN_BUFFER 0x1d4
+#define H_POLL_PENDING		0x1d8
+/* Reserved ....
+#define H_QUERY_INT_STATE       0x1e4
+.... */
+#define H_LIOBN_ATTRIBUTES	0x240
+#define H_ILLAN_ATTRIBUTES	0x244
+#define H_REMOVE_RTCE	        0x24c
+/* Reserved ...
+#define H_MODIFY_HEA_QP		0x250
+#define H_QUERY_HEA_QP		0x254
+#define H_QUERY_HEA		0x258
+#define H_QUERY_HEA_PORT	0x25c
+#define H_MODIFY_HEA_PORT	0x260
+#define H_REG_BCMC		0x264
+#define H_DEREG_BCMC		0x268
+#define H_REGISTER_HEA_RPAGES	0x26c
+#define H_DISABLE_AND_GET_HEA	0x270
+#define H_GET_HEA_INFO		0x274
+#define H_ALLOC_HEA_RESOURCE	0x278
+#define H_ADD_CONN		0x284
+#define H_DEL_CONN		0x288
+... */
+#define H_JOIN			0x298
+#define H_DONOR_OPERATION	0x29c
+#define H_VASI_SIGNAL	       	0x2a0
+#define H_VASI_STATE            0x2a4
+#define H_VIOCTL	       	0x2a8
+#define H_VRMASD	       	0x2ac
+#define H_ENABLE_CRQ		0x2b0
+/* Reserved ...
+#define H_GET_EM_PARMS		0x2b8
+... */
+#define H_VPM_STAT	       	0x2bc
+#define H_SET_MPP		0x2d0
+#define H_GET_MPP		0x2d4
+#define MAX_HCALL_OPCODE	H_GET_MPP
+
+int64_t phyp_hcall(uint64_t opcode, ...);
+int64_t phyp_pft_hcall(uint64_t opcode, uint64_t flags, uint64_t pteidx,
+    uint64_t pte_hi, uint64_t pte_lo, uint64_t *pteidx_out, uint64_t *ptelo_out,
+    uint64_t *r6);
+
+#endif /* _PSERIES_PHYP_HVCALL_H_ */
+


Property changes on: trunk/sys/powerpc/pseries/phyp-hvcall.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/phyp_console.c
===================================================================
--- trunk/sys/powerpc/pseries/phyp_console.c	                        (rev 0)
+++ trunk/sys/powerpc/pseries/phyp_console.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,434 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2011 by Nathan Whitehorn. 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.
+ *
+ * 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 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/pseries/phyp_console.c 314667 2017-03-04 13:03:31Z avg $");
+
+#include <sys/param.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/priv.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/tty.h>
+#include <machine/bus.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_bus.h>
+
+#include "phyp-hvcall.h"
+#include "uart_if.h"
+
+struct uart_phyp_softc {
+	device_t dev;
+	phandle_t node;
+	int vtermid;
+
+	struct tty *tp;
+	struct resource *irqres;
+	int irqrid;
+	struct callout callout;
+	void *sc_icookie;
+	int polltime;
+
+	struct mtx sc_mtx;
+	int protocol;
+
+	union {
+		uint64_t u64[2];
+		char str[16];
+	} phyp_inbuf;
+	uint64_t inbuflen;
+	uint8_t outseqno;
+};
+
+static struct uart_phyp_softc	*console_sc = NULL;
+#if defined(KDB)
+static int			alt_break_state;
+#endif
+
+enum {
+	HVTERM1, HVTERMPROT
+};
+
+#define VS_DATA_PACKET_HEADER		0xff
+#define VS_CONTROL_PACKET_HEADER	0xfe
+#define  VSV_SET_MODEM_CTL		0x01
+#define  VSV_MODEM_CTL_UPDATE		0x02
+#define  VSV_RENEGOTIATE_CONNECTION	0x03
+#define VS_QUERY_PACKET_HEADER		0xfd
+#define  VSV_SEND_VERSION_NUMBER	0x01
+#define  VSV_SEND_MODEM_CTL_STATUS	0x02
+#define VS_QUERY_RESPONSE_PACKET_HEADER	0xfc
+
+static int uart_phyp_probe(device_t dev);
+static int uart_phyp_attach(device_t dev);
+static void uart_phyp_intr(void *v);
+
+static device_method_t uart_phyp_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		uart_phyp_probe),
+	DEVMETHOD(device_attach,	uart_phyp_attach),
+
+	DEVMETHOD_END
+};
+
+static driver_t uart_phyp_driver = {
+	"uart",
+	uart_phyp_methods,
+	sizeof(struct uart_phyp_softc),
+};
+ 
+DRIVER_MODULE(uart_phyp, vdevice, uart_phyp_driver, uart_devclass, 0, 0);
+
+static cn_probe_t uart_phyp_cnprobe;
+static cn_init_t uart_phyp_cninit;
+static cn_term_t uart_phyp_cnterm;
+static cn_getc_t uart_phyp_cngetc;
+static cn_putc_t uart_phyp_cnputc;
+static cn_grab_t uart_phyp_cngrab;
+static cn_ungrab_t uart_phyp_cnungrab;
+
+CONSOLE_DRIVER(uart_phyp);
+
+static void uart_phyp_ttyoutwakeup(struct tty *tp);
+
+static struct ttydevsw uart_phyp_tty_class = {
+	.tsw_flags	= TF_INITLOCK|TF_CALLOUT,
+	.tsw_outwakeup	= uart_phyp_ttyoutwakeup,
+};
+
+static int
+uart_phyp_probe_node(struct uart_phyp_softc *sc)
+{
+	phandle_t node = sc->node;
+	uint32_t reg;
+	char buf[64];
+
+	sc->inbuflen = 0;
+	sc->outseqno = 0;
+
+	if (OF_getprop(node, "name", buf, sizeof(buf)) <= 0)
+		return (ENXIO);
+	if (strcmp(buf, "vty") != 0)
+		return (ENXIO);
+
+	if (OF_getprop(node, "device_type", buf, sizeof(buf)) <= 0)
+		return (ENXIO);
+	if (strcmp(buf, "serial") != 0)
+		return (ENXIO);
+
+	reg = -1;
+	OF_getprop(node, "reg", &reg, sizeof(reg));
+	if (reg == -1)
+		return (ENXIO);
+	sc->vtermid = reg;
+	sc->node = node;
+
+	if (OF_getprop(node, "compatible", buf, sizeof(buf)) <= 0)
+		return (ENXIO);
+	if (strcmp(buf, "hvterm1") == 0) {
+		sc->protocol = HVTERM1;
+		return (0);
+	} else if (strcmp(buf, "hvterm-protocol") == 0) {
+		sc->protocol = HVTERMPROT;
+		return (0);
+	}
+
+	return (ENXIO);
+}
+
+static int
+uart_phyp_probe(device_t dev)
+{
+	const char *name;
+	struct uart_phyp_softc sc;
+	int err;
+
+	name = ofw_bus_get_name(dev);
+	if (name == NULL || strcmp(name, "vty") != 0)
+		return (ENXIO);
+
+	sc.node = ofw_bus_get_node(dev);
+	err = uart_phyp_probe_node(&sc);
+	if (err != 0)
+		return (err);
+
+	device_set_desc(dev, "POWER Hypervisor Virtual Serial Port");
+
+	return (err);
+}
+
+static void
+uart_phyp_cnprobe(struct consdev *cp)
+{
+	char buf[64];
+	ihandle_t stdout;
+	phandle_t input, chosen;
+	static struct uart_phyp_softc sc;
+
+	if ((chosen = OF_finddevice("/chosen")) == -1)
+		goto fail;
+
+	/* Check if OF has an active stdin/stdout */
+	input = -1;
+	if (OF_getprop(chosen, "stdout", &stdout,
+	    sizeof(stdout)) == sizeof(stdout) && stdout != 0)
+		input = OF_instance_to_package(stdout);
+	if (input == -1)
+		goto fail;
+
+	if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1)
+		goto fail;
+	if (strcmp(buf, "serial") != 0)
+		goto fail;
+
+	sc.node = input;
+	if (uart_phyp_probe_node(&sc) != 0)
+		goto fail;
+	mtx_init(&sc.sc_mtx, "uart_phyp", NULL, MTX_SPIN | MTX_QUIET |
+	    MTX_NOWITNESS);
+
+	cp->cn_pri = CN_NORMAL;
+	console_sc = ≻
+	return;
+	
+fail:
+	cp->cn_pri = CN_DEAD;
+	return;
+}
+
+static int
+uart_phyp_attach(device_t dev)
+{
+	struct uart_phyp_softc *sc;
+	int unit;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+	sc->node = ofw_bus_get_node(dev);
+	uart_phyp_probe_node(sc);
+
+	unit = device_get_unit(dev);
+	sc->tp = tty_alloc(&uart_phyp_tty_class, sc);
+	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL,
+	    MTX_SPIN | MTX_QUIET | MTX_NOWITNESS);
+
+	if (console_sc != NULL && console_sc->vtermid == sc->vtermid) {
+		sc->outseqno = console_sc->outseqno;
+		console_sc = sc;
+		sprintf(uart_phyp_consdev.cn_name, "ttyu%r", unit);
+		tty_init_console(sc->tp, 0);
+	}
+
+	sc->irqrid = 0;
+	sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid,
+	    RF_ACTIVE | RF_SHAREABLE);
+	if (sc->irqres != NULL) {
+		bus_setup_intr(dev, sc->irqres, INTR_TYPE_TTY | INTR_MPSAFE,
+		    NULL, uart_phyp_intr, sc, &sc->sc_icookie);
+	} else {
+		callout_init(&sc->callout, 1);
+		sc->polltime = hz / 20;
+		if (sc->polltime < 1)
+			sc->polltime = 1;
+		callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc);
+	}
+
+	tty_makedev(sc->tp, NULL, "u%r", unit);
+
+	return (0);
+}
+
+static void
+uart_phyp_cninit(struct consdev *cp)
+{
+
+	strcpy(cp->cn_name, "phypcons");
+}
+
+static void
+uart_phyp_cnterm(struct consdev *cp)
+{
+}
+
+static int
+uart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
+{
+	int err;
+	int hdr = 0;
+
+	uart_lock(&sc->sc_mtx);
+	if (sc->inbuflen == 0) {
+		err = phyp_pft_hcall(H_GET_TERM_CHAR, sc->vtermid,
+		    0, 0, 0, &sc->inbuflen, &sc->phyp_inbuf.u64[0],
+		    &sc->phyp_inbuf.u64[1]);
+		if (err != H_SUCCESS) {
+			uart_unlock(&sc->sc_mtx);
+			return (-1);
+		}
+		hdr = 1; 
+	}
+
+	if (sc->inbuflen == 0) {
+		uart_unlock(&sc->sc_mtx);
+		return (0);
+	}
+
+	if (bufsize > sc->inbuflen)
+		bufsize = sc->inbuflen;
+
+	if ((sc->protocol == HVTERMPROT) && (hdr == 1)) {
+		sc->inbuflen = sc->inbuflen - 4;
+		/* The VTERM protocol has a 4 byte header, skip it here. */
+		memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[4],
+		    sc->inbuflen);
+	}
+
+	memcpy(buffer, sc->phyp_inbuf.str, bufsize);
+	sc->inbuflen -= bufsize;
+	if (sc->inbuflen > 0)
+		memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[bufsize],
+		    sc->inbuflen);
+
+	uart_unlock(&sc->sc_mtx);
+	return (bufsize);
+}
+
+static int
+uart_phyp_put(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
+{
+	uint16_t seqno;
+	uint64_t len = 0;
+	int	err;
+
+	union {
+		uint64_t u64[2];
+		char bytes[16];
+	} cbuf;
+
+	uart_lock(&sc->sc_mtx);
+	switch (sc->protocol) {
+	case HVTERM1:
+		if (bufsize > 16)
+			bufsize = 16;
+		memcpy(&cbuf, buffer, bufsize);
+		len = bufsize;
+		break;
+	case HVTERMPROT:
+		if (bufsize > 12)
+			bufsize = 12;
+		seqno = sc->outseqno++;
+		cbuf.bytes[0] = VS_DATA_PACKET_HEADER;
+		cbuf.bytes[1] = 4 + bufsize; /* total length, max 16 bytes */
+		cbuf.bytes[2] = (seqno >> 8) & 0xff;
+		cbuf.bytes[3] = seqno & 0xff;
+		memcpy(&cbuf.bytes[4], buffer, bufsize);
+		len = 4 + bufsize;
+		break;
+	}
+
+	do {
+	    err = phyp_hcall(H_PUT_TERM_CHAR, sc->vtermid, len, cbuf.u64[0],
+			    cbuf.u64[1]);
+		DELAY(100);
+	} while (err == H_BUSY);
+
+	uart_unlock(&sc->sc_mtx);
+
+	return (bufsize);
+}
+
+static int
+uart_phyp_cngetc(struct consdev *cp)
+{
+	unsigned char c;
+	int retval;
+
+	retval = uart_phyp_get(console_sc, &c, 1);
+	if (retval != 1)
+		return (-1);
+#if defined(KDB)
+	kdb_alt_break(c, &alt_break_state);
+#endif
+
+	return (c);
+}
+
+static void
+uart_phyp_cnputc(struct consdev *cp, int c)
+{
+	unsigned char ch = c;
+	uart_phyp_put(console_sc, &ch, 1);
+}
+
+static void
+uart_phyp_cngrab(struct consdev *cp)
+{
+}
+
+static void
+uart_phyp_cnungrab(struct consdev *cp)
+{
+}
+
+static void
+uart_phyp_ttyoutwakeup(struct tty *tp)
+{
+	struct uart_phyp_softc *sc;
+	char buffer[8];
+	int len;
+
+	sc = tty_softc(tp);
+	
+	while ((len = ttydisc_getc(tp, buffer, sizeof(buffer))) != 0)
+		uart_phyp_put(sc, buffer, len);
+}
+
+static void
+uart_phyp_intr(void *v)
+{
+	struct uart_phyp_softc *sc = v;
+	struct tty *tp = sc->tp;
+	unsigned char c;
+	int len;
+
+	tty_lock(tp);
+	while ((len = uart_phyp_get(sc, &c, 1)) > 0)
+		ttydisc_rint(tp, c, 0);
+	ttydisc_rint_done(tp);
+	tty_unlock(tp);
+
+	if (sc->irqres == NULL)
+		callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc);
+}
+


Property changes on: trunk/sys/powerpc/pseries/phyp_console.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/phyp_llan.c
===================================================================
--- trunk/sys/powerpc/pseries/phyp_llan.c	                        (rev 0)
+++ trunk/sys/powerpc/pseries/phyp_llan.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,499 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2013 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/pseries/phyp_llan.c 257292 2013-10-28 23:47:52Z nwhitehorn $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/endian.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <powerpc/pseries/phyp-hvcall.h>
+
+#define LLAN_MAX_RX_PACKETS	100
+#define LLAN_MAX_TX_PACKETS	100
+#define LLAN_RX_BUF_LEN		8*PAGE_SIZE
+
+#define LLAN_BUFDESC_VALID	(1ULL << 63)
+#define LLAN_ADD_MULTICAST	0x1
+#define LLAN_DEL_MULTICAST	0x2
+#define LLAN_CLEAR_MULTICAST	0x3
+
+struct llan_xfer {
+	struct mbuf *rx_mbuf;
+	bus_dmamap_t rx_dmamap;
+	uint64_t rx_bufdesc;
+};
+
+struct llan_receive_queue_entry { /* PAPR page 539 */
+	uint8_t control;
+	uint8_t reserved;
+	uint16_t offset;
+	uint32_t length;
+	uint64_t handle;
+} __packed;
+
+struct llan_softc {
+	device_t	dev;
+	struct mtx	io_lock;
+
+	cell_t		unit;
+	uint8_t		mac_address[8];
+
+	int		irqid;
+	struct resource	*irq;
+	void		*irq_cookie;
+
+	bus_dma_tag_t	rx_dma_tag;
+	bus_dma_tag_t	rxbuf_dma_tag;
+	bus_dma_tag_t	tx_dma_tag;
+
+	bus_dmamap_t	tx_dma_map;
+
+	struct llan_receive_queue_entry *rx_buf;
+	int		rx_dma_slot;
+	int		rx_valid_val;
+	bus_dmamap_t	rx_buf_map;
+	bus_addr_t	rx_buf_phys;
+	bus_size_t	rx_buf_len;
+	bus_addr_t	input_buf_phys;
+	bus_addr_t	filter_buf_phys;
+	struct llan_xfer rx_xfer[LLAN_MAX_RX_PACKETS];
+
+	struct ifnet	*ifp;
+};
+
+static int	llan_probe(device_t);
+static int	llan_attach(device_t);
+static void	llan_intr(void *xsc);
+static void	llan_init(void *xsc);
+static void	llan_start(struct ifnet *ifp);
+static int	llan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
+static void	llan_rx_load_cb(void *xsc, bus_dma_segment_t *segs, int nsegs,
+		    int err);
+static int	llan_add_rxbuf(struct llan_softc *sc, struct llan_xfer *rx);
+static int	llan_set_multicast(struct llan_softc *sc);
+
+static devclass_t       llan_devclass;
+static device_method_t  llan_methods[] = {
+        DEVMETHOD(device_probe,         llan_probe),
+        DEVMETHOD(device_attach,        llan_attach),
+        
+        DEVMETHOD_END
+};
+static driver_t llan_driver = {
+        "llan",
+        llan_methods,
+        sizeof(struct llan_softc)
+};
+DRIVER_MODULE(llan, vdevice, llan_driver, llan_devclass, 0, 0);
+
+static int
+llan_probe(device_t dev)
+{
+	if (!ofw_bus_is_compatible(dev,"IBM,l-lan"))
+		return (ENXIO);
+
+	device_set_desc(dev, "POWER Hypervisor Virtual Ethernet");
+	return (0);
+}
+
+static int
+llan_attach(device_t dev)
+{
+	struct llan_softc *sc;
+	phandle_t node;
+	int error, i;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+
+	/* Get firmware properties */
+	node = ofw_bus_get_node(dev);
+	OF_getprop(node, "local-mac-address", sc->mac_address,
+	    sizeof(sc->mac_address));
+	OF_getprop(node, "reg", &sc->unit, sizeof(sc->unit));
+
+	mtx_init(&sc->io_lock, "llan", NULL, MTX_DEF);
+
+        /* Setup interrupt */
+	sc->irqid = 0;
+	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
+	    RF_ACTIVE);
+
+	if (!sc->irq) {
+		device_printf(dev, "Could not allocate IRQ\n");
+		mtx_destroy(&sc->io_lock);
+		return (ENXIO);
+	}
+
+	bus_setup_intr(dev, sc->irq, INTR_TYPE_MISC | INTR_MPSAFE |
+	    INTR_ENTROPY, NULL, llan_intr, sc, &sc->irq_cookie);
+
+	/* Setup DMA */
+	error = bus_dma_tag_create(bus_get_dma_tag(dev), 16, 0,
+            BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+	    LLAN_RX_BUF_LEN, 1, BUS_SPACE_MAXSIZE_32BIT,
+	    0, NULL, NULL, &sc->rx_dma_tag);
+	error = bus_dma_tag_create(bus_get_dma_tag(dev), 4, 0,
+            BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+	    BUS_SPACE_MAXSIZE, 1, BUS_SPACE_MAXSIZE_32BIT,
+	    0, NULL, NULL, &sc->rxbuf_dma_tag);
+	error = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
+            BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+	    BUS_SPACE_MAXSIZE, 6, BUS_SPACE_MAXSIZE_32BIT, 0,
+	    busdma_lock_mutex, &sc->io_lock, &sc->tx_dma_tag);
+
+	error = bus_dmamem_alloc(sc->rx_dma_tag, (void **)&sc->rx_buf,
+	    BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->rx_buf_map);
+	error = bus_dmamap_load(sc->rx_dma_tag, sc->rx_buf_map, sc->rx_buf,
+	    LLAN_RX_BUF_LEN, llan_rx_load_cb, sc, 0);
+
+	/* TX DMA maps */
+	bus_dmamap_create(sc->tx_dma_tag, 0, &sc->tx_dma_map);
+
+	/* RX DMA */
+	for (i = 0; i < LLAN_MAX_RX_PACKETS; i++) {
+		error = bus_dmamap_create(sc->rxbuf_dma_tag, 0,
+		    &sc->rx_xfer[i].rx_dmamap);
+		sc->rx_xfer[i].rx_mbuf = NULL;
+	}
+
+	/* Attach to network stack */
+	sc->ifp = if_alloc(IFT_ETHER);
+	sc->ifp->if_softc = sc;
+
+	if_initname(sc->ifp, device_get_name(dev), device_get_unit(dev));
+	sc->ifp->if_mtu = ETHERMTU; /* XXX max-frame-size from OF? */
+	sc->ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+	sc->ifp->if_hwassist = 0; /* XXX: ibm,illan-options */
+	sc->ifp->if_capabilities = 0;
+	sc->ifp->if_capenable = 0;
+	sc->ifp->if_start = llan_start;
+	sc->ifp->if_ioctl = llan_ioctl;
+	sc->ifp->if_init = llan_init;
+
+	IFQ_SET_MAXLEN(&sc->ifp->if_snd, LLAN_MAX_TX_PACKETS);
+	sc->ifp->if_snd.ifq_drv_maxlen = LLAN_MAX_TX_PACKETS;
+	IFQ_SET_READY(&sc->ifp->if_snd);
+
+	ether_ifattach(sc->ifp, &sc->mac_address[2]);
+
+	return (0);
+}
+
+static void
+llan_rx_load_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int err)
+{
+	struct llan_softc *sc = xsc;
+
+	sc->rx_buf_phys = segs[0].ds_addr;
+	sc->rx_buf_len = segs[0].ds_len - 2*PAGE_SIZE;
+	sc->input_buf_phys = segs[0].ds_addr + segs[0].ds_len - PAGE_SIZE;
+	sc->filter_buf_phys = segs[0].ds_addr + segs[0].ds_len - 2*PAGE_SIZE;
+}
+
+static void
+llan_init(void *xsc)
+{
+	struct llan_softc *sc = xsc;
+	uint64_t rx_buf_desc;
+	uint64_t macaddr;
+	int err, i;
+
+	mtx_lock(&sc->io_lock);
+
+	phyp_hcall(H_FREE_LOGICAL_LAN, sc->unit);
+
+	/* Create buffers (page 539) */
+	sc->rx_dma_slot = 0;
+	sc->rx_valid_val = 1;
+
+	rx_buf_desc = LLAN_BUFDESC_VALID;
+	rx_buf_desc |= (sc->rx_buf_len << 32);
+	rx_buf_desc |= sc->rx_buf_phys;
+	memcpy(&macaddr, sc->mac_address, 8);
+	err = phyp_hcall(H_REGISTER_LOGICAL_LAN, sc->unit, sc->input_buf_phys,
+	    rx_buf_desc, sc->filter_buf_phys, macaddr);
+
+	for (i = 0; i < LLAN_MAX_RX_PACKETS; i++)
+		llan_add_rxbuf(sc, &sc->rx_xfer[i]);
+
+	phyp_hcall(H_VIO_SIGNAL, sc->unit, 1); /* Enable interrupts */
+
+	/* Tell stack we're up */
+	sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
+	sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+	mtx_unlock(&sc->io_lock);
+}
+
+static int
+llan_add_rxbuf(struct llan_softc *sc, struct llan_xfer *rx)
+{
+	struct mbuf *m;
+	bus_dma_segment_t segs[1];
+	int error, nsegs;
+
+	mtx_assert(&sc->io_lock, MA_OWNED);
+
+	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+	if (m == NULL)
+		return (ENOBUFS);
+
+	m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
+	if (rx->rx_mbuf != NULL) {
+		bus_dmamap_sync(sc->rxbuf_dma_tag, rx->rx_dmamap,
+		    BUS_DMASYNC_POSTREAD);
+		bus_dmamap_unload(sc->rxbuf_dma_tag, rx->rx_dmamap);
+	}
+
+	/* Save pointer to buffer structure */
+	m_copyback(m, 0, 8, (void *)&rx);
+
+	error = bus_dmamap_load_mbuf_sg(sc->rxbuf_dma_tag, rx->rx_dmamap, m,
+	    segs, &nsegs, BUS_DMA_NOWAIT);
+	if (error != 0) {
+		device_printf(sc->dev,
+		    "cannot load RX DMA map %p, error = %d\n", rx, error);
+		m_freem(m);
+		return (error);
+	}
+
+	/* If nsegs is wrong then the stack is corrupt. */
+	KASSERT(nsegs == 1,
+	    ("%s: too many DMA segments (%d)", __func__, nsegs));
+	rx->rx_mbuf = m;
+
+	bus_dmamap_sync(sc->rxbuf_dma_tag, rx->rx_dmamap, BUS_DMASYNC_PREREAD);
+
+	rx->rx_bufdesc = LLAN_BUFDESC_VALID;
+	rx->rx_bufdesc |= (((uint64_t)segs[0].ds_len) << 32);
+	rx->rx_bufdesc |= segs[0].ds_addr;
+	error = phyp_hcall(H_ADD_LOGICAL_LAN_BUFFER, sc->unit, rx->rx_bufdesc);
+	if (error != 0) {
+		m_freem(m);
+		rx->rx_mbuf = NULL;
+		return (ENOBUFS);
+	}
+
+        return (0);
+}
+
+static void
+llan_intr(void *xsc)
+{
+	struct llan_softc *sc = xsc;
+	struct llan_xfer *rx;
+	struct mbuf *m;
+
+	mtx_lock(&sc->io_lock);
+	phyp_hcall(H_VIO_SIGNAL, sc->unit, 0);
+
+	while ((sc->rx_buf[sc->rx_dma_slot].control >> 7) == sc->rx_valid_val) {
+		rx = (struct llan_xfer *)sc->rx_buf[sc->rx_dma_slot].handle;
+		m = rx->rx_mbuf;
+		m_adj(m, sc->rx_buf[sc->rx_dma_slot].offset - 8);
+		m->m_len = sc->rx_buf[sc->rx_dma_slot].length;
+
+		/* llan_add_rxbuf does DMA sync and unload as well as requeue */
+		if (llan_add_rxbuf(sc, rx) != 0) {
+			sc->ifp->if_ierrors++;
+			phyp_hcall(H_ADD_LOGICAL_LAN_BUFFER, sc->unit,
+			    rx->rx_bufdesc);
+			continue;
+		}
+
+		sc->ifp->if_ipackets++;
+		m_adj(m, sc->rx_buf[sc->rx_dma_slot].offset);
+		m->m_len = sc->rx_buf[sc->rx_dma_slot].length;
+		m->m_pkthdr.rcvif = sc->ifp;
+		m->m_pkthdr.len = m->m_len;
+		sc->rx_dma_slot++;
+
+		if (sc->rx_dma_slot >= sc->rx_buf_len/sizeof(sc->rx_buf[0])) {
+			sc->rx_dma_slot = 0;
+			sc->rx_valid_val = !sc->rx_valid_val;
+		}
+
+		mtx_unlock(&sc->io_lock);
+		(*sc->ifp->if_input)(sc->ifp, m);
+		mtx_lock(&sc->io_lock);
+	}
+
+	phyp_hcall(H_VIO_SIGNAL, sc->unit, 1);
+	mtx_unlock(&sc->io_lock);
+}
+
+static void
+llan_send_packet(void *xsc, bus_dma_segment_t *segs, int nsegs,
+    bus_size_t mapsize, int error)
+{
+	struct llan_softc *sc = xsc;
+	uint64_t bufdescs[6];
+	int i;
+
+	bzero(bufdescs, sizeof(bufdescs));
+
+	for (i = 0; i < nsegs; i++) {
+		bufdescs[i] = LLAN_BUFDESC_VALID;
+		bufdescs[i] |= (((uint64_t)segs[i].ds_len) << 32);
+		bufdescs[i] |= segs[i].ds_addr;
+	}
+
+	phyp_hcall(H_SEND_LOGICAL_LAN, sc->unit, bufdescs[0],
+	    bufdescs[1], bufdescs[2], bufdescs[3], bufdescs[4], bufdescs[5], 0);
+	/*
+	 * The hypercall returning implies completion -- or that the call will
+	 * not complete. In principle, we should try a few times if we get back
+	 * H_BUSY based on the continuation token in R4. For now, just drop
+	 * the packet in such cases.
+	 */
+}
+
+static void
+llan_start_locked(struct ifnet *ifp)
+{
+	struct llan_softc *sc = ifp->if_softc;
+	bus_addr_t first;
+	int nsegs;
+	struct mbuf *mb_head, *m;
+
+	mtx_assert(&sc->io_lock, MA_OWNED);
+	first = 0;
+
+	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+	    IFF_DRV_RUNNING)
+		return;
+
+	while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+		IFQ_DRV_DEQUEUE(&ifp->if_snd, mb_head);
+
+		if (mb_head == NULL)
+			break;
+
+		BPF_MTAP(ifp, mb_head);
+
+		for (m = mb_head, nsegs = 0; m != NULL; m = m->m_next)
+			nsegs++;
+		if (nsegs > 6) {
+			m = m_collapse(mb_head, M_NOWAIT, 6);
+			if (m == NULL) {
+				m_freem(mb_head);
+				continue;
+			}
+		}
+
+		bus_dmamap_load_mbuf(sc->tx_dma_tag, sc->tx_dma_map,
+			mb_head, llan_send_packet, sc, 0);
+		bus_dmamap_unload(sc->tx_dma_tag, sc->tx_dma_map);
+		m_freem(mb_head);
+	}
+}
+
+static void
+llan_start(struct ifnet *ifp)
+{
+	struct llan_softc *sc = ifp->if_softc;
+
+	mtx_lock(&sc->io_lock);
+	llan_start_locked(ifp);
+	mtx_unlock(&sc->io_lock);
+}
+
+static int
+llan_set_multicast(struct llan_softc *sc)
+{
+	struct ifnet *ifp = sc->ifp;
+	struct ifmultiaddr *inm;
+	uint64_t macaddr;
+
+	mtx_assert(&sc->io_lock, MA_OWNED);
+
+	phyp_hcall(H_MULTICAST_CTRL, sc->unit, LLAN_CLEAR_MULTICAST, 0);
+
+	if_maddr_rlock(ifp);
+	TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) {
+		if (inm->ifma_addr->sa_family != AF_LINK)
+			continue;
+
+		memcpy((uint8_t *)&macaddr + 2,
+		    LLADDR((struct sockaddr_dl *)inm->ifma_addr), 6);
+		phyp_hcall(H_MULTICAST_CTRL, sc->unit, LLAN_ADD_MULTICAST,
+		    macaddr);
+	}
+	if_maddr_runlock(ifp);
+
+	return (0);
+}
+
+static int
+llan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+	int err = 0;
+	struct llan_softc *sc = ifp->if_softc;
+
+	switch (cmd) {
+	case SIOCADDMULTI:
+	case SIOCDELMULTI:
+		mtx_lock(&sc->io_lock);
+		if ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+			llan_set_multicast(sc);
+		mtx_unlock(&sc->io_lock);
+		break;
+	case SIOCSIFFLAGS:
+	default:
+		err = ether_ioctl(ifp, cmd, data);
+		break;
+	}
+
+	return (err);
+}
+


Property changes on: trunk/sys/powerpc/pseries/phyp_llan.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/phyp_vscsi.c
===================================================================
--- trunk/sys/powerpc/pseries/phyp_vscsi.c	                        (rev 0)
+++ trunk/sys/powerpc/pseries/phyp_vscsi.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,992 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2013 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/pseries/phyp_vscsi.c 315813 2017-03-23 06:41:13Z mav $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/selinfo.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/eventhandler.h>
+#include <sys/rman.h>
+#include <sys/bus_dma.h>
+#include <sys/bio.h>
+#include <sys/ioccom.h>
+#include <sys/uio.h>
+#include <sys/proc.h>
+#include <sys/signalvar.h>
+#include <sys/sysctl.h>
+#include <sys/endian.h>
+#include <sys/vmem.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_debug.h>
+#include <cam/cam_periph.h>
+#include <cam/cam_sim.h>
+#include <cam/cam_xpt_periph.h>
+#include <cam/cam_xpt_sim.h>
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_message.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <powerpc/pseries/phyp-hvcall.h>
+
+struct vscsi_softc;
+
+/* VSCSI CRQ format from table 260 of PAPR spec 2.4 (page 760) */
+struct vscsi_crq {
+	uint8_t valid;
+	uint8_t format;
+	uint8_t reserved;
+	uint8_t status;
+	uint16_t timeout;
+	uint16_t iu_length;
+	uint64_t iu_data;
+};
+
+struct vscsi_xfer {
+        TAILQ_ENTRY(vscsi_xfer) queue;
+        struct vscsi_softc *sc;
+        union ccb *ccb;
+        bus_dmamap_t dmamap;
+        uint64_t tag;
+	
+	vmem_addr_t srp_iu_offset;
+	vmem_size_t srp_iu_size;
+};
+
+TAILQ_HEAD(vscsi_xferq, vscsi_xfer);
+
+struct vscsi_softc {
+	device_t	dev;
+	struct cam_devq *devq;
+	struct cam_sim	*sim;
+	struct cam_path	*path;
+	struct mtx io_lock;
+
+	cell_t		unit;
+	int		bus_initialized;
+	int		bus_logged_in;
+	int		max_transactions;
+
+	int		irqid;
+	struct resource	*irq;
+	void		*irq_cookie;
+
+	bus_dma_tag_t	crq_tag;
+	struct vscsi_crq *crq_queue;
+	int		n_crqs, cur_crq;
+	bus_dmamap_t	crq_map;
+	bus_addr_t	crq_phys;
+
+	vmem_t		*srp_iu_arena;
+	void		*srp_iu_queue;
+	bus_addr_t	srp_iu_phys;
+
+	bus_dma_tag_t	data_tag;
+
+	struct vscsi_xfer loginxp;
+	struct vscsi_xfer *xfer;
+	struct vscsi_xferq active_xferq;
+	struct vscsi_xferq free_xferq;
+};
+
+struct srp_login {
+	uint8_t type;
+	uint8_t reserved[7];
+	uint64_t tag;
+	uint64_t max_cmd_length;
+	uint32_t reserved2;
+	uint16_t buffer_formats;
+	uint8_t flags;
+	uint8_t reserved3[5];
+	uint8_t initiator_port_id[16];
+	uint8_t target_port_id[16];
+} __packed;
+
+struct srp_login_rsp {
+	uint8_t type;
+	uint8_t reserved[3];
+	uint32_t request_limit_delta;
+	uint8_t tag;
+	uint32_t max_i_to_t_len;
+	uint32_t max_t_to_i_len;
+	uint16_t buffer_formats;
+	uint8_t flags;
+	/* Some reserved bits follow */
+} __packed;
+
+struct srp_cmd {
+	uint8_t type;
+	uint8_t flags1;
+	uint8_t reserved[3];
+	uint8_t formats;
+	uint8_t out_buffer_count;
+	uint8_t in_buffer_count;
+	uint64_t tag;
+	uint32_t reserved2;
+	uint64_t lun;
+	uint8_t reserved3[3];
+	uint8_t additional_cdb;
+	uint8_t cdb[16];
+	uint8_t data_payload[0];
+} __packed;
+
+struct srp_rsp {
+	uint8_t type;
+	uint8_t reserved[3];
+	uint32_t request_limit_delta;
+	uint64_t tag;
+	uint16_t reserved2;
+	uint8_t flags;
+	uint8_t status;
+	uint32_t data_out_resid;
+	uint32_t data_in_resid;
+	uint32_t sense_data_len;
+	uint32_t response_data_len;
+	uint8_t data_payload[0];
+} __packed;
+
+struct srp_tsk_mgmt {
+	uint8_t type;
+	uint8_t reserved[7];
+	uint64_t tag;
+	uint32_t reserved2;
+	uint64_t lun;
+	uint8_t reserved3[2];
+	uint8_t function;
+	uint8_t reserved4;
+	uint64_t manage_tag;
+	uint64_t reserved5;
+} __packed;
+
+/* Message code type */
+#define SRP_LOGIN_REQ	0x00
+#define SRP_TSK_MGMT	0x01
+#define SRP_CMD		0x02
+#define SRP_I_LOGOUT	0x03
+
+#define SRP_LOGIN_RSP	0xC0
+#define SRP_RSP		0xC1
+#define SRP_LOGIN_REJ	0xC2
+
+#define SRP_T_LOGOUT	0x80
+#define SRP_CRED_REQ	0x81
+#define SRP_AER_REQ	0x82
+
+#define SRP_CRED_RSP	0x41
+#define SRP_AER_RSP	0x41
+
+/* Flags for srp_rsp flags field */
+#define SRP_RSPVALID	0x01
+#define SRP_SNSVALID	0x02
+#define SRP_DOOVER	0x04
+#define SRP_DOUNDER	0x08
+#define SRP_DIOVER	0x10
+#define SRP_DIUNDER	0x20
+
+#define	MAD_SUCESS			0x00
+#define	MAD_NOT_SUPPORTED		0xf1
+#define	MAD_FAILED			0xf7
+
+#define	MAD_EMPTY_IU			0x01
+#define	MAD_ERROR_LOGGING_REQUEST	0x02
+#define	MAD_ADAPTER_INFO_REQUEST	0x03
+#define	MAD_CAPABILITIES_EXCHANGE	0x05
+#define	MAD_PHYS_ADAP_INFO_REQUEST	0x06
+#define	MAD_TAPE_PASSTHROUGH_REQUEST	0x07
+#define	MAD_ENABLE_FAST_FAIL		0x08
+
+static int	vscsi_probe(device_t);
+static int	vscsi_attach(device_t);
+static int	vscsi_detach(device_t);
+static void	vscsi_cam_action(struct cam_sim *, union ccb *);
+static void	vscsi_cam_poll(struct cam_sim *);
+static void	vscsi_intr(void *arg);
+static void	vscsi_check_response_queue(struct vscsi_softc *sc);
+static void	vscsi_setup_bus(struct vscsi_softc *sc);
+
+static void	vscsi_srp_login(struct vscsi_softc *sc);
+static void	vscsi_crq_load_cb(void *, bus_dma_segment_t *, int, int);
+static void	vscsi_scsi_command(void *xxp, bus_dma_segment_t *segs,
+		    int nsegs, int err);
+static void	vscsi_task_management(struct vscsi_softc *sc, union ccb *ccb);
+static void	vscsi_srp_response(struct vscsi_xfer *, struct vscsi_crq *);
+
+static devclass_t	vscsi_devclass;
+static device_method_t	vscsi_methods[] = {
+	DEVMETHOD(device_probe,		vscsi_probe),
+	DEVMETHOD(device_attach,	vscsi_attach),
+	DEVMETHOD(device_detach,	vscsi_detach),
+
+	DEVMETHOD_END
+};
+static driver_t vscsi_driver = {
+	"vscsi",
+	vscsi_methods,
+	sizeof(struct vscsi_softc)
+};
+DRIVER_MODULE(vscsi, vdevice, vscsi_driver, vscsi_devclass, 0, 0);
+MALLOC_DEFINE(M_VSCSI, "vscsi", "CAM device queue for VSCSI");
+
+static int
+vscsi_probe(device_t dev)
+{
+
+	if (!ofw_bus_is_compatible(dev, "IBM,v-scsi"))
+		return (ENXIO);
+
+	device_set_desc(dev, "POWER Hypervisor Virtual SCSI Bus");
+	return (0);
+}
+
+static int
+vscsi_attach(device_t dev)
+{
+	struct vscsi_softc *sc;
+	struct vscsi_xfer *xp;
+	int error, i;
+
+	sc = device_get_softc(dev);
+	if (sc == NULL)
+		return (EINVAL);
+
+	sc->dev = dev;
+	mtx_init(&sc->io_lock, "vscsi", NULL, MTX_DEF);
+
+	/* Get properties */
+	OF_getprop(ofw_bus_get_node(dev), "reg", &sc->unit, sizeof(sc->unit));
+
+	/* Setup interrupt */
+	sc->irqid = 0;
+	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
+	    RF_ACTIVE);
+
+	if (!sc->irq) {
+		device_printf(dev, "Could not allocate IRQ\n");
+		mtx_destroy(&sc->io_lock);
+		return (ENXIO);
+	}
+
+	bus_setup_intr(dev, sc->irq, INTR_TYPE_CAM | INTR_MPSAFE |
+	    INTR_ENTROPY, NULL, vscsi_intr, sc, &sc->irq_cookie);
+
+	/* Data DMA */
+	error = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
+	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, BUS_SPACE_MAXSIZE,
+	    256, BUS_SPACE_MAXSIZE_32BIT, 0, busdma_lock_mutex, &sc->io_lock,
+	    &sc->data_tag);
+
+	TAILQ_INIT(&sc->active_xferq);
+	TAILQ_INIT(&sc->free_xferq);
+
+	/* First XFER for login data */
+	sc->loginxp.sc = sc;
+	bus_dmamap_create(sc->data_tag, 0, &sc->loginxp.dmamap);
+	TAILQ_INSERT_TAIL(&sc->free_xferq, &sc->loginxp, queue);
+	 
+	/* CRQ area */
+	error = bus_dma_tag_create(bus_get_dma_tag(dev), PAGE_SIZE, 0,
+	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 8*PAGE_SIZE,
+	    1, BUS_SPACE_MAXSIZE, 0, NULL, NULL, &sc->crq_tag);
+	error = bus_dmamem_alloc(sc->crq_tag, (void **)&sc->crq_queue,
+	    BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->crq_map);
+	sc->crq_phys = 0;
+	sc->n_crqs = 0;
+	error = bus_dmamap_load(sc->crq_tag, sc->crq_map, sc->crq_queue,
+	    8*PAGE_SIZE, vscsi_crq_load_cb, sc, 0);
+
+	mtx_lock(&sc->io_lock);
+	vscsi_setup_bus(sc);
+	sc->xfer = malloc(sizeof(sc->xfer[0])*sc->max_transactions, M_VSCSI,
+	    M_NOWAIT);
+	for (i = 0; i < sc->max_transactions; i++) {
+		xp = &sc->xfer[i];
+		xp->sc = sc;
+
+		error = bus_dmamap_create(sc->data_tag, 0, &xp->dmamap);
+		if (error) {
+			device_printf(dev, "Could not create DMA map (%d)\n",
+			    error);
+			break;
+		}
+
+		TAILQ_INSERT_TAIL(&sc->free_xferq, xp, queue);
+	}
+	mtx_unlock(&sc->io_lock);
+
+	/* Allocate CAM bits */
+	if ((sc->devq = cam_simq_alloc(sc->max_transactions)) == NULL)
+		return (ENOMEM);
+
+	sc->sim = cam_sim_alloc(vscsi_cam_action, vscsi_cam_poll, "vscsi", sc,
+				device_get_unit(dev), &sc->io_lock,
+				sc->max_transactions, sc->max_transactions,
+				sc->devq);
+	if (sc->sim == NULL) {
+		cam_simq_free(sc->devq);
+		sc->devq = NULL;
+		device_printf(dev, "CAM SIM attach failed\n");
+		return (EINVAL);
+	}
+
+
+	mtx_lock(&sc->io_lock);
+	if (xpt_bus_register(sc->sim, dev, 0) != 0) {
+		device_printf(dev, "XPT bus registration failed\n");
+		cam_sim_free(sc->sim, FALSE);
+		sc->sim = NULL;
+		cam_simq_free(sc->devq);
+		sc->devq = NULL;
+		mtx_unlock(&sc->io_lock);
+		return (EINVAL);
+	}
+	mtx_unlock(&sc->io_lock);
+
+	return (0);
+}
+
+static int
+vscsi_detach(device_t dev)
+{
+	struct vscsi_softc *sc;
+
+	sc = device_get_softc(dev);
+	if (sc == NULL)
+		return (EINVAL);
+
+	if (sc->sim != NULL) {
+		mtx_lock(&sc->io_lock);
+		xpt_bus_deregister(cam_sim_path(sc->sim));
+		cam_sim_free(sc->sim, FALSE);
+		sc->sim = NULL;
+		mtx_unlock(&sc->io_lock);
+	}
+
+	if (sc->devq != NULL) {
+		cam_simq_free(sc->devq);
+		sc->devq = NULL;
+	}
+	
+	mtx_destroy(&sc->io_lock);
+
+	return (0);
+}
+
+static void
+vscsi_cam_action(struct cam_sim *sim, union ccb *ccb)
+{
+	struct vscsi_softc *sc = cam_sim_softc(sim);
+
+	mtx_assert(&sc->io_lock, MA_OWNED);
+
+	switch (ccb->ccb_h.func_code) {
+	case XPT_PATH_INQ:
+	{
+		struct ccb_pathinq *cpi = &ccb->cpi;
+
+		cpi->version_num = 1;
+		cpi->hba_inquiry = PI_TAG_ABLE;
+		cpi->hba_misc = PIM_EXTLUNS;
+		cpi->target_sprt = 0;
+		cpi->hba_eng_cnt = 0;
+		cpi->max_target = 0;
+		cpi->max_lun = ~(lun_id_t)(0);
+		cpi->initiator_id = ~0;
+		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
+		strlcpy(cpi->hba_vid, "IBM", HBA_IDLEN);
+		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+		cpi->unit_number = cam_sim_unit(sim);
+		cpi->bus_id = cam_sim_bus(sim);
+		cpi->base_transfer_speed = 150000;
+		cpi->transport = XPORT_SRP;
+		cpi->transport_version = 0;
+		cpi->protocol = PROTO_SCSI;
+		cpi->protocol_version = SCSI_REV_SPC4;
+		cpi->ccb_h.status = CAM_REQ_CMP;
+		break;
+	}
+	case XPT_RESET_BUS:
+		ccb->ccb_h.status = CAM_REQ_CMP;
+		break;
+	case XPT_RESET_DEV:
+		ccb->ccb_h.status = CAM_REQ_INPROG;
+		vscsi_task_management(sc, ccb);
+		return;
+	case XPT_GET_TRAN_SETTINGS:
+		ccb->cts.protocol = PROTO_SCSI;
+		ccb->cts.protocol_version = SCSI_REV_SPC4;
+		ccb->cts.transport = XPORT_SRP;
+		ccb->cts.transport_version = 0;
+		ccb->cts.proto_specific.valid = 0;
+		ccb->cts.xport_specific.valid = 0;
+		ccb->ccb_h.status = CAM_REQ_CMP;
+		break;
+	case XPT_SET_TRAN_SETTINGS:
+		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
+		break;
+	case XPT_SCSI_IO:
+	{
+		struct vscsi_xfer *xp;
+
+		ccb->ccb_h.status = CAM_REQ_INPROG;
+
+		xp = TAILQ_FIRST(&sc->free_xferq);
+		if (xp == NULL)
+			panic("SCSI queue flooded");
+		xp->ccb = ccb;
+		TAILQ_REMOVE(&sc->free_xferq, xp, queue);
+		TAILQ_INSERT_TAIL(&sc->active_xferq, xp, queue);
+		bus_dmamap_load_ccb(sc->data_tag, xp->dmamap,
+		    ccb, vscsi_scsi_command, xp, 0);
+
+		return;
+	}
+	default:
+		ccb->ccb_h.status = CAM_REQ_INVALID;
+		break;
+	}
+
+	xpt_done(ccb);
+	return;
+}
+
+static void
+vscsi_srp_login(struct vscsi_softc *sc)
+{
+	struct vscsi_xfer *xp;
+	struct srp_login *login;
+	struct vscsi_crq crq;
+	int err;
+
+	mtx_assert(&sc->io_lock, MA_OWNED);
+
+	xp = TAILQ_FIRST(&sc->free_xferq);
+	if (xp == NULL)
+		panic("SCSI queue flooded");
+	xp->ccb = NULL;
+	TAILQ_REMOVE(&sc->free_xferq, xp, queue);
+	TAILQ_INSERT_TAIL(&sc->active_xferq, xp, queue);
+	
+	/* Set up command */
+	xp->srp_iu_size = crq.iu_length = 64;
+	err = vmem_alloc(xp->sc->srp_iu_arena, xp->srp_iu_size,
+	    M_BESTFIT | M_NOWAIT, &xp->srp_iu_offset);
+	if (err)
+		panic("Error during VMEM allocation (%d)", err);
+
+	login = (struct srp_login *)((uint8_t *)xp->sc->srp_iu_queue +
+	    (uintptr_t)xp->srp_iu_offset);
+	bzero(login, xp->srp_iu_size);
+	login->type = SRP_LOGIN_REQ;
+	login->tag = (uint64_t)(xp);
+	login->max_cmd_length = htobe64(256);
+	login->buffer_formats = htobe16(0x1 | 0x2); /* Direct and indirect */
+	login->flags = 0;
+
+	/* Create CRQ entry */
+	crq.valid = 0x80;
+	crq.format = 0x01;
+	crq.iu_data = xp->sc->srp_iu_phys + xp->srp_iu_offset;
+	bus_dmamap_sync(sc->crq_tag, sc->crq_map, BUS_DMASYNC_PREWRITE);
+
+	err = phyp_hcall(H_SEND_CRQ, xp->sc->unit, ((uint64_t *)(&crq))[0],
+	    ((uint64_t *)(&crq))[1]);
+	if (err != 0)
+		panic("CRQ send failure (%d)", err);
+}
+
+static void
+vscsi_task_management(struct vscsi_softc *sc, union ccb *ccb)
+{
+	struct srp_tsk_mgmt *cmd;
+	struct vscsi_xfer *xp;
+	struct vscsi_crq crq;
+	int err;
+
+	mtx_assert(&sc->io_lock, MA_OWNED);
+
+	xp = TAILQ_FIRST(&sc->free_xferq);
+	if (xp == NULL)
+		panic("SCSI queue flooded");
+	xp->ccb = ccb;
+	TAILQ_REMOVE(&sc->free_xferq, xp, queue);
+	TAILQ_INSERT_TAIL(&sc->active_xferq, xp, queue);
+
+	xp->srp_iu_size = crq.iu_length = sizeof(*cmd);
+	err = vmem_alloc(xp->sc->srp_iu_arena, xp->srp_iu_size,
+	    M_BESTFIT | M_NOWAIT, &xp->srp_iu_offset);
+	if (err)
+		panic("Error during VMEM allocation (%d)", err);
+
+	cmd = (struct srp_tsk_mgmt *)((uint8_t *)xp->sc->srp_iu_queue +
+	    (uintptr_t)xp->srp_iu_offset);
+	bzero(cmd, xp->srp_iu_size);
+	cmd->type = SRP_TSK_MGMT;
+	cmd->tag = (uint64_t)xp;
+	cmd->lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
+
+	switch (ccb->ccb_h.func_code) {
+	case XPT_RESET_DEV:
+		cmd->function = 0x08;
+		break;
+	default:
+		panic("Unimplemented code %d", ccb->ccb_h.func_code);
+		break;
+	}
+
+	bus_dmamap_sync(xp->sc->crq_tag, xp->sc->crq_map, BUS_DMASYNC_PREWRITE);
+
+	/* Create CRQ entry */
+	crq.valid = 0x80;
+	crq.format = 0x01;
+	crq.iu_data = xp->sc->srp_iu_phys + xp->srp_iu_offset;
+
+	err = phyp_hcall(H_SEND_CRQ, xp->sc->unit, ((uint64_t *)(&crq))[0],
+	    ((uint64_t *)(&crq))[1]);
+	if (err != 0)
+		panic("CRQ send failure (%d)", err);
+}
+
+static void
+vscsi_scsi_command(void *xxp, bus_dma_segment_t *segs, int nsegs, int err)
+{
+	struct vscsi_xfer *xp = xxp;
+	uint8_t *cdb;
+	union ccb *ccb = xp->ccb;
+	struct srp_cmd *cmd;
+	uint64_t chunk_addr;
+	uint32_t chunk_size;
+	int desc_start, i;
+	struct vscsi_crq crq;
+
+	KASSERT(err == 0, ("DMA error %d\n", err));
+
+	mtx_assert(&xp->sc->io_lock, MA_OWNED);
+
+	cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
+	    ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes;
+
+	/* Command format from Table 20, page 37 of SRP spec */
+	crq.iu_length = 48 + ((nsegs > 1) ? 20 : 16) + 
+	    ((ccb->csio.cdb_len > 16) ? (ccb->csio.cdb_len - 16) : 0);
+	xp->srp_iu_size = crq.iu_length;
+	if (nsegs > 1)
+		xp->srp_iu_size += nsegs*16;
+	xp->srp_iu_size = roundup(xp->srp_iu_size, 16);
+	err = vmem_alloc(xp->sc->srp_iu_arena, xp->srp_iu_size,
+	    M_BESTFIT | M_NOWAIT, &xp->srp_iu_offset);
+	if (err)
+		panic("Error during VMEM allocation (%d)", err);
+
+	cmd = (struct srp_cmd *)((uint8_t *)xp->sc->srp_iu_queue +
+	    (uintptr_t)xp->srp_iu_offset);
+	bzero(cmd, xp->srp_iu_size);
+	cmd->type = SRP_CMD;
+	if (ccb->csio.cdb_len > 16)
+		cmd->additional_cdb = (ccb->csio.cdb_len - 16) << 2;
+	memcpy(cmd->cdb, cdb, ccb->csio.cdb_len);
+
+	cmd->tag = (uint64_t)(xp); /* Let the responder find this again */
+	cmd->lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
+
+	if (nsegs > 1) {
+		/* Use indirect descriptors */
+		switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
+		case CAM_DIR_OUT:
+			cmd->formats = (2 << 4);
+			break;
+		case CAM_DIR_IN:
+			cmd->formats = 2;
+			break;
+		default:
+			panic("Does not support bidirectional commands (%d)",
+			    ccb->ccb_h.flags & CAM_DIR_MASK);
+			break;
+		}
+
+		desc_start = ((ccb->csio.cdb_len > 16) ?
+		    ccb->csio.cdb_len - 16 : 0);
+		chunk_addr = xp->sc->srp_iu_phys + xp->srp_iu_offset + 20 +
+		    desc_start + sizeof(*cmd);
+		chunk_size = 16*nsegs;
+		memcpy(&cmd->data_payload[desc_start], &chunk_addr, 8);
+		memcpy(&cmd->data_payload[desc_start+12], &chunk_size, 4);
+		chunk_size = 0;
+		for (i = 0; i < nsegs; i++)
+			chunk_size += segs[i].ds_len;
+		memcpy(&cmd->data_payload[desc_start+16], &chunk_size, 4);
+		desc_start += 20;
+		for (i = 0; i < nsegs; i++) {
+			chunk_addr = segs[i].ds_addr;
+			chunk_size = segs[i].ds_len;
+
+			memcpy(&cmd->data_payload[desc_start + 16*i],
+			    &chunk_addr, 8);
+			/* Set handle tag to 0 */
+			memcpy(&cmd->data_payload[desc_start + 16*i + 12],
+			    &chunk_size, 4);
+		}
+	} else if (nsegs == 1) {
+		switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
+		case CAM_DIR_OUT:
+			cmd->formats = (1 << 4);
+			break;
+		case CAM_DIR_IN:
+			cmd->formats = 1;
+			break;
+		default:
+			panic("Does not support bidirectional commands (%d)",
+			    ccb->ccb_h.flags & CAM_DIR_MASK);
+			break;
+		}
+
+		/*
+		 * Memory descriptor:
+		 * 8 byte address
+		 * 4 byte handle
+		 * 4 byte length
+		 */
+
+		chunk_addr = segs[0].ds_addr;
+		chunk_size = segs[0].ds_len;
+		desc_start = ((ccb->csio.cdb_len > 16) ?
+		    ccb->csio.cdb_len - 16 : 0);
+
+		memcpy(&cmd->data_payload[desc_start], &chunk_addr, 8);
+		/* Set handle tag to 0 */
+		memcpy(&cmd->data_payload[desc_start+12], &chunk_size, 4);
+		KASSERT(xp->srp_iu_size >= 48 + ((ccb->csio.cdb_len > 16) ?
+		    ccb->csio.cdb_len : 16), ("SRP IU command length"));
+	} else {
+		cmd->formats = 0;
+	}
+	bus_dmamap_sync(xp->sc->crq_tag, xp->sc->crq_map, BUS_DMASYNC_PREWRITE);
+
+	/* Create CRQ entry */
+	crq.valid = 0x80;
+	crq.format = 0x01;
+	crq.iu_data = xp->sc->srp_iu_phys + xp->srp_iu_offset;
+
+	err = phyp_hcall(H_SEND_CRQ, xp->sc->unit, ((uint64_t *)(&crq))[0],
+	    ((uint64_t *)(&crq))[1]);
+	if (err != 0)
+		panic("CRQ send failure (%d)", err);
+}
+
+static void
+vscsi_crq_load_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int err)
+{
+	struct vscsi_softc *sc = xsc;
+	
+	sc->crq_phys = segs[0].ds_addr;
+	sc->n_crqs = PAGE_SIZE/sizeof(struct vscsi_crq);
+
+	sc->srp_iu_queue = (uint8_t *)(sc->crq_queue);
+	sc->srp_iu_phys = segs[0].ds_addr;
+	sc->srp_iu_arena = vmem_create("VSCSI SRP IU", PAGE_SIZE,
+	    segs[0].ds_len - PAGE_SIZE, 16, 0, M_BESTFIT | M_NOWAIT);
+}
+
+static void
+vscsi_setup_bus(struct vscsi_softc *sc)
+{
+	struct vscsi_crq crq;
+	struct vscsi_xfer *xp;
+	int error;
+
+	struct {
+		uint32_t type;
+		uint16_t status;
+		uint16_t length;
+		uint64_t tag;
+		uint64_t buffer;
+		struct {
+			char srp_version[8];
+			char partition_name[96];
+			uint32_t partition_number;
+			uint32_t mad_version;
+			uint32_t os_type;
+			uint32_t port_max_txu[8];
+		} payload;
+	} mad_adapter_info;
+
+	bzero(&crq, sizeof(crq));
+
+	/* Init message */
+	crq.valid = 0xc0;
+	crq.format = 0x01;
+
+	do {
+		error = phyp_hcall(H_FREE_CRQ, sc->unit);
+	} while (error == H_BUSY);
+
+	/* See initialization sequence page 757 */
+	bzero(sc->crq_queue, sc->n_crqs*sizeof(sc->crq_queue[0]));
+	sc->cur_crq = 0;
+	sc->bus_initialized = 0;
+	sc->bus_logged_in = 0;
+	bus_dmamap_sync(sc->crq_tag, sc->crq_map, BUS_DMASYNC_PREWRITE);
+	error = phyp_hcall(H_REG_CRQ, sc->unit, sc->crq_phys,
+	    sc->n_crqs*sizeof(sc->crq_queue[0]));
+	KASSERT(error == 0, ("CRQ registration success"));
+
+	error = phyp_hcall(H_SEND_CRQ, sc->unit, ((uint64_t *)(&crq))[0],
+	    ((uint64_t *)(&crq))[1]);
+	if (error != 0)
+		panic("CRQ setup failure (%d)", error);
+
+	while (sc->bus_initialized == 0)
+		vscsi_check_response_queue(sc);
+
+	/* Send MAD adapter info */
+	mad_adapter_info.type = MAD_ADAPTER_INFO_REQUEST;
+	mad_adapter_info.status = 0;
+	mad_adapter_info.length = sizeof(mad_adapter_info.payload);
+
+	strcpy(mad_adapter_info.payload.srp_version, "16.a");
+	strcpy(mad_adapter_info.payload.partition_name, "UNKNOWN");
+	mad_adapter_info.payload.partition_number = -1;
+	mad_adapter_info.payload.mad_version = 1;
+	mad_adapter_info.payload.os_type = 2; /* Claim we are Linux */
+	mad_adapter_info.payload.port_max_txu[0] = 0;
+	/* If this fails, we get the defaults above */
+	OF_getprop(OF_finddevice("/"), "ibm,partition-name",
+	    mad_adapter_info.payload.partition_name,
+	    sizeof(mad_adapter_info.payload.partition_name));
+	OF_getprop(OF_finddevice("/"), "ibm,partition-no",
+	    &mad_adapter_info.payload.partition_number,
+	    sizeof(mad_adapter_info.payload.partition_number));
+
+	xp = TAILQ_FIRST(&sc->free_xferq);
+	xp->ccb = NULL;
+	TAILQ_REMOVE(&sc->free_xferq, xp, queue);
+	TAILQ_INSERT_TAIL(&sc->active_xferq, xp, queue);
+	xp->srp_iu_size = crq.iu_length = sizeof(mad_adapter_info);
+	vmem_alloc(xp->sc->srp_iu_arena, xp->srp_iu_size,
+	    M_BESTFIT | M_NOWAIT, &xp->srp_iu_offset);
+	mad_adapter_info.buffer = xp->sc->srp_iu_phys + xp->srp_iu_offset + 24;
+	mad_adapter_info.tag = (uint64_t)xp;
+	memcpy((uint8_t *)xp->sc->srp_iu_queue + (uintptr_t)xp->srp_iu_offset,
+		&mad_adapter_info, sizeof(mad_adapter_info));
+	crq.valid = 0x80;
+	crq.format = 0x02;
+	crq.iu_data = xp->sc->srp_iu_phys + xp->srp_iu_offset;
+	bus_dmamap_sync(sc->crq_tag, sc->crq_map, BUS_DMASYNC_PREWRITE);
+	phyp_hcall(H_SEND_CRQ, xp->sc->unit, ((uint64_t *)(&crq))[0],
+	    ((uint64_t *)(&crq))[1]);
+
+	while (TAILQ_EMPTY(&sc->free_xferq))
+		vscsi_check_response_queue(sc);
+
+	/* Send SRP login */
+	vscsi_srp_login(sc);
+	while (sc->bus_logged_in == 0)
+		vscsi_check_response_queue(sc);
+
+	error = phyp_hcall(H_VIO_SIGNAL, sc->unit, 1); /* Enable interrupts */
+}
+	
+
+static void
+vscsi_intr(void *xsc)
+{
+	struct vscsi_softc *sc = xsc;
+
+	mtx_lock(&sc->io_lock);
+	vscsi_check_response_queue(sc);
+	mtx_unlock(&sc->io_lock);
+}
+
+static void
+vscsi_srp_response(struct vscsi_xfer *xp, struct vscsi_crq *crq)
+{
+	union ccb *ccb = xp->ccb;
+	struct vscsi_softc *sc = xp->sc;
+	struct srp_rsp *rsp;
+	uint32_t sense_len;
+
+	/* SRP response packet in original request */
+	rsp = (struct srp_rsp *)((uint8_t *)sc->srp_iu_queue +
+	    (uintptr_t)xp->srp_iu_offset);
+	ccb->csio.scsi_status = rsp->status;
+	if (ccb->csio.scsi_status == SCSI_STATUS_OK)
+		ccb->ccb_h.status = CAM_REQ_CMP;
+	else
+		ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+#ifdef NOTYET
+	/* Collect fast fail codes */
+	if (crq->status != 0)
+		ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+#endif
+
+	if (ccb->ccb_h.status != CAM_REQ_CMP) {
+		ccb->ccb_h.status |= CAM_DEV_QFRZN;
+		xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1);
+	}
+
+	if (!(rsp->flags & SRP_RSPVALID))
+		rsp->response_data_len = 0;
+	if (!(rsp->flags & SRP_SNSVALID))
+		rsp->sense_data_len = 0;
+	if (!(rsp->flags & (SRP_DOOVER | SRP_DOUNDER)))
+		rsp->data_out_resid = 0;
+	if (!(rsp->flags & (SRP_DIOVER | SRP_DIUNDER)))
+		rsp->data_in_resid = 0;
+
+	if (rsp->flags & SRP_SNSVALID) {
+		bzero(&ccb->csio.sense_data, sizeof(struct scsi_sense_data));
+		ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
+		sense_len = min(be32toh(rsp->sense_data_len),
+		    ccb->csio.sense_len);
+		memcpy(&ccb->csio.sense_data,
+		    &rsp->data_payload[be32toh(rsp->response_data_len)],
+		    sense_len);
+		ccb->csio.sense_resid = ccb->csio.sense_len -
+		    be32toh(rsp->sense_data_len);
+	}
+
+	switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
+	case CAM_DIR_OUT:
+		ccb->csio.resid = rsp->data_out_resid;
+		break;
+	case CAM_DIR_IN:
+		ccb->csio.resid = rsp->data_in_resid;
+		break;
+	}
+
+	bus_dmamap_sync(sc->data_tag, xp->dmamap, BUS_DMASYNC_POSTREAD);
+	bus_dmamap_unload(sc->data_tag, xp->dmamap);
+	xpt_done(ccb);
+	xp->ccb = NULL;
+}
+
+static void
+vscsi_login_response(struct vscsi_xfer *xp, struct vscsi_crq *crq)
+{
+	struct vscsi_softc *sc = xp->sc;
+	struct srp_login_rsp *rsp;
+
+	/* SRP response packet in original request */
+	rsp = (struct srp_login_rsp *)((uint8_t *)sc->srp_iu_queue +
+	    (uintptr_t)xp->srp_iu_offset);
+	KASSERT(be16toh(rsp->buffer_formats) & 0x3, ("Both direct and indirect "
+	    "buffers supported"));
+
+	sc->max_transactions = be32toh(rsp->request_limit_delta);
+	device_printf(sc->dev, "Queue depth %d commands\n",
+	    sc->max_transactions);
+	sc->bus_logged_in = 1;
+}
+
+static void
+vscsi_cam_poll(struct cam_sim *sim)
+{
+	struct vscsi_softc *sc = cam_sim_softc(sim);
+
+	vscsi_check_response_queue(sc);
+}
+
+static void
+vscsi_check_response_queue(struct vscsi_softc *sc)
+{
+	struct vscsi_crq *crq;
+	struct vscsi_xfer *xp;
+	int code;
+
+	mtx_assert(&sc->io_lock, MA_OWNED);
+
+	phyp_hcall(H_VIO_SIGNAL, sc->unit, 0);
+	bus_dmamap_sync(sc->crq_tag, sc->crq_map, BUS_DMASYNC_POSTREAD);
+
+	while (sc->crq_queue[sc->cur_crq].valid != 0) {
+		crq = &sc->crq_queue[sc->cur_crq];
+
+		switch (crq->valid) {
+		case 0xc0:
+			if (crq->format == 0x02)
+				sc->bus_initialized = 1;
+			break;
+		case 0x80:
+			/* IU data is set to tag pointer (the XP) */
+			xp = (struct vscsi_xfer *)crq->iu_data;
+
+			switch (crq->format) {
+			case 0x01:
+				code = *((uint8_t *)sc->srp_iu_queue +
+	    			    (uintptr_t)xp->srp_iu_offset);
+				switch (code) {
+				case SRP_RSP:
+					vscsi_srp_response(xp, crq);
+					break;
+				case SRP_LOGIN_RSP:
+					vscsi_login_response(xp, crq);
+					break;
+				default:
+					device_printf(sc->dev, "Unknown SRP "
+					    "response code %d\n", code);
+					break;
+				}
+				break;
+			case 0x02:
+				/* Ignore management datagrams */
+				break;
+			default:
+				panic("Unknown CRQ format %d\n", crq->format);
+				break;
+			}
+			vmem_free(sc->srp_iu_arena, xp->srp_iu_offset,
+			    xp->srp_iu_size);
+			TAILQ_REMOVE(&sc->active_xferq, xp, queue);
+			TAILQ_INSERT_TAIL(&sc->free_xferq, xp, queue);
+			break;
+		default:
+			device_printf(sc->dev,
+			    "Unknown CRQ message type %d\n", crq->valid);
+			break;
+		}
+
+		crq->valid = 0;
+		sc->cur_crq = (sc->cur_crq + 1) % sc->n_crqs;
+	};
+
+	bus_dmamap_sync(sc->crq_tag, sc->crq_map, BUS_DMASYNC_PREWRITE);
+	phyp_hcall(H_VIO_SIGNAL, sc->unit, 1);
+}
+


Property changes on: trunk/sys/powerpc/pseries/phyp_vscsi.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/platform_chrp.c
===================================================================
--- trunk/sys/powerpc/pseries/platform_chrp.c	                        (rev 0)
+++ trunk/sys/powerpc/pseries/platform_chrp.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,509 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2008 Marcel Moolenaar
+ * Copyright (c) 2009 Nathan Whitehorn
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/pseries/platform_chrp.c 266020 2014-05-14 14:17:51Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/hid.h>
+#include <machine/platformvar.h>
+#include <machine/pmap.h>
+#include <machine/rtas.h>
+#include <machine/smp.h>
+#include <machine/spr.h>
+#include <machine/trap.h>
+
+#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
+
+#include "platform_if.h"
+
+#ifdef SMP
+extern void *ap_pcpu;
+#endif
+
+#ifdef __powerpc64__
+static uint8_t splpar_vpa[640] __aligned(64);
+#endif
+
+static vm_offset_t realmaxaddr = VM_MAX_ADDRESS;
+
+static int chrp_probe(platform_t);
+static int chrp_attach(platform_t);
+void chrp_mem_regions(platform_t, struct mem_region *phys, int *physsz,
+    struct mem_region *avail, int *availsz);
+static vm_offset_t chrp_real_maxaddr(platform_t);
+static u_long chrp_timebase_freq(platform_t, struct cpuref *cpuref);
+static int chrp_smp_first_cpu(platform_t, struct cpuref *cpuref);
+static int chrp_smp_next_cpu(platform_t, struct cpuref *cpuref);
+static int chrp_smp_get_bsp(platform_t, struct cpuref *cpuref);
+static void chrp_smp_ap_init(platform_t);
+#ifdef SMP
+static int chrp_smp_start_cpu(platform_t, struct pcpu *cpu);
+static struct cpu_group *chrp_smp_topo(platform_t plat);
+#endif
+static void chrp_reset(platform_t);
+#ifdef __powerpc64__
+#include "phyp-hvcall.h"
+static void phyp_cpu_idle(sbintime_t sbt);
+#endif
+
+static platform_method_t chrp_methods[] = {
+	PLATFORMMETHOD(platform_probe, 		chrp_probe),
+	PLATFORMMETHOD(platform_attach,		chrp_attach),
+	PLATFORMMETHOD(platform_mem_regions,	chrp_mem_regions),
+	PLATFORMMETHOD(platform_real_maxaddr,	chrp_real_maxaddr),
+	PLATFORMMETHOD(platform_timebase_freq,	chrp_timebase_freq),
+	
+	PLATFORMMETHOD(platform_smp_ap_init,	chrp_smp_ap_init),
+	PLATFORMMETHOD(platform_smp_first_cpu,	chrp_smp_first_cpu),
+	PLATFORMMETHOD(platform_smp_next_cpu,	chrp_smp_next_cpu),
+	PLATFORMMETHOD(platform_smp_get_bsp,	chrp_smp_get_bsp),
+#ifdef SMP
+	PLATFORMMETHOD(platform_smp_start_cpu,	chrp_smp_start_cpu),
+	PLATFORMMETHOD(platform_smp_topo,	chrp_smp_topo),
+#endif
+
+	PLATFORMMETHOD(platform_reset,		chrp_reset),
+
+	{ 0, 0 }
+};
+
+static platform_def_t chrp_platform = {
+	"chrp",
+	chrp_methods,
+	0
+};
+
+PLATFORM_DEF(chrp_platform);
+
+static int
+chrp_probe(platform_t plat)
+{
+	if (OF_finddevice("/memory") != -1 || OF_finddevice("/memory at 0") != -1)
+		return (BUS_PROBE_GENERIC);
+
+	return (ENXIO);
+}
+
+static int
+chrp_attach(platform_t plat)
+{
+#ifdef __powerpc64__
+	/* XXX: check for /rtas/ibm,hypertas-functions? */
+	if (!(mfmsr() & PSL_HV)) {
+		struct mem_region *phys, *avail;
+		int nphys, navail;
+		mem_regions(&phys, &nphys, &avail, &navail);
+		realmaxaddr = phys[0].mr_size;
+
+		pmap_mmu_install("mmu_phyp", BUS_PROBE_SPECIFIC);
+		cpu_idle_hook = phyp_cpu_idle;
+
+		/* Set up important VPA fields */
+		bzero(splpar_vpa, sizeof(splpar_vpa));
+		splpar_vpa[4] = (uint8_t)((sizeof(splpar_vpa) >> 8) & 0xff);
+		splpar_vpa[5] = (uint8_t)(sizeof(splpar_vpa) & 0xff);
+		splpar_vpa[0xba] = 1;			/* Maintain FPRs */
+		splpar_vpa[0xbb] = 1;			/* Maintain PMCs */
+		splpar_vpa[0xfc] = 0xff;		/* Maintain full SLB */
+		splpar_vpa[0xfd] = 0xff;
+		splpar_vpa[0xff] = 1;			/* Maintain Altivec */
+		mb();
+
+		/* Set up hypervisor CPU stuff */
+		chrp_smp_ap_init(plat);
+	}
+#endif
+
+	/* Some systems (e.g. QEMU) need Open Firmware to stand down */
+	ofw_quiesce();
+
+	return (0);
+}
+
+static int
+parse_drconf_memory(int *msz, int *asz, struct mem_region *ofmem,
+		    struct mem_region *ofavail)
+{
+	phandle_t phandle;
+	vm_offset_t base;
+	int i, idx, len, lasz, lmsz, res;
+	uint32_t lmb_size[2];
+	unsigned long *dmem, flags;
+
+	lmsz = *msz;
+	lasz = *asz;
+
+	phandle = OF_finddevice("/ibm,dynamic-reconfiguration-memory");
+	if (phandle == -1)
+		/* No drconf node, return. */
+		return (0);
+
+	res = OF_getprop(phandle, "ibm,lmb-size", lmb_size, sizeof(lmb_size));
+	if (res == -1)
+		return (0);
+	printf("Logical Memory Block size: %d MB\n", lmb_size[1] >> 20);
+
+	/* Parse the /ibm,dynamic-memory.
+	   The first position gives the # of entries. The next two words
+ 	   reflect the address of the memory block. The next four words are
+	   the DRC index, reserved, list index and flags.
+	   (see PAPR C.6.6.2 ibm,dynamic-reconfiguration-memory)
+	   
+	    #el  Addr   DRC-idx  res   list-idx  flags
+	   -------------------------------------------------
+	   | 4 |   8   |   4   |   4   |   4   |   4   |....
+	   -------------------------------------------------
+	*/
+
+	len = OF_getproplen(phandle, "ibm,dynamic-memory");
+	if (len > 0) {
+
+		/* We have to use a variable length array on the stack
+		   since we have very limited stack space.
+		*/
+		cell_t arr[len/sizeof(cell_t)];
+
+		res = OF_getprop(phandle, "ibm,dynamic-memory", &arr,
+				 sizeof(arr));
+		if (res == -1)
+			return (0);
+
+		/* Number of elements */
+		idx = arr[0];
+
+		/* First address. */
+		dmem = (void*)&arr[1];
+	
+		for (i = 0; i < idx; i++) {
+			base = *dmem;
+			dmem += 2;
+			flags = *dmem;
+			/* Use region only if available and not reserved. */
+			if ((flags & 0x8) && !(flags & 0x80)) {
+				ofmem[lmsz].mr_start = base;
+				ofmem[lmsz].mr_size = (vm_size_t)lmb_size[1];
+				ofavail[lasz].mr_start = base;
+				ofavail[lasz].mr_size = (vm_size_t)lmb_size[1];
+				lmsz++;
+				lasz++;
+			}
+			dmem++;
+		}
+	}
+
+	*msz = lmsz;
+	*asz = lasz;
+
+	return (1);
+}
+
+void
+chrp_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
+    struct mem_region *avail, int *availsz)
+{
+	vm_offset_t maxphysaddr;
+	int i;
+
+	ofw_mem_regions(phys, physsz, avail, availsz);
+	parse_drconf_memory(physsz, availsz, phys, avail);
+
+	/*
+	 * On some firmwares (SLOF), some memory may be marked available that
+	 * doesn't actually exist. This manifests as an extension of the last
+	 * available segment past the end of physical memory, so truncate that
+	 * one.
+	 */
+	maxphysaddr = 0;
+	for (i = 0; i < *physsz; i++)
+		if (phys[i].mr_start + phys[i].mr_size > maxphysaddr)
+			maxphysaddr = phys[i].mr_start + phys[i].mr_size;
+
+	for (i = 0; i < *availsz; i++)
+		if (avail[i].mr_start + avail[i].mr_size > maxphysaddr)
+			avail[i].mr_size = maxphysaddr - avail[i].mr_start;
+}
+
+static vm_offset_t
+chrp_real_maxaddr(platform_t plat)
+{
+	return (realmaxaddr);
+}
+
+static u_long
+chrp_timebase_freq(platform_t plat, struct cpuref *cpuref)
+{
+	phandle_t phandle;
+	int32_t ticks = -1;
+
+	phandle = cpuref->cr_hwref;
+
+	OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks));
+
+	if (ticks <= 0)
+		panic("Unable to determine timebase frequency!");
+
+	return (ticks);
+}
+
+static int
+chrp_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
+{
+	char buf[8];
+	phandle_t cpu, dev, root;
+	int res, cpuid;
+
+	root = OF_peer(0);
+
+	dev = OF_child(root);
+	while (dev != 0) {
+		res = OF_getprop(dev, "name", buf, sizeof(buf));
+		if (res > 0 && strcmp(buf, "cpus") == 0)
+			break;
+		dev = OF_peer(dev);
+	}
+	if (dev == 0) {
+		/*
+		 * psim doesn't have a name property on the /cpus node,
+		 * but it can be found directly
+		 */
+		dev = OF_finddevice("/cpus");
+		if (dev == 0)
+			return (ENOENT);
+	}
+
+	cpu = OF_child(dev);
+
+	while (cpu != 0) {
+		res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
+		if (res > 0 && strcmp(buf, "cpu") == 0)
+			break;
+		cpu = OF_peer(cpu);
+	}
+	if (cpu == 0)
+		return (ENOENT);
+
+	cpuref->cr_hwref = cpu;
+	res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
+	    sizeof(cpuid));
+	if (res <= 0)
+		res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid));
+	if (res <= 0)
+		cpuid = 0;
+	cpuref->cr_cpuid = cpuid;
+
+	return (0);
+}
+
+static int
+chrp_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
+{
+	char buf[8];
+	phandle_t cpu;
+	int i, res, cpuid;
+
+	/* Check for whether it should be the next thread */
+	res = OF_getproplen(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s");
+	if (res > 0) {
+		cell_t interrupt_servers[res/sizeof(cell_t)];
+		OF_getprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s",
+		    interrupt_servers, res);
+		for (i = 0; i < res/sizeof(cell_t) - 1; i++) {
+			if (interrupt_servers[i] == cpuref->cr_cpuid) {
+				cpuref->cr_cpuid = interrupt_servers[i+1];
+				return (0);
+			}
+		}
+	}
+
+	/* Next CPU core/package */
+	cpu = OF_peer(cpuref->cr_hwref);
+	while (cpu != 0) {
+		res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
+		if (res > 0 && strcmp(buf, "cpu") == 0)
+			break;
+		cpu = OF_peer(cpu);
+	}
+	if (cpu == 0)
+		return (ENOENT);
+
+	cpuref->cr_hwref = cpu;
+	res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
+	    sizeof(cpuid));
+	if (res <= 0)
+		res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid));
+	if (res <= 0)
+		cpuid = 0;
+	cpuref->cr_cpuid = cpuid;
+
+	return (0);
+}
+
+static int
+chrp_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
+{
+	ihandle_t inst;
+	phandle_t bsp, chosen;
+	int res, cpuid;
+
+	chosen = OF_finddevice("/chosen");
+	if (chosen == 0)
+		return (ENXIO);
+
+	res = OF_getprop(chosen, "cpu", &inst, sizeof(inst));
+	if (res < 0)
+		return (ENXIO);
+
+	bsp = OF_instance_to_package(inst);
+
+	/* Pick the primary thread. Can it be any other? */
+	cpuref->cr_hwref = bsp;
+	res = OF_getprop(bsp, "ibm,ppc-interrupt-server#s", &cpuid,
+	    sizeof(cpuid));
+	if (res <= 0)
+		res = OF_getprop(bsp, "reg", &cpuid, sizeof(cpuid));
+	if (res <= 0)
+		cpuid = 0;
+	cpuref->cr_cpuid = cpuid;
+
+	return (0);
+}
+
+#ifdef SMP
+static int
+chrp_smp_start_cpu(platform_t plat, struct pcpu *pc)
+{
+	cell_t start_cpu;
+	int result, err, timeout;
+
+	if (!rtas_exists()) {
+		printf("RTAS uninitialized: unable to start AP %d\n",
+		    pc->pc_cpuid);
+		return (ENXIO);
+	}
+
+	start_cpu = rtas_token_lookup("start-cpu");
+	if (start_cpu == -1) {
+		printf("RTAS unknown method: unable to start AP %d\n",
+		    pc->pc_cpuid);
+		return (ENXIO);
+	}
+
+	ap_pcpu = pc;
+	powerpc_sync();
+
+	result = rtas_call_method(start_cpu, 3, 1, pc->pc_cpuid, EXC_RST, pc,
+	    &err);
+	if (result < 0 || err != 0) {
+		printf("RTAS error (%d/%d): unable to start AP %d\n",
+		    result, err, pc->pc_cpuid);
+		return (ENXIO);
+	}
+
+	timeout = 10000;
+	while (!pc->pc_awake && timeout--)
+		DELAY(100);
+
+	return ((pc->pc_awake) ? 0 : EBUSY);
+}
+
+static struct cpu_group *
+chrp_smp_topo(platform_t plat)
+{
+	struct pcpu *pc, *last_pc;
+	int i, ncores, ncpus;
+
+	ncores = ncpus = 0;
+	last_pc = NULL;
+	for (i = 0; i <= mp_maxid; i++) {
+		pc = pcpu_find(i);
+		if (pc == NULL)
+			continue;
+		if (last_pc == NULL || pc->pc_hwref != last_pc->pc_hwref)
+			ncores++;
+		last_pc = pc;
+		ncpus++;
+	}
+
+	if (ncpus % ncores != 0) {
+		printf("WARNING: Irregular SMP topology. Performance may be "
+		     "suboptimal (%d CPUS, %d cores)\n", ncpus, ncores);
+		return (smp_topo_none());
+	}
+
+	/* Don't do anything fancier for non-threaded SMP */
+	if (ncpus == ncores)
+		return (smp_topo_none());
+
+	return (smp_topo_1level(CG_SHARE_L1, ncpus / ncores, CG_FLAG_SMT));
+}
+#endif
+
+static void
+chrp_reset(platform_t platform)
+{
+	OF_reboot();
+}
+
+#ifdef __powerpc64__
+static void
+phyp_cpu_idle(sbintime_t sbt)
+{
+	phyp_hcall(H_CEDE);
+}
+
+static void
+chrp_smp_ap_init(platform_t platform)
+{
+	if (!(mfmsr() & PSL_HV)) {
+		/* Set interrupt priority */
+		phyp_hcall(H_CPPR, 0xff);
+
+		/* Register VPA */
+		phyp_hcall(H_REGISTER_VPA, 1UL, PCPU_GET(cpuid), splpar_vpa);
+	}
+}
+#else
+static void
+chrp_smp_ap_init(platform_t platform)
+{
+}
+#endif
+


Property changes on: trunk/sys/powerpc/pseries/platform_chrp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/plpar_iommu.c
===================================================================
--- trunk/sys/powerpc/pseries/plpar_iommu.c	                        (rev 0)
+++ trunk/sys/powerpc/pseries/plpar_iommu.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,245 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013, Nathan Whitehorn <nwhitehorn at FreeBSD.org>
+ * 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 unmodified, 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/pseries/plpar_iommu.c 278122 2015-02-03 00:29:58Z nwhitehorn $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/libkern.h>
+#include <sys/module.h>
+#include <sys/vmem.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+
+#include <powerpc/pseries/phyp-hvcall.h>
+#include <powerpc/pseries/plpar_iommu.h>
+
+MALLOC_DEFINE(M_PHYPIOMMU, "iommu", "IOMMU data for PAPR LPARs");
+
+struct papr_iommu_map {
+	uint32_t iobn;
+	vmem_t *vmem;
+	struct papr_iommu_map *next;
+};
+
+static SLIST_HEAD(iommu_maps, iommu_map) iommu_map_head =
+    SLIST_HEAD_INITIALIZER(iommu_map_head);
+static int papr_supports_stuff_tce = -1;
+
+struct iommu_map {
+	uint32_t iobn;
+	vmem_t *vmem;
+
+	SLIST_ENTRY(iommu_map) entries;
+};
+
+struct dma_window {
+	struct iommu_map *map;
+	bus_addr_t start;
+	bus_addr_t end;
+};
+
+int
+phyp_iommu_set_dma_tag(device_t bus, device_t dev, bus_dma_tag_t tag)
+{
+	device_t p;
+	phandle_t node;
+	cell_t dma_acells, dma_scells, dmawindow[6];
+	struct iommu_map *i;
+	int cell;
+
+	for (p = dev; device_get_parent(p) != NULL; p = device_get_parent(p)) {
+		if (ofw_bus_has_prop(p, "ibm,my-dma-window"))
+			break;
+		if (ofw_bus_has_prop(p, "ibm,dma-window"))
+			break;
+	}
+
+	if (p == NULL)
+		return (ENXIO);
+
+	node = ofw_bus_get_node(p);
+	if (OF_getprop(node, "ibm,#dma-size-cells", &dma_scells,
+	    sizeof(cell_t)) <= 0)
+		OF_searchprop(node, "#size-cells", &dma_scells, sizeof(cell_t));
+	if (OF_getprop(node, "ibm,#dma-address-cells", &dma_acells,
+	    sizeof(cell_t)) <= 0)
+		OF_searchprop(node, "#address-cells", &dma_acells,
+		    sizeof(cell_t));
+
+	if (ofw_bus_has_prop(p, "ibm,my-dma-window"))
+		OF_getprop(node, "ibm,my-dma-window", dmawindow,
+		    sizeof(cell_t)*(dma_scells + dma_acells + 1));
+	else
+		OF_getprop(node, "ibm,dma-window", dmawindow,
+		    sizeof(cell_t)*(dma_scells + dma_acells + 1));
+
+	struct dma_window *window = malloc(sizeof(struct dma_window),
+	    M_PHYPIOMMU, M_WAITOK);
+	window->start = 0;
+	for (cell = 1; cell < 1 + dma_acells; cell++) {
+		window->start <<= 32;
+		window->start |= dmawindow[cell];
+	}
+	window->end = 0;
+	for (; cell < 1 + dma_acells + dma_scells; cell++) {
+		window->end <<= 32;
+		window->end |= dmawindow[cell];
+	}
+	window->end += window->start;
+
+	if (bootverbose)
+		device_printf(dev, "Mapping IOMMU domain %#x\n", dmawindow[0]);
+	window->map = NULL;
+	SLIST_FOREACH(i, &iommu_map_head, entries) {
+		if (i->iobn == dmawindow[0]) {
+			window->map = i;
+			break;
+		}
+	}
+
+	if (window->map == NULL) {
+		window->map = malloc(sizeof(struct iommu_map), M_PHYPIOMMU,
+		    M_WAITOK);
+		window->map->iobn = dmawindow[0];
+		/*
+		 * Allocate IOMMU range beginning at PAGE_SIZE. Some drivers
+		 * (em(4), for example) do not like getting mappings at 0.
+		 */
+		window->map->vmem = vmem_create("IOMMU mappings", PAGE_SIZE,
+		    trunc_page(VMEM_ADDR_MAX) - PAGE_SIZE, PAGE_SIZE, 0,
+		    M_BESTFIT | M_NOWAIT);
+		SLIST_INSERT_HEAD(&iommu_map_head, window->map, entries);
+	}
+
+	/*
+	 * Check experimentally whether we can use H_STUFF_TCE. It is required
+	 * by the spec but some firmware (e.g. QEMU) does not actually support
+	 * it
+	 */
+	if (papr_supports_stuff_tce == -1)
+		papr_supports_stuff_tce = !(phyp_hcall(H_STUFF_TCE,
+		    window->map->iobn, 0, 0, 0) == H_FUNCTION);
+
+	bus_dma_tag_set_iommu(tag, bus, window);
+
+	return (0);
+}
+
+int
+phyp_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs,
+    bus_addr_t min, bus_addr_t max, bus_size_t alignment, bus_addr_t boundary,
+    void *cookie)
+{
+	struct dma_window *window = cookie;
+	bus_addr_t minaddr, maxaddr;
+	bus_addr_t alloced;
+	bus_size_t allocsize;
+	int error, i, j;
+	uint64_t tce;
+	minaddr = window->start;
+	maxaddr = window->end;
+
+	/* XXX: handle exclusion range in a more useful way */
+	if (min < maxaddr)
+		maxaddr = min;
+
+	/* XXX: consolidate segs? */
+	for (i = 0; i < *nsegs; i++) {
+		allocsize = round_page(segs[i].ds_len +
+		    (segs[i].ds_addr & PAGE_MASK));
+		error = vmem_xalloc(window->map->vmem, allocsize,
+		    (alignment < PAGE_SIZE) ? PAGE_SIZE : alignment, 0,
+		    boundary, minaddr, maxaddr, M_BESTFIT | M_NOWAIT, &alloced);
+		if (error != 0) {
+			panic("VMEM failure: %d\n", error);
+			return (error);
+		}
+		KASSERT(alloced % PAGE_SIZE == 0, ("Alloc not page aligned"));
+		KASSERT((alloced + (segs[i].ds_addr & PAGE_MASK)) %
+		    alignment == 0,
+		    ("Allocated segment does not match alignment constraint"));
+
+		tce = trunc_page(segs[i].ds_addr);
+		tce |= 0x3; /* read/write */
+		for (j = 0; j < allocsize; j += PAGE_SIZE) {
+			error = phyp_hcall(H_PUT_TCE, window->map->iobn,
+			    alloced + j, tce + j);
+			if (error < 0) {
+				panic("IOMMU mapping error: %d\n", error);
+				return (ENOMEM);
+			}
+		}
+
+		segs[i].ds_addr = alloced + (segs[i].ds_addr & PAGE_MASK);
+		KASSERT(segs[i].ds_addr > 0, ("Address needs to be positive"));
+		KASSERT(segs[i].ds_addr + segs[i].ds_len < maxaddr,
+		    ("Address not in range"));
+		if (error < 0) {
+			panic("IOMMU mapping error: %d\n", error);
+			return (ENOMEM);
+		}
+	}
+
+	return (0);
+}
+	
+int
+phyp_iommu_unmap(device_t dev, bus_dma_segment_t *segs, int nsegs, void *cookie)
+{
+	struct dma_window *window = cookie;
+	bus_addr_t pageround;
+	bus_size_t roundedsize;
+	int i;
+	bus_addr_t j;
+
+	for (i = 0; i < nsegs; i++) {
+		pageround = trunc_page(segs[i].ds_addr);
+		roundedsize = round_page(segs[i].ds_len +
+		    (segs[i].ds_addr & PAGE_MASK));
+
+		if (papr_supports_stuff_tce) {
+			phyp_hcall(H_STUFF_TCE, window->map->iobn, pageround, 0,
+			    roundedsize/PAGE_SIZE);
+		} else {
+			for (j = 0; j < roundedsize; j += PAGE_SIZE)
+				phyp_hcall(H_PUT_TCE, window->map->iobn,
+				    pageround + j, 0);
+		}
+
+		vmem_xfree(window->map->vmem, pageround, roundedsize);
+	}
+
+	return (0);
+}
+


Property changes on: trunk/sys/powerpc/pseries/plpar_iommu.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/plpar_iommu.h
===================================================================
--- trunk/sys/powerpc/pseries/plpar_iommu.h	                        (rev 0)
+++ trunk/sys/powerpc/pseries/plpar_iommu.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,44 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013, Nathan Whitehorn <nwhitehorn at FreeBSD.org>
+ * 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 unmodified, 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/pseries/plpar_iommu.h 255643 2013-09-17 17:37:04Z nwhitehorn $
+ */
+
+#ifndef _PSERIES_PHYP_IOMMU_H_
+#define _PSERIES_PHYP_IOMMU_H_
+
+#include <sys/types.h>
+#include <sys/bus_dma.h>
+
+int phyp_iommu_set_dma_tag(device_t dev, device_t child, bus_dma_tag_t tag);
+int phyp_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs,
+    bus_addr_t min, bus_addr_t max, bus_size_t alignment, bus_addr_t boundary,
+    void *cookie);
+int phyp_iommu_unmap(device_t dev, bus_dma_segment_t *segs, int nsegs,
+    void *cookie);
+
+#endif
+


Property changes on: trunk/sys/powerpc/pseries/plpar_iommu.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/plpar_pcibus.c
===================================================================
--- trunk/sys/powerpc/pseries/plpar_pcibus.c	                        (rev 0)
+++ trunk/sys/powerpc/pseries/plpar_pcibus.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,114 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/pseries/plpar_pcibus.c 259257 2013-12-12 12:36:40Z andreast $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/libkern.h>
+#include <sys/module.h>
+#include <sys/pciio.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pci_private.h>
+
+#include <machine/bus.h>
+#include <machine/rtas.h>
+
+#include <powerpc/ofw/ofw_pcibus.h>
+#include <powerpc/pseries/plpar_iommu.h>
+
+#include "pci_if.h"
+#include "iommu_if.h"
+
+static int		plpar_pcibus_probe(device_t);
+static bus_dma_tag_t	plpar_pcibus_get_dma_tag(device_t dev, device_t child);
+
+/*
+ * Driver methods.
+ */
+static device_method_t	plpar_pcibus_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		plpar_pcibus_probe),
+
+	/* IOMMU functions */
+	DEVMETHOD(bus_get_dma_tag,	plpar_pcibus_get_dma_tag),
+	DEVMETHOD(iommu_map,		phyp_iommu_map),
+	DEVMETHOD(iommu_unmap,		phyp_iommu_unmap),
+
+	DEVMETHOD_END
+};
+
+static devclass_t pci_devclass;
+DEFINE_CLASS_1(pci, plpar_pcibus_driver, plpar_pcibus_methods,
+    sizeof(struct pci_softc), ofw_pcibus_driver);
+DRIVER_MODULE(plpar_pcibus, pcib, plpar_pcibus_driver, pci_devclass, 0, 0);
+
+static int
+plpar_pcibus_probe(device_t dev)
+{
+	phandle_t rtas;
+ 
+	if (ofw_bus_get_node(dev) == -1 || !rtas_exists())
+		return (ENXIO);
+
+	rtas = OF_finddevice("/rtas");
+	if (!OF_hasprop(rtas, "ibm,hypertas-functions"))
+		return (ENXIO);
+
+	device_set_desc(dev, "POWER Hypervisor PCI bus");
+
+	return (BUS_PROBE_SPECIFIC);
+}
+
+static bus_dma_tag_t
+plpar_pcibus_get_dma_tag(device_t dev, device_t child)
+{
+	struct ofw_pcibus_devinfo *dinfo;
+
+	while (device_get_parent(child) != dev)
+		child = device_get_parent(child);
+
+	dinfo = device_get_ivars(child);
+
+	if (dinfo->opd_dma_tag != NULL)
+		return (dinfo->opd_dma_tag);
+
+	bus_dma_tag_create(bus_get_dma_tag(dev),
+	    1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
+	    NULL, NULL, BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED,
+	    BUS_SPACE_MAXSIZE, 0, NULL, NULL, &dinfo->opd_dma_tag);
+	phyp_iommu_set_dma_tag(dev, child, dinfo->opd_dma_tag);
+
+	return (dinfo->opd_dma_tag);
+}
+


Property changes on: trunk/sys/powerpc/pseries/plpar_pcibus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/rtas_dev.c
===================================================================
--- trunk/sys/powerpc/pseries/rtas_dev.c	                        (rev 0)
+++ trunk/sys/powerpc/pseries/rtas_dev.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,174 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/pseries/rtas_dev.c 266160 2014-05-15 17:30:16Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/clock.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/reboot.h>
+#include <sys/sysctl.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/rtas.h>
+
+#include "clock_if.h"
+
+static int	rtasdev_probe(device_t);
+static int	rtasdev_attach(device_t);
+/* clock interface */
+static int	rtas_gettime(device_t dev, struct timespec *ts);
+static int	rtas_settime(device_t dev, struct timespec *ts);
+
+static void	rtas_shutdown(void *arg, int howto);
+
+static device_method_t  rtasdev_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		rtasdev_probe),
+	DEVMETHOD(device_attach,	rtasdev_attach),
+
+	/* clock interface */
+	DEVMETHOD(clock_gettime,	rtas_gettime),
+	DEVMETHOD(clock_settime,	rtas_settime),
+	
+	{ 0, 0 },
+};
+
+static driver_t rtasdev_driver = {
+	"rtas",
+	rtasdev_methods,
+	0
+};
+
+static devclass_t rtasdev_devclass;
+
+DRIVER_MODULE(rtasdev, ofwbus, rtasdev_driver, rtasdev_devclass, 0, 0);
+
+static int
+rtasdev_probe(device_t dev)
+{
+	const char *name = ofw_bus_get_name(dev);
+
+	if (strcmp(name, "rtas") != 0)
+		return (ENXIO);
+	if (!rtas_exists())
+		return (ENXIO);
+
+	device_set_desc(dev, "Run-Time Abstraction Services");
+	return (0);
+}
+
+static int
+rtasdev_attach(device_t dev)
+{
+	if (rtas_token_lookup("get-time-of-day") != -1)
+		clock_register(dev, 2000);
+	
+	EVENTHANDLER_REGISTER(shutdown_final, rtas_shutdown, NULL,
+	    SHUTDOWN_PRI_LAST);
+
+	return (0);
+}
+
+static int
+rtas_gettime(device_t dev, struct timespec *ts) {
+	struct clocktime ct;
+	cell_t tod[8];
+	cell_t token;
+	int error;
+	
+	token = rtas_token_lookup("get-time-of-day");
+	if (token == -1)
+		return (ENXIO);
+	error = rtas_call_method(token, 0, 8, &tod[0], &tod[1], &tod[2],
+	    &tod[3], &tod[4], &tod[5], &tod[6], &tod[7]);
+	if (error < 0)
+		return (ENXIO);
+	if (tod[0] != 0)
+		return ((tod[0] == -1) ? ENXIO : EAGAIN);
+
+	ct.year = tod[1];
+	ct.mon  = tod[2];
+	ct.day  = tod[3];
+	ct.hour = tod[4];
+	ct.min  = tod[5];
+	ct.sec  = tod[6];
+	ct.nsec = tod[7];
+
+	return (clock_ct_to_ts(&ct, ts));
+}
+
+static int
+rtas_settime(device_t dev, struct timespec *ts)
+{
+	struct clocktime ct;
+	cell_t token, status;
+	int error;
+	
+	token = rtas_token_lookup("set-time-of-day");
+	if (token == -1)
+		return (ENXIO);
+
+	clock_ts_to_ct(ts, &ct);
+	error = rtas_call_method(token, 7, 1, ct.year, ct.mon, ct.day, ct.hour,
+	    ct.min, ct.sec, ct.nsec, &status);
+	if (error < 0)
+		return (ENXIO);
+	if (status != 0)
+		return (((int)status < 0) ? ENXIO : EAGAIN);
+
+	return (0);
+}
+
+static void
+rtas_shutdown(void *arg, int howto)
+{
+	cell_t token, status;
+	
+	if (howto & RB_HALT) {
+		token = rtas_token_lookup("power-off");
+		if (token == -1)
+			return;
+
+		rtas_call_method(token, 2, 1, 0, 0, &status);
+	} else {
+		token = rtas_token_lookup("system-reboot");
+		if (token == -1)
+			return;
+
+		rtas_call_method(token, 0, 1, &status);
+	}
+}
+


Property changes on: trunk/sys/powerpc/pseries/rtas_dev.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/rtas_pci.c
===================================================================
--- trunk/sys/powerpc/pseries/rtas_pci.c	                        (rev 0)
+++ trunk/sys/powerpc/pseries/rtas_pci.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,206 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/pseries/rtas_pci.c 266160 2014-05-15 17:30:16Z ian $");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+#include <machine/rtas.h>
+
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <powerpc/ofw/ofw_pci.h>
+#include <powerpc/pseries/plpar_iommu.h>
+
+#include "pcib_if.h"
+#include "iommu_if.h"
+
+/*
+ * Device interface.
+ */
+static int		rtaspci_probe(device_t);
+static int		rtaspci_attach(device_t);
+
+/*
+ * pcib interface.
+ */
+static u_int32_t	rtaspci_read_config(device_t, u_int, u_int, u_int,
+			    u_int, int);
+static void		rtaspci_write_config(device_t, u_int, u_int, u_int,
+			    u_int, u_int32_t, int);
+
+/*
+ * Driver methods.
+ */
+static device_method_t	rtaspci_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		rtaspci_probe),
+	DEVMETHOD(device_attach,	rtaspci_attach),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_read_config,	rtaspci_read_config),
+	DEVMETHOD(pcib_write_config,	rtaspci_write_config),
+
+	DEVMETHOD_END
+};
+
+struct rtaspci_softc {
+	struct ofw_pci_softc	pci_sc;
+
+	cell_t			read_pci_config, write_pci_config;
+	cell_t			ex_read_pci_config, ex_write_pci_config;
+	int			sc_extended_config;
+};
+
+static devclass_t	rtaspci_devclass;
+DEFINE_CLASS_1(pcib, rtaspci_driver, rtaspci_methods,
+    sizeof(struct rtaspci_softc), ofw_pci_driver);
+DRIVER_MODULE(rtaspci, ofwbus, rtaspci_driver, rtaspci_devclass, 0, 0);
+
+static int
+rtaspci_probe(device_t dev)
+{
+	const char	*type;
+
+	if (!rtas_exists())
+		return (ENXIO);
+
+	type = ofw_bus_get_type(dev);
+
+	if (OF_getproplen(ofw_bus_get_node(dev), "used-by-rtas") < 0)
+		return (ENXIO);
+	if (type == NULL || strcmp(type, "pci") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "RTAS Host-PCI bridge");
+	return (BUS_PROBE_GENERIC);
+}
+
+static int
+rtaspci_attach(device_t dev)
+{
+	struct		rtaspci_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	sc->read_pci_config = rtas_token_lookup("read-pci-config");
+	sc->write_pci_config = rtas_token_lookup("write-pci-config");
+	sc->ex_read_pci_config = rtas_token_lookup("ibm,read-pci-config");
+	sc->ex_write_pci_config = rtas_token_lookup("ibm,write-pci-config");
+
+	sc->sc_extended_config = 0;
+	OF_getprop(ofw_bus_get_node(dev), "ibm,pci-config-space-type",
+	    &sc->sc_extended_config, sizeof(sc->sc_extended_config));
+
+	return (ofw_pci_attach(dev));
+}
+
+static uint32_t
+rtaspci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
+    int width)
+{
+	struct rtaspci_softc *sc;
+	uint32_t retval = 0xffffffff;
+	uint32_t config_addr;
+	int error, pcierror;
+
+	sc = device_get_softc(dev);
+	
+	config_addr = ((bus & 0xff) << 16) | ((slot & 0x1f) << 11) |
+	    ((func & 0x7) << 8) | (reg & 0xff);
+	if (sc->sc_extended_config)
+		config_addr |= (reg & 0xf00) << 16;
+		
+	if (sc->ex_read_pci_config != -1)
+		error = rtas_call_method(sc->ex_read_pci_config, 4, 2,
+		    config_addr, sc->pci_sc.sc_pcir.phys_hi,
+		    sc->pci_sc.sc_pcir.phys_mid, width, &pcierror, &retval);
+	else
+		error = rtas_call_method(sc->read_pci_config, 2, 2,
+		    config_addr, width, &pcierror, &retval);
+
+	/* Sign-extend output */
+	switch (width) {
+	case 1:
+		retval = (int32_t)(int8_t)(retval);
+		break;
+	case 2:
+		retval = (int32_t)(int16_t)(retval);
+		break;
+	}
+	
+	if (error < 0 || pcierror != 0)
+		retval = 0xffffffff;
+
+	return (retval);
+}
+
+static void
+rtaspci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+    u_int reg, uint32_t val, int width)
+{
+	struct rtaspci_softc *sc;
+	uint32_t config_addr;
+	int pcierror;
+
+	sc = device_get_softc(dev);
+	
+	config_addr = ((bus & 0xff) << 16) | ((slot & 0x1f) << 11) |
+	    ((func & 0x7) << 8) | (reg & 0xff);
+	if (sc->sc_extended_config)
+		config_addr |= (reg & 0xf00) << 16;
+		
+	if (sc->ex_write_pci_config != -1)
+		rtas_call_method(sc->ex_write_pci_config, 5, 1, config_addr,
+		    sc->pci_sc.sc_pcir.phys_hi, sc->pci_sc.sc_pcir.phys_mid,
+		    width, val, &pcierror);
+	else
+		rtas_call_method(sc->write_pci_config, 3, 1, config_addr,
+		    width, val, &pcierror);
+}
+


Property changes on: trunk/sys/powerpc/pseries/rtas_pci.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/vdevice.c
===================================================================
--- trunk/sys/powerpc/pseries/vdevice.c	                        (rev 0)
+++ trunk/sys/powerpc/pseries/vdevice.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,214 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/pseries/vdevice.c 273675 2014-10-26 04:01:57Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <powerpc/pseries/plpar_iommu.h>
+
+#include "iommu_if.h"
+
+static int	vdevice_probe(device_t);
+static int	vdevice_attach(device_t);
+static const struct ofw_bus_devinfo *vdevice_get_devinfo(device_t dev,
+    device_t child);
+static int	vdevice_print_child(device_t dev, device_t child);
+static struct resource_list *vdevice_get_resource_list(device_t, device_t);
+static bus_dma_tag_t vdevice_get_dma_tag(device_t dev, device_t child);
+
+/*
+ * VDevice devinfo
+ */
+struct vdevice_devinfo {
+	struct ofw_bus_devinfo mdi_obdinfo;
+	struct resource_list mdi_resources;
+	bus_dma_tag_t mdi_dma_tag;
+};
+
+static device_method_t vdevice_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		vdevice_probe),
+	DEVMETHOD(device_attach,	vdevice_attach),
+
+	/* Bus interface */
+	DEVMETHOD(bus_add_child,	bus_generic_add_child),
+	DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
+	DEVMETHOD(bus_print_child,	vdevice_print_child),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+	DEVMETHOD(bus_alloc_resource,	bus_generic_rl_alloc_resource),
+	DEVMETHOD(bus_release_resource,	bus_generic_rl_release_resource),
+	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+	DEVMETHOD(bus_get_resource_list, vdevice_get_resource_list),
+
+	/* ofw_bus interface */
+	DEVMETHOD(ofw_bus_get_devinfo,	vdevice_get_devinfo),
+	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
+	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
+	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
+	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
+	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
+
+	/* IOMMU interface */
+	DEVMETHOD(bus_get_dma_tag,	vdevice_get_dma_tag),
+	DEVMETHOD(iommu_map,		phyp_iommu_map),
+	DEVMETHOD(iommu_unmap,		phyp_iommu_unmap),
+
+	DEVMETHOD_END
+};
+
+static driver_t vdevice_driver = {
+	"vdevice",
+	vdevice_methods,
+	0
+};
+
+static devclass_t vdevice_devclass;
+
+DRIVER_MODULE(vdevice, ofwbus, vdevice_driver, vdevice_devclass, 0, 0);
+
+static int 
+vdevice_probe(device_t dev) 
+{
+	const char	*name;
+
+	name = ofw_bus_get_name(dev);
+
+	if (name == NULL || strcmp(name, "vdevice") != 0)
+		return (ENXIO);
+
+	if (!ofw_bus_is_compatible(dev, "IBM,vdevice"))
+		return (ENXIO);
+
+	device_set_desc(dev, "POWER Hypervisor Virtual Device Root");
+
+	return (0);
+}
+
+static int 
+vdevice_attach(device_t dev) 
+{
+	phandle_t root, child;
+	device_t cdev;
+	struct vdevice_devinfo *dinfo;
+
+	root = ofw_bus_get_node(dev);
+
+	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
+		dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO);
+
+                if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo,
+		    child) != 0) {
+                        free(dinfo, M_DEVBUF);
+                        continue;
+                }
+		resource_list_init(&dinfo->mdi_resources);
+
+		ofw_bus_intr_to_rl(dev, child, &dinfo->mdi_resources);
+
+                cdev = device_add_child(dev, NULL, -1);
+                if (cdev == NULL) {
+                        device_printf(dev, "<%s>: device_add_child failed\n",
+                            dinfo->mdi_obdinfo.obd_name);
+                        ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
+                        free(dinfo, M_DEVBUF);
+                        continue;
+                }
+		device_set_ivars(cdev, dinfo);
+	}
+
+	return (bus_generic_attach(dev));
+}
+
+static const struct ofw_bus_devinfo *
+vdevice_get_devinfo(device_t dev, device_t child) 
+{
+	return (device_get_ivars(child));	
+}
+
+static int
+vdevice_print_child(device_t dev, device_t child)
+{
+	struct vdevice_devinfo *dinfo;
+	struct resource_list *rl;
+	int retval = 0;
+
+	dinfo = device_get_ivars(child);
+	rl = &dinfo->mdi_resources;
+
+	retval += bus_print_child_header(dev, child);
+
+	retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+
+	retval += bus_print_child_footer(dev, child);
+
+	return (retval);
+}
+
+static struct resource_list *
+vdevice_get_resource_list (device_t dev, device_t child)
+{
+        struct vdevice_devinfo *dinfo;
+
+        dinfo = device_get_ivars(child);
+        return (&dinfo->mdi_resources);
+}
+
+static bus_dma_tag_t
+vdevice_get_dma_tag(device_t dev, device_t child)
+{
+	struct vdevice_devinfo *dinfo;
+	while (child != NULL && device_get_parent(child) != dev)
+		child = device_get_parent(child);
+        dinfo = device_get_ivars(child);
+
+	if (dinfo->mdi_dma_tag == NULL) {
+		bus_dma_tag_create(bus_get_dma_tag(dev),
+		    1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
+		    NULL, NULL, BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED,
+		    BUS_SPACE_MAXSIZE, 0, NULL, NULL, &dinfo->mdi_dma_tag);
+		phyp_iommu_set_dma_tag(dev, child, dinfo->mdi_dma_tag);
+	}
+
+        return (dinfo->mdi_dma_tag);
+}
+


Property changes on: trunk/sys/powerpc/pseries/vdevice.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/pseries/xics.c
===================================================================
--- trunk/sys/powerpc/pseries/xics.c	                        (rev 0)
+++ trunk/sys/powerpc/pseries/xics.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,324 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2011 Nathan Whitehorn
+ *
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/pseries/xics.c 266160 2014-05-15 17:30:16Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/rtas.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "phyp-hvcall.h"
+#include "pic_if.h"
+
+#define XICP_PRIORITY	5	/* Random non-zero number */
+#define XICP_IPI	2
+#define MAX_XICP_IRQS	(1<<24)	/* 24-bit XIRR field */
+
+static int	xicp_probe(device_t);
+static int	xicp_attach(device_t);
+static int	xics_probe(device_t);
+static int	xics_attach(device_t);
+
+static void	xicp_bind(device_t dev, u_int irq, cpuset_t cpumask);
+static void	xicp_dispatch(device_t, struct trapframe *);
+static void	xicp_enable(device_t, u_int, u_int);
+static void	xicp_eoi(device_t, u_int);
+static void	xicp_ipi(device_t, u_int);
+static void	xicp_mask(device_t, u_int);
+static void	xicp_unmask(device_t, u_int);
+
+static device_method_t  xicp_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		xicp_probe),
+	DEVMETHOD(device_attach,	xicp_attach),
+
+	/* PIC interface */
+	DEVMETHOD(pic_bind,		xicp_bind),
+	DEVMETHOD(pic_dispatch,		xicp_dispatch),
+	DEVMETHOD(pic_enable,		xicp_enable),
+	DEVMETHOD(pic_eoi,		xicp_eoi),
+	DEVMETHOD(pic_ipi,		xicp_ipi),
+	DEVMETHOD(pic_mask,		xicp_mask),
+	DEVMETHOD(pic_unmask,		xicp_unmask),
+
+	{ 0, 0 },
+};
+
+static device_method_t  xics_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		xics_probe),
+	DEVMETHOD(device_attach,	xics_attach),
+
+	{ 0, 0 },
+};
+
+struct xicp_softc {
+	struct mtx sc_mtx;
+
+	int ibm_int_on;
+	int ibm_int_off;
+	int ibm_get_xive;
+	int ibm_set_xive;
+
+	/* XXX: inefficient -- hash table? tree? */
+	struct {
+		int irq;
+		int vector;
+	} intvecs[256];
+	int nintvecs;
+};
+
+static driver_t xicp_driver = {
+	"xicp",
+	xicp_methods,
+	sizeof(struct xicp_softc)
+};
+
+static driver_t xics_driver = {
+	"xics",
+	xics_methods,
+	0
+};
+
+static devclass_t xicp_devclass;
+static devclass_t xics_devclass;
+
+EARLY_DRIVER_MODULE(xicp, ofwbus, xicp_driver, xicp_devclass, 0, 0,
+    BUS_PASS_INTERRUPT-1);
+EARLY_DRIVER_MODULE(xics, ofwbus, xics_driver, xics_devclass, 0, 0,
+    BUS_PASS_INTERRUPT);
+
+static int
+xicp_probe(device_t dev)
+{
+	if (ofw_bus_get_name(dev) == NULL || strcmp(ofw_bus_get_name(dev),
+	    "interrupt-controller") != 0)
+		return (ENXIO);
+
+	if (!ofw_bus_is_compatible(dev, "ibm,ppc-xicp"))
+		return (ENXIO);
+
+	device_set_desc(dev, "PAPR virtual interrupt controller");
+	return (BUS_PROBE_GENERIC);
+}
+
+static int
+xics_probe(device_t dev)
+{
+	if (ofw_bus_get_name(dev) == NULL || strcmp(ofw_bus_get_name(dev),
+	    "interrupt-controller") != 0)
+		return (ENXIO);
+
+	if (!ofw_bus_is_compatible(dev, "ibm,ppc-xics"))
+		return (ENXIO);
+
+	device_set_desc(dev, "PAPR virtual interrupt source");
+	return (BUS_PROBE_GENERIC);
+}
+
+static int
+xicp_attach(device_t dev)
+{
+	struct xicp_softc *sc = device_get_softc(dev);
+	phandle_t phandle = ofw_bus_get_node(dev);
+
+	mtx_init(&sc->sc_mtx, "XICP", NULL, MTX_DEF);
+	sc->nintvecs = 0;
+
+	sc->ibm_int_on = rtas_token_lookup("ibm,int-on");
+	sc->ibm_int_off = rtas_token_lookup("ibm,int-off");
+	sc->ibm_set_xive = rtas_token_lookup("ibm,set-xive");
+	sc->ibm_get_xive = rtas_token_lookup("ibm,get-xive");
+
+	if (OF_getproplen(phandle, "ibm,phandle") > 0)
+		OF_getprop(phandle, "ibm,phandle", &phandle, sizeof(phandle));
+
+	powerpc_register_pic(dev, phandle, MAX_XICP_IRQS,
+	    1 /* Number of IPIs */, FALSE);
+	root_pic = dev;
+
+	return (0);
+}
+
+static int
+xics_attach(device_t dev)
+{
+	phandle_t phandle = ofw_bus_get_node(dev);
+
+	if (OF_getproplen(phandle, "ibm,phandle") > 0)
+		OF_getprop(phandle, "ibm,phandle", &phandle, sizeof(phandle));
+
+	/* The XICP (root PIC) will handle all our interrupts */
+	powerpc_register_pic(root_pic, phandle, MAX_XICP_IRQS,
+	    1 /* Number of IPIs */, FALSE);
+
+	return (0);
+}
+
+/*
+ * PIC I/F methods.
+ */
+
+static void
+xicp_bind(device_t dev, u_int irq, cpuset_t cpumask)
+{
+	struct xicp_softc *sc = device_get_softc(dev);
+	cell_t status, cpu;
+
+	/*
+	 * This doesn't appear to actually support affinity groups, so just
+	 * use the first CPU.
+	 */
+	CPU_FOREACH(cpu)
+		if (CPU_ISSET(cpu, &cpumask)) break;
+
+	rtas_call_method(sc->ibm_set_xive, 3, 1, irq, cpu, XICP_PRIORITY,
+	    &status);
+}
+
+static void
+xicp_dispatch(device_t dev, struct trapframe *tf)
+{
+	struct xicp_softc *sc;
+	uint64_t xirr, junk;
+	int i;
+
+	sc = device_get_softc(dev);
+	for (;;) {
+		/* Return value in R4, use the PFT call */
+		phyp_pft_hcall(H_XIRR, 0, 0, 0, 0, &xirr, &junk, &junk);
+		xirr &= 0x00ffffff;
+
+		if (xirr == 0) { /* No more pending interrupts? */
+			phyp_hcall(H_CPPR, (uint64_t)0xff);
+			break;
+		}
+		if (xirr == XICP_IPI) {		/* Magic number for IPIs */
+			xirr = MAX_XICP_IRQS;	/* Map to FreeBSD magic */
+			phyp_hcall(H_IPI, (uint64_t)(PCPU_GET(cpuid)),
+			    0xff); /* Clear IPI */
+		}
+
+		/* XXX: super inefficient */
+		for (i = 0; i < sc->nintvecs; i++) {
+			if (sc->intvecs[i].irq == xirr)
+				break;
+		}
+
+		KASSERT(i < sc->nintvecs, ("Unmapped XIRR"));
+		powerpc_dispatch_intr(sc->intvecs[i].vector, tf);
+	}
+}
+
+static void
+xicp_enable(device_t dev, u_int irq, u_int vector)
+{
+	struct xicp_softc *sc;
+	cell_t status, cpu;
+
+	sc = device_get_softc(dev);
+
+	KASSERT(sc->nintvecs + 1 < sizeof(sc->intvecs)/sizeof(sc->intvecs[0]),
+	    ("Too many XICP interrupts"));
+
+	mtx_lock(&sc->sc_mtx);
+	sc->intvecs[sc->nintvecs].irq = irq;
+	sc->intvecs[sc->nintvecs].vector = vector;
+	mb();
+	sc->nintvecs++;
+	mtx_unlock(&sc->sc_mtx);
+
+	/* IPIs are also enabled */
+	if (irq == MAX_XICP_IRQS)
+		return;
+
+	/* Bind to this CPU to start: distrib. ID is last entry in gserver# */
+	cpu = PCPU_GET(cpuid);
+	rtas_call_method(sc->ibm_set_xive, 3, 1, irq, cpu, XICP_PRIORITY,
+	    &status);
+	xicp_unmask(dev, irq);
+}
+
+static void
+xicp_eoi(device_t dev, u_int irq)
+{
+	uint64_t xirr;
+
+	if (irq == MAX_XICP_IRQS) /* Remap IPI interrupt to internal value */
+		irq = XICP_IPI;
+	xirr = irq | (XICP_PRIORITY << 24);
+
+	phyp_hcall(H_EOI, xirr);
+}
+
+static void
+xicp_ipi(device_t dev, u_int cpu)
+{
+
+	phyp_hcall(H_IPI, (uint64_t)cpu, XICP_PRIORITY);
+}
+
+static void
+xicp_mask(device_t dev, u_int irq)
+{
+	struct xicp_softc *sc = device_get_softc(dev);
+	cell_t status;
+
+	if (irq == MAX_XICP_IRQS)
+		return;
+
+	rtas_call_method(sc->ibm_int_off, 1, 1, irq, &status);
+}
+
+static void
+xicp_unmask(device_t dev, u_int irq)
+{
+	struct xicp_softc *sc = device_get_softc(dev);
+	cell_t status;
+
+	if (irq == MAX_XICP_IRQS)
+		return;
+
+	rtas_call_method(sc->ibm_int_on, 1, 1, irq, &status);
+}
+


Property changes on: trunk/sys/powerpc/pseries/xics.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/psim/ata_iobus.c
===================================================================
--- trunk/sys/powerpc/psim/ata_iobus.c	                        (rev 0)
+++ trunk/sys/powerpc/psim/ata_iobus.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,255 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2002 by Peter Grehan. 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. 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/psim/ata_iobus.c 249213 2013-04-06 19:12:49Z marius $");
+
+/*
+ * PSIM local bus ATA controller
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/sema.h>
+#include <sys/taskqueue.h>
+#include <machine/stdarg.h>
+#include <vm/uma.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/ata.h>
+#include <dev/ata/ata-all.h>
+#include <ata_if.h>
+
+#include <dev/ofw/openfirm.h>
+#include <powerpc/psim/iobusvar.h>
+
+/*
+ * Define the iobus ata bus attachment. This creates a pseudo-bus that
+ * the ATA device can be attached to
+ */
+static  int  ata_iobus_attach(device_t dev);
+static  int  ata_iobus_probe(device_t dev);
+static  int  ata_iobus_print_child(device_t dev, device_t child);
+struct resource *ata_iobus_alloc_resource(device_t, device_t, int, int *,
+					  u_long, u_long, u_long, u_int);
+static int ata_iobus_release_resource(device_t, device_t, int, int,
+				      struct resource *);
+
+static device_method_t ata_iobus_methods[] = {
+        /* Device interface */
+	DEVMETHOD(device_probe,		ata_iobus_probe),
+	DEVMETHOD(device_attach,        ata_iobus_attach),
+	DEVMETHOD(device_shutdown,      bus_generic_shutdown),
+	DEVMETHOD(device_suspend,       bus_generic_suspend),
+	DEVMETHOD(device_resume,        bus_generic_resume),
+
+	/* Bus methods */
+	DEVMETHOD(bus_print_child,          ata_iobus_print_child),
+	DEVMETHOD(bus_alloc_resource,       ata_iobus_alloc_resource),
+	DEVMETHOD(bus_release_resource,     ata_iobus_release_resource),
+	DEVMETHOD(bus_activate_resource,    bus_generic_activate_resource),
+	DEVMETHOD(bus_deactivate_resource,  bus_generic_deactivate_resource),
+	DEVMETHOD(bus_setup_intr,           bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,        bus_generic_teardown_intr),
+
+	DEVMETHOD_END
+};
+
+static driver_t ata_iobus_driver = {
+	"ataiobus",
+	ata_iobus_methods,
+	0,
+};
+
+static devclass_t ata_iobus_devclass;
+
+DRIVER_MODULE(ataiobus, iobus, ata_iobus_driver, ata_iobus_devclass, NULL,
+    NULL);
+MODULE_DEPEND(ata, ata, 1, 1, 1);
+
+static int
+ata_iobus_probe(device_t dev)
+{
+	char *type = iobus_get_name(dev);
+
+	if (strncmp(type, "ata", 3) != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "PSIM ATA Controller");
+	return (0);
+}
+
+
+static int
+ata_iobus_attach(device_t dev)
+{
+	/*
+	 * Add a single child per controller. Should be able
+	 * to add two
+	 */
+	device_add_child(dev, "ata", -1);
+	return (bus_generic_attach(dev));
+}
+
+
+static int
+ata_iobus_print_child(device_t dev, device_t child)
+{
+	int retval = 0;
+
+	retval += bus_print_child_header(dev, child);
+	/* irq ? */
+	retval += bus_print_child_footer(dev, child);
+
+	return (retval);
+}
+
+
+struct resource *
+ata_iobus_alloc_resource(device_t dev, device_t child, int type, int *rid,
+			 u_long start, u_long end, u_long count, u_int flags)
+{
+	struct resource *res = NULL;
+	int myrid;
+	u_int *ofw_regs;
+
+	ofw_regs = iobus_get_regs(dev);
+
+	/*
+	 * The reg array for the PSIM ata device has 6 start/size entries:
+	 *  0 - unused
+	 *  1/2/3 - unused
+	 *  4/5/6 - primary command
+	 *  7/8/9 - secondary command
+	 *  10/11/12 - primary control
+	 *  13/14/15 - secondary control
+	 *  16/17/18 - primary/secondary dma registers, unimplemented
+	 *
+	 *  The resource values are calculated from these registers
+	 */
+	if (type == SYS_RES_IOPORT) {
+		switch (*rid) {
+		case ATA_IOADDR_RID:
+			myrid = 0;
+			start = ofw_regs[4];
+			end = start + ATA_IOSIZE - 1;
+			count = ATA_IOSIZE;
+			res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
+						 SYS_RES_MEMORY, &myrid,
+						 start, end, count, flags);
+			break;
+
+		case ATA_CTLADDR_RID:
+			myrid = 0;
+			start = ofw_regs[10];
+			end = start + ATA_CTLIOSIZE - 1;
+			count = ATA_CTLIOSIZE;
+			res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
+						 SYS_RES_MEMORY, &myrid,
+						 start, end, count, flags);
+			break;
+
+		case ATA_BMADDR_RID:
+			/* DMA not properly supported by psim */
+			break;
+		}
+		return (res);
+
+	} else if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
+		/*
+		 * Pass this on to the parent
+		 */
+		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
+					   SYS_RES_IRQ, rid, 0, ~0, 1, flags));
+
+	} else {
+		return (NULL);
+	}
+}
+
+
+static int
+ata_iobus_release_resource(device_t dev, device_t child, int type, int rid,
+			   struct resource *r)
+{
+	/* no hotplug... */
+	return (0);
+}
+
+
+/*
+ * Define the actual ATA device. This is a sub-bus to the ata-iobus layer
+ * to allow the higher layer bus to massage the resource allocation.
+ */
+
+static  int  ata_iobus_sub_probe(device_t dev);
+static  int  ata_iobus_sub_setmode(device_t dev, int target, int mode);
+
+static device_method_t ata_iobus_sub_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,     ata_iobus_sub_probe),
+	DEVMETHOD(device_attach,    ata_attach),
+	DEVMETHOD(device_detach,    ata_detach),
+	DEVMETHOD(device_resume,    ata_resume),
+
+	/* ATA interface */
+	DEVMETHOD(ata_setmode,	    ata_iobus_sub_setmode),
+	DEVMETHOD_END
+};
+
+static driver_t ata_iobus_sub_driver = {
+	"ata",
+	ata_iobus_sub_methods,
+	sizeof(struct ata_channel),
+};
+
+DRIVER_MODULE(ata, ataiobus, ata_iobus_sub_driver, ata_devclass, NULL, NULL);
+
+static int
+ata_iobus_sub_probe(device_t dev)
+{
+	struct ata_channel *ch = device_get_softc(dev);
+
+	/* Only a single unit per controller thus far */
+	ch->unit = 0;
+	ch->flags = (ATA_USE_16BIT|ATA_NO_SLAVE);
+	ata_generic_hw(dev);
+
+	return ata_probe(dev);
+}
+
+static int
+ata_iobus_sub_setmode(device_t parent, int target, int mode)
+{
+	/* Only ever PIO mode here... */
+	return (ATA_PIO);
+}


Property changes on: trunk/sys/powerpc/psim/ata_iobus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/psim/iobus.c
===================================================================
--- trunk/sys/powerpc/psim/iobus.c	                        (rev 0)
+++ trunk/sys/powerpc/psim/iobus.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,413 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2002 by Peter Grehan. 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/psim/iobus.c 266160 2014-05-15 17:30:16Z ian $
+ */
+
+/*
+ *  PSIM 'iobus' local bus. Should be set up in the device tree like:
+ *
+ *     /iobus at 0x80000000/name psim-iobus
+ *
+ *  Code borrowed from various nexus.c and uninorth.c :-)
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/vmparam.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/pmap.h>
+
+#include <machine/resource.h>
+
+#include <powerpc/psim/iobusvar.h>
+
+struct iobus_softc {
+	phandle_t     sc_node;
+	vm_offset_t   sc_addr;
+	vm_offset_t   sc_size;
+	struct        rman sc_mem_rman;
+};
+
+static MALLOC_DEFINE(M_IOBUS, "iobus", "iobus device information");
+
+static int  iobus_probe(device_t);
+static int  iobus_attach(device_t);
+static int  iobus_print_child(device_t dev, device_t child);
+static void iobus_probe_nomatch(device_t, device_t);
+static int  iobus_read_ivar(device_t, device_t, int, uintptr_t *);
+static int  iobus_write_ivar(device_t, device_t, int, uintptr_t);
+static struct   resource *iobus_alloc_resource(device_t, device_t, int, int *,
+					       u_long, u_long, u_long, u_int);
+static int  iobus_activate_resource(device_t, device_t, int, int,
+				    struct resource *);
+static int  iobus_deactivate_resource(device_t, device_t, int, int,
+				      struct resource *);
+static int  iobus_release_resource(device_t, device_t, int, int,
+				   struct resource *);
+
+/*
+ * Bus interface definition
+ */
+static device_method_t iobus_methods[] = {
+        /* Device interface */
+        DEVMETHOD(device_probe,         iobus_probe),
+        DEVMETHOD(device_attach,        iobus_attach),
+        DEVMETHOD(device_detach,        bus_generic_detach),
+        DEVMETHOD(device_shutdown,      bus_generic_shutdown),
+        DEVMETHOD(device_suspend,       bus_generic_suspend),
+        DEVMETHOD(device_resume,        bus_generic_resume),
+
+        /* Bus interface */
+        DEVMETHOD(bus_print_child,      iobus_print_child),
+        DEVMETHOD(bus_probe_nomatch,    iobus_probe_nomatch),
+        DEVMETHOD(bus_read_ivar,        iobus_read_ivar),
+        DEVMETHOD(bus_write_ivar,       iobus_write_ivar),
+        DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
+        DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
+
+        DEVMETHOD(bus_alloc_resource,   iobus_alloc_resource),
+        DEVMETHOD(bus_release_resource, iobus_release_resource),
+        DEVMETHOD(bus_activate_resource, iobus_activate_resource),
+        DEVMETHOD(bus_deactivate_resource, iobus_deactivate_resource),
+
+        { 0, 0 }
+};
+
+static driver_t iobus_driver = {
+        "iobus",
+        iobus_methods,
+        sizeof(struct iobus_softc)
+};
+
+devclass_t iobus_devclass;
+
+DRIVER_MODULE(iobus, ofwbus, iobus_driver, iobus_devclass, 0, 0);
+
+static int
+iobus_probe(device_t dev)
+{
+	const char *type = ofw_bus_get_name(dev);
+
+	if (strcmp(type, "psim-iobus") != 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "PSIM local bus");
+	return (0);	
+}
+
+/*
+ * Add interrupt/addr range to the dev's resource list if present
+ */
+static void
+iobus_add_intr(phandle_t devnode, struct iobus_devinfo *dinfo)
+{
+	u_int intr = -1;
+
+	if (OF_getprop(devnode, "interrupt", &intr, sizeof(intr)) != -1) {
+		resource_list_add(&dinfo->id_resources, 
+				  SYS_RES_IRQ, 0, intr, intr, 1);
+	}
+	dinfo->id_interrupt = intr;
+}
+
+
+static void
+iobus_add_reg(phandle_t devnode, struct iobus_devinfo *dinfo,
+	      vm_offset_t iobus_off)
+{
+	u_int size;
+	int i;
+
+	size = OF_getprop(devnode, "reg", dinfo->id_reg,sizeof(dinfo->id_reg));
+
+	if (size != -1) {
+		dinfo->id_nregs = size / (sizeof(dinfo->id_reg[0]));
+
+		for (i = 0; i < dinfo->id_nregs; i+= 3) {
+			/*
+			 * Scale the absolute addresses back to iobus
+			 * relative offsets. This is to better simulate
+			 * macio
+			 */
+			dinfo->id_reg[i+1] -= iobus_off;
+
+			resource_list_add(&dinfo->id_resources,
+					  SYS_RES_MEMORY, 0,
+					  dinfo->id_reg[i+1], 
+					  dinfo->id_reg[i+1] + 
+					      dinfo->id_reg[i+2],
+					  dinfo->id_reg[i+2]);
+		}
+	}
+}
+
+
+static int
+iobus_attach(device_t dev)
+{
+	struct iobus_softc *sc;
+        struct iobus_devinfo *dinfo;
+        phandle_t  root;
+        phandle_t  child;
+        device_t   cdev;
+        char *name;
+	u_int reg[2];
+	int size;
+
+	sc = device_get_softc(dev);
+	sc->sc_node = ofw_bus_get_node(dev);
+
+	/*
+	 * Find the base addr/size of the iobus, and initialize the
+	 * resource manager
+	 */
+	size = OF_getprop(sc->sc_node, "reg", reg, sizeof(reg));
+	if (size == sizeof(reg)) {
+		sc->sc_addr = reg[0];
+		sc->sc_size = reg[1];
+	} else {
+		return (ENXIO);
+	}
+
+	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+        sc->sc_mem_rman.rm_descr = "IOBus Device Memory";
+        if (rman_init(&sc->sc_mem_rman) != 0) {
+		device_printf(dev,
+                    "failed to init mem range resources\n");
+                return (ENXIO);
+	}
+	rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size);
+
+        /*
+         * Iterate through the sub-devices
+         */
+        root = sc->sc_node;
+
+        for (child = OF_child(root); child != 0; child = OF_peer(child)) {
+                OF_getprop_alloc(child, "name", 1, (void **)&name);
+
+                cdev = device_add_child(dev, NULL, -1);
+                if (cdev != NULL) {
+                        dinfo = malloc(sizeof(*dinfo), M_IOBUS, M_WAITOK);
+			memset(dinfo, 0, sizeof(*dinfo));
+			resource_list_init(&dinfo->id_resources);
+                        dinfo->id_node = child;
+                        dinfo->id_name = name;
+			iobus_add_intr(child, dinfo);
+			iobus_add_reg(child, dinfo, sc->sc_addr);
+                        device_set_ivars(cdev, dinfo);
+                } else {
+                        free(name, M_OFWPROP);
+                }
+        }
+
+        return (bus_generic_attach(dev));
+}
+
+
+static int
+iobus_print_child(device_t dev, device_t child)
+{
+        struct iobus_devinfo *dinfo;
+        struct resource_list *rl;
+        int retval = 0;
+	
+	dinfo = device_get_ivars(child);
+        rl = &dinfo->id_resources;
+
+	retval += bus_print_child_header(dev, child);
+	
+        retval += printf(" offset 0x%x", dinfo->id_reg[1]);
+        retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+	
+        retval += bus_print_child_footer(dev, child);
+
+        return (retval);	
+}
+
+
+static void
+iobus_probe_nomatch(device_t dev, device_t child)
+{
+}
+
+
+static int
+iobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+        struct iobus_devinfo *dinfo;
+
+        if ((dinfo = device_get_ivars(child)) == 0)
+                return (ENOENT);
+
+        switch (which) {
+        case IOBUS_IVAR_NODE:
+                *result = dinfo->id_node;
+                break;
+        case IOBUS_IVAR_NAME:
+                *result = (uintptr_t)dinfo->id_name;
+                break;
+	case IOBUS_IVAR_NREGS:
+		*result = dinfo->id_nregs;
+		break;
+	case IOBUS_IVAR_REGS:
+		*result = (uintptr_t)dinfo->id_reg;
+		break;
+        default:
+                return (ENOENT);
+        }
+
+        return (0);
+}
+
+
+static int
+iobus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+        return (EINVAL);
+}
+
+
+static struct resource *
+iobus_alloc_resource(device_t bus, device_t child, int type, int *rid,
+		     u_long start, u_long end, u_long count, u_int flags)
+{
+	struct iobus_softc *sc;
+	int  needactivate;
+	struct  resource *rv;
+	struct  rman *rm;
+
+	sc = device_get_softc(bus);
+
+	needactivate = flags & RF_ACTIVE;
+	flags &= ~RF_ACTIVE;
+
+	switch (type) {
+	case SYS_RES_MEMORY:
+	case SYS_RES_IOPORT:
+		rm = &sc->sc_mem_rman;
+		break;
+	case SYS_RES_IRQ:
+		return (bus_alloc_resource(bus, type, rid, start, end, count,
+		    flags));
+	default:
+		device_printf(bus, "unknown resource request from %s\n",
+		    device_get_nameunit(child));
+		return (NULL);
+	}
+
+	rv = rman_reserve_resource(rm, start, end, count, flags, child);
+	if (rv == NULL) {
+		device_printf(bus, "failed to reserve resource for %s\n",
+			      device_get_nameunit(child));
+		return (NULL);
+	}
+
+	rman_set_rid(rv, *rid);
+
+	if (needactivate) {
+		if (bus_activate_resource(child, type, *rid, rv) != 0) {
+                        device_printf(bus,
+				      "failed to activate resource for %s\n",
+				      device_get_nameunit(child));
+			rman_release_resource(rv);
+			return (NULL);
+                }
+        }
+
+	return (rv);	
+}
+
+
+static int
+iobus_release_resource(device_t bus, device_t child, int type, int rid,
+		       struct resource *res)
+{
+	if (rman_get_flags(res) & RF_ACTIVE) {
+		int error = bus_deactivate_resource(child, type, rid, res);
+		if (error)
+			return error;
+	}
+
+	return (rman_release_resource(res));
+}
+
+
+static int
+iobus_activate_resource(device_t bus, device_t child, int type, int rid,
+			   struct resource *res)
+{
+	struct iobus_softc *sc;
+	void    *p;
+
+	sc = device_get_softc(bus);
+
+	if (type == SYS_RES_IRQ)
+                return (bus_activate_resource(bus, type, rid, res));
+
+	if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
+		p = pmap_mapdev((vm_offset_t)rman_get_start(res) + sc->sc_addr,
+				(vm_size_t)rman_get_size(res));
+		if (p == NULL)
+			return (ENOMEM);
+		rman_set_virtual(res, p);
+		rman_set_bustag(res, &bs_le_tag);
+		rman_set_bushandle(res, (u_long)p);
+	}
+
+	return (rman_activate_resource(res));
+}
+
+
+static int
+iobus_deactivate_resource(device_t bus, device_t child, int type, int rid,
+			  struct resource *res)
+{
+        /*
+         * If this is a memory resource, unmap it.
+         */
+        if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
+		u_int32_t psize;
+
+		psize = rman_get_size(res);
+		pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize);
+	}
+
+	return (rman_deactivate_resource(res));
+}


Property changes on: trunk/sys/powerpc/psim/iobus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/psim/iobusvar.h
===================================================================
--- trunk/sys/powerpc/psim/iobusvar.h	                        (rev 0)
+++ trunk/sys/powerpc/psim/iobusvar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,67 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2002 by Peter Grehan. 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/psim/iobusvar.h 139825 2005-01-07 02:29:27Z imp $
+ */
+
+#ifndef _PSIM_IOBUSVAR_H_
+#define _PSIM_IOBUSVAR_H_
+
+/* 
+ * Accessors for iobus devices
+ */
+
+enum iobus_ivars {
+        IOBUS_IVAR_NODE,
+        IOBUS_IVAR_NAME,
+	IOBUS_IVAR_NREGS,
+	IOBUS_IVAR_REGS,
+};
+
+#define IOBUS_ACCESSOR(var, ivar, type)                                 \
+        __BUS_ACCESSOR(iobus, var, IOBUS, ivar, type)
+
+IOBUS_ACCESSOR(node,            NODE,                   phandle_t)
+IOBUS_ACCESSOR(name,            NAME,                   char *)
+IOBUS_ACCESSOR(nregs,           NREGS,                  u_int)
+IOBUS_ACCESSOR(regs,            REGS,                   u_int *)
+
+#undef IOBUS_ACCESSOR
+
+/*
+ * Per-device structure.
+ */
+struct iobus_devinfo {
+        phandle_t  id_node;
+        char      *id_name;
+        int        id_interrupt;
+	u_int      id_nregs;
+	u_int      id_reg[24];
+        struct resource_list id_resources;
+};
+
+#endif /* _PSIM_IOBUSVAR_H_ */


Property changes on: trunk/sys/powerpc/psim/iobusvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/psim/openpic_iobus.c
===================================================================
--- trunk/sys/powerpc/psim/openpic_iobus.c	                        (rev 0)
+++ trunk/sys/powerpc/psim/openpic_iobus.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,120 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2003 by Peter Grehan. 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. 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.
+ *
+ */
+
+/*
+ * The psim iobus attachment for the OpenPIC interrupt controller.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/psim/openpic_iobus.c 218075 2011-01-29 20:58:38Z marcel $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <sys/rman.h>
+
+#include <machine/openpicvar.h>
+#include <powerpc/psim/iobusvar.h>
+
+#include "pic_if.h"
+
+/*
+ * PSIM IOBus interface
+ */
+static int	openpic_iobus_probe(device_t);
+static int	openpic_iobus_attach(device_t);
+
+static device_method_t  openpic_iobus_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		openpic_iobus_probe),
+	DEVMETHOD(device_attach,	openpic_iobus_attach),
+
+	/* PIC interface */
+	DEVMETHOD(pic_config,		openpic_config),
+	DEVMETHOD(pic_dispatch,		openpic_dispatch),
+	DEVMETHOD(pic_enable,		openpic_enable),
+	DEVMETHOD(pic_eoi,		openpic_eoi),
+	DEVMETHOD(pic_ipi,		openpic_ipi),
+	DEVMETHOD(pic_mask,		openpic_mask),
+	DEVMETHOD(pic_unmask,		openpic_unmask),
+
+	{ 0, 0 }
+};
+
+static driver_t openpic_iobus_driver = {
+	"openpic",
+	openpic_iobus_methods,
+	sizeof(struct openpic_softc)
+};
+
+DRIVER_MODULE(openpic, iobus, openpic_iobus_driver, openpic_devclass, 0, 0);
+
+static int
+openpic_iobus_probe(device_t dev)
+{
+	struct openpic_softc *sc;
+	char *name;
+
+	name = iobus_get_name(dev);
+	if (strcmp(name, "interrupt-controller") != 0)
+		return (ENXIO);
+
+	/*
+	 * The description was already printed out in the nexus
+	 * probe, so don't do it again here
+	 */
+	device_set_desc(dev, OPENPIC_DEVSTR);
+
+	sc = device_get_softc(dev);
+	sc->sc_psim = 1;
+
+	return (0);
+}
+
+static int
+openpic_iobus_attach(device_t dev)
+{
+
+	return (openpic_common_attach(dev, 0));
+}


Property changes on: trunk/sys/powerpc/psim/openpic_iobus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/psim/psim-tree
===================================================================
--- trunk/sys/powerpc/psim/psim-tree	                        (rev 0)
+++ trunk/sys/powerpc/psim/psim-tree	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,91 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/sys/powerpc/psim/psim-tree 125443 2004-02-04 13:23:05Z grehan $
+#
+# Simple psim h/w description
+#
+# The .gdbinit should contain something like:
+#
+#   target sim -e chirp -r 33554432 -f psim-tree
+#   load
+#
+#  (The -r option is the amount of physical RAM the simulator has)
+#
+
+/#address-cells 1
+/openprom/options/use-stdio? false
+#/openprom/options/strict-alignment? true
+
+/options
+	./output-device "psim-stdout
+
+#
+# Define the disk device alias so ofwd can identify it
+#
+/aliases
+	./ofwdisk "/phb at 0x70000000/ide at 1/disk at 0
+
+#
+# CPU definition. The phandle property is to help nexus.c locate the
+# interrupt controller.
+#
+/cpus/cpu at 0
+
+#
+# disk file, done via phb. maybe there's a simpler way.
+#
+/phb at 0x70000000
+        ./device_type "pci
+        ./name "pci
+        ./#address-cells 3
+        ./#size-cells 2
+        ./ranges ni0,0,0,0 0xc0000000 0x10000
+
+/phb at 0x70000000/ide at 1
+        ./device_type "ide
+        ./name "ide
+        ./assigned-addresses \
+                ni0,0,10,1f0 8 \
+                ni0,0,14,3f8 8 \
+                ni0,0,18,170 8 \
+                ni0,0,1c,378 8 \
+                ni0,0,20,200 8
+        ./reg \
+                1 0 \
+                i0,0,10,0 8 \
+                i0,0,18,0 8 \
+                i0,0,14,6 1 \
+                i0,0,1c,6 1 \
+                i0,0,20,0 8
+        ./ready-delay 1000
+
+/phb at 0x70000000/ide at 1/disk at 0/file "../image.iso
+
+#
+# I/O Bus
+#
+/iobus at 0x90000000
+	./name psim-iobus
+	./reg 0x90000000 0x20000000
+
+#
+# OpenPIC
+#
+/iobus at 0x90000000/opic at 0x90000000
+        ./name         interrupt-controller
+        ./device_type  open-pic
+        ./compatible   psim,open-pic
+        ./reg 0x90000000 0x40000
+        ./interrupt-ranges 0 256
+
+/iobus/opic > intr0 int /cpus/cpu at 0x0
+
+#
+# IDE1
+#
+#/iobus at 0x90000000/ide at 0x90052000
+#        ./name ata-4
+#        ./ioport 1
+#        ./device_type ata
+#        ./interrupt  12
+#        ./reg 0x90052000 8 0x90052010 8 0x90052020 8 0x90052030 1 0x90052040 1 0x90052050 8
+#/iobus at 0x90000000/ide at 0x90052000 > a irq12 /iobus/opic


Property changes on: trunk/sys/powerpc/psim/psim-tree
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/sys/powerpc/psim/uart_iobus.c
===================================================================
--- trunk/sys/powerpc/psim/uart_iobus.c	                        (rev 0)
+++ trunk/sys/powerpc/psim/uart_iobus.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,88 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright 2002 by Peter Grehan. 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. 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/psim/uart_iobus.c 160722 2006-07-26 19:39:55Z marcel $
+ */
+
+/*
+ * PSIM local bus 16550
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+#include <sys/tty.h>
+#include <machine/bus.h>
+#include <sys/timepps.h>
+
+#include <dev/ofw/openfirm.h>
+#include <powerpc/psim/iobusvar.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+
+static int uart_iobus_probe(device_t dev);
+
+static device_method_t uart_iobus_methods[] = {
+        /* Device interface */
+	DEVMETHOD(device_probe,		uart_iobus_probe),
+	DEVMETHOD(device_attach,	uart_bus_attach),
+	DEVMETHOD(device_detach,	uart_bus_detach),
+
+	{ 0, 0 }
+};
+
+static driver_t uart_iobus_driver = {
+	uart_driver_name,
+	uart_iobus_methods,
+	sizeof(struct uart_softc),
+};
+
+static int
+uart_iobus_probe(device_t dev)
+{
+	struct uart_softc *sc;
+	char *type;
+
+	type = iobus_get_name(dev);
+	if (strncmp(type, "com", 3) != 0)
+		return (ENXIO);
+
+	sc = device_get_softc(dev);
+	sc->sc_class = &uart_ns8250_class;
+
+	device_set_desc(dev, "PSIM serial port");
+	return (uart_bus_probe(dev, 0, 0, 0, 0));
+}
+
+DRIVER_MODULE(uart, iobus, uart_iobus_driver, uart_devclass, 0, 0);


Property changes on: trunk/sys/powerpc/psim/uart_iobus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/locore.S
===================================================================
--- trunk/sys/powerpc/wii/locore.S	                        (rev 0)
+++ trunk/sys/powerpc/wii/locore.S	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,132 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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.
+ *
+ * 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 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/wii/locore.S 244179 2012-12-13 06:42:44Z rpaulo $
+ */
+
+#include <machine/bat.h>
+/*
+ * When we are invoked from Wii loaders, the state of the MMU and the BAT
+ * mappings can vary.  In this file we try to reset the MMU to a state
+ * that lets us boot FreeBSD.
+ *
+ * N.B.: keep the BAT0 in sync with mmu_oea.c and never touch BAT1 later.
+ *
+ * This file is being included from aim/locore32.S.
+ */
+
+#define	MMU_REALMODE()				\
+	mfmsr	%r12;				\
+	rlwinm	%r12, %r12, 0, ~(PSL_DR|PSL_IR);\
+	sync;					\
+	bl	1f;				\
+1:						\
+	mflr    %r11;				\
+	clrlwi  %r11, %r11, 3;	/* XXX why? */	\
+	addi    %r11, %r11, 2f - 1b;		\
+	mtsrr0  %r11;				\
+	mtsrr1	%r12;	/* Disables the MMU */	\
+	isync;					\
+	rfi;					\
+2:
+
+#define	MMU_VIRTUALMODE()			\
+	bl	3f;				\
+3:						\
+	mflr	%r11;				\
+	addi	%r11, %r11, 4f - 3b;		\
+	mfmsr	%r12;				\
+	ori	%r12, %r12, PSL_DR|PSL_IR;	\
+	mtsrr0	%r11;				\
+	mtsrr1	%r12;	/* Enables the MMU */	\
+	isync;					\
+	rfi;					\
+4:
+
+	MMU_REALMODE()
+
+	/* Reset standard BATs */
+	li	%r11, 0
+	mtibatu 0, %r11
+	mtibatl 0, %r11
+	mtdbatu 0, %r11
+	mtdbatl 0, %r11
+	mtibatu 1, %r11
+	mtibatl 1, %r11
+	mtdbatu 1, %r11
+	mtdbatl 1, %r11
+	mtibatu 2, %r11
+	mtibatl 2, %r11
+	mtdbatu 2, %r11
+	mtdbatl 2, %r11
+	mtibatu 3, %r11
+	mtibatl 3, %r11
+	mtdbatu 3, %r11
+	mtdbatl 3, %r11
+
+	/* Reset high BATs. IBAT[4-7][UL] + DBAT[4-7][UL] */
+	mtspr	560, %r11
+	mtspr	561, %r11
+	mtspr	562, %r11
+	mtspr	563, %r11
+	mtspr	564, %r11
+	mtspr	565, %r11
+	mtspr	566, %r11
+	mtspr	567, %r11
+	mtspr	568, %r11
+	mtspr	569, %r11
+	mtspr	570, %r11
+	mtspr	571, %r11
+	mtspr	572, %r11
+	mtspr	573, %r11
+	mtspr	574, %r11
+	mtspr	575, %r11
+
+	/*
+	 * We need to setup BAT0 as in mmu_oea.c.
+	 */
+	li	%r11, BATU(0x00000000, BAT_BL_256M, BAT_Vs)
+	li	%r12, BATL(0x00000000, BAT_M, BAT_PP_RW)
+	mtdbatu	0, %r11
+	mtdbatl	0, %r12
+	mtibatu	0, %r11
+	mtibatl	0, %r12
+	isync
+
+	/*
+	 * We use BAT1 to be able to write I/O memory, including the
+	 * framebuffer registers.
+	 */
+	/* BATU(0x0c000000, BAT_BL_32M, BAT_Vs) */
+	lis	%r11, 0x0c00
+	ori	%r11, %r11, BAT_BL_32M|BAT_Vs
+	/* BATL(0x0c000000, BAT_I|BAT_G, BAT_PP_RW) */
+	lis	%r12, 0x0c00
+	ori	%r12, %r12, BAT_I|BAT_G|BAT_PP_RW
+	mtdbatu	1, %r11
+	mtdbatl	1, %r12
+	isync
+
+	MMU_VIRTUALMODE()


Property changes on: trunk/sys/powerpc/wii/locore.S
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/platform_wii.c
===================================================================
--- trunk/sys/powerpc/wii/platform_wii.c	                        (rev 0)
+++ trunk/sys/powerpc/wii/platform_wii.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,162 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/wii/platform_wii.c 266020 2014-05-14 14:17:51Z ian $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/smp.h>
+#include <sys/fbio.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/hid.h>
+#include <machine/platform.h>
+#include <machine/platformvar.h>
+#include <machine/pmap.h>
+#include <machine/smp.h>
+#include <machine/spr.h>
+#include <machine/vmparam.h>
+
+#include <powerpc/wii/wii_fbreg.h>
+#include <powerpc/wii/wii_ipcreg.h>
+
+#include "platform_if.h"
+
+static int		wii_probe(platform_t);
+static int		wii_attach(platform_t);
+static void		wii_mem_regions(platform_t, struct mem_region *,
+			    int *, struct mem_region *, int *);
+static unsigned long	wii_timebase_freq(platform_t, struct cpuref *);
+static void		wii_reset(platform_t);
+static void		wii_cpu_idle(sbintime_t);
+
+extern void		 wiibus_reset_system(void);
+
+static platform_method_t wii_methods[] = {
+	PLATFORMMETHOD(platform_probe,		wii_probe),
+	PLATFORMMETHOD(platform_attach,		wii_attach),
+	PLATFORMMETHOD(platform_mem_regions,	wii_mem_regions),
+	PLATFORMMETHOD(platform_timebase_freq,	wii_timebase_freq),
+	PLATFORMMETHOD(platform_reset,		wii_reset),
+ 
+	PLATFORMMETHOD_END
+};
+
+static platform_def_t wii_platform = {
+	"wii",
+	wii_methods,
+	0
+};
+
+PLATFORM_DEF(wii_platform);
+
+static int
+wii_probe(platform_t plat)
+{
+	register_t vers = mfpvr();
+
+	/*
+	 * The Wii includes a PowerPC 750CL with custom modifications
+	 * ("Broadway").
+	 * For now, we just assume that if we are running on a
+	 * PowerPC 750CL, then this platform is a Nintendo Wii.
+	 */
+	if ((vers & 0xfffff0e0) == (MPC750 << 16 | MPC750CL))
+		return (BUS_PROBE_SPECIFIC);
+
+	return (ENXIO);
+}
+
+static int
+wii_attach(platform_t plat)
+{
+	cpu_idle_hook = wii_cpu_idle;
+
+	return (0);
+}
+
+static void
+wii_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
+    struct mem_region *avail_regions, int *availsz)
+{
+	/* 24MB 1T-SRAM */
+	avail_regions[0].mr_start = 0x00000000;
+	avail_regions[0].mr_size  = 0x01800000;
+
+	/*
+	 * Reserve space for the framebuffer which is located
+	 * at the end of this 24MB memory region. See wii_fbreg.h.
+	 */
+	avail_regions[0].mr_size -= WIIFB_FB_LEN;
+
+	/* 64MB GDDR3 SDRAM */
+	avail_regions[1].mr_start = 0x10000000;
+	avail_regions[1].mr_size  = 0x04000000;
+
+	/*
+	 * Reserve space for the DSP.
+	 */
+	avail_regions[1].mr_start += 0x4000;
+	avail_regions[1].mr_size -= 0x4000;
+
+	/*
+	 * Reserve space for the IOS I/O memory.
+	 */
+	avail_regions[1].mr_size -= WIIIPC_IOH_LEN + 1;
+
+	memcpy(phys, avail_regions, 2*sizeof(*avail_regions));
+	*physsz = *availsz = 2;
+}
+
+static u_long
+wii_timebase_freq(platform_t plat, struct cpuref *cpuref)
+{
+	
+	/* Bus Frequency (243MHz) / 4 */
+	return (60750000);
+}
+
+static void
+wii_reset(platform_t plat __unused)
+{
+
+	wiibus_reset_system();
+}
+
+static void
+wii_cpu_idle(sbintime_t sbt)
+{
+}


Property changes on: trunk/sys/powerpc/wii/platform_wii.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/wii_bus.c
===================================================================
--- trunk/sys/powerpc/wii/wii_bus.c	                        (rev 0)
+++ trunk/sys/powerpc/wii/wii_bus.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,341 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/wii/wii_bus.c 249973 2013-04-27 06:54:49Z rpaulo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/cpu.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/platform.h>
+#include <machine/pmap.h>
+#include <machine/resource.h>
+#include <machine/platformvar.h>
+
+#include <powerpc/wii/wii_picreg.h>
+#include <powerpc/wii/wii_fbreg.h>
+#include <powerpc/wii/wii_exireg.h>
+#include <powerpc/wii/wii_ipcreg.h>
+#include <powerpc/wii/wii_gpioreg.h>
+
+#define	WIIBUS_CSR_ADDR		0x0d800100
+#define	WIIBUS_CSR_LEN		0x300
+#define	WIIBUS_CSR_RESET	0x94
+
+struct wiibus_softc {
+	device_t		sc_dev;
+	struct rman		sc_rman;
+	bus_space_tag_t		sc_tag;
+	bus_space_handle_t	sc_handle;
+};
+
+static struct wiibus_softc *wiibus_sc = NULL;
+
+static uint32_t	wiibus_csr_read(struct wiibus_softc *, uint16_t);
+static void	wiibus_csr_write(struct wiibus_softc *, uint16_t, uint32_t);
+static void	wiibus_identify(driver_t *, device_t);
+static int	wiibus_probe(device_t);
+static int	wiibus_attach(device_t);
+static int	wiibus_print_child(device_t, device_t);
+static struct resource *
+		wiibus_alloc_resource(device_t, device_t, int, int *,
+		    unsigned long, unsigned long, unsigned long,
+		    unsigned int);
+static int	wiibus_activate_resource(device_t, device_t, int, int,
+		    struct resource *);
+       void	wiibus_reset_system(void);
+
+static device_method_t wiibus_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_identify,	wiibus_identify),
+	DEVMETHOD(device_probe,		wiibus_probe),
+	DEVMETHOD(device_attach,	wiibus_attach),
+
+        /* Bus interface */
+	DEVMETHOD(bus_add_child,	bus_generic_add_child),
+	DEVMETHOD(bus_print_child,	wiibus_print_child),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+	DEVMETHOD(bus_alloc_resource,   wiibus_alloc_resource),
+	DEVMETHOD(bus_activate_resource,wiibus_activate_resource),
+
+	DEVMETHOD_END
+};
+
+static MALLOC_DEFINE(M_WIIBUS, "wiibus", "Nintendo Wii system bus");
+
+struct wiibus_devinfo {
+	struct resource_list	di_resources;
+	uint8_t			di_init;
+};
+
+static driver_t wiibus_driver = {
+	"wiibus",
+	wiibus_methods,
+	sizeof(struct wiibus_softc)
+};
+
+static devclass_t wiibus_devclass;
+
+DRIVER_MODULE(wiibus, nexus, wiibus_driver, wiibus_devclass, 0, 0);
+
+static uint32_t
+wiibus_csr_read(struct wiibus_softc *sc, uint16_t reg)
+{
+
+	return (bus_space_read_4(sc->sc_tag, sc->sc_handle, reg));
+}
+
+static void
+wiibus_csr_write(struct wiibus_softc *sc, uint16_t reg,
+    uint32_t val)
+{
+
+	bus_space_write_4(sc->sc_tag, sc->sc_handle, reg, val);
+}
+
+static void
+wiibus_identify(driver_t *driver, device_t parent)
+{
+
+	if (strcmp(installed_platform(), "wii") != 0)
+		return;
+
+	if (device_find_child(parent, "wiibus", -1) == NULL)
+		BUS_ADD_CHILD(parent, 0, "wiibus", 0);
+}
+
+
+static int
+wiibus_probe(device_t dev)
+{
+
+	device_set_desc(dev, "Nintendo Wii System Bus");
+
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static void
+wiibus_init_device_resources(struct rman *rm, struct wiibus_devinfo *dinfo,
+    unsigned int rid, uintptr_t addr, size_t len, unsigned int irq)
+
+{
+
+	if (!dinfo->di_init) {
+		resource_list_init(&dinfo->di_resources);
+		dinfo->di_init++;
+	}
+	if (addr) {
+		rman_manage_region(rm, addr, addr + len - 1);
+		resource_list_add(&dinfo->di_resources, SYS_RES_MEMORY, rid,
+		    addr, addr + len, len);
+	}
+	if (irq)
+		resource_list_add(&dinfo->di_resources, SYS_RES_IRQ, rid,
+		    irq, irq, 1);
+}
+
+static int
+wiibus_attach(device_t self)
+{
+	struct wiibus_softc *sc;
+	struct wiibus_devinfo *dinfo;
+	device_t cdev;
+
+	sc = device_get_softc(self);
+	sc->sc_rman.rm_type = RMAN_ARRAY;
+	sc->sc_rman.rm_descr = "Wii Bus Memory Mapped I/O";
+	rman_init(&sc->sc_rman);
+	KASSERT(wiibus_sc == NULL, ("wiibus_sc already initialised"));
+	wiibus_sc = sc;
+
+	/* Nintendo PIC */
+	dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIPIC_REG_ADDR,
+	    WIIPIC_REG_LEN, 1);
+	cdev = BUS_ADD_CHILD(self, 0, "wiipic", 0);
+	device_set_ivars(cdev, dinfo);
+
+	/* Framebuffer */
+	dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIFB_REG_ADDR,
+	    WIIFB_REG_LEN, 8);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 1, WIIFB_FB_ADDR,
+	    WIIFB_FB_LEN, 0);
+	cdev = BUS_ADD_CHILD(self, 0, "wiifb", 0);
+	device_set_ivars(cdev, dinfo);
+
+	/* External Interface Bus */
+	dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIEXI_REG_ADDR,
+	    WIIEXI_REG_LEN, 4);
+	cdev = BUS_ADD_CHILD(self, 0, "wiiexi", 0);
+	device_set_ivars(cdev, dinfo);
+
+	/* Nintendo IOS IPC */
+	dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIIPC_REG_ADDR,
+	    WIIIPC_REG_LEN, 14);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 1, WIIIPC_IOH_ADDR,
+	    WIIIPC_IOH_LEN, 0);
+	cdev = BUS_ADD_CHILD(self, 0, "wiiipc", 0);
+	device_set_ivars(cdev, dinfo);
+
+	/* GPIO */
+	dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIGPIO_REG_ADDR,
+	    WIIGPIO_REG_LEN, 0);
+	cdev = BUS_ADD_CHILD(self, 0, "wiigpio", 0);
+	device_set_ivars(cdev, dinfo);
+
+	/* The control registers */
+	sc->sc_tag    = &bs_be_tag;
+	sc->sc_handle = (bus_space_handle_t)pmap_mapdev(WIIBUS_CSR_ADDR,
+	    WIIBUS_CSR_LEN);
+
+	return (bus_generic_attach(self));
+}
+
+static int
+wiibus_print_child(device_t dev, device_t child)
+{
+	struct wiibus_devinfo *dinfo = device_get_ivars(child);
+	int retval = 0;
+
+	retval += bus_print_child_header(dev, child);
+	retval += resource_list_print_type(&dinfo->di_resources, "mem",
+	    SYS_RES_MEMORY, "%#lx");
+	retval += resource_list_print_type(&dinfo->di_resources, "irq",
+	    SYS_RES_IRQ, "%ld");
+	retval += bus_print_child_footer(dev, child);
+
+	return (retval);
+}
+
+static struct resource *
+wiibus_alloc_resource(device_t bus, device_t child, int type,
+    int *rid, unsigned long start, unsigned long end,
+    unsigned long count, unsigned int flags)
+{
+	struct wiibus_softc *sc;
+	struct wiibus_devinfo *dinfo;
+	struct resource_list_entry *rle;
+	struct resource *rv;
+	int needactivate;
+
+	sc = device_get_softc(bus);
+	dinfo = device_get_ivars(child);
+	needactivate = flags & RF_ACTIVE;
+	flags &= ~RF_ACTIVE;
+
+	switch (type) {
+	case SYS_RES_MEMORY:
+		rle = resource_list_find(&dinfo->di_resources, SYS_RES_MEMORY,
+		    *rid);
+		if (rle == NULL) {
+			device_printf(bus, "no res entry for %s memory 0x%x\n",
+			    device_get_nameunit(child), *rid);
+			return (NULL);
+		}
+		rv = rman_reserve_resource(&sc->sc_rman, rle->start, rle->end,
+		    rle->count, flags, child);
+		if (rv == NULL) {
+			device_printf(bus,
+			    "failed to reserve resource for %s\n",
+			    device_get_nameunit(child));
+			return (NULL);
+		}
+		rman_set_rid(rv, *rid);
+		break;
+	case SYS_RES_IRQ:
+		return (resource_list_alloc(&dinfo->di_resources, bus, child,
+		    type, rid, start, end, count, flags));
+	default:
+		device_printf(bus, "unknown resource request from %s\n",
+		    device_get_nameunit(child));
+		return (NULL);
+	}
+
+	if (needactivate) {
+		if (bus_activate_resource(child, type, *rid, rv) != 0) {
+			device_printf(bus,
+			    "failed to activate resource for %s\n",
+			    device_get_nameunit(child));
+			return (NULL);
+		}
+	}
+	
+	return (rv);
+}
+
+static int
+wiibus_activate_resource(device_t bus, device_t child, int type, int rid,
+    struct resource *res)
+{
+	void *p;
+
+	switch (type) {
+	case SYS_RES_MEMORY:
+		p = pmap_mapdev(rman_get_start(res), rman_get_size(res));
+		if (p == NULL)
+			return (ENOMEM);
+		rman_set_virtual(res, p);
+		rman_set_bustag(res, &bs_be_tag);
+		rman_set_bushandle(res, (unsigned long)p);
+		break;
+	case SYS_RES_IRQ:
+		return (bus_activate_resource(bus, type, rid, res));
+	default:
+		device_printf(bus,
+		    "unknown activate resource request from %s\n",
+		    device_get_nameunit(child));
+		return (ENXIO);
+	}
+	
+	return (rman_activate_resource(res));
+}
+
+void
+wiibus_reset_system(void)
+{
+	uint32_t r;
+
+	r = wiibus_csr_read(wiibus_sc, WIIBUS_CSR_RESET);
+	r &= ~1;
+	wiibus_csr_write(wiibus_sc, WIIBUS_CSR_RESET, r);
+}


Property changes on: trunk/sys/powerpc/wii/wii_bus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/wii_exireg.h
===================================================================
--- trunk/sys/powerpc/wii/wii_exireg.h	                        (rev 0)
+++ trunk/sys/powerpc/wii/wii_exireg.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,36 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/wii/wii_exireg.h 239478 2012-08-21 06:31:26Z adrian $
+ */
+
+#ifndef	_POWERPC_WII_WII_EXIREG_H
+#define	_POWERPC_WII_WII_EXIREG_H
+
+#define	WIIEXI_REG_ADDR		0x0d006800
+#define	WIIEXI_REG_LEN		0x40
+
+#endif	/* _POWERPC_WII_WII_IPCREG_H */


Property changes on: trunk/sys/powerpc/wii/wii_exireg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/wii_fb.c
===================================================================
--- trunk/sys/powerpc/wii/wii_fb.c	                        (rev 0)
+++ trunk/sys/powerpc/wii/wii_fb.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,886 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * Copyright (c) 2003 Peter Grehan
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/wii/wii_fb.c 249965 2013-04-27 01:57:45Z rpaulo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/limits.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/fbio.h>
+#include <sys/consio.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/sc_machdep.h>
+#include <machine/platform.h>
+#include <machine/pmap.h>
+
+#include <sys/rman.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/syscons/syscons.h>
+
+#include <powerpc/wii/wii_fbreg.h>
+#include <powerpc/wii/wii_fbvar.h>
+
+/*
+ * Driver for the Nintendo Wii's framebuffer. Based on Linux's gcnfb.c.
+ */
+
+/*
+ * Syscons glue.
+ */
+static int	wiifb_scprobe(device_t);
+static int	wiifb_scattach(device_t);
+
+static device_method_t wiifb_sc_methods[] = {
+	DEVMETHOD(device_probe,		wiifb_scprobe),
+	DEVMETHOD(device_attach,	wiifb_scattach),
+
+	DEVMETHOD_END
+};
+
+static driver_t wiifb_sc_driver = {
+	"wiifb",
+	wiifb_sc_methods,
+	sizeof(sc_softc_t),
+};
+
+static devclass_t sc_devclass;
+
+DRIVER_MODULE(sc, wiibus, wiifb_sc_driver, sc_devclass, 0, 0);
+
+static int
+wiifb_scprobe(device_t dev)
+{
+	int error;
+
+	device_set_desc(dev, "Nintendo Wii frambuffer");
+
+	error = sc_probe_unit(device_get_unit(dev),
+	    device_get_flags(dev) | SC_AUTODETECT_KBD);
+	if (error != 0)
+		return (error);
+
+	/* This is a fake device, so make sure we added it ourselves */
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+wiifb_scattach(device_t dev)
+{
+
+	return (sc_attach_unit(device_get_unit(dev),
+	    device_get_flags(dev) | SC_AUTODETECT_KBD));
+}
+
+/*
+ * Video driver routines and glue.
+ */
+static void			wiifb_reset_video(struct wiifb_softc *);
+static void			wiifb_enable_interrupts(struct wiifb_softc *);
+static void			wiifb_configure_tv_mode(struct wiifb_softc *);
+static void			wiifb_setup_framebuffer(struct wiifb_softc *);
+static int			wiifb_configure(int);
+static vi_probe_t		wiifb_probe;
+static vi_init_t		wiifb_init;
+static vi_get_info_t		wiifb_get_info;
+static vi_query_mode_t		wiifb_query_mode;
+static vi_set_mode_t		wiifb_set_mode;
+static vi_save_font_t		wiifb_save_font;
+static vi_load_font_t		wiifb_load_font;
+static vi_show_font_t		wiifb_show_font;
+static vi_save_palette_t	wiifb_save_palette;
+static vi_load_palette_t	wiifb_load_palette;
+static vi_set_border_t		wiifb_set_border;
+static vi_save_state_t		wiifb_save_state;
+static vi_load_state_t		wiifb_load_state;
+static vi_set_win_org_t		wiifb_set_win_org;
+static vi_read_hw_cursor_t	wiifb_read_hw_cursor;
+static vi_set_hw_cursor_t	wiifb_set_hw_cursor;
+static vi_set_hw_cursor_shape_t	wiifb_set_hw_cursor_shape;
+static vi_blank_display_t	wiifb_blank_display;
+static vi_mmap_t		wiifb_mmap;
+static vi_ioctl_t		wiifb_ioctl;
+static vi_clear_t		wiifb_clear;
+static vi_fill_rect_t		wiifb_fill_rect;
+static vi_bitblt_t		wiifb_bitblt;
+static vi_diag_t		wiifb_diag;
+static vi_save_cursor_palette_t	wiifb_save_cursor_palette;
+static vi_load_cursor_palette_t	wiifb_load_cursor_palette;
+static vi_copy_t		wiifb_copy;
+static vi_putp_t		wiifb_putp;
+static vi_putc_t		wiifb_putc;
+static vi_puts_t		wiifb_puts;
+static vi_putm_t		wiifb_putm;
+
+static video_switch_t wiifbvidsw = {
+	.probe			= wiifb_probe,
+	.init			= wiifb_init,
+	.get_info		= wiifb_get_info,
+	.query_mode		= wiifb_query_mode,
+	.set_mode		= wiifb_set_mode,
+	.save_font		= wiifb_save_font,
+	.load_font		= wiifb_load_font,
+	.show_font		= wiifb_show_font,
+	.save_palette		= wiifb_save_palette,
+	.load_palette		= wiifb_load_palette,
+	.set_border		= wiifb_set_border,
+	.save_state		= wiifb_save_state,
+	.load_state		= wiifb_load_state,
+	.set_win_org		= wiifb_set_win_org,
+	.read_hw_cursor		= wiifb_read_hw_cursor,
+	.set_hw_cursor		= wiifb_set_hw_cursor,
+	.set_hw_cursor_shape	= wiifb_set_hw_cursor_shape,
+	.blank_display		= wiifb_blank_display,
+	.mmap			= wiifb_mmap,
+	.ioctl			= wiifb_ioctl,
+	.clear			= wiifb_clear,
+	.fill_rect		= wiifb_fill_rect,
+	.bitblt			= wiifb_bitblt,
+	.diag			= wiifb_diag,
+	.save_cursor_palette	= wiifb_save_cursor_palette,
+	.load_cursor_palette	= wiifb_load_cursor_palette,
+	.copy			= wiifb_copy,
+	.putp			= wiifb_putp,
+	.putc			= wiifb_putc,
+	.puts			= wiifb_puts,
+	.putm			= wiifb_putm,
+};
+
+VIDEO_DRIVER(wiifb, wiifbvidsw, wiifb_configure);
+
+extern sc_rndr_sw_t txtrndrsw;
+RENDERER(wiifb, 0, txtrndrsw, gfb_set);
+RENDERER_MODULE(wiifb, gfb_set);
+
+static struct wiifb_softc wiifb_softc;
+static uint16_t wiifb_static_window[ROW*COL];
+extern u_char dflt_font_8[];
+
+/*
+ * Map the syscons colors to YUY2 (Y'UV422).
+ * Some colours are an approximation.
+ *
+ * The Wii has a 16 bit pixel, so each 32 bit DWORD encodes
+ * two pixels.  The upper 16 bits is for pixel 0 (left hand pixel
+ * in a pair), the lower 16 bits is for pixel 1. 
+ *
+ * For now, we're going to ignore that entirely and just use the
+ * lower 16 bits for each pixel. We'll take the upper value into
+ * account later.
+ */
+static uint32_t wiifb_cmap[16] = {
+	0x00800080,	/* Black */
+	0x1dff1d6b,	/* Blue */
+	0x4b554b4a,	/* Green */
+	0x80808080,	/* Cyan */
+	0x4c544cff,	/* Red */
+	0x3aaa34b5,	/* Magenta */
+	0x7140718a,	/* Brown */
+	0xff80ff80,	/* White */
+	0x80808080,	/* Gray */
+	0xc399c36a,	/* Bright Blue */
+	0xd076d074,	/* Bright Green */
+	0x80808080,	/* Bright Cyan */
+	0x4c544cff,	/* Bright Red */
+	0x3aaa34b5,	/* Bright Magenta */
+	0xe100e194,	/* Bright Yellow */
+	0xff80ff80	/* Bright White */
+};
+
+static struct wiifb_mode_desc wiifb_modes[] = {
+	[WIIFB_MODE_NTSC_480i] = {
+		"NTSC 480i",
+		640, 480,
+		525,
+		WIIFB_MODE_FLAG_INTERLACED,
+	},
+	[WIIFB_MODE_NTSC_480p] = {
+		"NTSC 480p",
+		640, 480,
+		525,
+		WIIFB_MODE_FLAG_PROGRESSIVE,
+	},
+	[WIIFB_MODE_PAL_576i] = {
+		"PAL 576i (50Hz)",
+		640, 574,
+		625,
+		WIIFB_MODE_FLAG_INTERLACED,
+	},
+	[WIIFB_MODE_PAL_480i] = {
+		"PAL 480i (60Hz)",
+		640, 480,
+		525,
+		WIIFB_MODE_FLAG_INTERLACED,
+	},
+	[WIIFB_MODE_PAL_480p] = {
+		"PAL 480p",
+		640, 480,
+		525,
+		WIIFB_MODE_FLAG_PROGRESSIVE,
+	},
+};
+
+static const uint32_t wiifb_filter_coeft[] = {
+	0x1ae771f0, 0x0db4a574, 0x00c1188e, 0xc4c0cbe2, 0xfcecdecf,
+	0x13130f08, 0x00080c0f
+};
+
+static __inline int
+wiifb_background(uint8_t attr)
+{
+
+	return (attr >> 4);
+}
+
+static __inline int
+wiifb_foreground(uint8_t attr)
+{
+
+	return (attr & 0x0f);
+}
+
+static void
+wiifb_reset_video(struct wiifb_softc *sc)
+{
+	struct wiifb_dispcfg dc;
+
+	wiifb_dispcfg_read(sc, &dc);
+	dc.dc_reset = 1;
+	wiifb_dispcfg_write(sc, &dc);
+	dc.dc_reset = 0;
+	wiifb_dispcfg_write(sc, &dc);
+}
+
+static void
+wiifb_enable_interrupts(struct wiifb_softc *sc)
+{
+	struct wiifb_dispint di;
+
+#ifdef notyet
+	/*
+	 * Display Interrupt 0
+	 */
+	di.di_htiming = 1;
+	di.di_vtiming = 1;
+	di.di_enable = 1;
+	di.di_irq    = 1;
+	wiifb_dispint_write(sc, 0, &di);
+
+	/*
+	 * Display Interrupt 1
+	 */
+	di.di_htiming = sc->sc_format == WIIFB_FORMAT_PAL ? 433 : 430;
+	di.di_vtiming = sc->sc_mode->fd_lines;
+	di.di_enable = 1;
+	di.di_irq    = 1;
+	if (sc->sc_mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED)
+		di.di_vtiming /= 2;
+	wiifb_dispint_write(sc, 1, &di);
+
+	/*
+	 * Display Interrupts 2 and 3 are not used.
+	 */
+	memset(&di, 0, sizeof(di));
+	wiifb_dispint_write(sc, 2, &di);
+	wiifb_dispint_write(sc, 3, &di);
+#else
+	memset(&di, 0, sizeof(di));
+	wiifb_dispint_write(sc, 0, &di);
+	wiifb_dispint_write(sc, 1, &di);
+	wiifb_dispint_write(sc, 2, &di);
+	wiifb_dispint_write(sc, 3, &di);
+#endif
+}
+
+/*
+ * Reference gcnfb.c for an in depth explanation.
+ * XXX only works with NTSC.
+ */
+static void
+wiifb_configure_tv_mode(struct wiifb_softc *sc)
+{
+	struct wiifb_vtiming vt;
+	struct wiifb_hscaling hs;
+	struct wiifb_htiming0 ht0;
+	struct wiifb_htiming1 ht1;
+	struct wiifb_vtimingodd vto;
+	struct wiifb_vtimingeven vte;
+	struct wiifb_burstblankodd bbo;
+	struct wiifb_burstblankeven bbe;
+	struct wiifb_picconf pc;
+	struct wiifb_mode_desc *mode = sc->sc_mode;
+	unsigned int height = mode->fd_height;
+	unsigned int width = mode->fd_width;
+	unsigned int eqpulse, interlacebias, shift;
+	const unsigned int maxwidth = 714;
+	unsigned int hblanking = maxwidth - width;
+	unsigned int hmargin = hblanking / 2;
+	unsigned int A = 20 + hmargin, C = 60 + hblanking - hmargin;
+	unsigned int maxheight = 484;
+	unsigned int P = 2 * (20 - 10 + 1);
+	unsigned int Q = 1;
+	unsigned int vblanking = maxheight - height;
+	unsigned int vmargin = vblanking / 2;
+	unsigned int prb = vmargin;
+	unsigned int psb = vblanking - vmargin;
+	int i;
+
+	/*
+	 * Vertical timing.
+	 */
+	if (mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED) {
+		vt.vt_actvideo = height / 2;
+		interlacebias = 1;
+		shift = 0;
+	} else {
+		vt.vt_actvideo = height;
+		interlacebias = 0;
+		shift = 1;
+	}
+	/* Lines of equalization */
+	if (mode->fd_lines == 625)
+		eqpulse = 2 * 2.5;
+	else
+		eqpulse = 2 * 3;
+	vt.vt_eqpulse = eqpulse << shift;
+	wiifb_vtiming_write(sc, &vt);
+
+	/*
+	 * Horizontal timings.
+	 */
+	ht0.ht0_hlinew = 858 / 2;
+	ht1.ht1_hsyncw = 64;
+	ht0.ht0_hcolourstart = 71;
+	ht0.ht0_hcolourend = 71 + 34;
+	ht1.ht1_hblankstart = (858 / 2) - A;
+	ht1.ht1_hblankend = 64 + C;
+	wiifb_htiming0_write(sc, &ht0);
+	wiifb_htiming1_write(sc, &ht1);
+
+	/*
+	 * Vertical timing odd/even.
+	 */
+	if (vmargin & 1) {
+		vto.vto_preb = (P + interlacebias + prb) << shift;
+		vto.vto_postb = (Q - interlacebias + psb) << shift;
+		vte.vte_preb = (P + prb) << shift;
+		vte.vte_postb = (Q - psb) << shift;
+	} else {
+		/* XXX if this isn't 0, it doesn't work? */
+		prb = 0;
+		psb = 0;
+		vte.vte_preb = (P + interlacebias + prb) << shift;
+		vte.vte_postb = (Q - interlacebias + psb) << shift;
+		vto.vto_preb = (P + prb) << shift;
+		vto.vto_postb = (Q - psb) << shift;
+	}
+	wiifb_vtimingodd_write(sc, &vto);
+	wiifb_vtimingeven_write(sc, &vte);
+
+	/*
+	 * Burst blanking odd/even interval.
+	 */
+	bbo.bbo_bs1 = 2 * (18 - 7 + 1);
+	bbe.bbe_bs2 = bbo.bbo_bs3 = bbe.bbe_bs4 = bbo.bbo_bs1;
+	bbo.bbo_be1 = 2 * (525 - 7 + 1);
+	bbe.bbe_be2 = bbo.bbo_be3 = bbe.bbe_be4 = bbo.bbo_be1;
+	wiifb_burstblankodd_write(sc, &bbo);
+	wiifb_burstblankeven_write(sc, &bbe);
+
+	/*
+	 * Picture configuration.
+	 */ 
+	pc.pc_strides = (mode->fd_width * 2) / 32;
+	if (mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED)
+		pc.pc_strides *= 2;
+	pc.pc_reads = (mode->fd_width * 2) / 32;
+	wiifb_picconf_write(sc, &pc);
+
+	/*
+	 * Horizontal scaling disabled.
+	 */
+	hs.hs_enable = 0;
+	hs.hs_step = 256;
+	wiifb_hscaling_write(sc, &hs);
+
+	/*
+	 * Filter coeficient table.
+	 */
+	for (i = 0; i < 7; i++)
+		wiifb_filtcoeft_write(sc, i, wiifb_filter_coeft[i]);
+
+	/*
+	 * Anti alias.
+	 */
+	wiifb_antialias_write(sc, 0x00ff0000);
+
+	/*
+	 * Video clock.
+	 */
+	wiifb_videoclk_write(sc, 
+	    mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED ? 0 : 1);
+
+	/*
+	 * Disable horizontal scaling width.
+	 */
+	wiifb_hscalingw_write(sc, mode->fd_width);
+
+	/*
+	 * DEBUG mode borders. Not used.
+	 */
+	wiifb_hborderend_write(sc, 0);
+	wiifb_hborderstart_write(sc, 0);
+
+	/*
+	 * XXX unknown registers.
+	 */
+	wiifb_unknown1_write(sc, 0x00ff);
+	wiifb_unknown2_write(sc, 0x00ff00ff);
+	wiifb_unknown3_write(sc, 0x00ff00ff);
+}
+
+static void
+wiifb_setup_framebuffer(struct wiifb_softc *sc)
+{
+	intptr_t addr = sc->sc_fb_addr;
+	struct wiifb_topfieldbasel tfbl;
+	struct wiifb_bottomfieldbasel bfbl;
+	struct wiifb_topfieldbaser tfbr;
+	struct wiifb_bottomfieldbaser bfbr;
+
+	tfbl.tfbl_fbaddr     = addr >> 5;
+	tfbl.tfbl_xoffset    = (addr / 2) & 0xf;
+	tfbl.tfbl_pageoffbit = 1;
+	wiifb_topfieldbasel_write(sc, &tfbl);
+
+	if (sc->sc_mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED)
+		addr += sc->sc_mode->fd_width * 2;
+	bfbl.bfbl_fbaddr     = addr >> 5;
+	bfbl.bfbl_xoffset    = (addr / 2) & 0xf;
+	bfbl.bfbl_pageoffbit = 1;
+	wiifb_bottomfieldbasel_write(sc, &bfbl);
+
+	/*
+	 * Only used used for 3D.
+	 */
+	memset(&tfbr, 0, sizeof(tfbr));
+	memset(&bfbr, 0, sizeof(bfbr));
+	wiifb_topfieldbaser_write(sc, &tfbr);
+	wiifb_bottomfieldbaser_write(sc, &bfbr);
+}
+
+static int
+wiifb_configure(int flags)
+{
+	struct wiifb_softc *sc;
+	struct wiifb_dispcfg dc;
+	int progressive;
+
+	sc = &wiifb_softc;
+	if (sc->sc_initialized) {
+		/* XXX We should instead use bus_space */
+		sc->sc_fb_addr = (intptr_t)pmap_mapdev(WIIFB_FB_ADDR, WIIFB_FB_LEN);
+		sc->sc_reg_addr = (intptr_t)pmap_mapdev(WIIFB_REG_ADDR, WIIFB_REG_LEN);
+		return 0;
+	}
+
+	sc->sc_console = 1;
+
+	sc->sc_fb_addr = WIIFB_FB_ADDR;
+	sc->sc_fb_size = WIIFB_FB_LEN;
+
+	sc->sc_reg_addr = WIIFB_REG_ADDR;
+	sc->sc_reg_size = WIIFB_REG_LEN;
+
+	wiifb_reset_video(sc);
+	wiifb_dispcfg_read(sc, &dc);
+	sc->sc_format = dc.dc_format;
+	sc->sc_component = wiifb_component_enabled(sc);
+	progressive = dc.dc_noninterlaced;
+	switch (sc->sc_format) {
+	case WIIFB_FORMAT_MPAL:
+	case WIIFB_FORMAT_DEBUG:
+	case WIIFB_FORMAT_NTSC:
+		sc->sc_mode = progressive ?
+		    &wiifb_modes[WIIFB_MODE_NTSC_480p] :
+		    &wiifb_modes[WIIFB_MODE_NTSC_480i];
+		break;
+	case WIIFB_FORMAT_PAL:
+		sc->sc_mode = progressive ?
+		    &wiifb_modes[WIIFB_MODE_PAL_480p] :
+		    &wiifb_modes[WIIFB_MODE_PAL_480i];
+		break;
+	}
+	sc->sc_height = sc->sc_mode->fd_height;
+	sc->sc_width = sc->sc_mode->fd_width;
+	/* Usually we multiply by 4, but I think this looks better. */
+	sc->sc_stride = sc->sc_width * 2;
+
+	wiifb_init(0, &sc->sc_va, 0);
+
+	sc->sc_initialized = 1;
+
+	return (0);
+}
+
+static int
+wiifb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
+{
+
+	return (0);
+}
+
+static int
+wiifb_init(int unit, video_adapter_t *adp, int flags)
+{
+	struct wiifb_softc *sc;
+	video_info_t *vi;
+
+	sc = (struct wiifb_softc *)adp;
+	vi = &adp->va_info;
+
+	vid_init_struct(adp, "wiifb", -1, unit);
+
+	sc->sc_font = dflt_font_8;
+	vi->vi_cheight = WIIFB_FONT_HEIGHT;
+	vi->vi_width = sc->sc_width/8;
+	vi->vi_height = sc->sc_height/vi->vi_cheight;
+	vi->vi_cwidth = 8;
+
+	/*
+	 * Clamp width/height to syscons maximums
+	 */
+	if (vi->vi_width > COL)
+		vi->vi_width = COL;
+	if (vi->vi_height > ROW)
+		vi->vi_height = ROW;
+
+	sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2;
+	sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight))/2;
+
+	adp->va_window = (vm_offset_t) wiifb_static_window;
+	/* XXX no colour support */
+	adp->va_flags |= V_ADP_FONT | /*V_ADP_COLOR |*/ V_ADP_MODECHANGE;
+
+	vid_register(&sc->sc_va);
+
+	wiifb_configure_tv_mode(sc);
+	wiifb_setup_framebuffer(sc);
+	wiifb_enable_interrupts(sc);
+	wiifb_clear(adp);
+
+	return (0);
+}
+
+static int
+wiifb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
+{
+
+	bcopy(&adp->va_info, info, sizeof(*info));
+	return (0);
+}
+
+static int
+wiifb_query_mode(video_adapter_t *adp, video_info_t *info)
+{
+
+	return (0);
+}
+
+static int
+wiifb_set_mode(video_adapter_t *adp, int mode)
+{
+
+	return (0);
+}
+
+static int
+wiifb_save_font(video_adapter_t *adp, int page, int size, int width,
+    u_char *data, int c, int count)
+{
+
+	return (0);
+}
+
+static int
+wiifb_load_font(video_adapter_t *adp, int page, int size, int width,
+    u_char *data, int c, int count)
+{
+	struct wiifb_softc *sc = (struct wiifb_softc *)adp;
+
+	sc->sc_font = data;
+
+	return (0);
+}
+
+static int
+wiifb_show_font(video_adapter_t *adp, int page)
+{
+
+	return (0);
+}
+
+static int
+wiifb_save_palette(video_adapter_t *adp, u_char *palette)
+{
+
+	return (0);
+}
+
+static int
+wiifb_load_palette(video_adapter_t *adp, u_char *palette)
+{
+
+	return (0);
+}
+
+static int
+wiifb_set_border(video_adapter_t *adp, int border)
+{
+
+	return (wiifb_blank_display(adp, border));
+}
+
+static int
+wiifb_save_state(video_adapter_t *adp, void *p, size_t size)
+{
+
+	return (0);
+}
+
+static int
+wiifb_load_state(video_adapter_t *adp, void *p)
+{
+
+	return (0);
+}
+
+static int
+wiifb_set_win_org(video_adapter_t *adp, off_t offset)
+{
+
+	return (0);
+}
+
+static int
+wiifb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
+{
+
+	*col = *row = 0;
+
+	return (0);
+}
+
+static int
+wiifb_set_hw_cursor(video_adapter_t *adp, int col, int row)
+{
+
+	return (0);
+}
+
+static int
+wiifb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
+    int celsize, int blink)
+{
+
+	return (0);
+}
+
+static int
+wiifb_blank_display(video_adapter_t *adp, int mode)
+{
+	struct wiifb_softc *sc = (struct wiifb_softc *)adp;
+	uint32_t *p;
+
+	for (p = (uint32_t *)sc->sc_fb_addr;
+	    p < (uint32_t *)(sc->sc_fb_addr + sc->sc_fb_size);
+	    p++)
+		*p = wiifb_cmap[wiifb_background(SC_NORM_ATTR)];
+
+	return (0);
+}
+
+static int
+wiifb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
+    int prot, vm_memattr_t *memattr)
+{
+	struct wiifb_softc *sc;
+
+	sc = (struct wiifb_softc *)adp;
+
+	/*
+	 * This might be a legacy VGA mem request: if so, just point it at the
+	 * framebuffer, since it shouldn't be touched
+	 */
+	if (offset < sc->sc_stride*sc->sc_height) {
+		*paddr = sc->sc_fb_addr + offset;
+		return (0);
+	}
+
+	return (EINVAL);
+}
+
+static int
+wiifb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
+{
+
+	return (0);
+}
+
+static int
+wiifb_clear(video_adapter_t *adp)
+{
+
+	return (wiifb_blank_display(adp, 0));
+}
+
+static int
+wiifb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
+{
+
+	return (0);
+}
+
+static int
+wiifb_bitblt(video_adapter_t *adp, ...)
+{
+
+	return (0);
+}
+
+static int
+wiifb_diag(video_adapter_t *adp, int level)
+{
+
+	return (0);
+}
+
+static int
+wiifb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
+{
+
+	return (0);
+}
+
+static int
+wiifb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
+{
+
+	return (0);
+}
+
+static int
+wiifb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
+{
+
+	return (0);
+}
+
+static int
+wiifb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
+    int size, int bpp, int bit_ltor, int byte_ltor)
+{
+
+	return (0);
+}
+
+static int
+wiifb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
+{
+	struct wiifb_softc *sc;
+	int row;
+	int col;
+	int i, j, k;
+	uint32_t *addr;
+	u_char *p;
+	uint32_t fg, bg;
+	unsigned long pixel[2];
+
+	sc = (struct wiifb_softc *)adp;
+	row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
+	col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth / 2;
+	p = sc->sc_font + c*WIIFB_FONT_HEIGHT;
+	addr = (uint32_t *)sc->sc_fb_addr
+	    + (row + sc->sc_ymargin)*(sc->sc_stride/4)
+	    + col + sc->sc_xmargin;
+
+	bg = wiifb_cmap[wiifb_background(a)];
+	fg = wiifb_cmap[wiifb_foreground(a)];
+
+	for (i = 0; i < WIIFB_FONT_HEIGHT; i++) {
+		for (j = 0, k = 7; j < 4; j++, k--) {
+			if ((p[i] & (1 << k)) == 0)
+				pixel[0] = bg;
+			else
+				pixel[0] = fg;
+			k--;	
+			if ((p[i] & (1 << k)) == 0)
+				pixel[1] = bg;
+			else
+				pixel[1] = fg;
+
+			addr[j] = (pixel[0] & 0xffff00ff) |
+			          (pixel[1] & 0x0000ff00);
+		}
+		addr += (sc->sc_stride/4);
+	}
+
+        return (0);
+}
+
+static int
+wiifb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++) 
+		wiifb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
+
+	return (0);
+}
+
+static int
+wiifb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
+    uint32_t pixel_mask, int size, int width)
+{
+	
+	return (0);
+}


Property changes on: trunk/sys/powerpc/wii/wii_fb.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/wii_fbreg.h
===================================================================
--- trunk/sys/powerpc/wii/wii_fbreg.h	                        (rev 0)
+++ trunk/sys/powerpc/wii/wii_fbreg.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,41 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/wii/wii_fbreg.h 239478 2012-08-21 06:31:26Z adrian $
+ */
+
+#ifndef	_POWERPC_WII_WII_FBREG_H
+#define	_POWERPC_WII_WII_FBREG_H
+
+/*
+ * Memory addresses for the I/O and the framebuffer.
+ */
+#define	WIIFB_REG_ADDR	0x0c002000
+#define	WIIFB_REG_LEN	0x100
+#define	WIIFB_FB_ADDR	0x01698000	/* at the end of 1T SRAM */
+#define	WIIFB_FB_LEN	0x168000
+
+#endif /* _POWERPC_WII_WII_FBREG_H */


Property changes on: trunk/sys/powerpc/wii/wii_fbreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/wii_fbvar.h
===================================================================
--- trunk/sys/powerpc/wii/wii_fbvar.h	                        (rev 0)
+++ trunk/sys/powerpc/wii/wii_fbvar.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,858 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/wii/wii_fbvar.h 239478 2012-08-21 06:31:26Z adrian $
+ */
+
+#ifndef	_POWERPC_WII_WIIFB_H
+#define	_POWERPC_WII_WIIFB_H
+
+#define	WIIFB_FONT_HEIGHT	8
+
+enum wiifb_format {
+	WIIFB_FORMAT_NTSC  = 0,
+	WIIFB_FORMAT_PAL   = 1,
+	WIIFB_FORMAT_MPAL  = 2,
+	WIIFB_FORMAT_DEBUG = 3
+};
+
+enum wiifb_mode {
+	WIIFB_MODE_NTSC_480i = 0,
+	WIIFB_MODE_NTSC_480p = 1,
+	WIIFB_MODE_PAL_576i  = 2,
+	WIIFB_MODE_PAL_480i  = 3,
+	WIIFB_MODE_PAL_480p  = 4
+};
+
+struct wiifb_mode_desc {
+	const char 	*fd_name;
+	unsigned int	fd_width;
+	unsigned int	fd_height;
+	unsigned int	fd_lines;
+	uint8_t		fd_flags;
+#define WIIFB_MODE_FLAG_PROGRESSIVE	0x00
+#define WIIFB_MODE_FLAG_INTERLACED	0x01
+};
+
+struct wiifb_softc {
+	video_adapter_t	sc_va;
+	struct cdev	*sc_si;
+	int		sc_console;
+
+	intptr_t	sc_reg_addr;
+	unsigned int	sc_reg_size;
+
+	intptr_t	sc_fb_addr;
+	unsigned int	sc_fb_size;
+
+	unsigned int	sc_height;
+	unsigned int	sc_width;
+	unsigned int	sc_stride;
+
+	unsigned int	sc_xmargin;
+	unsigned int	sc_ymargin;
+
+	boolean_t	sc_component;
+	enum wiifb_format sc_format;
+	struct wiifb_mode_desc *sc_mode;
+
+	unsigned int	sc_vtiming;
+	unsigned int	sc_htiming;
+
+	unsigned char	*sc_font;
+	int		sc_initialized;
+	int		sc_rrid;
+};
+
+/*
+ * Vertical timing
+ * 16 bit
+ */
+#define	WIIFB_REG_VTIMING	0x00
+struct wiifb_vtiming {
+	uint8_t		vt_eqpulse;
+	uint16_t	vt_actvideo;
+};
+
+static __inline void
+wiifb_vtiming_read(struct wiifb_softc *sc, struct wiifb_vtiming *vt)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_VTIMING);
+	
+	vt->vt_eqpulse  = *reg & 0xf;
+	vt->vt_actvideo = (*reg >> 4) & 0x3ff;
+}
+
+static __inline void
+wiifb_vtiming_write(struct wiifb_softc *sc, struct wiifb_vtiming *vt)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_VTIMING);
+
+	*reg = ((vt->vt_actvideo & 0x3ff) << 4) |
+	        (vt->vt_eqpulse & 0xf);
+	powerpc_sync();
+}
+
+/*
+ * Display configuration
+ * 16 bit
+ */
+#define	WIIFB_REG_DISPCFG	0x02
+struct wiifb_dispcfg {
+	uint8_t		  dc_enable;
+	uint8_t		  dc_reset;
+	uint8_t		  dc_noninterlaced;
+	uint8_t		  dc_3dmode;
+	uint8_t		  dc_latchenb0;
+	uint8_t		  dc_latchenb1;
+	enum wiifb_format dc_format;
+};
+
+static __inline void
+wiifb_dispcfg_read(struct wiifb_softc *sc, struct wiifb_dispcfg *dc)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_DISPCFG);
+
+	dc->dc_enable        = *reg & 0x1;
+	dc->dc_reset         = (*reg >> 1) & 0x1;
+	dc->dc_noninterlaced = (*reg >> 2) & 0x1;
+	dc->dc_3dmode        = (*reg >> 3) & 0x1;
+	dc->dc_latchenb0     = (*reg >> 4) & 0x3;
+	dc->dc_latchenb1     = (*reg >> 6) & 0x3;
+	dc->dc_format        = (*reg >> 8) & 0x3;
+}
+
+static __inline void
+wiifb_dispcfg_write(struct wiifb_softc *sc, struct wiifb_dispcfg *dc)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_DISPCFG);
+
+	*reg = ((dc->dc_format & 0x3) << 8)        |
+	       ((dc->dc_latchenb1 & 0x3) << 6)     |
+	       ((dc->dc_latchenb0 & 0x3) << 4)     |
+	       ((dc->dc_3dmode & 0x1) << 3)        |
+	       ((dc->dc_noninterlaced & 0x1) << 2) |
+	       ((dc->dc_reset & 0x1) << 1)         |
+	        (dc->dc_enable & 0x1);
+	powerpc_sync();
+}
+
+/*
+ * Horizontal Timing 0
+ * 32 bit
+ */
+#define	WIIFB_REG_HTIMING0		0x04
+struct wiifb_htiming0 {
+	uint16_t	ht0_hlinew;	/* half line width */
+	uint8_t		ht0_hcolourend;
+	uint8_t		ht0_hcolourstart;
+};
+
+static __inline void
+wiifb_htiming0_read(struct wiifb_softc *sc, struct wiifb_htiming0 *ht0)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_HTIMING0);
+
+	ht0->ht0_hlinew       = *reg & 0x1ff;
+	ht0->ht0_hcolourend   = (*reg >> 16) & 0x7f;
+	ht0->ht0_hcolourstart = (*reg >> 24) & 0x7f;
+}
+
+static __inline void
+wiifb_htiming0_write(struct wiifb_softc *sc, struct wiifb_htiming0 *ht0)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_HTIMING0);
+
+	*reg = ((ht0->ht0_hcolourstart & 0x7f) << 24) |
+	       ((ht0->ht0_hcolourend & 0x7f) << 16)   |
+	        (ht0->ht0_hlinew & 0x1ff);
+	powerpc_sync();
+}
+/*
+ * Horizontal Timing 1
+ * 32 bit
+ */
+#define	WIIFB_REG_HTIMING1		0x08
+struct wiifb_htiming1 {
+	uint8_t		ht1_hsyncw;
+	uint16_t	ht1_hblankend;
+	uint16_t	ht1_hblankstart;
+};
+
+static __inline void
+wiifb_htiming1_read(struct wiifb_softc *sc, struct wiifb_htiming1 *ht1)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_HTIMING1);
+
+	ht1->ht1_hsyncw      = *reg & 0x7f;
+	ht1->ht1_hblankend   = (*reg >> 7) & 0x3ff;
+	ht1->ht1_hblankstart = (*reg >> 17) & 0x3ff;
+}
+
+static __inline void
+wiifb_htiming1_write(struct wiifb_softc *sc, struct wiifb_htiming1 *ht1)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_HTIMING1);
+
+	*reg = ((ht1->ht1_hblankstart & 0x3ff) << 17) |
+	       ((ht1->ht1_hblankend & 0x3ff) << 7)    |
+	        (ht1->ht1_hsyncw & 0x7f);
+	powerpc_sync();
+}
+
+/*
+ * Vertical Timing Odd
+ * 32 bit
+ */
+#define	WIIFB_REG_VTIMINGODD		0x0c
+struct wiifb_vtimingodd {
+	uint16_t	vto_preb;	/* pre blanking */
+	uint16_t	vto_postb;	/* post blanking */
+};
+
+static __inline void
+wiifb_vtimingodd_read(struct wiifb_softc *sc, struct wiifb_vtimingodd *vto)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_VTIMINGODD);
+
+	vto->vto_preb  = *reg & 0x3ff;
+	vto->vto_postb = (*reg >> 16) & 0x3ff;
+}
+
+static __inline void
+wiifb_vtimingodd_write(struct wiifb_softc *sc, struct wiifb_vtimingodd *vto)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_VTIMINGODD);
+
+	*reg = ((vto->vto_postb & 0x3ff) << 16) | 
+	        (vto->vto_preb & 0x3ff);
+	powerpc_sync();
+}
+
+/*
+ * Vertical Timing Even
+ * 32 bit
+ */
+#define	WIIFB_REG_VTIMINGEVEN		0x10
+struct wiifb_vtimingeven {
+	uint16_t	vte_preb;	/* pre blanking */
+	uint16_t	vte_postb;	/* post blanking */
+};
+
+static __inline void
+wiifb_vtimingeven_read(struct wiifb_softc *sc, struct wiifb_vtimingeven *vte)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_VTIMINGEVEN);
+
+	vte->vte_preb  = *reg & 0x3ff;
+	vte->vte_postb = (*reg >> 16) & 0x3ff;
+}
+
+static __inline void
+wiifb_vtimingeven_write(struct wiifb_softc *sc, struct wiifb_vtimingeven *vte)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_VTIMINGEVEN);
+
+	*reg = ((vte->vte_postb & 0x3ff) << 16) | 
+	        (vte->vte_preb & 0x3ff);
+	powerpc_sync();
+}
+
+/*
+ * Burst Blanking Odd Interval
+ * 32 bit
+ */
+#define	WIIFB_REG_BURSTBLANKODD		0x14
+struct wiifb_burstblankodd {
+	uint8_t		bbo_bs1;
+	uint16_t	bbo_be1;
+	uint8_t		bbo_bs3;
+	uint16_t	bbo_be3;
+};
+
+static __inline void
+wiifb_burstblankodd_read(struct wiifb_softc *sc,
+    struct wiifb_burstblankodd *bbo)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BURSTBLANKODD);
+
+	bbo->bbo_bs1 = *reg & 0x1f;
+	bbo->bbo_be1 = (*reg >> 5) & 0x7ff;
+	bbo->bbo_bs3 = (*reg >> 16) & 0x1f;
+	bbo->bbo_be3 = (*reg >> 21) & 0x7ff;
+}
+
+static __inline void
+wiifb_burstblankodd_write(struct wiifb_softc *sc,
+    struct wiifb_burstblankodd *bbo)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BURSTBLANKODD);
+
+	*reg = ((bbo->bbo_be3 & 0x7ff) << 21) |
+	       ((bbo->bbo_bs3 & 0x1f) << 16)  |
+	       ((bbo->bbo_be1 & 0x7ff) << 5)  |
+	        (bbo->bbo_bs1 & 0x1f);
+	powerpc_sync();
+}
+
+/*
+ * Burst Blanking Even Interval
+ * 32 bit
+ */
+#define	WIIFB_REG_BURSTBLANKEVEN	0x18
+struct wiifb_burstblankeven {
+	uint8_t		bbe_bs2;
+	uint16_t	bbe_be2;
+	uint8_t		bbe_bs4;
+	uint16_t	bbe_be4;
+};
+
+static __inline void
+wiifb_burstblankeven_read(struct wiifb_softc *sc,
+    struct wiifb_burstblankeven *bbe)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BURSTBLANKEVEN);
+
+	bbe->bbe_bs2 = *reg & 0x1f;
+	bbe->bbe_be2 = (*reg >> 5) & 0x7ff;
+	bbe->bbe_bs4 = (*reg >> 16) & 0x1f;
+	bbe->bbe_be4 = (*reg >> 21) & 0x7ff;
+}
+
+static __inline void
+wiifb_burstblankeven_write(struct wiifb_softc *sc,
+    struct wiifb_burstblankeven *bbe)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BURSTBLANKEVEN);
+
+	*reg = ((bbe->bbe_be4 & 0x7ff) << 21) |
+	       ((bbe->bbe_bs4 & 0x1f) << 16)  |
+	       ((bbe->bbe_be2 & 0x7ff) << 5)  |
+	        (bbe->bbe_bs2 & 0x1f);
+	powerpc_sync();
+}
+
+/*
+ * Top Field Base Left
+ * 32 bit
+ */
+#define	WIIFB_REG_TOPFIELDBASEL		0x1c
+struct wiifb_topfieldbasel {
+	uint32_t	tfbl_fbaddr;
+	uint8_t		tfbl_xoffset;
+	uint8_t		tfbl_pageoffbit;
+};
+
+static __inline void
+wiifb_topfieldbasel_read(struct wiifb_softc *sc,
+    struct wiifb_topfieldbasel *tfbl)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_TOPFIELDBASEL);
+
+	tfbl->tfbl_fbaddr     = *reg & 0xffffff;
+	tfbl->tfbl_xoffset    = (*reg >> 24) & 0xf;
+	tfbl->tfbl_pageoffbit = (*reg >> 28) & 0x1;
+}
+
+static __inline void
+wiifb_topfieldbasel_write(struct wiifb_softc *sc,
+    struct wiifb_topfieldbasel *tfbl)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_TOPFIELDBASEL);
+
+	*reg = ((tfbl->tfbl_pageoffbit & 0x1) << 28) |
+	       ((tfbl->tfbl_xoffset & 0xf) << 24)    |
+	        (tfbl->tfbl_fbaddr & 0xffffff);
+	powerpc_sync();
+}
+
+/*
+ * Top Field Base Right
+ * 32 bit
+ */
+#define	WIIFB_REG_TOPFIELDBASER		0x20
+struct wiifb_topfieldbaser {
+	uint32_t	tfbr_fbaddr;
+	uint8_t		tfbr_pageoffbit;
+};
+
+static __inline void
+wiifb_topfieldbaser_read(struct wiifb_softc *sc,
+    struct wiifb_topfieldbaser *tfbr)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_TOPFIELDBASER);
+
+	tfbr->tfbr_fbaddr     = *reg & 0xffffff;
+	tfbr->tfbr_pageoffbit = (*reg >> 28) & 0x1;
+}
+
+static __inline void
+wiifb_topfieldbaser_write(struct wiifb_softc *sc,
+    struct wiifb_topfieldbaser *tfbr)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_TOPFIELDBASER);
+
+	*reg  = ((tfbr->tfbr_pageoffbit & 0x1) << 28) |
+		 (tfbr->tfbr_fbaddr & 0xffffff);
+	powerpc_sync();
+}
+
+/*
+ * Bottom Field Base Left
+ * 32 bit
+ */
+#define	WIIFB_REG_BOTTOMFIELDBASEL	0x24
+struct wiifb_bottomfieldbasel {
+	uint32_t	bfbl_fbaddr;
+	uint8_t		bfbl_xoffset;
+	uint8_t		bfbl_pageoffbit;
+};
+
+static __inline void
+wiifb_bottomfieldbasel_read(struct wiifb_softc *sc,
+    struct wiifb_bottomfieldbasel *bfbl)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BOTTOMFIELDBASEL);
+
+	bfbl->bfbl_fbaddr     = *reg & 0xffffff;
+	bfbl->bfbl_xoffset    = (*reg >> 24) & 0xf;
+	bfbl->bfbl_pageoffbit = (*reg >> 28) & 0x1;
+}
+
+static __inline void
+wiifb_bottomfieldbasel_write(struct wiifb_softc *sc,
+    struct wiifb_bottomfieldbasel *bfbl)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BOTTOMFIELDBASEL);
+
+	*reg  = ((bfbl->bfbl_pageoffbit & 0x1) << 28) |
+	        ((bfbl->bfbl_xoffset & 0xf) << 24)    |
+		 (bfbl->bfbl_fbaddr & 0xffffff);
+	powerpc_sync();
+}
+
+/*
+ * Bottom Field Base Right
+ * 32 bit
+ */
+#define	WIIFB_REG_BOTTOMFIELDBASER	0x28
+struct wiifb_bottomfieldbaser {
+	uint32_t	bfbr_fbaddr;
+	uint8_t		bfbr_pageoffbit;
+};
+
+static __inline void
+wiifb_bottomfieldbaser_read(struct wiifb_softc *sc,
+    struct wiifb_bottomfieldbaser *bfbr)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BOTTOMFIELDBASER);
+
+	bfbr->bfbr_fbaddr     = *reg & 0xffffff;
+	bfbr->bfbr_pageoffbit = (*reg >> 28) & 0x1;
+}
+
+static __inline void
+wiifb_bottomfieldbaser_write(struct wiifb_softc *sc,
+    struct wiifb_bottomfieldbaser *bfbr)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BOTTOMFIELDBASER);
+
+	*reg  = ((bfbr->bfbr_pageoffbit & 0x1) << 28) |
+		 (bfbr->bfbr_fbaddr & 0xffffff);
+	powerpc_sync();
+}
+
+/*
+ * Display Position Vertical
+ * 16 bit
+ */
+#define	WIIFB_REG_DISPPOSV		0x2c
+static __inline uint16_t
+wiifb_dispposv_read(struct wiifb_softc *sc)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_DISPPOSV);
+
+	return (*reg & 0x7ff);
+}
+
+static __inline void
+wiifb_dispposv_write(struct wiifb_softc *sc, uint16_t val)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_DISPPOSV);
+
+	*reg = val & 0x7ff;
+	powerpc_sync();
+}
+
+/*
+ * Display Position Horizontal
+ * 16 bit
+ */
+#define	WIIFB_REG_DISPPOSH		0x2e
+static __inline uint16_t
+wiifb_dispposh_read(struct wiifb_softc *sc)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_DISPPOSH);
+
+	return (*reg & 0x7ff);
+}
+
+static __inline void
+wiifb_dispposh_write(struct wiifb_softc *sc, uint16_t val)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_DISPPOSH);
+
+	*reg = val & 0x7ff;
+	powerpc_sync();
+}
+
+/*
+ * Display Interrupts.
+ * There are 4 display interrupt registers, all 32 bit.
+ */
+#define	WIIFB_REG_DISPINT0		0x30
+#define	WIIFB_REG_DISPINT1		0x34
+#define	WIIFB_REG_DISPINT2		0x38
+#define	WIIFB_REG_DISPINT3		0x3c
+struct wiifb_dispint {
+	uint16_t	di_htiming;
+	uint16_t	di_vtiming;
+	uint8_t		di_enable;
+	uint8_t		di_irq;
+};
+
+static __inline void
+wiifb_dispint_read(struct wiifb_softc *sc, int regno, struct wiifb_dispint *di)
+{
+	volatile uint32_t *reg = (uint32_t *)(sc->sc_reg_addr +
+	    WIIFB_REG_DISPINT0 + regno * 4);
+
+	di->di_htiming = *reg & 0x3ff;
+	di->di_vtiming = (*reg >> 16) & 0x3ff;
+	di->di_enable   = (*reg >> 28) & 0x1;
+	di->di_irq      = (*reg >> 31) & 0x1;
+}
+
+static __inline void
+wiifb_dispint_write(struct wiifb_softc *sc, int regno, struct wiifb_dispint *di)
+{
+	volatile uint32_t *reg = (uint32_t *)(sc->sc_reg_addr +
+	    WIIFB_REG_DISPINT0 + regno * 4);
+
+	*reg = ((di->di_irq & 0x1) << 31)        |
+	       ((di->di_enable & 0x1) << 28)     |
+	       ((di->di_vtiming & 0x3ff) << 16)  |
+	        (di->di_htiming & 0x3ff);
+	powerpc_sync();
+}
+
+/*
+ * Display Latch 0
+ * 32 bit
+ */
+#define	WIIFB_REG_DISPLAYTCH0		0x40
+
+/*
+ * Display Latch 1
+ * 32 bit
+ */
+#define	WIIFB_REG_DISPLAYTCH1		0x44
+
+/*
+ * Picture Configuration
+ * 16 bit
+ */
+#define	WIIFB_REG_PICCONF		0x48
+struct wiifb_picconf {
+	uint8_t		pc_strides;	/* strides per line (words) */
+	uint8_t		pc_reads;	/* reads per line (words */
+};
+
+static __inline void
+wiifb_picconf_read(struct wiifb_softc *sc, struct wiifb_picconf *pc)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_PICCONF);
+
+	pc->pc_strides = *reg & 0xff;
+	pc->pc_reads   = (*reg >> 8) & 0xff;
+}
+
+static __inline void
+wiifb_picconf_write(struct wiifb_softc *sc, struct wiifb_picconf *pc)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_PICCONF);
+
+	*reg = ((pc->pc_reads & 0xff) << 8) |
+	        (pc->pc_strides & 0xff);
+	powerpc_sync();
+}
+
+/*
+ * Horizontal Scaling
+ * 16 bit
+ */
+#define	WIIFB_REG_HSCALING		0x4a
+struct wiifb_hscaling {
+	uint16_t	hs_step;
+	uint8_t		hs_enable;
+};
+
+static __inline void
+wiifb_hscaling_read(struct wiifb_softc *sc, struct wiifb_hscaling *hs)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_HSCALING);
+
+	hs->hs_step   = *reg & 0x1ff;
+	hs->hs_enable = (*reg >> 12) & 0x1;
+}
+
+static __inline void
+wiifb_hscaling_write(struct wiifb_softc *sc, struct wiifb_hscaling *hs)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_HSCALING);
+
+	*reg = ((hs->hs_step & 0x1ff) << 12) |
+	        (hs->hs_enable & 0x1);
+	powerpc_sync();
+}
+
+/*
+ * Filter Coeficient Table 0-6
+ * 32 bit
+ */
+#define	WIIFB_REG_FILTCOEFT0		0x4c
+#define	WIIFB_REG_FILTCOEFT1		0x50
+#define	WIIFB_REG_FILTCOEFT2		0x54
+#define	WIIFB_REG_FILTCOEFT3		0x58
+#define	WIIFB_REG_FILTCOEFT4		0x5c
+#define	WIIFB_REG_FILTCOEFT5		0x60
+#define	WIIFB_REG_FILTCOEFT6		0x64
+static __inline void
+wiifb_filtcoeft_write(struct wiifb_softc *sc, unsigned int regno,
+    uint32_t coeft)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_FILTCOEFT0 + 4 * regno);
+
+	*reg = coeft;
+	powerpc_sync();
+}
+
+/*
+ * Anti-aliasing
+ * 32 bit
+ */
+#define	WIIFB_REG_ANTIALIAS		0x68
+static __inline void
+wiifb_antialias_write(struct wiifb_softc *sc, uint32_t antialias)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_ANTIALIAS);
+
+	*reg = antialias;
+	powerpc_sync();
+}
+
+/*
+ * Video Clock
+ * 16 bit
+ */
+#define	WIIFB_REG_VIDEOCLK		0x6c
+static __inline uint8_t
+wiifb_videoclk_read(struct wiifb_softc *sc)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_VIDEOCLK);
+
+	return (*reg & 0x1);
+}
+
+static __inline void
+wiifb_videoclk_write(struct wiifb_softc *sc, uint16_t clk54mhz)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_VIDEOCLK);
+
+	*reg = clk54mhz & 0x1;
+	powerpc_sync();
+}
+
+/*
+ * DTV Status
+ * 16 bit
+ *
+ * DTV is another name for the Component Cable output.
+ */
+#define	WIIFB_REG_DTVSTATUS		0x6e
+static __inline uint16_t
+wiifb_dtvstatus_read(struct wiifb_softc *sc)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_DTVSTATUS);
+
+	return (*reg & 0x1);
+}
+
+static __inline uint16_t
+wiifb_component_enabled(struct wiifb_softc *sc)
+{
+	
+	return wiifb_dtvstatus_read(sc);
+}
+
+/*
+ * Horizontal Scaling Width
+ * 16 bit
+ */
+#define	WIIFB_REG_HSCALINGW		0x70
+static __inline uint16_t
+wiifb_hscalingw_read(struct wiifb_softc *sc)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_HSCALINGW);
+
+	return (*reg & 0x3ff);
+}
+
+static __inline void
+wiifb_hscalingw_write(struct wiifb_softc *sc, uint16_t width)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_HSCALINGW);
+
+	*reg = width & 0x3ff;
+	powerpc_sync();
+}
+
+/* 
+ * Horizontal Border End
+ * For debug mode only. Not used by this driver.
+ * 16 bit
+ */
+#define	WIIFB_REG_HBORDEREND		0x72
+static __inline void
+wiifb_hborderend_write(struct wiifb_softc *sc, uint16_t border)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_HBORDEREND);
+
+	*reg = border;
+	powerpc_sync();
+}
+
+/* 
+ * Horizontal Border Start
+ * 16 bit
+ */
+#define	WIIFB_REG_HBORDERSTART		0x74
+static __inline void
+wiifb_hborderstart_write(struct wiifb_softc *sc, uint16_t border)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_HBORDERSTART);
+
+	*reg = border;
+	powerpc_sync();
+}
+
+/*
+ * Unknown register
+ * 16 bit
+ */
+#define	WIIFB_REG_UNKNOWN1		0x76
+static __inline void
+wiifb_unknown1_write(struct wiifb_softc *sc, uint16_t unknown)
+{
+	volatile uint16_t *reg =
+	    (uint16_t *)(sc->sc_reg_addr + WIIFB_REG_UNKNOWN1);
+
+	*reg = unknown;
+	powerpc_sync();
+}
+
+/* 
+ * Unknown register
+ * 32 bit
+ */
+#define	WIIFB_REG_UNKNOWN2		0x78
+static __inline void
+wiifb_unknown2_write(struct wiifb_softc *sc, uint32_t unknown)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_UNKNOWN2);
+
+	*reg = unknown;
+	powerpc_sync();
+}
+
+/*
+ * Unknown register
+ * 32 bit
+ */
+#define	WIIFB_REG_UNKNOWN3		0x7c
+static __inline void
+wiifb_unknown3_write(struct wiifb_softc *sc, uint32_t unknown)
+{
+	volatile uint32_t *reg =
+	    (uint32_t *)(sc->sc_reg_addr + WIIFB_REG_UNKNOWN3);
+
+	*reg = unknown;
+	powerpc_sync();
+}
+
+#endif /* _POWERPC_WII_WIIFB_H */


Property changes on: trunk/sys/powerpc/wii/wii_fbvar.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/wii_gpio.c
===================================================================
--- trunk/sys/powerpc/wii/wii_gpio.c	                        (rev 0)
+++ trunk/sys/powerpc/wii/wii_gpio.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,354 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/wii/wii_gpio.c 278786 2015-02-14 21:16:19Z loos $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/gpio.h>
+#include <sys/reboot.h>
+
+#include <machine/bus.h>
+#include <machine/platform.h>
+#include <machine/intr_machdep.h>
+#include <machine/resource.h>
+
+#include <powerpc/wii/wii_gpioreg.h>
+
+#include "gpio_if.h"
+
+struct wiigpio_softc {
+	device_t		 sc_dev;
+	struct resource		*sc_rres;
+	bus_space_tag_t		 sc_bt;
+	bus_space_handle_t	 sc_bh;
+	int			 sc_rrid;
+	struct mtx		 sc_mtx;
+	struct gpio_pin		 sc_pins[WIIGPIO_NPINS];
+};
+
+
+#define	WIIGPIO_PINBANK(_p)	((_p) / (WIIGPIO_NPINS / 2))
+#define	WIIGPIO_PINMASK(_p)	(1 << ((_p) % (WIIGPIO_NPINS / 2)))
+#define WIIGPIO_LOCK(sc)	mtx_lock(&(sc)->sc_mtx)
+#define WIIGPIO_UNLOCK(sc)	mtx_unlock(&(sc)->sc_mtx)
+
+static int	wiigpio_probe(device_t);
+static int	wiigpio_attach(device_t);
+static int	wiigpio_detach(device_t);
+static int	wiigpio_pin_max(device_t, int *);
+static int	wiigpio_pin_getname(device_t, uint32_t, char *);
+static int	wiigpio_pin_getflags(device_t, uint32_t, uint32_t *);
+static int	wiigpio_pin_setflags(device_t, uint32_t, uint32_t);
+static int	wiigpio_pin_getcaps(device_t, uint32_t, uint32_t *);
+static int	wiigpio_pin_get(device_t, uint32_t, unsigned int *);
+static int	wiigpio_pin_set(device_t, uint32_t, unsigned int);
+static int	wiigpio_pin_toggle(device_t, uint32_t);
+static void	wiigpio_shutdown(void *, int);
+
+static device_method_t wiigpio_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		wiigpio_probe),
+	DEVMETHOD(device_attach,	wiigpio_attach),
+	DEVMETHOD(device_detach,	wiigpio_detach),
+
+	/* GPIO protocol */
+	DEVMETHOD(gpio_pin_max,		wiigpio_pin_max),
+	DEVMETHOD(gpio_pin_getname,	wiigpio_pin_getname),
+	DEVMETHOD(gpio_pin_getflags,	wiigpio_pin_getflags),
+	DEVMETHOD(gpio_pin_setflags,	wiigpio_pin_setflags),
+	DEVMETHOD(gpio_pin_getcaps,	wiigpio_pin_getcaps),
+	DEVMETHOD(gpio_pin_get,		wiigpio_pin_get),
+	DEVMETHOD(gpio_pin_set,		wiigpio_pin_set),
+	DEVMETHOD(gpio_pin_toggle,	wiigpio_pin_toggle),
+
+        DEVMETHOD_END
+};
+
+static driver_t wiigpio_driver = {
+	"wiigpio",
+	wiigpio_methods,
+	sizeof(struct wiigpio_softc)
+};
+
+static devclass_t wiigpio_devclass;
+
+DRIVER_MODULE(wiigpio, wiibus, wiigpio_driver, wiigpio_devclass, 0, 0);
+
+static __inline uint32_t
+wiigpio_read(struct wiigpio_softc *sc, int n)
+{
+
+	return (bus_space_read_4(sc->sc_bt, sc->sc_bh, n * 0x20));
+}
+
+static __inline void
+wiigpio_write(struct wiigpio_softc *sc, int n, uint32_t reg)
+{
+
+	bus_space_write_4(sc->sc_bt, sc->sc_bh, n * 0x20, reg);
+}
+
+static __inline uint32_t
+wiigpio_dir_read(struct wiigpio_softc *sc, int n)
+{
+
+	return (bus_space_read_4(sc->sc_bt, sc->sc_bh, n * 0x20 + 4));
+}
+
+static __inline void
+wiigpio_dir_write(struct wiigpio_softc *sc, int n, uint32_t reg)
+{
+
+	bus_space_write_4(sc->sc_bt, sc->sc_bh, n * 0x20 + 4, reg);
+}
+
+static int
+wiigpio_probe(device_t dev)
+{
+        device_set_desc(dev, "Nintendo Wii GPIO");
+
+        return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+wiigpio_attach(device_t dev)
+{
+	struct wiigpio_softc *sc;
+	int i;
+	uint32_t d;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+	sc->sc_rrid = 0;
+	sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->sc_rrid, RF_ACTIVE);
+	if (sc->sc_rres == NULL) {
+		device_printf(dev, "could not alloc mem resource\n");
+		return (ENXIO);
+	}
+	sc->sc_bt = rman_get_bustag(sc->sc_rres);
+	sc->sc_bh = rman_get_bushandle(sc->sc_rres);
+	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+#ifdef WIIGPIO_DEBUG
+	device_printf(dev, "dir bank0=0x%08x bank1=0x%08x\n",
+	    wiigpio_dir_read(sc, 0), wiigpio_dir_read(sc, 1));
+	device_printf(dev, "val bank0=0x%08x bank1=0x%08x\n",
+	    wiigpio_read(sc, 0), wiigpio_read(sc, 1));
+#endif
+	for (i = 0; i < WIIGPIO_NPINS; i++) {
+		sc->sc_pins[i].gp_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
+		sc->sc_pins[i].gp_pin = i;
+		d = wiigpio_dir_read(sc, WIIGPIO_PINBANK(i));
+		if (d & WIIGPIO_PINMASK(i))
+			sc->sc_pins[i].gp_flags = GPIO_PIN_OUTPUT;
+		else
+			sc->sc_pins[i].gp_flags = GPIO_PIN_INPUT;
+		snprintf(sc->sc_pins[i].gp_name, GPIOMAXNAME, "PIN %d", i);
+#ifdef WIIGPIO_DEBUG
+		device_printf(dev, "PIN %d state %d flag %s\n", i,
+		    wiigpio_read(sc, WIIGPIO_PINBANK(i)) >> 
+			(i % (WIIGPIO_NPINS / 2)) & 1,
+		    sc->sc_pins[i].gp_flags == GPIO_PIN_INPUT ?
+		    "GPIO_PIN_INPUT" : "GPIO_PIN_OUTPUT");
+#endif
+	}
+	device_add_child(dev, "gpioc", -1);
+	device_add_child(dev, "gpiobus", -1);
+	/*
+	 * We will be responsible for powering off the system.
+	 */
+	EVENTHANDLER_REGISTER(shutdown_final, wiigpio_shutdown, dev,
+	    SHUTDOWN_PRI_LAST);
+
+	return (bus_generic_attach(dev));
+}
+
+static int
+wiigpio_detach(device_t dev)
+{
+	struct wiigpio_softc *sc;
+
+	sc = device_get_softc(dev);
+	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres);
+	mtx_destroy(&sc->sc_mtx);
+
+	return (0);
+}
+
+static int
+wiigpio_pin_max(device_t dev, int *maxpin)
+{
+	
+	*maxpin = WIIGPIO_NPINS - 1;
+
+	return (0);
+}
+
+static int
+wiigpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+	struct wiigpio_softc *sc;
+
+	if (pin >= WIIGPIO_NPINS)
+		return (EINVAL);
+	sc = device_get_softc(dev);
+	*caps = sc->sc_pins[pin].gp_caps;
+
+	return (0);
+}
+
+static int
+wiigpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+{
+	struct wiigpio_softc *sc;
+	uint32_t reg;
+
+	if (pin >= WIIGPIO_NPINS)
+		return (EINVAL);
+	sc = device_get_softc(dev);
+	WIIGPIO_LOCK(sc);
+	reg = wiigpio_read(sc, WIIGPIO_PINBANK(pin));
+	*val = !!(reg & WIIGPIO_PINMASK(pin));
+	WIIGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+wiigpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+	struct wiigpio_softc *sc;
+	uint32_t reg, pinbank, pinmask;
+
+	if (pin >= WIIGPIO_NPINS)
+		return (EINVAL);
+	sc = device_get_softc(dev);
+	pinbank = WIIGPIO_PINBANK(pin);
+	pinmask = WIIGPIO_PINMASK(pin);
+	WIIGPIO_LOCK(sc);
+	reg = wiigpio_read(sc, pinbank) & ~pinmask;
+	if (value)
+		reg |= pinmask;
+	wiigpio_write(sc, pinbank, reg);
+	WIIGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+wiigpio_pin_toggle(device_t dev, uint32_t pin)
+{
+	struct wiigpio_softc *sc;
+	uint32_t val, pinbank, pinmask;
+
+	if (pin >= WIIGPIO_NPINS)
+		return (EINVAL);
+	sc = device_get_softc(dev);
+	pinbank = WIIGPIO_PINBANK(pin);
+	pinmask = WIIGPIO_PINMASK(pin);
+	WIIGPIO_LOCK(sc);
+	val = wiigpio_read(sc, pinbank);
+	if (val & pinmask)
+		wiigpio_write(sc, pinbank, val & ~pinmask);
+	else
+		wiigpio_write(sc, pinbank, val | pinmask);
+	WIIGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+wiigpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+	struct wiigpio_softc *sc;
+	uint32_t reg, pinbank, pinmask;
+
+	if (pin >= WIIGPIO_NPINS)
+		return (EINVAL);
+	sc = device_get_softc(dev);
+	pinbank = WIIGPIO_PINBANK(pin);
+	pinmask = WIIGPIO_PINMASK(pin);
+	WIIGPIO_LOCK(sc);
+	reg = wiigpio_dir_read(sc, WIIGPIO_PINBANK(pin));
+	if (flags & GPIO_PIN_OUTPUT)
+		wiigpio_dir_write(sc, pinbank, reg | pinmask);
+	else
+		wiigpio_dir_write(sc, pinbank, reg & ~pinmask);
+	sc->sc_pins[pin].gp_flags = flags;
+	WIIGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+wiigpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+	struct wiigpio_softc *sc;
+
+	if (pin >= WIIGPIO_NPINS)
+		return (EINVAL);
+	sc = device_get_softc(dev);
+	WIIGPIO_LOCK(sc);
+	*flags = sc->sc_pins[pin].gp_flags;
+	WIIGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+wiigpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+	struct wiigpio_softc *sc;
+
+	if (pin >= WIIGPIO_NPINS)
+		return (EINVAL);
+	sc = device_get_softc(dev);
+	WIIGPIO_LOCK(sc);
+	memcpy(name, sc->sc_pins[pin].gp_name, GPIOMAXNAME);
+	WIIGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static void
+wiigpio_shutdown(void *xdev, int howto)
+{
+	device_t dev;
+
+	if (!(howto & RB_POWEROFF))
+		return;
+	dev = (device_t)xdev;
+	wiigpio_pin_setflags(dev, WIIGPIO_POWEROFF_PIN, GPIO_PIN_OUTPUT);
+	wiigpio_pin_set(dev, WIIGPIO_POWEROFF_PIN, 1);
+}


Property changes on: trunk/sys/powerpc/wii/wii_gpio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/wii_gpioreg.h
===================================================================
--- trunk/sys/powerpc/wii/wii_gpioreg.h	                        (rev 0)
+++ trunk/sys/powerpc/wii/wii_gpioreg.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,39 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/wii/wii_gpioreg.h 250788 2013-05-18 19:30:42Z rpaulo $
+ */
+
+#ifndef	_POWERPC_WII_WII_GPIOREG_H
+#define	_POWERPC_WII_WII_GPIOREG_H
+
+#define	WIIGPIO_NPINS		64
+#define	WIIGPIO_POWEROFF_PIN	33
+
+#define	WIIGPIO_REG_ADDR	0x0d8000c0
+#define	WIIGPIO_REG_LEN		0x40
+
+#endif	/* _POWERPC_WII_WII_GPIOREG_H */


Property changes on: trunk/sys/powerpc/wii/wii_gpioreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/wii_ipc.c
===================================================================
--- trunk/sys/powerpc/wii/wii_ipc.c	                        (rev 0)
+++ trunk/sys/powerpc/wii/wii_ipc.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,103 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/wii/wii_ipc.c 246655 2013-02-11 08:20:21Z rpaulo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/platform.h>
+#include <machine/intr_machdep.h>
+#include <machine/resource.h>
+
+#include <powerpc/wii/wii_ipcreg.h>
+
+/*
+ * Driver to interface with the Wii's IOS. IOS are small "microkernels" that run
+ * on the Broadway GPU and provide access to system services like USB.
+ */
+static int	wiiipc_probe(device_t);
+static int	wiiipc_attach(device_t);
+
+struct wiiipc_softc {
+};
+
+static device_method_t wiiipc_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		wiiipc_probe),
+	DEVMETHOD(device_attach,	wiiipc_attach),
+
+	DEVMETHOD_END
+};
+
+static driver_t wiiipc_driver = {
+	"wiiipc",
+	wiiipc_methods,
+	sizeof(struct wiiipc_softc)
+};
+
+static devclass_t wiiipc_devclass;
+
+DRIVER_MODULE(wiiipc, wiibus, wiiipc_driver, wiiipc_devclass, 0, 0);
+
+static int
+wiiipc_probe(device_t dev)
+{
+        device_set_desc(dev, "Nintendo Wii IOS IPC");
+
+        return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+wiiipc_attach(device_t dev)
+{
+	struct wiiipc_softc *sc;
+
+	sc = device_get_softc(dev);
+#ifdef notyet
+	sc->sc_dev = dev;
+
+	sc->sc_rrid = 0;
+	sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->sc_rrid, RF_ACTIVE);
+	if (sc->sc_rres == NULL) {
+		device_printf(dev, "could not alloc mem resource\n");
+		return (ENXIO);
+	}
+	sc->sc_bt = rman_get_bustag(sc->sc_rres);
+	sc->sc_bh = rman_get_bushandle(sc->sc_rres);
+#endif
+
+	return (0);
+}


Property changes on: trunk/sys/powerpc/wii/wii_ipc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/wii_ipcreg.h
===================================================================
--- trunk/sys/powerpc/wii/wii_ipcreg.h	                        (rev 0)
+++ trunk/sys/powerpc/wii/wii_ipcreg.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,103 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/wii/wii_ipcreg.h 252500 2013-07-02 07:17:56Z rpaulo $
+ */
+
+#ifndef	_POWERPC_WII_WII_IPCREG_H
+#define	_POWERPC_WII_WII_IPCREG_H
+
+#define	WIIIPC_REG_ADDR		0x0d000000
+#define	WIIIPC_REG_LEN		0x40
+#define	WIIIPC_IOH_ADDR		0x133e0000
+#define	WIIIPC_IOH_LEN		0xc20000
+
+#define	WIIIPC_TXBUF		0x00
+#define	WIIIPC_CSR		0x04
+#define	WIIIPC_CSR_TXSTART	0x01
+#define	WIIIPC_CSR_TBEI		0x02
+#define	WIIIPC_CSR_RBFI		0x04
+#define	WIIIPC_CSR_RXREADY	0x08
+#define	WIIIPC_CSR_RBFIMASK	0x10
+#define	WIIIPC_CSR_TBEIMASK	0x20
+#define	WIIIPC_RXBUF		0x08
+#define	WIIIPC_ISR		0x30
+#define	WIIIPC_ISR_MAGIC 	0x40000000
+
+enum wiiipc_cmd {
+	WIIIPC_CMD_OPEN		= 1,
+	WIIIPC_CMD_CLOSE	= 2,
+	WIIIPC_CMD_READ		= 3,
+	WIIIPC_CMD_WRITE	= 4,
+	WIIIPC_CMD_SEEK		= 5,
+	WIIIPC_CMD_IOCTL	= 6,
+	WIIIPC_CMD_IOCTLV	= 7,
+	WIIIPC_CMD_ASYNCRESP	= 8
+};
+
+struct wiiipc_ipc_msg {
+	uint32_t	ipc_cmd;
+	int32_t		ipc_result;
+	int32_t	 	ipc_fd;	/* WIIIPC_CMD_ASYNCRESP - the original cmd */
+	union {
+		struct {
+			intptr_t  pathname;
+			uint32_t  mode;
+		} _ipc_open;
+		struct {
+			intptr_t  data;
+			uint32_t  len;
+		} _ipc_read, _ipc_write;
+		struct {
+			int32_t   offset;
+			int32_t   whence;
+		} _ipc_seek;
+		struct {
+			uint32_t  request;
+			intptr_t  ibuf;
+			uint32_t  ilen;
+			intptr_t  obuf;
+			uint32_t  olen;
+		} _ipc_ioctl;
+		struct {
+			uint32_t  request;
+			uint32_t  argin;
+			uint32_t  argout;
+			intptr_t  iovec;
+		} _ipc_ioctlv;
+		uint32_t _ipc_argv[5];
+	} args;
+} __attribute__((packed));
+
+CTASSERT(sizeof(struct wiiipc_ipc_msg) == 32);
+
+#define	ipc_open 	args._ipc_open
+#define	ipc_read	args._ipc_read
+#define	ipc_write	args._ipc_write
+#define	ipc_ioctl 	args._ipc_ioctl
+#define	ipc_ioctlv	args._ipc_ioctlv
+
+#endif	/* _POWERPC_WII_WII_IPCREG_H */


Property changes on: trunk/sys/powerpc/wii/wii_ipcreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/wii_pic.c
===================================================================
--- trunk/sys/powerpc/wii/wii_pic.c	                        (rev 0)
+++ trunk/sys/powerpc/wii/wii_pic.c	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,245 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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.
+ *
+ * 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/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/powerpc/wii/wii_pic.c 249826 2013-04-24 01:36:35Z rpaulo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/reboot.h>
+
+#include <machine/bus.h>
+#include <machine/platform.h>
+#include <machine/intr_machdep.h>
+#include <machine/resource.h>
+
+#include <powerpc/wii/wii_picreg.h>
+
+#include "pic_if.h"
+
+static int	wiipic_probe(device_t);
+static int	wiipic_attach(device_t);
+static void	wiipic_dispatch(device_t, struct trapframe *);
+static void	wiipic_enable(device_t, unsigned int, unsigned int);
+static void	wiipic_eoi(device_t, unsigned int);
+static void	wiipic_mask(device_t, unsigned int);
+static void	wiipic_unmask(device_t, unsigned int);
+static void	wiipic_intr(void *);
+
+struct wiipic_softc {
+	device_t		 sc_dev;
+	struct resource		*sc_rres;
+	bus_space_tag_t		 sc_bt;
+	bus_space_handle_t	 sc_bh;
+	int			 sc_rrid;
+	int			 sc_irqid;
+	struct resource		*sc_irq;
+	void			*sc_irqctx;
+	int			 sc_vector[WIIPIC_NIRQ];
+};
+
+static device_method_t wiipic_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		wiipic_probe),
+	DEVMETHOD(device_attach,	wiipic_attach),
+
+	/* PIC interface */
+	DEVMETHOD(pic_dispatch,		wiipic_dispatch),
+	DEVMETHOD(pic_enable,		wiipic_enable),
+	DEVMETHOD(pic_eoi,		wiipic_eoi),
+	DEVMETHOD(pic_mask,		wiipic_mask),
+	DEVMETHOD(pic_unmask,		wiipic_unmask),
+
+        DEVMETHOD_END
+};
+
+static driver_t wiipic_driver = {
+	"wiipic",
+	wiipic_methods,
+	sizeof(struct wiipic_softc)
+};
+
+static devclass_t wiipic_devclass;
+
+DRIVER_MODULE(wiipic, wiibus, wiipic_driver, wiipic_devclass, 0, 0);
+
+static __inline uint32_t
+wiipic_imr_read(struct wiipic_softc *sc)
+{
+
+	return (bus_space_read_4(sc->sc_bt, sc->sc_bh, WIIPIC_IMR));
+}
+
+static __inline void
+wiipic_imr_write(struct wiipic_softc *sc, uint32_t imr)
+{
+
+	bus_space_write_4(sc->sc_bt, sc->sc_bh, WIIPIC_IMR, imr);
+}
+
+static __inline uint32_t
+wiipic_icr_read(struct wiipic_softc *sc)
+{
+
+	return (bus_space_read_4(sc->sc_bt, sc->sc_bh, WIIPIC_ICR));
+}
+
+static __inline void
+wiipic_icr_write(struct wiipic_softc *sc, uint32_t icr)
+{
+
+	bus_space_write_4(sc->sc_bt, sc->sc_bh, WIIPIC_ICR, icr);
+}
+
+static int
+wiipic_probe(device_t dev)
+{
+        device_set_desc(dev, "Nintendo Wii PIC");
+
+        return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+wiipic_attach(device_t dev)
+{
+	struct wiipic_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+
+	sc->sc_rrid = 0;
+	sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->sc_rrid, RF_ACTIVE);
+	if (sc->sc_rres == NULL) {
+		device_printf(dev, "could not alloc mem resource\n");
+		return (ENXIO);
+	}
+	sc->sc_bt = rman_get_bustag(sc->sc_rres);
+	sc->sc_bh = rman_get_bushandle(sc->sc_rres);
+
+	/* Turn off all interrupts */
+	wiipic_imr_write(sc, 0x00000000);
+	wiipic_icr_write(sc, 0xffffffff);
+
+	powerpc_register_pic(dev, 0, WIIPIC_NIRQ, 0, FALSE);
+
+	/*
+	 * Setup the interrupt handler.
+	 */
+	sc->sc_irqid = 0;
+	sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid,
+	    RF_ACTIVE);
+	if (sc->sc_irq == NULL) {
+		device_printf(dev, "could not alloc IRQ resource\n");
+		return (ENXIO);
+	}
+	bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE,
+	    NULL, wiipic_intr, sc, &sc->sc_irqctx);
+
+	return (0);
+}
+
+static void
+wiipic_dispatch(device_t dev, struct trapframe *tf)
+{
+	struct wiipic_softc *sc;
+	uint32_t irq;
+
+	sc = device_get_softc(dev);
+	irq = wiipic_icr_read(sc) & wiipic_imr_read(sc);
+	if (irq == 0)
+		return;
+	irq = ffs(irq) - 1;
+	KASSERT(irq < WIIPIC_NIRQ, ("bogus irq %d", irq));
+	powerpc_dispatch_intr(sc->sc_vector[irq], tf);
+}
+
+static void
+wiipic_enable(device_t dev, unsigned int irq, unsigned int vector)
+{
+	struct wiipic_softc *sc;
+
+	KASSERT(irq < WIIPIC_NIRQ, ("bogus irq %d", irq));
+	sc = device_get_softc(dev);
+	sc->sc_vector[irq] = vector;
+	wiipic_unmask(dev, irq);
+}
+
+static void
+wiipic_eoi(device_t dev, unsigned int irq)
+{
+	struct wiipic_softc *sc;
+	uint32_t icr;
+
+	sc = device_get_softc(dev);
+	icr = wiipic_icr_read(sc);
+	icr |= (1 << irq);
+	wiipic_icr_write(sc, icr);
+}
+
+static void
+wiipic_mask(device_t dev, unsigned int irq)
+{
+	struct wiipic_softc *sc;
+	uint32_t imr;
+
+	sc = device_get_softc(dev);
+	imr = wiipic_imr_read(sc);
+	imr &= ~(1 << irq);
+	wiipic_imr_write(sc, imr);
+}
+
+static void
+wiipic_unmask(device_t dev, unsigned int irq)
+{
+	struct wiipic_softc *sc;
+	uint32_t imr;
+
+	sc = device_get_softc(dev);
+	imr = wiipic_imr_read(sc);
+	imr |= (1 << irq);
+	wiipic_imr_write(sc, imr);
+}
+
+/*
+ * Reset button interrupt.
+ */
+static void
+wiipic_intr(void *xsc)
+{
+	struct wiipic_softc *sc;
+
+	sc = (struct wiipic_softc *)xsc;
+	if (wiipic_icr_read(sc) & WIIPIC_RBS)
+		shutdown_nice(RB_AUTOBOOT);
+}
+


Property changes on: trunk/sys/powerpc/wii/wii_pic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/powerpc/wii/wii_picreg.h
===================================================================
--- trunk/sys/powerpc/wii/wii_picreg.h	                        (rev 0)
+++ trunk/sys/powerpc/wii/wii_picreg.h	2018-05-25 12:54:08 UTC (rev 9916)
@@ -0,0 +1,43 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD: stable/10/sys/powerpc/wii/wii_picreg.h 249826 2013-04-24 01:36:35Z rpaulo $
+ */
+
+#ifndef	_POWERPC_WII_WII_PICREG_H
+#define	_POWERPC_WII_WII_PICREG_H
+
+#define	WIIPIC_REG_ADDR		0x0c003000
+#define	WIIPIC_REG_LEN		0x28
+
+#define	WIIPIC_ICR		0x00
+#define	WIIPIC_RBS		0x10000
+#define	WIIPIC_IMR		0x04
+#define	WIIPIC_RESET		0x24
+
+#define	WIIPIC_NIRQ		32
+
+#endif	/* _POWERPC_WII_WII_PICREG_H */


Property changes on: trunk/sys/powerpc/wii/wii_picreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property


More information about the Midnightbsd-cvs mailing list