[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, ®ions, ®ions_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,
+ ®ions, ®ions_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, ®ions, ®ions_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, ®s);
+ (*dtrace_pid_probe_ptr)(®s);
+ 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(©_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(©_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(©_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(©_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(©_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 **)®);
+ 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(®, 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, ®, 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(®, 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, ®,
+ 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, ® },
+ { 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", ®, 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 **)®);
+ 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 **)®p);
+ 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, ®, 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, ®, 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, ®},
+ {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 **)®);
+ 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"), ®_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", ®, 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