summaryrefslogtreecommitdiff
path: root/sys/powerpc
diff options
context:
space:
mode:
authorcvs2svn <cvs2svn@FreeBSD.org>2007-12-22 06:32:46 +0000
committercvs2svn <cvs2svn@FreeBSD.org>2007-12-22 06:32:46 +0000
commitca0202a548c669f45a9e0a63fce138303da6fc65 (patch)
treed2e3b3331009b65497a28406543d489372f03151 /sys/powerpc
parent6b0086231aa03c59acb964c0c94a023019f2bd5b (diff)
parent0f36dbfe3db4f983de562e87103d20899cbfb655 (diff)
Notes
Diffstat (limited to 'sys/powerpc')
-rw-r--r--sys/powerpc/compile/.cvsignore1
-rw-r--r--sys/powerpc/conf/.cvsignore1
-rw-r--r--sys/powerpc/conf/DEFAULTS19
-rw-r--r--sys/powerpc/conf/GENERIC147
-rw-r--r--sys/powerpc/conf/GENERIC.hints1
-rw-r--r--sys/powerpc/conf/MAC28
-rw-r--r--sys/powerpc/conf/Makefile3
-rw-r--r--sys/powerpc/conf/NOTES64
-rw-r--r--sys/powerpc/include/_bus.h46
-rw-r--r--sys/powerpc/include/_inttypes.h220
-rw-r--r--sys/powerpc/include/_limits.h99
-rw-r--r--sys/powerpc/include/_stdint.h171
-rw-r--r--sys/powerpc/include/_types.h134
-rw-r--r--sys/powerpc/include/asm.h99
-rw-r--r--sys/powerpc/include/atomic.h465
-rw-r--r--sys/powerpc/include/bat.h172
-rw-r--r--sys/powerpc/include/bootinfo.h87
-rw-r--r--sys/powerpc/include/bus.h741
-rw-r--r--sys/powerpc/include/bus_dma.h33
-rw-r--r--sys/powerpc/include/clock.h24
-rw-r--r--sys/powerpc/include/cpu.h81
-rw-r--r--sys/powerpc/include/cpufunc.h175
-rw-r--r--sys/powerpc/include/db_machdep.h92
-rw-r--r--sys/powerpc/include/elf.h101
-rw-r--r--sys/powerpc/include/endian.h111
-rw-r--r--sys/powerpc/include/exec.h37
-rw-r--r--sys/powerpc/include/float.h80
-rw-r--r--sys/powerpc/include/floatingpoint.h37
-rw-r--r--sys/powerpc/include/fpu.h82
-rw-r--r--sys/powerpc/include/frame.h84
-rw-r--r--sys/powerpc/include/gdb_machdep.h53
-rw-r--r--sys/powerpc/include/hid.h137
-rw-r--r--sys/powerpc/include/ieee.h142
-rw-r--r--sys/powerpc/include/ieeefp.h25
-rw-r--r--sys/powerpc/include/in_cksum.h76
-rw-r--r--sys/powerpc/include/intr.h164
-rw-r--r--sys/powerpc/include/intr_machdep.h45
-rw-r--r--sys/powerpc/include/kdb.h60
-rw-r--r--sys/powerpc/include/limits.h44
-rw-r--r--sys/powerpc/include/md_var.h65
-rw-r--r--sys/powerpc/include/memdev.h40
-rw-r--r--sys/powerpc/include/metadata.h36
-rw-r--r--sys/powerpc/include/mmuvar.h96
-rw-r--r--sys/powerpc/include/mutex.h65
-rw-r--r--sys/powerpc/include/nexusvar.h58
-rw-r--r--sys/powerpc/include/ofw_machdep.h36
-rw-r--r--sys/powerpc/include/openpicreg.h109
-rw-r--r--sys/powerpc/include/openpicvar.h63
-rw-r--r--sys/powerpc/include/param.h107
-rw-r--r--sys/powerpc/include/pcb.h74
-rw-r--r--sys/powerpc/include/pcpu.h72
-rw-r--r--sys/powerpc/include/pio.h256
-rw-r--r--sys/powerpc/include/pmap.h114
-rw-r--r--sys/powerpc/include/pmc_mdep.h25
-rw-r--r--sys/powerpc/include/powerpc.h59
-rw-r--r--sys/powerpc/include/proc.h49
-rw-r--r--sys/powerpc/include/profile.h146
-rw-r--r--sys/powerpc/include/psl.h86
-rw-r--r--sys/powerpc/include/pte.h159
-rw-r--r--sys/powerpc/include/ptrace.h36
-rw-r--r--sys/powerpc/include/reg.h39
-rw-r--r--sys/powerpc/include/reloc.h30
-rw-r--r--sys/powerpc/include/resource.h44
-rw-r--r--sys/powerpc/include/runq.h46
-rw-r--r--sys/powerpc/include/sc_machdep.h71
-rw-r--r--sys/powerpc/include/setjmp.h24
-rw-r--r--sys/powerpc/include/sf_buf.h58
-rw-r--r--sys/powerpc/include/sigframe.h39
-rw-r--r--sys/powerpc/include/signal.h53
-rw-r--r--sys/powerpc/include/smp.h7
-rw-r--r--sys/powerpc/include/spr.h481
-rw-r--r--sys/powerpc/include/sr.h56
-rw-r--r--sys/powerpc/include/stdarg.h150
-rw-r--r--sys/powerpc/include/trap.h113
-rw-r--r--sys/powerpc/include/ucontext.h73
-rw-r--r--sys/powerpc/include/varargs.h80
-rw-r--r--sys/powerpc/include/vmparam.h146
-rw-r--r--sys/powerpc/ofw/ofw_pci.c229
-rw-r--r--sys/powerpc/ofw/ofw_pci.h34
-rw-r--r--sys/powerpc/ofw/ofw_pcib_pci.c117
-rw-r--r--sys/powerpc/ofw/ofw_syscons.c932
-rw-r--r--sys/powerpc/ofw/ofw_syscons.h61
-rw-r--r--sys/powerpc/powermac/ata_kauai.c198
-rw-r--r--sys/powerpc/powermac/ata_macio.c136
-rw-r--r--sys/powerpc/powermac/grackle.c556
-rw-r--r--sys/powerpc/powermac/gracklevar.h69
-rw-r--r--sys/powerpc/powermac/hrowpic.c271
-rw-r--r--sys/powerpc/powermac/hrowpicvar.h75
-rw-r--r--sys/powerpc/powermac/macio.c542
-rw-r--r--sys/powerpc/powermac/maciovar.h59
-rw-r--r--sys/powerpc/powermac/openpic_macio.c97
-rw-r--r--sys/powerpc/powermac/pswitch.c144
-rw-r--r--sys/powerpc/powermac/uninorth.c600
-rw-r--r--sys/powerpc/powermac/uninorthvar.h74
-rw-r--r--sys/powerpc/powerpc/atomic.S137
-rw-r--r--sys/powerpc/powerpc/autoconf.c84
-rw-r--r--sys/powerpc/powerpc/bcopy.c149
-rw-r--r--sys/powerpc/powerpc/busdma_machdep.c589
-rw-r--r--sys/powerpc/powerpc/clock.c318
-rw-r--r--sys/powerpc/powerpc/copyinout.c356
-rw-r--r--sys/powerpc/powerpc/copystr.c68
-rw-r--r--sys/powerpc/powerpc/cpu.c385
-rw-r--r--sys/powerpc/powerpc/db_disasm.c962
-rw-r--r--sys/powerpc/powerpc/db_hwwatch.c54
-rw-r--r--sys/powerpc/powerpc/db_interface.c81
-rw-r--r--sys/powerpc/powerpc/db_memrw.c110
-rw-r--r--sys/powerpc/powerpc/db_trace.c323
-rw-r--r--sys/powerpc/powerpc/elf_machdep.c234
-rw-r--r--sys/powerpc/powerpc/fpu.c151
-rw-r--r--sys/powerpc/powerpc/fuswintr.c51
-rw-r--r--sys/powerpc/powerpc/gdb_machdep.c72
-rw-r--r--sys/powerpc/powerpc/genassym.c154
-rw-r--r--sys/powerpc/powerpc/in_cksum.c250
-rw-r--r--sys/powerpc/powerpc/interrupt.c101
-rw-r--r--sys/powerpc/powerpc/intr_machdep.c306
-rw-r--r--sys/powerpc/powerpc/locore.S208
-rw-r--r--sys/powerpc/powerpc/machdep.c995
-rw-r--r--sys/powerpc/powerpc/mem.c181
-rw-r--r--sys/powerpc/powerpc/mmu_if.m768
-rw-r--r--sys/powerpc/powerpc/mmu_oea.c2522
-rw-r--r--sys/powerpc/powerpc/mp_machdep.c68
-rw-r--r--sys/powerpc/powerpc/nexus.c487
-rw-r--r--sys/powerpc/powerpc/ofw_machdep.c436
-rw-r--r--sys/powerpc/powerpc/ofwmagic.S75
-rw-r--r--sys/powerpc/powerpc/openpic.c238
-rw-r--r--sys/powerpc/powerpc/pic_if.m59
-rw-r--r--sys/powerpc/powerpc/pmap_dispatch.c382
-rw-r--r--sys/powerpc/powerpc/sc_machdep.c90
-rw-r--r--sys/powerpc/powerpc/setjmp.S103
-rw-r--r--sys/powerpc/powerpc/sigcode.S59
-rw-r--r--sys/powerpc/powerpc/suswintr.c51
-rw-r--r--sys/powerpc/powerpc/swtch.S154
-rw-r--r--sys/powerpc/powerpc/syncicache.c96
-rw-r--r--sys/powerpc/powerpc/sys_machdep.c39
-rw-r--r--sys/powerpc/powerpc/trap.c681
-rw-r--r--sys/powerpc/powerpc/trap_subr.S540
-rw-r--r--sys/powerpc/powerpc/uio_machdep.c124
-rw-r--r--sys/powerpc/powerpc/uma_machdep.c91
-rw-r--r--sys/powerpc/powerpc/vm_machdep.c364
-rw-r--r--sys/powerpc/psim/ata_iobus.c257
-rw-r--r--sys/powerpc/psim/iobus.c416
-rw-r--r--sys/powerpc/psim/iobusvar.h66
-rw-r--r--sys/powerpc/psim/openpic_iobus.c106
-rw-r--r--sys/powerpc/psim/psim-tree90
-rw-r--r--sys/powerpc/psim/uart_iobus.c87
145 files changed, 26404 insertions, 0 deletions
diff --git a/sys/powerpc/compile/.cvsignore b/sys/powerpc/compile/.cvsignore
new file mode 100644
index 000000000000..232298edb15f
--- /dev/null
+++ b/sys/powerpc/compile/.cvsignore
@@ -0,0 +1 @@
+[A-Za-z0-9]*
diff --git a/sys/powerpc/conf/.cvsignore b/sys/powerpc/conf/.cvsignore
new file mode 100644
index 000000000000..232298edb15f
--- /dev/null
+++ b/sys/powerpc/conf/.cvsignore
@@ -0,0 +1 @@
+[A-Za-z0-9]*
diff --git a/sys/powerpc/conf/DEFAULTS b/sys/powerpc/conf/DEFAULTS
new file mode 100644
index 000000000000..7204e8b23279
--- /dev/null
+++ b/sys/powerpc/conf/DEFAULTS
@@ -0,0 +1,19 @@
+#
+# DEFAULTS -- Default kernel configuration file for FreeBSD/powerpc
+#
+# $FreeBSD$
+
+machine powerpc
+
+# Pseudo devices.
+device mem # Memory and kernel memory devices
+
+# UART chips on this platform
+device uart_ns8250
+device uart_z8530
+
+options GEOM_PART_APM
+options GEOM_PART_MBR
+
+# KSE support went from being default to a kernel option
+options KSE
diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC
new file mode 100644
index 000000000000..ddeec38a6805
--- /dev/null
+++ b/sys/powerpc/conf/GENERIC
@@ -0,0 +1,147 @@
+#
+# 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$
+
+cpu OEA
+ident GENERIC
+
+#To statically compile in device wiring instead of /boot/device.hints
+#hints "GENERIC.hints"
+
+makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
+
+# Platform support
+options POWERMAC #NewWorld Apple PowerMacs
+options PSIM #GDB PSIM ppc simulator
+
+options SCHED_4BSD #4BSD scheduler
+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 NFSCLIENT #Network Filesystem Client
+options NFSSERVER #Network Filesystem Server
+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 COMPAT_43TTY #BSD 4.3 TTY compat [KEEP THIS!]
+options COMPAT_FREEBSD4 #Keep this for a while
+options COMPAT_FREEBSD5 #Compatible with FreeBSD5
+options COMPAT_FREEBSD6 #Compatible with FreeBSD6
+options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI
+options KTRACE #ktrace(1) syscall trace 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 AUDIT # Security event auditing
+
+# To make an SMP kernel, the next line is needed
+#options SMP # Symmetric MultiProcessor Kernel
+
+# Standard busses
+device pci
+
+# ATA and ATAPI devices
+device ata
+device atadisk # ATA disk drives
+device atapicd # ATAPI CDROM drives
+#device atapifd # ATAPI floppy drives
+#device atapist # ATAPI tape drives
+
+# SCSI peripherals
+device scbus # SCSI bus (required for SCSI)
+device da # Direct Access (disks)
+device sa # Sequential Access (tape etc)
+device cd # CD
+device pass # Passthrough device (direct 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
+
+# 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)
+
+# Pseudo devices.
+device loop # Network loopback
+device random # Entropy device
+device ether # Ethernet support
+device sl # Kernel SLIP
+device ppp # Kernel PPP
+device tun # Packet tunnel.
+device pty # Pseudo-ttys (telnet etc)
+device md # Memory "disks"
+device ofwd # Open Firmware disks
+device gif # IPv6 and IPv4 tunneling
+device faith # IPv6-to-IPv4 relaying/(translation)
+
+# 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
+device uhci # UHCI PCI->USB interface
+device ohci # OHCI PCI->USB interface
+device ehci # EHCI PCI->USB interface
+device usb # USB Bus (required)
+device ugen # Generic
+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
+device uscanner # Scanners
+# 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
+
+# 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 powermac_nvram # Open Firmware configuration NVRAM
diff --git a/sys/powerpc/conf/GENERIC.hints b/sys/powerpc/conf/GENERIC.hints
new file mode 100644
index 000000000000..e8c0da7a1d7e
--- /dev/null
+++ b/sys/powerpc/conf/GENERIC.hints
@@ -0,0 +1 @@
+# $FreeBSD$
diff --git a/sys/powerpc/conf/MAC b/sys/powerpc/conf/MAC
new file mode 100644
index 000000000000..862638397da7
--- /dev/null
+++ b/sys/powerpc/conf/MAC
@@ -0,0 +1,28 @@
+# MAC -- Generic kernel configuration file for FreeBSD/powerpc MAC
+#
+# The Mandatory Access Control, or MAC, framework allows administrators to
+# finely control system security by providing for a loadable security pol-
+# icy architecture.
+#
+# For more information see:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/mac.html
+#
+# $FreeBSD$
+
+include GENERIC
+ident MAC
+
+options MAC
+
+#options MAC_BIBA # BIBA data integrity policy
+#options MAC_BSDEXTENDED # File system firewall policy
+#options MAC_IFOFF # Network interface silencing policy
+#options MAC_LOMAC # Low-watermark data integrity policy
+#options MAC_MLS # Multi-level confidentiality policy
+#options MAC_NONE # NULL policy
+#options MAC_PARTITION # Process partition policy
+#options MAC_PORTACL # Network port access control policy
+#options MAC_SEEOTHERUIDS # UID visibility policy
+#options MAC_STUB # Stub policy
+#options MAC_TEST # Testing policy for the MAC framework
diff --git a/sys/powerpc/conf/Makefile b/sys/powerpc/conf/Makefile
new file mode 100644
index 000000000000..2c006e9c2c80
--- /dev/null
+++ b/sys/powerpc/conf/Makefile
@@ -0,0 +1,3 @@
+# $FreeBSD$
+
+.include "${.CURDIR}/../../conf/makeLINT.mk"
diff --git a/sys/powerpc/conf/NOTES b/sys/powerpc/conf/NOTES
new file mode 100644
index 000000000000..176e66134153
--- /dev/null
+++ b/sys/powerpc/conf/NOTES
@@ -0,0 +1,64 @@
+# $FreeBSD$
+#
+# This file contains machine dependent kernel configuration notes. For
+# machine independent notes, look in /sys/conf/NOTES.
+
+
+
+#####################################################################
+# CPU OPTIONS
+
+#
+# You must specify at least one CPU (the one you intend to run on).
+cpu OEA
+
+options POWERMAC #NewWorld Apple PowerMacs
+options PSIM #GDB PSIM ppc simulator
+
+options SC_OFWFB # OFW frame buffer
+
+# Standard busses
+device pci
+
+device ofwd # Open Firmware disks
+
+
+#####################################################################
+# Devices we don't want to deal with
+
+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
+# wants gdb_cur
+nodevice dcons
+nodevice dcons_crom
+
+
+#####################################################################
+# Options we don't want to deal with
+
+nooption SMP
+nooption ADAPTIVE_SX
+nooption GDB
+nooption PPC_DEBUG
+nooption PPC_PROBE_CHIPSET
+nooption SC_NO_MODE_CHANGE
+nooption UKBD_DFLT_KEYMAP
diff --git a/sys/powerpc/include/_bus.h b/sys/powerpc/include/_bus.h
new file mode 100644
index 000000000000..5561ce734127
--- /dev/null
+++ b/sys/powerpc/include/_bus.h
@@ -0,0 +1,46 @@
+/*-
+ * 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$
+ */
+
+#ifndef POWERPC_INCLUDE__BUS_H
+#define POWERPC_INCLUDE__BUS_H
+
+/*
+ * Bus address and size types
+ */
+typedef u_int32_t bus_addr_t;
+typedef u_int32_t bus_size_t;
+
+/*
+ * Access methods for bus resources and address space.
+ */
+typedef u_int32_t bus_space_tag_t;
+typedef u_int32_t bus_space_handle_t;
+
+#endif /* POWERPC_INCLUDE__BUS_H */
diff --git a/sys/powerpc/include/_inttypes.h b/sys/powerpc/include/_inttypes.h
new file mode 100644
index 000000000000..7da589d8a771
--- /dev/null
+++ b/sys/powerpc/include/_inttypes.h
@@ -0,0 +1,220 @@
+/*-
+ * 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.
+ *
+ * From: $NetBSD: int_fmtio.h,v 1.2 2001/04/26 16:25:21 kleink Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_INTTYPES_H_
+#define _MACHINE_INTTYPES_H_
+
+/*
+ * Macros for format specifiers.
+ */
+
+/* fprintf(3) macros for signed integers. */
+
+#define PRId8 "d" /* int8_t */
+#define PRId16 "d" /* int16_t */
+#define PRId32 "d" /* int32_t */
+#define PRId64 "lld" /* int64_t */
+#define PRIdLEAST8 "d" /* int_least8_t */
+#define PRIdLEAST16 "d" /* int_least16_t */
+#define PRIdLEAST32 "d" /* int_least32_t */
+#define PRIdLEAST64 "lld" /* int_least64_t */
+#define PRIdFAST8 "d" /* int_fast8_t */
+#define PRIdFAST16 "d" /* int_fast16_t */
+#define PRIdFAST32 "d" /* int_fast32_t */
+#define PRIdFAST64 "lld" /* int_fast64_t */
+#define PRIdMAX "jd" /* intmax_t */
+#define PRIdPTR "d" /* intptr_t */
+
+#define PRIi8 "i" /* int8_t */
+#define PRIi16 "i" /* int16_t */
+#define PRIi32 "i" /* int32_t */
+#define PRIi64 "lli" /* int64_t */
+#define PRIiLEAST8 "i" /* int_least8_t */
+#define PRIiLEAST16 "i" /* int_least16_t */
+#define PRIiLEAST32 "i" /* int_least32_t */
+#define PRIiLEAST64 "lli" /* int_least64_t */
+#define PRIiFAST8 "i" /* int_fast8_t */
+#define PRIiFAST16 "i" /* int_fast16_t */
+#define PRIiFAST32 "i" /* int_fast32_t */
+#define PRIiFAST64 "lli" /* int_fast64_t */
+#define PRIiMAX "ji" /* intmax_t */
+#define PRIiPTR "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 "llo" /* uint64_t */
+#define PRIoLEAST8 "o" /* uint_least8_t */
+#define PRIoLEAST16 "o" /* uint_least16_t */
+#define PRIoLEAST32 "o" /* uint_least32_t */
+#define PRIoLEAST64 "llo" /* uint_least64_t */
+#define PRIoFAST8 "o" /* uint_fast8_t */
+#define PRIoFAST16 "o" /* uint_fast16_t */
+#define PRIoFAST32 "o" /* uint_fast32_t */
+#define PRIoFAST64 "llo" /* uint_fast64_t */
+#define PRIoMAX "jo" /* uintmax_t */
+#define PRIoPTR "o" /* uintptr_t */
+
+#define PRIu8 "u" /* uint8_t */
+#define PRIu16 "u" /* uint16_t */
+#define PRIu32 "u" /* uint32_t */
+#define PRIu64 "llu" /* uint64_t */
+#define PRIuLEAST8 "u" /* uint_least8_t */
+#define PRIuLEAST16 "u" /* uint_least16_t */
+#define PRIuLEAST32 "u" /* uint_least32_t */
+#define PRIuLEAST64 "llu" /* uint_least64_t */
+#define PRIuFAST8 "u" /* uint_fast8_t */
+#define PRIuFAST16 "u" /* uint_fast16_t */
+#define PRIuFAST32 "u" /* uint_fast32_t */
+#define PRIuFAST64 "llu" /* uint_fast64_t */
+#define PRIuMAX "ju" /* uintmax_t */
+#define PRIuPTR "u" /* uintptr_t */
+
+#define PRIx8 "x" /* uint8_t */
+#define PRIx16 "x" /* uint16_t */
+#define PRIx32 "x" /* uint32_t */
+#define PRIx64 "llx" /* uint64_t */
+#define PRIxLEAST8 "x" /* uint_least8_t */
+#define PRIxLEAST16 "x" /* uint_least16_t */
+#define PRIxLEAST32 "x" /* uint_least32_t */
+#define PRIxLEAST64 "llx" /* uint_least64_t */
+#define PRIxFAST8 "x" /* uint_fast8_t */
+#define PRIxFAST16 "x" /* uint_fast16_t */
+#define PRIxFAST32 "x" /* uint_fast32_t */
+#define PRIxFAST64 "llx" /* uint_fast64_t */
+#define PRIxMAX "jx" /* uintmax_t */
+#define PRIxPTR "x" /* uintptr_t */
+
+#define PRIX8 "X" /* uint8_t */
+#define PRIX16 "X" /* uint16_t */
+#define PRIX32 "X" /* uint32_t */
+#define PRIX64 "llX" /* uint64_t */
+#define PRIXLEAST8 "X" /* uint_least8_t */
+#define PRIXLEAST16 "X" /* uint_least16_t */
+#define PRIXLEAST32 "X" /* uint_least32_t */
+#define PRIXLEAST64 "llX" /* uint_least64_t */
+#define PRIXFAST8 "X" /* uint_fast8_t */
+#define PRIXFAST16 "X" /* uint_fast16_t */
+#define PRIXFAST32 "X" /* uint_fast32_t */
+#define PRIXFAST64 "llX" /* uint_fast64_t */
+#define PRIXMAX "jX" /* uintmax_t */
+#define PRIXPTR "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 "lld" /* int64_t */
+#define SCNdLEAST8 "hhd" /* int_least8_t */
+#define SCNdLEAST16 "hd" /* int_least16_t */
+#define SCNdLEAST32 "d" /* int_least32_t */
+#define SCNdLEAST64 "lld" /* int_least64_t */
+#define SCNdFAST8 "d" /* int_fast8_t */
+#define SCNdFAST16 "d" /* int_fast16_t */
+#define SCNdFAST32 "d" /* int_fast32_t */
+#define SCNdFAST64 "lld" /* int_fast64_t */
+#define SCNdMAX "jd" /* intmax_t */
+#define SCNdPTR "d" /* intptr_t */
+
+#define SCNi8 "hhi" /* int8_t */
+#define SCNi16 "hi" /* int16_t */
+#define SCNi32 "i" /* int32_t */
+#define SCNi64 "lli" /* int64_t */
+#define SCNiLEAST8 "hhi" /* int_least8_t */
+#define SCNiLEAST16 "hi" /* int_least16_t */
+#define SCNiLEAST32 "i" /* int_least32_t */
+#define SCNiLEAST64 "lli" /* int_least64_t */
+#define SCNiFAST8 "i" /* int_fast8_t */
+#define SCNiFAST16 "i" /* int_fast16_t */
+#define SCNiFAST32 "i" /* int_fast32_t */
+#define SCNiFAST64 "lli" /* int_fast64_t */
+#define SCNiMAX "ji" /* intmax_t */
+#define SCNiPTR "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 "llo" /* uint64_t */
+#define SCNoLEAST8 "hho" /* uint_least8_t */
+#define SCNoLEAST16 "ho" /* uint_least16_t */
+#define SCNoLEAST32 "o" /* uint_least32_t */
+#define SCNoLEAST64 "llo" /* uint_least64_t */
+#define SCNoFAST8 "o" /* uint_fast8_t */
+#define SCNoFAST16 "o" /* uint_fast16_t */
+#define SCNoFAST32 "o" /* uint_fast32_t */
+#define SCNoFAST64 "llo" /* uint_fast64_t */
+#define SCNoMAX "jo" /* uintmax_t */
+#define SCNoPTR "o" /* uintptr_t */
+
+#define SCNu8 "hhu" /* uint8_t */
+#define SCNu16 "hu" /* uint16_t */
+#define SCNu32 "u" /* uint32_t */
+#define SCNu64 "llu" /* uint64_t */
+#define SCNuLEAST8 "hhu" /* uint_least8_t */
+#define SCNuLEAST16 "hu" /* uint_least16_t */
+#define SCNuLEAST32 "u" /* uint_least32_t */
+#define SCNuLEAST64 "llu" /* uint_least64_t */
+#define SCNuFAST8 "u" /* uint_fast8_t */
+#define SCNuFAST16 "u" /* uint_fast16_t */
+#define SCNuFAST32 "u" /* uint_fast32_t */
+#define SCNuFAST64 "llu" /* uint_fast64_t */
+#define SCNuMAX "ju" /* uintmax_t */
+#define SCNuPTR "u" /* uintptr_t */
+
+#define SCNx8 "hhx" /* uint8_t */
+#define SCNx16 "hx" /* uint16_t */
+#define SCNx32 "x" /* uint32_t */
+#define SCNx64 "llx" /* uint64_t */
+#define SCNxLEAST8 "hhx" /* uint_least8_t */
+#define SCNxLEAST16 "hx" /* uint_least16_t */
+#define SCNxLEAST32 "x" /* uint_least32_t */
+#define SCNxLEAST64 "llx" /* uint_least64_t */
+#define SCNxFAST8 "x" /* uint_fast8_t */
+#define SCNxFAST16 "x" /* uint_fast16_t */
+#define SCNxFAST32 "x" /* uint_fast32_t */
+#define SCNxFAST64 "llx" /* uint_fast64_t */
+#define SCNxMAX "jx" /* uintmax_t */
+#define SCNxPTR "x" /* uintptr_t */
+
+#endif /* !_MACHINE_INTTYPES_H_ */
diff --git a/sys/powerpc/include/_limits.h b/sys/powerpc/include/_limits.h
new file mode 100644
index 000000000000..76e73544de64
--- /dev/null
+++ b/sys/powerpc/include/_limits.h
@@ -0,0 +1,99 @@
+/*-
+ * 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$
+ */
+
+#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).
+ * These numbers are for the default configuration of gcc. They work for
+ * some other compilers as well, but this should not be depended on.
+ */
+
+#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 0xffffffffU /* 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 */
+
+/* Bad hack for gcc configured to give 64-bit longs. */
+#ifdef _LARGE_LONG
+#define __ULONG_MAX 0xffffffffffffffffUL
+#define __LONG_MAX 0x7fffffffffffffffL
+#define __LONG_MIN (-0x7fffffffffffffffL - 1)
+#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 */
+#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 */
+
+#define __SSIZE_MAX __INT_MAX /* max value for a ssize_t */
+
+#define __SIZE_T_MAX __UINT_MAX /* max value for a size_t */
+
+#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 */
+
+#ifdef _LARGE_LONG
+#define __LONG_BIT 64
+#else
+#define __LONG_BIT 32
+#endif
+#define __WORD_BIT 32
+
+/* Minimum signal stack size. */
+#define __MINSIGSTKSZ (512 * 4)
+
+#endif /* !_MACHINE__LIMITS_H_ */
diff --git a/sys/powerpc/include/_stdint.h b/sys/powerpc/include/_stdint.h
new file mode 100644
index 000000000000..0d8aedfff5d6
--- /dev/null
+++ b/sys/powerpc/include/_stdint.h
@@ -0,0 +1,171 @@
+/*-
+ * Copyright (c) 2001, 2002 Mike Barcroft <mike@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$
+ */
+
+#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 INT64_C(c) (c ## LL)
+
+#define UINT8_C(c) (c)
+#define UINT16_C(c) (c)
+#define UINT32_C(c) (c ## U)
+#define UINT64_C(c) (c ## ULL)
+
+#define INTMAX_C(c) (c ## LL)
+#define UINTMAX_C(c) (c ## ULL)
+
+#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
+
+/*
+ * 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 (-0x7fffffffffffffffLL-1)
+
+/* Maximum values of exact-width signed integer types. */
+#define INT8_MAX 0x7f
+#define INT16_MAX 0x7fff
+#define INT32_MAX 0x7fffffff
+#define INT64_MAX 0x7fffffffffffffffLL
+
+/* Maximum values of exact-width unsigned integer types. */
+#define UINT8_MAX 0xff
+#define UINT16_MAX 0xffff
+#define UINT32_MAX 0xffffffffU
+#define UINT64_MAX 0xffffffffffffffffULL
+
+/*
+ * 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
+ */
+#define INTPTR_MIN INT32_MIN
+#define INTPTR_MAX INT32_MAX
+#define UINTPTR_MAX UINT32_MAX
+
+/*
+ * 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
+ */
+/* 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
+
+#ifndef WCHAR_MIN /* Also possibly defined in <wchar.h> */
+/* Limits of wchar_t. */
+#define WCHAR_MIN INT32_MIN
+#define WCHAR_MAX INT32_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_ */
diff --git a/sys/powerpc/include/_types.h b/sys/powerpc/include/_types.h
new file mode 100644
index 000000000000..c6babcf4a108
--- /dev/null
+++ b/sys/powerpc/include/_types.h
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 2002 Mike Barcroft <mike@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$
+ */
+
+#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;
+
+#if defined(lint)
+/* LONGLONG */
+typedef long long __int64_t;
+/* LONGLONG */
+typedef unsigned long long __uint64_t;
+#elif defined(__GNUCLIKE_ATTRIBUTE_MODE_DI)
+typedef int __attribute__((__mode__(__DI__))) __int64_t;
+typedef unsigned int __attribute__((__mode__(__DI__))) __uint64_t;
+#else
+/* LONGLONG */
+typedef long long __int64_t;
+/* LONGLONG */
+typedef unsigned long long __uint64_t;
+#endif
+
+/*
+ * Standard type definitions.
+ */
+typedef __uint32_t __clock_t; /* clock()... */
+typedef unsigned int __cpumask_t;
+typedef __int32_t __critical_t;
+typedef double __double_t;
+typedef double __float_t;
+typedef __int32_t __intfptr_t;
+typedef __int64_t __intmax_t;
+typedef __int32_t __intptr_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;
+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 __uint64_t __uintmax_t;
+typedef __uint32_t __uintptr_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;
+typedef __uint32_t __u_register_t;
+typedef __uint32_t __vm_offset_t;
+typedef __int64_t __vm_ooffset_t;
+typedef __uint32_t __vm_paddr_t;
+typedef __uint64_t __vm_pindex_t;
+typedef __uint32_t __vm_size_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_ */
diff --git a/sys/powerpc/include/asm.h b/sys/powerpc/include/asm.h
new file mode 100644
index 000000000000..34d8ad65e8d7
--- /dev/null
+++ b/sys/powerpc/include/asm.h
@@ -0,0 +1,99 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_ASM_H_
+#define _MACHINE_ASM_H_
+
+#include <sys/cdefs.h>
+
+#ifdef PIC
+#define PIC_PROLOGUE XXX
+#define PIC_EPILOGUE XXX
+#define PIC_PLT(x) x@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
+#define HIDENAME(asmsym) __CONCAT(.,asmsym)
+
+#define _GLOBAL(x) \
+ .data; .align 2; .globl x; x:
+
+#define _ENTRY(x) \
+ .text; .align 2; .globl x; .type x,@function; x:
+
+#ifdef GPROF
+# define _PROF_PROLOGUE mflr 0; stw 0,4(1); bl _mcount
+#else
+# define _PROF_PROLOGUE
+#endif
+
+#define ENTRY(y) _ENTRY(CNAME(y)); _PROF_PROLOGUE
+#define ASENTRY(y) _ENTRY(ASMNAME(y)); _PROF_PROLOGUE
+#define GLOBAL(y) _GLOBAL(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_ALIAS(alias,sym) \
+ .weak alias; \
+ 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_ */
diff --git a/sys/powerpc/include/atomic.h b/sys/powerpc/include/atomic.h
new file mode 100644
index 000000000000..9bbf3bf30564
--- /dev/null
+++ b/sys/powerpc/include/atomic.h
@@ -0,0 +1,465 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_ATOMIC_H_
+#define _MACHINE_ATOMIC_H_
+
+#include <machine/cpufunc.h>
+
+#ifndef _SYS_CDEFS_H_
+#error this file needs sys/cdefs.h as a prerequisite
+#endif
+
+/*
+ * Various simple arithmetic on memory which is atomic in the presence
+ * of interrupts and SMP safe.
+ */
+
+void atomic_set_8(volatile uint8_t *, uint8_t);
+void atomic_clear_8(volatile uint8_t *, uint8_t);
+void atomic_add_8(volatile uint8_t *, uint8_t);
+void atomic_subtract_8(volatile uint8_t *, uint8_t);
+
+void atomic_set_16(volatile uint16_t *, uint16_t);
+void atomic_clear_16(volatile uint16_t *, uint16_t);
+void atomic_add_16(volatile uint16_t *, uint16_t);
+void atomic_subtract_16(volatile uint16_t *, uint16_t);
+
+static __inline void
+atomic_set_32(volatile uint32_t *p, uint32_t v)
+{
+ uint32_t temp;
+
+#ifdef __GNUCLIKE_ASM
+ __asm __volatile (
+ "1:\tlwarx %0, 0, %2\n\t" /* load old value */
+ "or %0, %3, %0\n\t" /* calculate new value */
+ "stwcx. %0, 0, %2\n\t" /* attempt to store */
+ "bne- 1b\n\t" /* spin if failed */
+ : "=&r" (temp), "=m" (*p)
+ : "r" (p), "r" (v), "m" (*p)
+ : "cc", "memory");
+#endif
+}
+
+static __inline void
+atomic_clear_32(volatile uint32_t *p, uint32_t v)
+{
+ uint32_t temp;
+
+#ifdef __GNUCLIKE_ASM
+ __asm __volatile (
+ "1:\tlwarx %0, 0, %2\n\t" /* load old value */
+ "andc %0, %0, %3\n\t" /* calculate new value */
+ "stwcx. %0, 0, %2\n\t" /* attempt to store */
+ "bne- 1b\n\t" /* spin if failed */
+ : "=&r" (temp), "=m" (*p)
+ : "r" (p), "r" (v), "m" (*p)
+ : "cc", "memory");
+#endif
+}
+
+static __inline void
+atomic_add_32(volatile uint32_t *p, uint32_t v)
+{
+ uint32_t temp;
+
+#ifdef __GNUCLIKE_ASM
+ __asm __volatile (
+ "1:\tlwarx %0, 0, %2\n\t" /* load old value */
+ "add %0, %3, %0\n\t" /* calculate new value */
+ "stwcx. %0, 0, %2\n\t" /* attempt to store */
+ "bne- 1b\n\t" /* spin if failed */
+ : "=&r" (temp), "=m" (*p)
+ : "r" (p), "r" (v), "m" (*p)
+ : "cc", "memory");
+#endif
+}
+
+static __inline void
+atomic_subtract_32(volatile uint32_t *p, uint32_t v)
+{
+ uint32_t temp;
+
+#ifdef __GNUCLIKE_ASM
+ __asm __volatile (
+ "1:\tlwarx %0, 0, %2\n\t" /* load old value */
+ "subf %0, %3, %0\n\t" /* calculate new value */
+ "stwcx. %0, 0, %2\n\t" /* attempt to store */
+ "bne- 1b\n\t" /* spin if failed */
+ : "=&r" (temp), "=m" (*p)
+ : "r" (p), "r" (v), "m" (*p)
+ : "cc", "memory");
+#endif
+}
+
+static __inline uint32_t
+atomic_readandclear_32(volatile uint32_t *addr)
+{
+ uint32_t 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);
+}
+
+#if 0
+
+/*
+ * So far I haven't found a way to implement atomic 64-bit ops on the
+ * 32-bit PowerPC without involving major headaches. If anyone has
+ * any ideas, please let me know. =)
+ * - benno@FreeBSD.org
+ */
+
+static __inline void
+atomic_set_64(volatile u_int64_t *p, u_int64_t v)
+{
+ u_int64_t temp;
+
+ __asm __volatile (
+ : "=&r" (temp), "=r" (*p)
+ : "r" (*p), "r" (v)
+ : "memory");
+}
+
+static __inline void
+atomic_clear_64(volatile u_int64_t *p, u_int64_t v)
+{
+ u_int64_t temp;
+
+ __asm __volatile (
+ : "=&r" (temp), "=r" (*p)
+ : "r" (*p), "r" (v)
+ : "memory");
+}
+
+static __inline void
+atomic_add_64(volatile u_int64_t *p, u_int64_t v)
+{
+ u_int64_t temp;
+
+ __asm __volatile (
+ : "=&r" (temp), "=r" (*p)
+ : "r" (*p), "r" (v)
+ : "memory");
+}
+
+static __inline void
+atomic_subtract_64(volatile u_int64_t *p, u_int64_t v)
+{
+ u_int64_t temp;
+
+ __asm __volatile (
+ : "=&r" (temp), "=r" (*p)
+ : "r" (*p), "r" (v)
+ : "memory");
+}
+
+static __inline u_int64_t
+atomic_readandclear_64(volatile u_int64_t *addr)
+{
+ u_int64_t result,temp;
+
+ __asm __volatile (
+ : "=&r"(result), "=&r"(temp), "=r" (*addr)
+ : "r"(*addr)
+ : "memory");
+
+ return result;
+}
+
+#endif /* 0 */
+
+#define atomic_set_char atomic_set_8
+#define atomic_clear_char atomic_clear_8
+#define atomic_add_char atomic_add_8
+#define atomic_subtract_char atomic_subtract_8
+
+#define atomic_set_short atomic_set_16
+#define atomic_clear_short atomic_clear_16
+#define atomic_add_short atomic_add_16
+#define atomic_subtract_short atomic_subtract_16
+
+#define atomic_set_int atomic_set_32
+#define atomic_clear_int atomic_clear_32
+#define atomic_add_int atomic_add_32
+#define atomic_subtract_int atomic_subtract_32
+#define atomic_readandclear_int atomic_readandclear_32
+
+#define atomic_set_long atomic_set_32
+#define atomic_clear_long atomic_clear_32
+#define atomic_add_long(p, v) atomic_add_32((uint32_t *)p, (uint32_t)v)
+#define atomic_subtract_long(p, v) atomic_subtract_32((uint32_t *)p, (uint32_t)v)
+#define atomic_readandclear_long atomic_readandclear_32
+
+#define atomic_set_ptr atomic_set_32
+#define atomic_clear_ptr atomic_clear_32
+#define atomic_add_ptr atomic_add_32
+#define atomic_subtract_ptr atomic_subtract_32
+
+#if 0
+
+/* See above. */
+
+#define atomic_set_long_long atomic_set_64
+#define atomic_clear_long_long atomic_clear_64
+#define atomic_add_long_long atomic_add_64
+#define atomic_subtract_long_long atomic_subtract_64
+#define atomic_readandclear_long_long atomic_readandclear_64
+
+#endif /* 0 */
+
+#define ATOMIC_ACQ_REL(NAME, WIDTH, TYPE) \
+static __inline void \
+atomic_##NAME##_acq_##WIDTH(volatile u_int##WIDTH##_t *p, u_int##WIDTH##_t v) \
+{ \
+ atomic_##NAME##_##WIDTH(p, v); \
+ powerpc_mb(); \
+} \
+ \
+static __inline void \
+atomic_##NAME##_rel_##WIDTH(volatile u_int##WIDTH##_t *p, u_int##WIDTH##_t v) \
+{ \
+ powerpc_mb(); \
+ atomic_##NAME##_##WIDTH(p, v); \
+} \
+ \
+static __inline void \
+atomic_##NAME##_acq_##TYPE(volatile u_int##WIDTH##_t *p, u_int##WIDTH##_t v) \
+{ \
+ atomic_##NAME##_##WIDTH(p, v); \
+ powerpc_mb(); \
+} \
+ \
+static __inline void \
+atomic_##NAME##_rel_##TYPE(volatile u_int##WIDTH##_t *p, u_int##WIDTH##_t v) \
+{ \
+ powerpc_mb(); \
+ atomic_##NAME##_##WIDTH(p, v); \
+}
+
+ATOMIC_ACQ_REL(set, 8, char)
+ATOMIC_ACQ_REL(clear, 8, char)
+ATOMIC_ACQ_REL(add, 8, char)
+ATOMIC_ACQ_REL(subtract, 8, char)
+ATOMIC_ACQ_REL(set, 16, short)
+ATOMIC_ACQ_REL(clear, 16, short)
+ATOMIC_ACQ_REL(add, 16, short)
+ATOMIC_ACQ_REL(subtract, 16, short)
+ATOMIC_ACQ_REL(set, 32, int)
+ATOMIC_ACQ_REL(clear, 32, int)
+ATOMIC_ACQ_REL(add, 32, int)
+ATOMIC_ACQ_REL(subtract, 32, int)
+
+#define atomic_set_acq_long atomic_set_acq_32
+#define atomic_set_rel_long atomic_set_rel_32
+#define atomic_clear_acq_long atomic_clear_acq_32
+#define atomic_clear_rel_long atomic_clear_rel_32
+#define atomic_add_acq_long atomic_add_acq_32
+#define atomic_add_rel_long atomic_add_rel_32
+#define atomic_subtract_acq_long atomic_subtract_acq_32
+#define atomic_subtract_rel_long atomic_subtract_rel_32
+
+#define atomic_set_acq_ptr atomic_set_acq_32
+#define atomic_set_rel_ptr atomic_set_rel_32
+#define atomic_clear_acq_ptr atomic_clear_acq_32
+#define atomic_clear_rel_ptr atomic_clear_rel_32
+#define atomic_add_acq_ptr atomic_add_acq_32
+#define atomic_add_rel_ptr atomic_add_rel_32
+#define atomic_subtract_acq_ptr atomic_subtract_acq_32
+#define atomic_subtract_rel_ptr atomic_subtract_rel_32
+
+#undef ATOMIC_ACQ_REL
+
+/*
+ * We assume that a = b will do atomic loads and stores.
+ */
+#define ATOMIC_STORE_LOAD(TYPE, WIDTH) \
+static __inline u_##TYPE \
+atomic_load_acq_##WIDTH(volatile u_##TYPE *p) \
+{ \
+ u_##TYPE v; \
+ \
+ v = *p; \
+ powerpc_mb(); \
+ return (v); \
+} \
+ \
+static __inline void \
+atomic_store_rel_##WIDTH(volatile u_##TYPE *p, u_##TYPE v) \
+{ \
+ powerpc_mb(); \
+ *p = v; \
+} \
+ \
+static __inline u_##TYPE \
+atomic_load_acq_##TYPE(volatile u_##TYPE *p) \
+{ \
+ u_##TYPE v; \
+ \
+ v = *p; \
+ powerpc_mb(); \
+ return (v); \
+} \
+ \
+static __inline void \
+atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) \
+{ \
+ powerpc_mb(); \
+ *p = v; \
+}
+
+ATOMIC_STORE_LOAD(char, 8)
+ATOMIC_STORE_LOAD(short, 16)
+ATOMIC_STORE_LOAD(int, 32)
+
+#define atomic_load_acq_long atomic_load_acq_32
+#define atomic_store_rel_long atomic_store_rel_32
+
+#define atomic_load_acq_ptr atomic_load_acq_32
+#define atomic_store_rel_ptr atomic_store_rel_32
+
+#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 uint32_t
+atomic_cmpset_32(volatile uint32_t* p, uint32_t cmpval, uint32_t newval)
+{
+ uint32_t 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);
+}
+
+#if 0
+
+/*
+ * 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 u_int64_t
+atomic_cmpset_64(volatile u_int64_t* p, u_int64_t cmpval, u_int64_t newval)
+{
+ u_int64_t ret;
+
+ __asm __volatile (
+ : "=&r" (ret), "=r" (*p)
+ : "r" (cmpval), "r" (newval), "r" (*p)
+ : "memory");
+
+ return ret;
+}
+
+#endif /* 0 */
+
+#define atomic_cmpset_int atomic_cmpset_32
+#define atomic_cmpset_long atomic_cmpset_32
+
+#define atomic_cmpset_ptr(dst, old, new) \
+ atomic_cmpset_32((volatile u_int *)(dst), (u_int)(old), (u_int)(new))
+
+#if 0
+#define atomic_cmpset_long_long atomic_cmpset_64
+#endif /* 0 */
+
+static __inline uint32_t
+atomic_cmpset_acq_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval)
+{
+ int retval;
+
+ retval = atomic_cmpset_32(p, cmpval, newval);
+ powerpc_mb();
+ return (retval);
+}
+
+static __inline uint32_t
+atomic_cmpset_rel_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval)
+{
+ powerpc_mb();
+ return (atomic_cmpset_32(p, cmpval, newval));
+}
+
+#define atomic_cmpset_acq_int atomic_cmpset_acq_32
+#define atomic_cmpset_rel_int atomic_cmpset_rel_32
+#define atomic_cmpset_acq_long atomic_cmpset_acq_32
+#define atomic_cmpset_rel_long atomic_cmpset_rel_32
+
+#define atomic_cmpset_acq_ptr(dst, old, new) \
+ atomic_cmpset_acq_32((volatile u_int *)(dst), (u_int)(old), (u_int)(new))
+#define atomic_cmpset_rel_ptr(dst, old, new) \
+ atomic_cmpset_rel_32((volatile u_int *)(dst), (u_int)(old), (u_int)(new))
+
+static __inline uint32_t
+atomic_fetchadd_32(volatile uint32_t *p, uint32_t v)
+{
+ uint32_t value;
+
+ do {
+ value = *p;
+ } while (!atomic_cmpset_32(p, value, value + v));
+ return (value);
+}
+
+#define atomic_fetchadd_int atomic_fetchadd_32
+
+#endif /* ! _MACHINE_ATOMIC_H_ */
diff --git a/sys/powerpc/include/bat.h b/sys/powerpc/include/bat.h
new file mode 100644
index 000000000000..27c6d5a895f6
--- /dev/null
+++ b/sys/powerpc/include/bat.h
@@ -0,0 +1,172 @@
+/*-
+ * 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.
+ * 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.
+ */
+
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_BAT_H_
+#define _MACHINE_BAT_H_
+
+struct bat {
+ u_int32_t batu;
+ u_int32_t batl;
+};
+
+/* 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))
+
+#ifdef _KERNEL
+extern struct bat battable[16];
+#endif
+
+#endif /* _MACHINE_BAT_H_ */
diff --git a/sys/powerpc/include/bootinfo.h b/sys/powerpc/include/bootinfo.h
new file mode 100644
index 000000000000..aa967ac59689
--- /dev/null
+++ b/sys/powerpc/include/bootinfo.h
@@ -0,0 +1,87 @@
+/*-
+ * 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@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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * The boot program passes a pointer (in the boot environment virtual
+ * address address space; "BEVA") to a bootinfo to the kernel using
+ * the following convention:
+ *
+ * a0 contains first free page frame number
+ * a1 contains page number of current level 1 page table
+ * if a2 contains BOOTINFO_MAGIC and a4 is nonzero:
+ * a3 contains pointer (BEVA) to bootinfo
+ * a4 contains bootinfo version number
+ * if a2 contains BOOTINFO_MAGIC and a4 contains 0 (backward compat):
+ * a3 contains pointer (BEVA) to bootinfo version
+ * (u_long), then the bootinfo
+ */
+
+#define BOOTINFO_MAGIC 0xdeadbeeffeedface
+
+struct bootinfo_v1 {
+ u_long ssym; /* 0: start of kernel sym table */
+ u_long esym; /* 8: end of kernel sym table */
+ char boot_flags[64]; /* 16: boot flags */
+ char booted_kernel[64]; /* 80: name of booted kernel */
+ void *hwrpb; /* 144: hwrpb pointer (BEVA) */
+ u_long hwrpbsize; /* 152: size of hwrpb data */
+ int (*cngetc)(void); /* 160: console getc pointer */
+ void (*cnputc)(int); /* 168: console putc pointer */
+ void (*cnpollc)(int); /* 176: console pollc pointer */
+ u_long pad[6]; /* 184: rsvd for future use */
+ char *envp; /* 232: start of environment */
+ u_long kernend; /* 240: end of kernel */
+ u_long modptr; /* 248: FreeBSD module base */
+ /* 256: total size */
+};
+
+/*
+ * Kernel-internal structure used to hold important bits of boot
+ * information. NOT to be used by boot blocks.
+ *
+ * Note that not all of the fields from the bootinfo struct(s)
+ * passed by the boot blocks aren't here (because they're not currently
+ * used by the kernel!). Fields here which aren't supplied by the
+ * bootinfo structure passed by the boot blocks are supposed to be
+ * filled in at startup with sane contents.
+ */
+struct bootinfo_kernel {
+ u_long ssym; /* start of syms */
+ u_long esym; /* end of syms */
+ u_long modptr; /* FreeBSD module pointer */
+ u_long kernend; /* "end of kernel" from boot code */
+ char *envp; /* "end of kernel" from boot code */
+ u_long hwrpb_phys; /* hwrpb physical address */
+ u_long hwrpb_size; /* size of hwrpb data */
+ char boot_flags[64]; /* boot flags */
+ char booted_kernel[64]; /* name of booted kernel */
+ char booted_dev[64]; /* name of booted device */
+};
+
+extern struct bootinfo_kernel bootinfo;
diff --git a/sys/powerpc/include/bus.h b/sys/powerpc/include/bus.h
new file mode 100644
index 000000000000..7460d130f70e
--- /dev/null
+++ b/sys/powerpc/include/bus.h
@@ -0,0 +1,741 @@
+/*-
+ * 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.
+ */
+
+/*-
+ * 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.
+ *
+ * $NetBSD: bus.h,v 1.9.4.1 2000/06/30 16:27:30 simonb Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _MACPPC_BUS_H_
+#define _MACPPC_BUS_H_
+
+#include <machine/_bus.h>
+#include <machine/pio.h>
+
+#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
+#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
+#define BUS_SPACE_MAXSIZE 0xFFFFFFFF
+#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
+#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
+#define BUS_SPACE_MAXADDR 0xFFFFFFFF
+
+#define BUS_SPACE_UNRESTRICTED (~0)
+
+/*
+ * Values for the macppc bus space tag, not to be used directly by MI code.
+ */
+
+#define __BUS_SPACE_HAS_STREAM_METHODS 1
+
+/*
+ * Define the PPC tag values
+ */
+#define PPC_BUS_SPACE_MEM 1 /* space is mem space */
+#define PPC_BUS_SPACE_IO 2 /* space is io space */
+
+static __inline void *
+__ppc_ba(bus_space_tag_t tag __unused, bus_space_handle_t handle,
+ bus_size_t offset)
+{
+ return ((void *)(handle + offset));
+}
+
+/*
+ * int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
+ * bus_size_t size, int flags, bus_space_handle_t *bshp));
+ *
+ * Map a region of bus space.
+ */
+
+static __inline int
+bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr,
+ bus_size_t size __unused, int flags __unused,
+ bus_space_handle_t *bshp)
+{
+
+ *bshp = addr;
+ return (0);
+}
+
+/*
+ * int bus_space_unmap(bus_space_tag_t t,
+ * bus_space_handle_t bsh, bus_size_t size));
+ *
+ * Unmap a region of bus space.
+ */
+
+static __inline void
+bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
+ bus_size_t size __unused)
+{
+}
+
+/*
+ * int bus_space_subregion(bus_space_tag_t t,
+ * bus_space_handle_t bsh, bus_size_t offset, bus_size_t size,
+ * bus_space_handle_t *nbshp));
+ *
+ * Get a new handle for a subregion of an already-mapped area of bus space.
+ */
+
+static __inline int
+bus_space_subregion(bus_space_tag_t t __unused, bus_space_handle_t bsh,
+ bus_size_t offset, bus_size_t size __unused, bus_space_handle_t *nbshp)
+{
+ *nbshp = bsh + offset;
+ return (0);
+}
+
+/*
+ * int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
+ * bus_addr_t rend, bus_size_t size, bus_size_t align,
+ * bus_size_t boundary, int flags, bus_addr_t *addrp,
+ * bus_space_handle_t *bshp));
+ *
+ * Allocate a region of bus space.
+ */
+
+#if 0
+#define bus_space_alloc(t, rs, re, s, a, b, f, ap, hp) !!! unimplemented !!!
+#endif
+
+/*
+ * int bus_space_free(bus_space_tag_t t,
+ * bus_space_handle_t bsh, bus_size_t size));
+ *
+ * Free a region of bus space.
+ */
+#if 0
+#define bus_space_free(t, h, s) !!! unimplemented !!!
+#endif
+
+/*
+ * u_intN_t bus_space_read_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset));
+ *
+ * Read a 1, 2, 4, or 8 byte quantity from bus space
+ * described by tag/handle/offset.
+ */
+
+static __inline u_int8_t
+bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
+{
+ return (in8(__ppc_ba(t, h, o)));
+}
+
+static __inline u_int16_t
+bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
+{
+ return (in16rb(__ppc_ba(t, h, o)));
+}
+
+static __inline u_int32_t
+bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
+{
+ return (in32rb(__ppc_ba(t, h, o)));
+}
+
+#if 0 /* Cause a link error for bus_space_read_8 */
+#define bus_space_read_8(t, h, o) !!! unimplemented !!!
+#endif
+
+static __inline u_int8_t
+bus_space_read_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
+{
+ return (in8(__ppc_ba(t, h, o)));
+}
+
+static __inline u_int16_t
+bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
+{
+ return (in16(__ppc_ba(t, h, o)));
+}
+
+static __inline u_int32_t
+bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
+{
+ return (in32(__ppc_ba(t, h, o)));
+}
+
+#if 0 /* Cause a link error for bus_space_read_stream_8 */
+#define bus_space_read_stream_8(t, h, o) !!! unimplemented !!!
+#endif
+
+/*
+ * void bus_space_read_multi_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * u_intN_t *addr, size_t count));
+ *
+ * Read `count' 1, 2, 4, or 8 byte quantities from bus space
+ * described by tag/handle/offset and copy into buffer provided.
+ */
+
+static __inline void
+bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int8_t *a, size_t c)
+{
+ ins8(__ppc_ba(t, h, o), a, c);
+}
+
+static __inline void
+bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int16_t *a, size_t c)
+{
+ ins16rb(__ppc_ba(t, h, o), a, c);
+}
+
+static __inline void
+bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int32_t *a, size_t c)
+{
+ ins32rb(__ppc_ba(t, h, o), a, c);
+}
+
+#if 0 /* Cause a link error for bus_space_read_multi_8 */
+#define bus_space_read_multi_8 !!! unimplemented !!!
+#endif
+
+static __inline void
+bus_space_read_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t o, u_int8_t *a, size_t c)
+{
+ ins8(__ppc_ba(t, h, o), a, c);
+}
+
+static __inline void
+bus_space_read_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t o, u_int16_t *a, size_t c)
+{
+ ins16(__ppc_ba(t, h, o), a, c);
+}
+
+static __inline void
+bus_space_read_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t o, u_int32_t *a, size_t c)
+{
+ ins32(__ppc_ba(t, h, o), a, c);
+}
+
+#if 0 /* Cause a link error for bus_space_read_multi_stream_8 */
+#define bus_space_read_multi_stream_8 !!! unimplemented !!!
+#endif
+
+/*
+ * void bus_space_read_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * u_intN_t *addr, size_t count));
+ *
+ * Read `count' 1, 2, 4, or 8 byte quantities from bus space
+ * described by tag/handle and starting at `offset' and copy into
+ * buffer provided.
+ */
+
+static __inline void
+bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t *addr, size_t count)
+{
+ volatile u_int8_t *s = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ *addr++ = *s++;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t *addr, size_t count)
+{
+ volatile u_int16_t *s = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ __asm __volatile("lhbrx %0, 0, %1" :
+ "=r"(*addr++) : "r"(s++));
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int32_t *addr, size_t count)
+{
+ volatile u_int32_t *s = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ __asm __volatile("lwbrx %0, 0, %1" :
+ "=r"(*addr++) : "r"(s++));
+ __asm __volatile("eieio; sync");
+}
+
+#if 0 /* Cause a link error for bus_space_read_region_8 */
+#define bus_space_read_region_8 !!! unimplemented !!!
+#endif
+
+static __inline void
+bus_space_read_region_stream_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t *addr, size_t count)
+{
+ volatile u_int16_t *s = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ *addr++ = *s++;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_read_region_stream_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int32_t *addr, size_t count)
+{
+ volatile u_int32_t *s = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ *addr++ = *s++;
+ __asm __volatile("eieio; sync");
+}
+
+#if 0 /* Cause a link error */
+#define bus_space_read_region_stream_8 !!! unimplemented !!!
+#endif
+
+/*
+ * void bus_space_write_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * u_intN_t value));
+ *
+ * Write the 1, 2, 4, or 8 byte value `value' to bus space
+ * described by tag/handle/offset.
+ */
+
+static __inline void
+bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ uint8_t v)
+{
+ out8(__ppc_ba(t, h, o), v);
+}
+
+static __inline void
+bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ uint16_t v)
+{
+ out16rb(__ppc_ba(t, h, o), v);
+}
+
+static __inline void
+bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ uint32_t v)
+{
+ out32rb(__ppc_ba(t, h, o), v);
+}
+
+#if 0 /* Cause a link error for bus_space_write_8 */
+#define bus_space_write_8 !!! unimplemented !!!
+#endif
+
+static __inline void
+bus_space_write_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ uint8_t v)
+{
+ out8(__ppc_ba(t, h, o), v);
+}
+
+static __inline void
+bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ uint16_t v)
+{
+ out16(__ppc_ba(t, h, o), v);
+}
+
+static __inline void
+bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ uint32_t v)
+{
+ out32(__ppc_ba(t, h, o), v);
+}
+
+#if 0 /* Cause a link error for bus_space_write_stream_8 */
+#define bus_space_write_stream_8 !!! unimplemented !!!
+#endif
+
+
+/*
+ * void bus_space_write_multi_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * const u_intN_t *addr, size_t count));
+ *
+ * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
+ * provided to bus space described by tag/handle/offset.
+ */
+
+static __inline void
+bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ uint8_t *a, size_t c)
+{
+ outsb(__ppc_ba(t, h, o), a, c);
+}
+
+static __inline void
+bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ uint16_t *a, size_t c)
+{
+ outsw(__ppc_ba(t, h, o), a, c);
+}
+
+static __inline void
+bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ uint32_t *a, size_t c)
+{
+ outsl(__ppc_ba(t, h, o), a, c);
+}
+
+#if 0
+#define bus_space_write_multi_8 !!! unimplemented !!!
+#endif
+
+static __inline void
+bus_space_write_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t o, const u_int8_t *a, size_t c)
+{
+ outsb(__ppc_ba(t, h, o), a, c);
+}
+
+static __inline void
+bus_space_write_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t o, const u_int16_t *a, size_t c)
+{
+ outsw(__ppc_ba(t, h, o), a, c);
+}
+
+static __inline void
+bus_space_write_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t o, const u_int32_t *a, size_t c)
+{
+ outsl(__ppc_ba(t, h, o), a, c);
+}
+
+#if 0
+#define bus_space_write_multi_stream_8 !!! unimplemented !!!
+#endif
+
+/*
+ * void bus_space_write_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * const u_intN_t *addr, size_t count));
+ *
+ * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
+ * to bus space described by tag/handle starting at `offset'.
+ */
+
+static __inline void
+bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, const u_int8_t *addr, size_t count)
+{
+ volatile u_int8_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ *d++ = *addr++;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, const u_int16_t *addr, size_t count)
+{
+ volatile u_int16_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ __asm __volatile("sthbrx %0, 0, %1" ::
+ "r"(*addr++), "r"(d++));
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, const u_int32_t *addr, size_t count)
+{
+ volatile u_int32_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ __asm __volatile("stwbrx %0, 0, %1" ::
+ "r"(*addr++), "r"(d++));
+ __asm __volatile("eieio; sync");
+}
+
+#if 0
+#define bus_space_write_region_8 !!! bus_space_write_region_8 unimplemented !!!
+#endif
+
+static __inline void
+bus_space_write_region_stream_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, const u_int16_t *addr, size_t count)
+{
+ volatile u_int16_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ *d++ = *addr++;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_write_region_stream_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, const u_int32_t *addr, size_t count)
+{
+ volatile u_int32_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ *d++ = *addr++;
+ __asm __volatile("eieio; sync");
+}
+
+#if 0
+#define bus_space_write_region_stream_8 !!! unimplemented !!!
+#endif
+
+/*
+ * void bus_space_set_multi_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
+ * size_t count));
+ *
+ * Write the 1, 2, 4, or 8 byte value `val' to bus space described
+ * by tag/handle/offset `count' times.
+ */
+
+static __inline void
+bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t val, size_t count)
+{
+ volatile u_int8_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ *d = val;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t val, size_t count)
+{
+ volatile u_int16_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ __asm __volatile("sthbrx %0, 0, %1" ::
+ "r"(val), "r"(d));
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int32_t val, size_t count)
+{
+ volatile u_int32_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ __asm __volatile("stwbrx %0, 0, %1" ::
+ "r"(val), "r"(d));
+ __asm __volatile("eieio; sync");
+}
+
+#if 0
+#define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
+#endif
+
+static __inline void
+bus_space_set_multi_stream_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t val, size_t count)
+{
+ volatile u_int16_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ *d = val;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_set_multi_stream_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int32_t val, size_t count)
+{
+ volatile u_int32_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ *d = val;
+ __asm __volatile("eieio; sync");
+}
+
+#if 0
+#define bus_space_set_multi_stream_8 !!! unimplemented !!!
+#endif
+
+/*
+ * void bus_space_set_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
+ * size_t count));
+ *
+ * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
+ * by tag/handle starting at `offset'.
+ */
+
+static __inline void
+bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t val, size_t count)
+{
+ volatile u_int8_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ *d++ = val;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t val, size_t count)
+{
+ volatile u_int16_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ __asm __volatile("sthbrx %0, 0, %1" ::
+ "r"(val), "r"(d++));
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int32_t val, size_t count)
+{
+ volatile u_int32_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ __asm __volatile("stwbrx %0, 0, %1" ::
+ "r"(val), "r"(d++));
+ __asm __volatile("eieio; sync");
+}
+
+#if 0
+#define bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!!
+#endif
+
+static __inline void
+bus_space_set_region_stream_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t val, size_t count)
+{
+ volatile u_int16_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ *d++ = val;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline void
+bus_space_set_region_stream_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+ bus_size_t offset, u_int32_t val, size_t count)
+{
+ volatile u_int32_t *d = __ppc_ba(tag, bsh, offset);
+
+ while (count--)
+ *d++ = val;
+ __asm __volatile("eieio; sync");
+}
+
+#if 0
+#define bus_space_set_region_stream_8 !!! unimplemented !!!
+#endif
+
+/*
+ * void bus_space_copy_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh1, bus_size_t off1,
+ * bus_space_handle_t bsh2, bus_size_t off2,
+ * size_t count));
+ *
+ * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
+ * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
+ */
+
+ /* XXX IMPLEMENT bus_space_copy_N() XXX */
+
+/*
+ * Bus read/write barrier methods.
+ *
+ * void bus_space_barrier(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * bus_size_t len, int flags));
+ *
+ * Note: the macppc does not currently require barriers, but we must
+ * provide the flags to MI code.
+ */
+
+#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */
+#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */
+
+static __inline void
+bus_space_barrier(bus_space_tag_t tag __unused,
+ bus_space_handle_t bsh __unused, bus_size_t offset __unused,
+ bus_size_t len __unused, int flags __unused)
+{
+ __asm __volatile("" : : : "memory");
+}
+
+
+#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
+
+#include <machine/bus_dma.h>
+
+#endif /* _MACPPC_BUS_H_ */
diff --git a/sys/powerpc/include/bus_dma.h b/sys/powerpc/include/bus_dma.h
new file mode 100644
index 000000000000..d10a0557bc6b
--- /dev/null
+++ b/sys/powerpc/include/bus_dma.h
@@ -0,0 +1,33 @@
+/*-
+ * 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$ */
+
+#ifndef _POWERPC_BUS_DMA_H_
+#define _POWERPC_BUS_DMA_H_
+
+#include <sys/bus_dma.h>
+
+#endif /* _POWERPC_BUS_DMA_H_ */
diff --git a/sys/powerpc/include/clock.h b/sys/powerpc/include/clock.h
new file mode 100644
index 000000000000..ead37ac149ab
--- /dev/null
+++ b/sys/powerpc/include/clock.h
@@ -0,0 +1,24 @@
+/*-
+ * Kernel interface to machine-dependent clock driver.
+ * Garrett Wollman, September 1994.
+ * This file is in the public domain.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_CLOCK_H_
+#define _MACHINE_CLOCK_H_
+
+#ifdef _KERNEL
+
+struct trapframe;
+
+int sysbeep(int pitch, int period);
+int acquire_timer2(int mode);
+int release_timer2(void);
+
+void decr_intr(struct trapframe *);
+
+#endif
+
+#endif /* !_MACHINE_CLOCK_H_ */
diff --git a/sys/powerpc/include/cpu.h b/sys/powerpc/include/cpu.h
new file mode 100644
index 000000000000..a8fea27d3dca
--- /dev/null
+++ b/sys/powerpc/include/cpu.h
@@ -0,0 +1,81 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_CPU_H_
+#define _MACHINE_CPU_H_
+
+#include <machine/frame.h>
+#include <machine/pcb.h>
+#include <machine/psl.h>
+
+#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 */
+
+void cpu_halt(void);
+void cpu_reset(void);
+void fork_trampoline(void);
+void swi_vm(void *);
+
+/* XXX the following should not be here. */
+void savectx(struct pcb *);
+int kcopy(const void *, void *, size_t);
+
+#endif /* _MACHINE_CPU_H_ */
diff --git a/sys/powerpc/include/cpufunc.h b/sys/powerpc/include/cpufunc.h
new file mode 100644
index 000000000000..f02ff3bd55a3
--- /dev/null
+++ b/sys/powerpc/include/cpufunc.h
@@ -0,0 +1,175 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_CPUFUNC_H_
+#define _MACHINE_CPUFUNC_H_
+
+/*
+ * Required for user-space atomic.h includes
+ */
+static __inline void
+powerpc_mb(void)
+{
+
+ __asm __volatile("eieio; sync" : : : "memory");
+}
+
+#ifdef _KERNEL
+
+#include <sys/types.h>
+
+#include <machine/psl.h>
+
+struct thread;
+
+#ifdef KDB
+void ppc_db_trap(void);
+#endif
+
+static __inline void
+breakpoint(void)
+{
+#ifdef KDB
+ ppc_db_trap();
+#endif
+}
+
+/* CPU register mangling inlines */
+
+static __inline void
+mtmsr(register_t value)
+{
+
+ __asm __volatile ("mtmsr %0; isync" :: "r"(value));
+}
+
+static __inline register_t
+mfmsr(void)
+{
+ register_t value;
+
+ __asm __volatile ("mfmsr %0" : "=r"(value));
+
+ return (value);
+}
+
+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);
+}
+
+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 void
+eieio(void)
+{
+
+ __asm __volatile ("eieio");
+}
+
+static __inline void
+isync(void)
+{
+
+ __asm __volatile ("isync");
+}
+
+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 void
+restore_intr(unsigned int msr)
+{
+
+ mtmsr(msr);
+}
+
+static __inline struct pcpu *
+powerpc_get_pcpup(void)
+{
+ struct pcpu *ret;
+
+ __asm ("mfsprg %0, 0" : "=r"(ret));
+
+ return(ret);
+}
+
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_CPUFUNC_H_ */
diff --git a/sys/powerpc/include/db_machdep.h b/sys/powerpc/include/db_machdep.h
new file mode 100644
index 000000000000..8873d43ac8bd
--- /dev/null
+++ b/sys/powerpc/include/db_machdep.h
@@ -0,0 +1,92 @@
+/*-
+ * 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@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$
+ */
+
+/*
+ * Machine-dependent defines for new kernel debugger.
+ */
+#ifndef _POWERPC_DB_MACHDEP_H_
+#define _POWERPC_DB_MACHDEP_H_
+
+#include <vm/vm_param.h>
+
+#define DB_ELF_SYMBOLS
+#define DB_ELFSIZE 32
+
+#define BYTE_MSF (1)
+
+typedef vm_offset_t db_addr_t; /* address - unsigned */
+typedef int 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_ */
diff --git a/sys/powerpc/include/elf.h b/sys/powerpc/include/elf.h
new file mode 100644
index 000000000000..d2b8e12107d8
--- /dev/null
+++ b/sys/powerpc/include/elf.h
@@ -0,0 +1,101 @@
+/*-
+ * 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$
+ */
+
+#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.
+ */
+
+#include <sys/elf32.h> /* Definitions common to all 32 bit architectures. */
+
+#define __ELF_WORD_SIZE 32 /* Used by <sys/elf_generic.h> */
+#include <sys/elf_generic.h>
+
+#define ELF_ARCH EM_PPC
+
+#define ELF_MACHINE_OK(x) ((x) == EM_PPC)
+
+/*
+ * 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;
+
+__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_COUNT 13 /* Count of defined aux entry types. */
+
+/* Used in John Polstra's testbed stuff. */
+#define AT_DEBUG 14 /* Debugging level. */
+
+/*
+ * 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 */
+#define ELF_TARG_CLASS ELFCLASS32
+#define ELF_TARG_DATA ELFDATA2MSB
+#define ELF_TARG_MACH EM_PPC
+#define ELF_TARG_VER 1
+
+#endif /* !_MACHINE_ELF_H_ */
diff --git a/sys/powerpc/include/endian.h b/sys/powerpc/include/endian.h
new file mode 100644
index 000000000000..bc96b9e4fc81
--- /dev/null
+++ b/sys/powerpc/include/endian.h
@@ -0,0 +1,111 @@
+/*-
+ * 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
+ * $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $
+ * $FreeBSD$
+ */
+
+#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
+
+/*
+ * Definitions for byte order, according to byte significance from low
+ * address to high.
+ */
+#undef _BIG_ENDIAN /* GCC annoyingly defines this for PowerPC */
+#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 */
+
+#define _BYTE_ORDER _BIG_ENDIAN
+
+/*
+ * 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
+
+#ifdef __CC_SUPPORTS___INLINE
+
+static __inline __uint16_t
+__bswap16(__uint16_t _x)
+{
+
+ return ((_x >> 8) | ((_x << 8) & 0xff00));
+}
+
+static __inline __uint32_t
+__bswap32(__uint32_t _x)
+{
+
+ return ((_x >> 24) | ((_x >> 8) & 0xff00) | ((_x << 8) & 0xff0000) |
+ ((_x << 24) & 0xff000000));
+}
+
+static __inline __uint64_t
+__bswap64(__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 __htonl(x) ((__uint32_t)(x))
+#define __htons(x) ((__uint16_t)(x))
+#define __ntohl(x) ((__uint32_t)(x))
+#define __ntohs(x) ((__uint16_t)(x))
+
+#else /* !__CC_SUPPORTS___INLINE */
+
+/*
+ * No optimizations are available for this compiler. Fall back to
+ * non-optimized functions by defining the constant usually used to prevent
+ * redefinition.
+ */
+#define _BYTEORDER_FUNC_DEFINED
+
+#endif /* __CC_SUPPORTS___INLINE */
+
+#endif /* !_MACHINE_ENDIAN_H_ */
diff --git a/sys/powerpc/include/exec.h b/sys/powerpc/include/exec.h
new file mode 100644
index 000000000000..f5a2bb26f61f
--- /dev/null
+++ b/sys/powerpc/include/exec.h
@@ -0,0 +1,37 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_EXEC_H_
+#define _MACHINE_EXEC_H_
+
+#define __LDPGSZ 4096
+
+#endif /* !_MACHINE_EXEC_H_ */
diff --git a/sys/powerpc/include/float.h b/sys/powerpc/include/float.h
new file mode 100644
index 000000000000..5ac715a04180
--- /dev/null
+++ b/sys/powerpc/include/float.h
@@ -0,0 +1,80 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_FLOAT_H_
+#define _MACHINE_FLOAT_H_ 1
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int __flt_rounds(void);
+__END_DECLS
+
+#define FLT_RADIX 2 /* b */
+#define FLT_ROUNDS __flt_rounds()
+#if __ISO_C_VISIBLE >= 1999
+#define FLT_EVAL_METHOD 1 /* operands promoted to double */
+#define DECIMAL_DIG 35 /* 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)) */
+
+#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
+
+#define LDBL_MANT_DIG DBL_MANT_DIG
+#define LDBL_EPSILON DBL_EPSILON
+#define LDBL_DIG DBL_DIG
+#define LDBL_MIN_EXP DBL_MIN_EXP
+#define LDBL_MIN DBL_MIN
+#define LDBL_MIN_10_EXP DBL_MIN_10_EXP
+#define LDBL_MAX_EXP DBL_MAX_EXP
+#define LDBL_MAX DBL_MAX
+#define LDBL_MAX_10_EXP DBL_MAX_10_EXP
+
+#endif /* _MACHINE_FLOAT_H_ */
diff --git a/sys/powerpc/include/floatingpoint.h b/sys/powerpc/include/floatingpoint.h
new file mode 100644
index 000000000000..e62e47415a74
--- /dev/null
+++ b/sys/powerpc/include/floatingpoint.h
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2004 Suleiman Souhlal <refugee@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$
+ */
+
+#ifndef _FLOATINGPOINT_H_
+#define _FLOATINGPOINT_H_
+
+#include <machine/ieeefp.h>
+
+#endif /* !_FLOATINGPOINT_H_ */
diff --git a/sys/powerpc/include/fpu.h b/sys/powerpc/include/fpu.h
new file mode 100644
index 000000000000..d712b9458903
--- /dev/null
+++ b/sys/powerpc/include/fpu.h
@@ -0,0 +1,82 @@
+/*-
+ * 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$
+ */
+
+#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
+
+/* List of PowerPC architectures that support FPUs. */
+#if defined(OEA)
+#define PPC_HAVE_FPU
+
+void enable_fpu(struct thread *);
+void save_fpu(struct thread *);
+#endif /* PPC_HAVE_FPU */
+#endif /* _KERNEL */
+
+#endif /* _MACHINE_FPU_H_ */
diff --git a/sys/powerpc/include/frame.h b/sys/powerpc/include/frame.h
new file mode 100644
index 000000000000..09b7a9517771
--- /dev/null
+++ b/sys/powerpc/include/frame.h
@@ -0,0 +1,84 @@
+/*-
+ * 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$
+ */
+
+#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;
+ int cr;
+ int xer;
+ register_t ctr;
+ register_t srr0;
+ register_t srr1;
+ register_t dar; /* dar & dsisr are only filled on a DSI trap */
+ int dsisr;
+ int exc;
+};
+/*
+ * This is to ensure alignment of the stackpointer
+ */
+#define FRAMELEN roundup(sizeof(struct trapframe) + 8, 16)
+#define trapframe(td) ((td)->td_frame)
+
+/*
+ * Call frame for PowerPC used during fork.
+ */
+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;
+};
+
+/* Definitions for syscalls */
+#define FIRSTARG 3 /* first arg in reg 3 */
+#define NARGREG 8 /* 8 args in regs */
+#define MOREARGS(sp) ((caddr_t)((int)(sp) + 8)) /* more args go here */
+
+#endif /* _MACHINE_FRAME_H_ */
diff --git a/sys/powerpc/include/gdb_machdep.h b/sys/powerpc/include/gdb_machdep.h
new file mode 100644
index 000000000000..e8c5055fdf5a
--- /dev/null
+++ b/sys/powerpc/include/gdb_machdep.h
@@ -0,0 +1,53 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_GDB_MACHDEP_H_
+#define _MACHINE_GDB_MACHDEP_H_
+
+#define GDB_NREGS 153
+#define GDB_REG_PC 64
+
+#define GDB_BUFSZ (GDB_NREGS*4)
+
+static __inline size_t
+gdb_cpu_regsz(int regnum)
+{
+ return (sizeof(int));
+}
+
+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_ */
diff --git a/sys/powerpc/include/hid.h b/sys/powerpc/include/hid.h
new file mode 100644
index 000000000000..3739839af252
--- /dev/null
+++ b/sys/powerpc/include/hid.h
@@ -0,0 +1,137 @@
+/*-
+ * 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$
+ */
+
+#ifndef _POWERPC_HID_H_
+#define _POWERPC_HID_H_
+
+/* Hardware Implementation Dependent registers for the PowerPC */
+
+#define HID0_EMCP 0x80000000 /* Enable MCP */
+#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_TBEN 0x04000000 /* Time base enable (7450) */
+#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_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_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_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"
+
+/*
+ * HID0 bit definitions per cpu model
+ *
+ * bit 603 604 750 7400 7410 7450 7457
+ * 0 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
+ * 9 NAP - NAP NAP NAP NAP NAP
+ * 10 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
+ * 18 ILOCK ILOCK ILOCK ILOCK ILOCK ILOCK ILOCK
+ * 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
+ * 25 - - 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
+ *
+ * 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
+ */
+
+#endif /* _POWERPC_HID_H_ */
diff --git a/sys/powerpc/include/ieee.h b/sys/powerpc/include/ieee.h
new file mode 100644
index 000000000000..793012de4435
--- /dev/null
+++ b/sys/powerpc/include/ieee.h
@@ -0,0 +1,142 @@
+/*-
+ * 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$
+ */
+
+#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
diff --git a/sys/powerpc/include/ieeefp.h b/sys/powerpc/include/ieeefp.h
new file mode 100644
index 000000000000..820fffe1cd9c
--- /dev/null
+++ b/sys/powerpc/include/ieeefp.h
@@ -0,0 +1,25 @@
+/* -
+ * 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$
+ */
+
+#ifndef _MACHINE_IEEEFP_H_
+#define _MACHINE_IEEEFP_H_
+
+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;
+
+#endif /* _MACHINE_IEEEFP_H_ */
diff --git a/sys/powerpc/include/in_cksum.h b/sys/powerpc/include/in_cksum.h
new file mode 100644
index 000000000000..09920062a0ae
--- /dev/null
+++ b/sys/powerpc/include/in_cksum.h
@@ -0,0 +1,76 @@
+/*-
+ * 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$
+ */
+
+#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)
+
+/*
+ * 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
+
+#ifdef _KERNEL
+u_int in_cksum_hdr(const struct ip *ip);
+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_ */
diff --git a/sys/powerpc/include/intr.h b/sys/powerpc/include/intr.h
new file mode 100644
index 000000000000..8bc417c6a9bd
--- /dev/null
+++ b/sys/powerpc/include/intr.h
@@ -0,0 +1,164 @@
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ *
+ * $NetBSD: intr.h,v 1.6 2000/02/11 13:15:44 tsubai Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _MACPPC_INTR_H_
+#define _MACPPC_INTR_H_
+
+/* Interrupt priority `levels'. */
+#define IPL_NONE 9 /* nothing */
+#define IPL_SOFTCLOCK 8 /* timeouts */
+#define IPL_SOFTNET 7 /* protocol stacks */
+#define IPL_BIO 6 /* block I/O */
+#define IPL_NET 5 /* network */
+#define IPL_SOFTSERIAL 4 /* serial */
+#define IPL_TTY 3 /* terminal */
+#define IPL_IMP 3 /* memory allocation */
+#define IPL_AUDIO 2 /* audio */
+#define IPL_CLOCK 1 /* clock */
+#define IPL_HIGH 1 /* everything */
+#define IPL_SERIAL 0 /* serial */
+#define NIPL 10
+
+/* Interrupt sharing types. */
+#define IST_NONE 0 /* none */
+#define IST_PULSE 1 /* pulsed */
+#define IST_EDGE 2 /* edge-triggered */
+#define IST_LEVEL 3 /* level-triggered */
+
+#ifndef LOCORE
+
+#if 0
+/*
+ * Interrupt handler chains. intr_establish() inserts a handler into
+ * the list. The handler is called with its (single) argument.
+ */
+struct intrhand {
+ int (*ih_fun)(void *);
+ void *ih_arg;
+ u_long ih_count;
+ struct intrhand *ih_next;
+ int ih_level;
+ int ih_irq;
+};
+#endif
+
+void setsoftclock(void);
+void clearsoftclock(void);
+void setsoftnet(void);
+void clearsoftnet(void);
+
+void do_pending_int(void);
+
+static __inline void softintr(int);
+
+extern u_int cpl, ipending, tickspending;
+extern int imask[];
+
+/* Following code should be implemented with lwarx/stwcx to avoid
+ * the disable/enable. i need to read the manual once more.... */
+static __inline void
+softintr(int ipl)
+{
+ unsigned int msrsave;
+
+ msrsave = mfmsr();
+ mtmsr(msrsave & ~PSL_EE);
+
+ ipending |= 1 << ipl;
+
+ mtmsr(msrsave);
+}
+
+#define ICU_LEN 64
+
+/* Soft interrupt masks. */
+#define SIR_CLOCK 28
+#define SIR_NET 29
+#define SIR_SERIAL 30
+#define SPL_CLOCK 31
+
+#if 0
+
+/*
+ * Hardware interrupt masks
+ */
+
+#define splbio() splraise(imask[IPL_BIO])
+#define splnet() splraise(imask[IPL_NET])
+#define spltty() splraise(imask[IPL_TTY])
+#define splaudio() splraise(imask[IPL_AUDIO])
+#define splclock() splraise(imask[IPL_CLOCK])
+#define splstatclock() splclock()
+#define splserial() splraise(imask[IPL_SERIAL])
+
+#define spllpt() spltty()
+
+/*
+ * Software interrupt masks
+ *
+ * NOTE: splsoftclock() is used by hardclock() to lower the priority from
+ * clock to softclock before it calls softclock().
+ */
+#define spllowersoftclock() spllower(imask[IPL_SOFTCLOCK])
+#define splsoftclock() splraise(imask[IPL_SOFTCLOCK])
+#define splsoftnet() splraise(imask[IPL_SOFTNET])
+#define splsoftserial() splraise(imask[IPL_SOFTSERIAL])
+
+/*
+ * Miscellaneous
+ */
+#define splimp() splraise(imask[IPL_IMP])
+#define splhigh() splraise(imask[IPL_HIGH])
+#define spl0() spllower(0)
+
+#endif /* 0 */
+
+#define setsoftclock() softintr(SIR_CLOCK)
+#define setsoftnet() softintr(SIR_NET)
+#define setsoftserial() softintr(SIR_SERIAL)
+
+#define CNT_IRQ0 0
+#define CNT_CLOCK 64
+#define CNT_SOFTCLOCK 65
+#define CNT_SOFTNET 66
+#define CNT_SOFTSERIAL 67
+
+#endif /* !LOCORE */
+
+#endif /* !_MACPPC_INTR_H_ */
diff --git a/sys/powerpc/include/intr_machdep.h b/sys/powerpc/include/intr_machdep.h
new file mode 100644
index 000000000000..25f47f0301c8
--- /dev/null
+++ b/sys/powerpc/include/intr_machdep.h
@@ -0,0 +1,45 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_INTR_MACHDEP_H_
+#define _MACHINE_INTR_MACHDEP_H_
+
+#define INTR_VECTORS 256
+
+extern device_t pic;
+
+struct trapframe;
+
+void powerpc_register_pic(device_t);
+
+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 *);
+
+#endif /* _MACHINE_INTR_MACHDEP_H_ */
diff --git a/sys/powerpc/include/kdb.h b/sys/powerpc/include/kdb.h
new file mode 100644
index 000000000000..2cb49a801b08
--- /dev/null
+++ b/sys/powerpc/include/kdb.h
@@ -0,0 +1,60 @@
+/*-
+ * 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$
+ */
+
+#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>
+
+static __inline void
+kdb_cpu_clear_singlestep(void)
+{
+ kdb_frame->srr1 &= ~PSL_SE;
+}
+
+static __inline void
+kdb_cpu_set_singlestep(void)
+{
+ kdb_frame->srr1 |= PSL_SE;
+}
+
+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_ */
diff --git a/sys/powerpc/include/limits.h b/sys/powerpc/include/limits.h
new file mode 100644
index 000000000000..35eea1f619de
--- /dev/null
+++ b/sys/powerpc/include/limits.h
@@ -0,0 +1,44 @@
+/*-
+ * 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$
+ */
+
+#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_ */
diff --git a/sys/powerpc/include/md_var.h b/sys/powerpc/include/md_var.h
new file mode 100644
index 000000000000..567b190876b8
--- /dev/null
+++ b/sys/powerpc/include/md_var.h
@@ -0,0 +1,65 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_MD_VAR_H_
+#define _MACHINE_MD_VAR_H_
+
+/*
+ * Miscellaneous machine-dependent declarations.
+ */
+
+extern char sigcode[];
+extern char esigcode[];
+extern int szsigcode;
+extern long Maxmem;
+extern int busdma_swi_pending;
+
+extern vm_offset_t kstack0;
+extern vm_offset_t kstack0_phys;
+
+extern u_long ns_per_tick;
+
+#if defined(_KERNEL) || defined(_STANDALONE)
+#define CACHELINESIZE 32
+#endif
+
+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_tc_init(void);
+
+void cpu_setup(u_int);
+
+struct trapframe;
+void powerpc_interrupt(struct trapframe *);
+
+#endif /* !_MACHINE_MD_VAR_H_ */
diff --git a/sys/powerpc/include/memdev.h b/sys/powerpc/include/memdev.h
new file mode 100644
index 000000000000..69072d9889ca
--- /dev/null
+++ b/sys/powerpc/include/memdev.h
@@ -0,0 +1,40 @@
+/*-
+ * 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$
+ */
+
+#define CDEV_MAJOR 2
+#define CDEV_MINOR_MEM 0
+#define CDEV_MINOR_KMEM 1
+
+d_open_t memopen;
+d_read_t memrw;
+#define memioctl (d_ioctl_t *)NULL
+d_mmap_t memmmap;
+
+void dev_mem_md_init(void);
+
+MALLOC_DECLARE(M_MEMDEV);
diff --git a/sys/powerpc/include/metadata.h b/sys/powerpc/include/metadata.h
new file mode 100644
index 000000000000..124d46b1b551
--- /dev/null
+++ b/sys/powerpc/include/metadata.h
@@ -0,0 +1,36 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_METADATA_H_
+#define _MACHINE_METADATA_H_
+
+#define MODINFOMD_ENVP 0x1001
+#define MODINFOMD_HOWTO 0x1002
+#define MODINFOMD_KERNEND 0x1003
+
+#endif /* !_MACHINE_METADATA_H_ */
diff --git a/sys/powerpc/include/mmuvar.h b/sys/powerpc/include/mmuvar.h
new file mode 100644
index 000000000000..fc2f8d5c9ca5
--- /dev/null
+++ b/sys/powerpc/include/mmuvar.h
@@ -0,0 +1,96 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_MMUVAR_H_
+#define _MACHINE_MMUVAR_H_
+
+/*
+ * A PowerPC MMU implementation is declared with a kernel object and
+ * an associated method table, similar to a device driver.
+ *
+ * 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 }
+ * };
+ *
+ * static mmu_def_t ppc8xx_mmu = {
+ * "ppc8xx",
+ * ppc8xx_methods,
+ * sizeof(ppc8xx_mmu_softc), // or 0 if no softc
+ * };
+ *
+ * MMU_DEF(ppc8xx_mmu);
+ */
+
+#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) DATA_SET(mmu_set, name)
+
+/*
+ * Known MMU names
+ */
+#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_ */
diff --git a/sys/powerpc/include/mutex.h b/sys/powerpc/include/mutex.h
new file mode 100644
index 000000000000..0b7fe2633e26
--- /dev/null
+++ b/sys/powerpc/include/mutex.h
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 1997 Berkeley Software Design, 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. Berkeley Software Design Inc's name may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN 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 BERKELEY SOFTWARE DESIGN 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.
+ *
+ * from BSDI $Id: mutex.h,v 2.7.2.35 2000/04/27 03:10:26 cp Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_MUTEX_H_
+#define _MACHINE_MUTEX_H_
+
+#ifdef LOCORE
+
+/*
+ * Simple assembly macros to get and release non-recursive spin locks
+ */
+#define MTX_ENTER(lck) \
+ mfmsr r10; \ /* disable interrupts */
+ rlwinm r0, r10, 0, 17, 15; \
+ mtmsr r0; \
+1: li r11, MTX_LOCK; \ /* MTX_LOCK offset */
+ lwarx r0, r11, lck; \ /* load current lock value */
+ cmplwi r0, r1, MTX_UNOWNED; \ /* compare with unowned */
+ beq 1; \ /* if owned, loop */
+ lwz r0, PC_CURPROC(pcpup); \ /* load curproc */
+ stwcx. r0, r11, lck; \ /* attempt to store */
+ beq 1; \ /* loop if failed */
+ sync; \ /* sync */
+ eieio; \ /* sync */
+ stw r10, MTX_SAVEINTR(lck) /* save flags */
+
+#define MTX_EXIT(lck) \
+ sync; \ /* sync */
+ eieio; \ /* sync */
+ li r0, MTX_UNOWNED; \ /* load in unowned */
+ stw r0, MTX_LOCK(lck); \ /* store to lock */
+ lwz r0, MTX_SAVEINTR(lck); \ /* load saved flags */
+ mtmsr r0 /* enable interrupts */
+
+#endif /* !LOCORE */
+
+#endif /* __MACHINE_MUTEX_H */
diff --git a/sys/powerpc/include/nexusvar.h b/sys/powerpc/include/nexusvar.h
new file mode 100644
index 000000000000..df8a0f69b92c
--- /dev/null
+++ b/sys/powerpc/include/nexusvar.h
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2001 by Thomas Moestl <tmm@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$
+ */
+
+#ifndef _MACHINE_NEXUSVAR_H_
+#define _MACHINE_NEXUSVAR_H_
+
+enum nexus_ivars {
+ NEXUS_IVAR_NODE,
+ NEXUS_IVAR_NAME,
+ NEXUS_IVAR_DEVICE_TYPE,
+ NEXUS_IVAR_COMPATIBLE,
+};
+
+/*
+ * Simplified accessors for nexus devices
+ * XXX: These should be made specializations of generic bus accessor macros
+ * instead of having multiple implementations around.
+ */
+#define NEXUS_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(nexus, var, NEXUS, ivar, type)
+
+NEXUS_ACCESSOR(node, NODE, phandle_t)
+NEXUS_ACCESSOR(name, NAME, char *)
+NEXUS_ACCESSOR(device_type, DEVICE_TYPE, char *)
+NEXUS_ACCESSOR(compatible, COMPATIBLE, char *)
+
+#undef NEXUS_ACCESSOR
+
+/*
+ * Install the interrupt controller device
+ */
+int nexus_install_intcntlr(device_t);
+
+#endif /* _MACHINE_NEXUSVAR_H_ */
diff --git a/sys/powerpc/include/ofw_machdep.h b/sys/powerpc/include/ofw_machdep.h
new file mode 100644
index 000000000000..a4b601e5499e
--- /dev/null
+++ b/sys/powerpc/include/ofw_machdep.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2001 by Thomas Moestl <tmm@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$
+ */
+
+#ifndef _MACHINE_OFW_MACHDEP_H_
+#define _MACHINE_OFW_MACHDEP_H_
+
+#include <sys/bus.h>
+
+int OF_decode_addr(phandle_t, int, bus_space_tag_t *, bus_space_handle_t *);
+void OF_getetheraddr(device_t dev, u_char *addr);
+
+#endif /* _MACHINE_OFW_MACHDEP_H_ */
diff --git a/sys/powerpc/include/openpicreg.h b/sys/powerpc/include/openpicreg.h
new file mode 100644
index 000000000000..2fa393d20fd2
--- /dev/null
+++ b/sys/powerpc/include/openpicreg.h
@@ -0,0 +1,109 @@
+/*-
+ * 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$
+ */
+
+/*
+ * Size of OpenPIC register space
+ */
+#define OPENPIC_SIZE 0x40000
+
+/*
+ * GLOBAL/TIMER register (IDU base + 0x1000)
+ */
+
+/* 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
+
+
+/*
+ * INTERRUPT SOURCE register (IDU base + 0x10000)
+ */
+
+/* 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
+
+/*
+ * PROCESSOR register (IDU base + 0x20000)
+ */
+
+/* IPI command reg */
+#define OPENPIC_IPI(cpu, ipi) (0x20040 + (cpu) * 0x1000 + (ipi))
+
+/* current task priority reg */
+#define OPENPIC_CPU_PRIORITY(cpu) (0x20080 + (cpu) * 0x1000)
+#define OPENPIC_CPU_PRIORITY_MASK 0x0000000f
+
+/* interrupt acknowledge reg */
+#define OPENPIC_IACK(cpu) (0x200a0 + (cpu) * 0x1000)
+
+/* end of interrupt reg */
+#define OPENPIC_EOI(cpu) (0x200b0 + (cpu) * 0x1000)
diff --git a/sys/powerpc/include/openpicvar.h b/sys/powerpc/include/openpicvar.h
new file mode 100644
index 000000000000..081cf7aecfcf
--- /dev/null
+++ b/sys/powerpc/include/openpicvar.h
@@ -0,0 +1,63 @@
+/*-
+ * 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$
+ */
+
+#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;
+ bus_space_tag_t sc_bt;
+ bus_space_handle_t sc_bh;
+ char *sc_version;
+ int sc_rid;
+ u_int sc_ncpu;
+ u_int sc_nirq;
+ int sc_psim;
+};
+
+extern devclass_t openpic_devclass;
+
+/*
+ * Bus-independent attach i/f
+ */
+int openpic_attach(device_t);
+
+/*
+ * PIC interface.
+ */
+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_mask(device_t, u_int);
+void openpic_unmask(device_t, u_int);
+
+#endif /* _POWERPC_OPENPICVAR_H_ */
diff --git a/sys/powerpc/include/param.h b/sys/powerpc/include/param.h
new file mode 100644
index 000000000000..6a2018eab0d8
--- /dev/null
+++ b/sys/powerpc/include/param.h
@@ -0,0 +1,107 @@
+/*-
+ * 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$
+ */
+
+/*
+ * Machine dependent constants for PowerPC (32-bit only currently)
+ */
+
+/*
+ * 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.
+ */
+#ifndef _ALIGNBYTES
+#define _ALIGNBYTES (sizeof(int) - 1)
+#endif
+#ifndef _ALIGN
+#define _ALIGN(p) (((unsigned)(p) + _ALIGNBYTES) & ~_ALIGNBYTES)
+#endif
+
+#ifndef _NO_NAMESPACE_POLLUTION
+
+#ifndef _MACHINE_PARAM_H_
+#define _MACHINE_PARAM_H_
+
+#ifndef MACHINE
+#define MACHINE "powerpc"
+#endif
+#ifndef MACHINE_ARCH
+#define MACHINE_ARCH "powerpc"
+#endif
+#define MID_MACHINE MID_POWERPC
+
+#ifdef SMP
+#define MAXCPU 2
+#else
+#define MAXCPU 1
+#endif /* SMP */
+
+#define ALIGNBYTES _ALIGNBYTES
+#define ALIGN(p) _ALIGN(p)
+
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (1 << PAGE_SHIFT) /* Page size */
+#define PAGE_MASK (PAGE_SIZE - 1)
+#define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t)))
+
+#ifndef KSTACK_PAGES
+#define KSTACK_PAGES 4 /* includes pcb */
+#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 trunc_4mpage(x) ((unsigned)(x) & ~PDRMASK)
+#define round_4mpage(x) ((((unsigned)(x)) + PDRMASK) & ~PDRMASK)
+
+#define atop(x) ((unsigned long)(x) >> PAGE_SHIFT)
+#define ptoa(x) ((unsigned long)(x) << PAGE_SHIFT)
+
+#define powerpc_btop(x) ((unsigned)(x) >> PAGE_SHIFT)
+#define powerpc_ptob(x) ((unsigned)(x) << PAGE_SHIFT)
+
+#define pgtok(x) ((x) * (PAGE_SIZE / 1024))
+
+#endif /* !_MACHINE_PARAM_H_ */
+#endif /* !_NO_NAMESPACE_POLLUTION */
diff --git a/sys/powerpc/include/pcb.h b/sys/powerpc/include/pcb.h
new file mode 100644
index 000000000000..3c31441d9b21
--- /dev/null
+++ b/sys/powerpc/include/pcb.h
@@ -0,0 +1,74 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_PCB_H_
+#define _MACHINE_PCB_H_
+
+typedef int faultbuf[23];
+
+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_lr; /* link register */
+ register_t pcb_usr; /* USER_SR segment register */
+ struct pmap *pcb_pm; /* pmap of our vmspace */
+ struct pmap *pcb_pmreal; /* real address of above */
+ faultbuf *pcb_onfault; /* For use during
+ copyin/copyout */
+ int pcb_flags;
+#define PCB_FPU 1 /* Process had FPU 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. */
+};
+
+#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 *);
+
+#endif
+#endif /* _MACHINE_PCB_H_ */
diff --git a/sys/powerpc/include/pcpu.h b/sys/powerpc/include/pcpu.h
new file mode 100644
index 000000000000..6e9507630126
--- /dev/null
+++ b/sys/powerpc/include/pcpu.h
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 1999 Luoqi Chen <luoqi@freebsd.org>
+ * Copyright (c) Peter Wemm <peter@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$
+ */
+
+#ifndef _MACHINE_PCPU_H_
+#define _MACHINE_PCPU_H_
+
+#ifdef _KERNEL
+#include <machine/cpufunc.h>
+
+struct pmap;
+#define CPUSAVE_LEN 8
+
+#define PCPU_MD_FIELDS \
+ int pc_inside_intr; \
+ struct pmap *pc_curpmap; /* current pmap */ \
+ struct thread *pc_fputhread; /* current fpu user */ \
+ register_t pc_tempsave[CPUSAVE_LEN]; \
+ register_t pc_disisave[CPUSAVE_LEN]; \
+ register_t pc_dbsave[CPUSAVE_LEN];
+
+/* Definitions for register offsets within the exception tmp save areas */
+#define CPUSAVE_R28 0 /* where r28 gets saved */
+#define CPUSAVE_R29 1 /* where r29 gets saved */
+#define CPUSAVE_R30 2 /* where r30 gets saved */
+#define CPUSAVE_R31 3 /* where r31 gets saved */
+#define CPUSAVE_DAR 4 /* where SPR_DAR gets saved */
+#define CPUSAVE_DSISR 5 /* where SPR_DSISR gets saved */
+#define CPUSAVE_SRR0 6 /* where SRR0 gets saved */
+#define CPUSAVE_SRR1 7 /* where SRR1 gets saved */
+
+#define PCPUP ((struct pcpu *) powerpc_get_pcpup())
+
+#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_ */
diff --git a/sys/powerpc/include/pio.h b/sys/powerpc/include/pio.h
new file mode 100644
index 000000000000..bf2cb5b67fcc
--- /dev/null
+++ b/sys/powerpc/include/pio.h
@@ -0,0 +1,256 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_PIO_H_
+#define _MACHINE_PIO_H_
+/*
+ * I/O macros.
+ */
+
+static __inline void
+__outb(volatile u_int8_t *a, u_int8_t v)
+{
+ *a = v;
+ __asm__ volatile("eieio; sync");
+}
+
+static __inline void
+__outw(volatile u_int16_t *a, u_int16_t v)
+{
+ *a = v;
+ __asm__ volatile("eieio; sync");
+}
+
+static __inline void
+__outl(volatile u_int32_t *a, u_int32_t v)
+{
+ *a = v;
+ __asm__ volatile("eieio; sync");
+}
+
+static __inline void
+__outwrb(volatile u_int16_t *a, u_int16_t v)
+{
+ __asm__ volatile("sthbrx %0, 0, %1" :: "r"(v), "r"(a));
+ __asm__ volatile("eieio; sync");
+}
+
+static __inline void
+__outlrb(volatile u_int32_t *a, u_int32_t v)
+{
+ __asm__ volatile("stwbrx %0, 0, %1" :: "r"(v), "r"(a));
+ __asm__ volatile("eieio; sync");
+}
+
+static __inline u_int8_t
+__inb(volatile u_int8_t *a)
+{
+ u_int8_t _v_;
+
+ _v_ = *a;
+ __asm__ volatile("eieio; sync");
+ return _v_;
+}
+
+static __inline u_int16_t
+__inw(volatile u_int16_t *a)
+{
+ u_int16_t _v_;
+
+ _v_ = *a;
+ __asm__ volatile("eieio; sync");
+ return _v_;
+}
+
+static __inline u_int32_t
+__inl(volatile u_int32_t *a)
+{
+ u_int32_t _v_;
+
+ _v_ = *a;
+ __asm__ volatile("eieio; sync");
+ 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));
+ __asm__ volatile("eieio; sync");
+ 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));
+ __asm__ volatile("eieio; sync");
+ 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 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 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++;
+ __asm__ volatile("eieio; sync");
+}
+
+static __inline void
+__outsw(volatile u_int16_t *a, const u_int16_t *s, size_t c)
+{
+ while (c--)
+ *a = *s++;
+ __asm__ volatile("eieio; sync");
+}
+
+static __inline void
+__outsl(volatile u_int32_t *a, const u_int32_t *s, size_t c)
+{
+ while (c--)
+ *a = *s++;
+ __asm__ volatile("eieio; sync");
+}
+
+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));
+ __asm__ volatile("eieio; sync");
+}
+
+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));
+ __asm__ volatile("eieio; sync");
+}
+
+static __inline void
+__insb(volatile u_int8_t *a, u_int8_t *d, size_t c)
+{
+ while (c--)
+ *d++ = *a;
+ __asm__ volatile("eieio; sync");
+}
+
+static __inline void
+__insw(volatile u_int16_t *a, u_int16_t *d, size_t c)
+{
+ while (c--)
+ *d++ = *a;
+ __asm__ volatile("eieio; sync");
+}
+
+static __inline void
+__insl(volatile u_int32_t *a, u_int32_t *d, size_t c)
+{
+ while (c--)
+ *d++ = *a;
+ __asm__ volatile("eieio; sync");
+}
+
+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));
+ __asm__ volatile("eieio; sync");
+}
+
+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));
+ __asm__ volatile("eieio; sync");
+}
+
+#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 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 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_*/
diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h
new file mode 100644
index 000000000000..d02f8d646c06
--- /dev/null
+++ b/sys/powerpc/include/pmap.h
@@ -0,0 +1,114 @@
+/*-
+ * 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.h,v 1.17 2000/03/30 16:18:24 jdolecek Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_PMAP_H_
+#define _MACHINE_PMAP_H_
+
+#include <sys/queue.h>
+#include <sys/_lock.h>
+#include <sys/_mutex.h>
+#include <machine/sr.h>
+#include <machine/pte.h>
+
+#if !defined(NPMAPS)
+#define NPMAPS 32768
+#endif /* !defined(NPMAPS) */
+
+struct pmap {
+ struct mtx pm_mtx;
+ u_int pm_sr[16];
+ u_int pm_active;
+ u_int pm_context;
+ struct pmap_statistics pm_stats;
+};
+
+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 */
+ struct pte pvo_pte; /* PTE */
+ pmap_t pvo_pmap; /* Owning pmap */
+ vm_offset_t pvo_vaddr; /* VA of entry */
+};
+LIST_HEAD(pvo_head, pvo_entry);
+
+struct md_page {
+ u_int mdpg_attrs;
+ struct pvo_head mdpg_pvoh;
+};
+
+extern struct pmap kernel_pmap_store;
+#define kernel_pmap (&kernel_pmap_store)
+
+#define pmap_page_is_mapped(m) (!LIST_EMPTY(&(m)->md.mdpg_pvoh))
+
+#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", \
+ 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)
+
+void pmap_bootstrap(vm_offset_t, vm_offset_t);
+void pmap_kenter(vm_offset_t va, vm_offset_t pa);
+void pmap_kremove(vm_offset_t);
+void *pmap_mapdev(vm_offset_t, vm_size_t);
+void pmap_unmapdev(vm_offset_t, vm_size_t);
+void pmap_deactivate(struct thread *);
+vm_offset_t pmap_kextract(vm_offset_t);
+int pmap_dev_direct_mapped(vm_offset_t, vm_size_t);
+boolean_t pmap_page_executable(vm_page_t);
+boolean_t pmap_mmu_install(char *name, int prio);
+
+#define vtophys(va) pmap_kextract((vm_offset_t)(va))
+
+#define PHYS_AVAIL_SZ 128
+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;
+
+#endif
+
+#endif /* !_MACHINE_PMAP_H_ */
diff --git a/sys/powerpc/include/pmc_mdep.h b/sys/powerpc/include/pmc_mdep.h
new file mode 100644
index 000000000000..d5417c3cedb6
--- /dev/null
+++ b/sys/powerpc/include/pmc_mdep.h
@@ -0,0 +1,25 @@
+/*-
+ * This file is in the public domain.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_PMC_MDEP_H_
+#define _MACHINE_PMC_MDEP_H_
+
+union pmc_md_op_pmcallocate {
+ uint64_t __pad[4];
+};
+
+/* Logging */
+#define PMCLOG_READADDR PMCLOG_READ32
+#define PMCLOG_EMITADDR PMCLOG_EMIT32
+
+#if _KERNEL
+
+union pmc_md_pmc {
+};
+
+#endif
+
+#endif /* !_MACHINE_PMC_MDEP_H_ */
diff --git a/sys/powerpc/include/powerpc.h b/sys/powerpc/include/powerpc.h
new file mode 100644
index 000000000000..3de078899dd3
--- /dev/null
+++ b/sys/powerpc/include/powerpc.h
@@ -0,0 +1,59 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_POWERPC_H_
+#define _MACHINE_POWERPC_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 *);
+
+/*
+ * These two functions get used solely in boot() in machdep.c.
+ *
+ * Not sure whether boot itself should be implementation dependent instead. XXX
+ */
+void OF_halt(void);
+void OF_reboot(void);
+
+int dk_match(char *name);
+
+void ofrootfound(void);
+
+extern int booted_partition;
+
+#endif /* _MACHINE_POWERPC_H_ */
diff --git a/sys/powerpc/include/proc.h b/sys/powerpc/include/proc.h
new file mode 100644
index 000000000000..c958fb76f0fb
--- /dev/null
+++ b/sys/powerpc/include/proc.h
@@ -0,0 +1,49 @@
+/*-
+ * 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$
+ */
+
+#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 {
+};
+
+#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/powerpc/include/profile.h b/sys/powerpc/include/profile.h
new file mode 100644
index 000000000000..96f3825e1dc4
--- /dev/null
+++ b/sys/powerpc/include/profile.h
@@ -0,0 +1,146 @@
+/*-
+ * 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@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$
+ */
+
+#ifndef _MACHINE_PROFILE_H_
+#define _MACHINE_PROFILE_H_
+
+#define _MCOUNT_DECL void __mcount
+
+#define FUNCTION_ALIGNMENT 16
+
+typedef u_int 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@ha
+ * stw %r0,4(%r1)
+ * addi %r0,%r11, .function_mc@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 PIC
+#define _PLT "@plt"
+#else
+#define _PLT
+#endif
+
+#define MCOUNT \
+__asm(" .globl _mcount \n" \
+" .type _mcount,@function \n" \
+"_mcount: \n" \
+" stwu %r1,-64(%r1) /* alloca for reg save space */ \n" \
+" stw %r3,16(%r1) /* save parameter registers, */ \n" \
+" stw %r4,20(%r1) /* r3-10 */ \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" \
+" \n" \
+" mflr %r4 /* link register is 'selfpc' */ \n" \
+" stw %r4,48(%r1) /* save since bl will scrub */ \n" \
+" lwz %r3,68(%r1) /* get 'frompc' from LR-save */ \n" \
+" bl __mcount" _PLT " /* __mcount(frompc, selfpc)*/ \n" \
+" lwz %r3,68(%r1) \n" \
+" mtlr %r3 /* restore caller's lr */ \n" \
+" lwz %r4,48(%r1) \n" \
+" mtctr %r4 /* set up ctr for call back */ \n" \
+" /* note that blr is not used!*/ \n" \
+" lwz %r3,16(%r1) /* restore r3-10 parameters */ \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 /* blow away alloca save area */ \n" \
+" bctr /* return with indirect call */ \n" \
+"_mcount_end: \n" \
+" .size _mcount,_mcount_end-_mcount");
+
+
+#ifdef _KERNEL
+#define MCOUNT_ENTER(s) s = intr_disable();
+#define MCOUNT_EXIT(s) intr_restore(s);
+#define MCOUNT_DECL(s) register_t s
+
+void bintr(void);
+void btrap(void);
+void eintr(void);
+void user(void);
+
+#define MCOUNT_FROMPC_USER(pc) \
+ ((pc < (uintfptr_t)VM_MAXUSER_ADDRESS) ? (uintfptr_t)user : pc)
+
+#define MCOUNT_FROMPC_INTR(pc) \
+ ((pc >= (uintfptr_t)btrap && pc < (uintfptr_t)eintr) ? \
+ ((pc >= (uintfptr_t)bintr) ? (uintfptr_t)bintr : \
+ (uintfptr_t)btrap) : ~0U)
+
+
+#else /* !_KERNEL */
+
+typedef u_int uintfptr_t;
+
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_PROFILE_H_ */
diff --git a/sys/powerpc/include/psl.h b/sys/powerpc/include/psl.h
new file mode 100644
index 000000000000..a7ab6f1354b3
--- /dev/null
+++ b/sys/powerpc/include/psl.h
@@ -0,0 +1,86 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_PSL_H_
+#define _MACHINE_PSL_H_
+
+/*
+ * Machine State Register (MSR)
+ *
+ * The PowerPC 601 does not implement the following bits:
+ *
+ * VEC, POW, ILE, BE, RI, LE[*]
+ *
+ * [*] Little-endian mode on the 601 is implemented in the HID0 register.
+ */
+#define PSL_VEC 0x02000000 /* AltiVec vector unit available */
+#define PSL_POW 0x00040000 /* power management */
+#define PSL_ILE 0x00010000 /* interrupt endian mode (1 == le) */
+#define PSL_EE 0x00008000 /* external interrupt enable */
+#define PSL_PR 0x00004000 /* privilege mode (1 == user) */
+#define PSL_FP 0x00002000 /* floating point enable */
+#define PSL_ME 0x00001000 /* machine check enable */
+#define PSL_FE0 0x00000800 /* floating point interrupt mode 0 */
+#define PSL_SE 0x00000400 /* single-step trace enable */
+#define PSL_BE 0x00000200 /* branch trace enable */
+#define PSL_FE1 0x00000100 /* floating point interrupt mode 1 */
+#define PSL_IP 0x00000040 /* interrupt prefix */
+#define PSL_IR 0x00000020 /* instruction address relocation */
+#define PSL_DR 0x00000010 /* data address relocation */
+#define PSL_RI 0x00000002 /* recoverable interrupt */
+#define PSL_LE 0x00000001 /* endian mode (1 == le) */
+
+#define PSL_601_MASK ~(PSL_POW|PSL_ILE|PSL_BE|PSL_RI|PSL_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 */
+
+/*
+ * Note that PSL_POW and PSL_ILE are not in the saved copy of the MSR
+ */
+#define PSL_MBO 0
+#define PSL_MBZ 0
+
+#define PSL_KERNSET (PSL_EE | PSL_ME | PSL_IR | PSL_DR | PSL_RI)
+#define PSL_USERSET (PSL_KERNSET | PSL_PR)
+
+#define PSL_USERSTATIC (PSL_USERSET | PSL_IP | 0x87c0008c)
+
+#endif /* _MACHINE_PSL_H_ */
diff --git a/sys/powerpc/include/pte.h b/sys/powerpc/include/pte.h
new file mode 100644
index 000000000000..391c82e45951
--- /dev/null
+++ b/sys/powerpc/include/pte.h
@@ -0,0 +1,159 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_PTE_H_
+#define _MACHINE_PTE_H_
+
+/*
+ * 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_API 0x0000000000000F80ULL
+#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 0x0ffff000
+#define ADDR_PIDX_SHFT 12
+#define ADDR_API_SHFT 22
+#define ADDR_POFF 0x00000fff
+
+/*
+ * 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 */
+#endif /* _MACHINE_PTE_H_ */
diff --git a/sys/powerpc/include/ptrace.h b/sys/powerpc/include/ptrace.h
new file mode 100644
index 000000000000..eef24f829b48
--- /dev/null
+++ b/sys/powerpc/include/ptrace.h
@@ -0,0 +1,36 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_PTRACE_H_
+#define _MACHINE_PTRACE_H_
+
+#endif
diff --git a/sys/powerpc/include/reg.h b/sys/powerpc/include/reg.h
new file mode 100644
index 000000000000..640365546e7c
--- /dev/null
+++ b/sys/powerpc/include/reg.h
@@ -0,0 +1,39 @@
+/* $NetBSD: reg.h,v 1.4 2000/06/04 09:30:44 tsubai Exp $ */
+/* $FreeBSD$ */
+
+#ifndef _POWERPC_REG_H_
+#define _POWERPC_REG_H_
+
+/* Must match struct trapframe */
+struct reg {
+ register_t fixreg[32];
+ register_t lr;
+ int cr;
+ int xer;
+ register_t ctr;
+ register_t pc;
+};
+
+/* Must match pcb.pcb_fpu */
+struct fpreg {
+ double fpreg[32];
+ double fpscr;
+};
+
+struct dbreg {
+ unsigned long junk;
+};
+
+#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 *);
+#endif
+
+#endif /* _POWERPC_REG_H_ */
diff --git a/sys/powerpc/include/reloc.h b/sys/powerpc/include/reloc.h
new file mode 100644
index 000000000000..0e4155dac4cf
--- /dev/null
+++ b/sys/powerpc/include/reloc.h
@@ -0,0 +1,30 @@
+/*-
+ * Copyright (c) 1998 John Birrell <jb@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$
+ */
diff --git a/sys/powerpc/include/resource.h b/sys/powerpc/include/resource.h
new file mode 100644
index 000000000000..edde5eb29908
--- /dev/null
+++ b/sys/powerpc/include/resource.h
@@ -0,0 +1,44 @@
+/* $FreeBSD$ */
+/*-
+ * 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_ */
diff --git a/sys/powerpc/include/runq.h b/sys/powerpc/include/runq.h
new file mode 100644
index 000000000000..e906fa192c6c
--- /dev/null
+++ b/sys/powerpc/include/runq.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2001 Jake Burkholder <jake@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$
+ */
+
+#ifndef _MACHINE_RUNQ_H_
+#define _MACHINE_RUNQ_H_
+
+#define RQB_LEN (2) /* Number of priority status words. */
+#define RQB_L2BPW (5) /* Log2(sizeof(rqb_word_t) * NBBY)). */
+#define RQB_BPW (1<<RQB_L2BPW) /* Bits in an rqb_word_t. */
+
+#define RQB_BIT(pri) (1 << ((pri) & (RQB_BPW - 1)))
+#define RQB_WORD(pri) ((pri) >> RQB_L2BPW)
+
+#define RQB_FFS(word) (ffs(word) - 1)
+
+/*
+ * Type of run queue status word.
+ */
+typedef u_int32_t rqb_word_t;
+
+#endif
diff --git a/sys/powerpc/include/sc_machdep.h b/sys/powerpc/include/sc_machdep.h
new file mode 100644
index 000000000000..4f3526fabcf0
--- /dev/null
+++ b/sys/powerpc/include/sc_machdep.h
@@ -0,0 +1,71 @@
+/*-
+ * 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$
+ */
+
+#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_ */
diff --git a/sys/powerpc/include/setjmp.h b/sys/powerpc/include/setjmp.h
new file mode 100644
index 000000000000..e453044dbf3b
--- /dev/null
+++ b/sys/powerpc/include/setjmp.h
@@ -0,0 +1,24 @@
+/*-
+ * $NetBSD: setjmp.h,v 1.3 1998/09/16 23:51:27 thorpej Exp $
+ * $FreeBSD$
+ */
+
+#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_ */
diff --git a/sys/powerpc/include/sf_buf.h b/sys/powerpc/include/sf_buf.h
new file mode 100644
index 000000000000..6997419c6423
--- /dev/null
+++ b/sys/powerpc/include/sf_buf.h
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2003 Alan L. Cox <alc@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$
+ */
+
+#ifndef _MACHINE_SF_BUF_H_
+#define _MACHINE_SF_BUF_H_
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_page.h>
+
+/*
+ * On this machine, 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.
+ */
+struct sf_buf;
+
+static __inline vm_offset_t
+sf_buf_kva(struct sf_buf *sf)
+{
+
+ return (VM_PAGE_TO_PHYS((vm_page_t)sf));
+}
+
+static __inline vm_page_t
+sf_buf_page(struct sf_buf *sf)
+{
+
+ return ((vm_page_t)sf);
+}
+
+#endif /* !_MACHINE_SF_BUF_H_ */
diff --git a/sys/powerpc/include/sigframe.h b/sys/powerpc/include/sigframe.h
new file mode 100644
index 000000000000..d0e886e9bc90
--- /dev/null
+++ b/sys/powerpc/include/sigframe.h
@@ -0,0 +1,39 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_SIGFRAME_H_
+#define _MACHINE_SIGFRAME_H_ 1
+
+struct sigframe {
+ ucontext_t sf_uc;
+ siginfo_t sf_si;
+};
+
+#endif /* _MACHINE_SIGFRAME_H_ */
diff --git a/sys/powerpc/include/signal.h b/sys/powerpc/include/signal.h
new file mode 100644
index 000000000000..ba0bee2b7797
--- /dev/null
+++ b/sys/powerpc/include/signal.h
@@ -0,0 +1,53 @@
+/*-
+ * 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$
+ */
+
+#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_ */
diff --git a/sys/powerpc/include/smp.h b/sys/powerpc/include/smp.h
new file mode 100644
index 000000000000..15ec74ce8f80
--- /dev/null
+++ b/sys/powerpc/include/smp.h
@@ -0,0 +1,7 @@
+/* $FreeBSD$ */
+
+/*
+ * An empty file now,
+ * Although in the times to come,
+ * More may be found here.
+ */
diff --git a/sys/powerpc/include/spr.h b/sys/powerpc/include/spr.h
new file mode 100644
index 000000000000..f3919f1a550f
--- /dev/null
+++ b/sys/powerpc/include/spr.h
@@ -0,0 +1,481 @@
+/*-
+ * 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.
+ * 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.
+ *
+ * $NetBSD: spr.h,v 1.25 2002/08/14 15:38:40 matt Exp $
+ * $FreeBSD$
+ */
+#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; } )
+#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 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_ASR 0x118 /* ... Address Space Register (PPC64) */
+#define SPR_EAR 0x11a /* .68 External Access Register */
+#define SPR_TBL 0x11c /* 468 Time Base Lower */
+#define SPR_TBU 0x11d /* 468 Time Base Upper */
+#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 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 IBMPOWER3 0x0041
+#define MPC860 0x0050
+#define MPC8240 0x0081
+#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 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_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) << 6) /* PMC1 selector */
+#define SPR_MMCR0_PMC2SEL(x) ((x) << 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) << 27) /* PMC 3 selector */
+#define SPR_MMCR1_PMC4SEL(x) ((x) << 22) /* PMC 4 selector */
+#define SPR_MMCR1_PMC5SEL(x) ((x) << 17) /* PMC 5 selector */
+#define SPR_MMCR1_PMC6SEL(x) ((x) << 11) /* PMC 6 selector */
+
+#define SPR_SU0R 0x3bc /* 4.. Storage User-defined 0 Register */
+#define SPR_DBCR1 0x3bd /* 4.. Debug Control Register 1 */
+#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_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_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 */
+#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 0x3d8 /* 4.. Timer Status 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_FIS 0x04000000 /* FIT Interrupt Status */
+#define SPR_TCR 0x3da /* 4.. Timer Control Register */
+#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_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_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_HID0 0x3f0 /* ..8 Hardware Implementation Register 0 */
+#define SPR_HID1 0x3f1 /* ..8 Hardware Implementation Register 1 */
+#define SPR_DBCR0 0x3f2 /* 4.. Debug Control Register 0 */
+#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_HID2 0x3f3 /* ..8 Hardware Implementation Register 2 */
+#define SPR_IAC1 0x3f4 /* 4.. Instruction Address Compare 1 */
+#define SPR_IAC2 0x3f5 /* 4.. Instruction Address Compare 2 */
+#define SPR_DABR 0x3f5 /* .6. Data Address Breakpoint Register */
+#define SPR_DAC1 0x3f6 /* 4.. Data Address Compare 1 */
+#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 SPR_DAC2 0x3f7 /* 4.. Data Address Compare 2 */
+#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_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_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_L3SIZ 0x10000000 /* 3: L3 size (0=1MB, 1=2MB) */
+#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 */
+#define SPR_PIR 0x3ff /* .6. Processor Identification Register */
+
+/* Time Base Register declarations */
+#define TBR_TBL 0x10c /* 468 Time Base Lower */
+#define TBR_TBU 0x10d /* 468 Time Base Upper */
+
+/* Performance counter declarations */
+#define PMC_OVERFLOW 0x80000000 /* Counter has overflowed */
+
+/* The first five countable [non-]events are common to all the 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 */
+
+#endif /* !_POWERPC_SPR_H_ */
diff --git a/sys/powerpc/include/sr.h b/sys/powerpc/include/sr.h
new file mode 100644
index 000000000000..2ef7b3585076
--- /dev/null
+++ b/sys/powerpc/include/sr.h
@@ -0,0 +1,56 @@
+/*-
+ * 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$
+ */
+
+#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 KERNEL_VSIDBITS 0xfffff
+#define KERNEL_SEGMENT (0xfffff0 + KERNEL_SR)
+#define KERNEL2_SEGMENT (0xfffff0 + KERNEL2_SR)
+#define EMPTY_SEGMENT 0xfffff0
+#define USER_ADDR ((void *)(USER_SR << ADDR_SR_SHFT))
+#define SEGMENT_LENGTH 0x10000000
+#define SEGMENT_MASK 0xf0000000
+
+#endif /* !_MACHINE_SR_H_ */
diff --git a/sys/powerpc/include/stdarg.h b/sys/powerpc/include/stdarg.h
new file mode 100644
index 000000000000..e81aab30b5c0
--- /dev/null
+++ b/sys/powerpc/include/stdarg.h
@@ -0,0 +1,150 @@
+/*-
+ * 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$
+ */
+
+#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_ */
diff --git a/sys/powerpc/include/trap.h b/sys/powerpc/include/trap.h
new file mode 100644
index 000000000000..18778a84cf8c
--- /dev/null
+++ b/sys/powerpc/include/trap.h
@@ -0,0 +1,113 @@
+/*-
+ * 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$
+ */
+
+#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_ISI 0x0400 /* Instruction Storage 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 7400(G4): */
+#define EXC_VEC 0x0f20 /* AltiVec Unavailable */
+#define EXC_VECAST 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 only available on 405 (and 403?) */
+#define EXC_CII 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_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)
+
+#ifndef LOCORE
+
+struct trapframe;
+void trap(struct trapframe *);
+
+#endif
+
+#endif /* _POWERPC_TRAP_H_ */
diff --git a/sys/powerpc/include/ucontext.h b/sys/powerpc/include/ucontext.h
new file mode 100644
index 000000000000..58b6a80bd2ac
--- /dev/null
+++ b/sys/powerpc/include/ucontext.h
@@ -0,0 +1,73 @@
+/*-
+ * 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$
+ */
+
+#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];
+ uint32_t mc_frame[41];
+ uint64_t mc_fpreg[33];
+} mcontext_t __aligned(16);
+
+/* 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_dar mc_frame[38]
+#define mc_dsisr mc_frame[39]
+#define mc_exc 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_ */
diff --git a/sys/powerpc/include/varargs.h b/sys/powerpc/include/varargs.h
new file mode 100644
index 000000000000..fed04c9463ed
--- /dev/null
+++ b/sys/powerpc/include/varargs.h
@@ -0,0 +1,80 @@
+/*-
+ * 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$
+ */
+
+#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_ */
diff --git a/sys/powerpc/include/vmparam.h b/sys/powerpc/include/vmparam.h
new file mode 100644
index 000000000000..0f8298e05c55
--- /dev/null
+++ b/sys/powerpc/include/vmparam.h
@@ -0,0 +1,146 @@
+/*-
+ * 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$
+ */
+
+#ifndef _MACHINE_VMPARAM_H_
+#define _MACHINE_VMPARAM_H_
+
+#define USRSTACK VM_MAXUSER_ADDRESS
+
+#ifndef MAXTSIZ
+#define MAXTSIZ (16*1024*1024) /* max text size */
+#endif
+
+#ifndef DFLDSIZ
+#define DFLDSIZ (32*1024*1024) /* default data size */
+#endif
+
+#ifndef MAXDSIZ
+#define MAXDSIZ (512*1024*1024) /* max data size */
+#endif
+
+#ifndef DFLSSIZ
+#define DFLSSIZ (1*1024*1024) /* default stack size */
+#endif
+
+#ifndef MAXSSIZ
+#define MAXSSIZ (32*1024*1024) /* max stack size */
+#endif
+
+/*
+ * Size of shared memory map
+ */
+#ifndef SHMMAXPGS
+#define SHMMAXPGS 1024
+#endif
+
+/*
+ * The time for a process to be blocked before being very swappable.
+ * This is a number of seconds which the system takes as being a non-trivial
+ * amount of real time. You probably shouldn't change this;
+ * it is used in subtle ways (fractions and multiples of it are, that is, like
+ * half of a ``long time'', almost a long time, etc.)
+ * It is related to human patience and other factors which don't really
+ * change over time.
+ */
+#define MAXSLP 20
+
+/*
+ * 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
+
+/*
+ * Would like to have MAX addresses = 0, but this doesn't (currently) work
+ */
+#define VM_MIN_ADDRESS ((vm_offset_t)0)
+#define VM_MAXUSER_ADDRESS ((vm_offset_t)0x7ffff000)
+#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS
+#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)(KERNEL_SR << ADDR_SR_SHFT))
+#define VM_MAX_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + 2*SEGMENT_LENGTH - 1)
+
+#define KERNBASE 0x100000 /* start of kernel virtual */
+
+/* XXX max. amount of KVM to be used by buffers. */
+#ifndef VM_MAX_KERNEL_BUF
+#define VM_MAX_KERNEL_BUF (SEGMENT_LENGTH * 7 / 10)
+#endif
+
+struct pmap_physseg {
+ struct pv_entry *pvent;
+ char *attrs;
+};
+
+#define VM_PHYSSEG_MAX 16 /* 1? */
+
+/*
+ * The physical address space is densely populated.
+ */
+#define VM_PHYSSEG_DENSE
+
+/*
+ * 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
+
+#ifndef VM_INITIAL_PAGEIN
+#define VM_INITIAL_PAGEIN 16
+#endif
+
+#ifndef SGROWSIZ
+#define SGROWSIZ (128UL*1024) /* amount to grow stack */
+#endif
+
+#ifndef VM_KMEM_SIZE
+#define VM_KMEM_SIZE (12 * 1024 * 1024)
+#endif
+
+#endif /* _MACHINE_VMPARAM_H_ */
diff --git a/sys/powerpc/ofw/ofw_pci.c b/sys/powerpc/ofw/ofw_pci.c
new file mode 100644
index 000000000000..ca4b36eb0456
--- /dev/null
+++ b/sys/powerpc/ofw/ofw_pci.c
@@ -0,0 +1,229 @@
+/*-
+ * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
+ * Copyright (c) 1994 Charles M. Hannum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 Charles M. Hannum.
+ * 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.
+ *
+ * from NetBSD: pci_machdep.c,v 1.18 2001/07/22 11:29:48 wiz Exp
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.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/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <powerpc/ofw/ofw_pci.h>
+
+#include "pcib_if.h"
+
+static void fixup_node(device_t, phandle_t);
+static int find_node_intr(phandle_t, u_int32_t *, u_int32_t *);
+
+phandle_t
+ofw_pci_find_node(device_t dev)
+{
+ phandle_t node, nextnode;
+ struct ofw_pci_register pcir;
+ int l, b, s, f;
+
+ for (node = OF_peer(0); node; node = nextnode) {
+ l = OF_getprop(node, "reg", &pcir, sizeof(pcir));
+ if (l > 4) {
+ 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);
+
+ if (b == pci_get_bus(dev) && s == pci_get_slot(dev) &&
+ f == pci_get_function(dev))
+ return (node);
+ }
+
+ if ((nextnode = OF_child(node)))
+ continue;
+ while (node) {
+ if ((nextnode = OF_peer(node)) != 0)
+ break;
+ node = OF_parent(node);
+ }
+ }
+
+ return (0);
+}
+
+void
+ofw_pci_fixup(device_t dev, u_int bus, phandle_t parentnode)
+{
+ phandle_t node;
+
+ for (node = OF_child(parentnode); node; node = OF_peer(node)) {
+ fixup_node(dev, node);
+ }
+}
+
+static void
+fixup_node(device_t dev, phandle_t node)
+{
+ u_int32_t csr, intr, irqs[4], npintr, paddr[4];
+ struct ofw_pci_register addr[8];
+ int len, i;
+
+ len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr));
+ if (len < (int)sizeof(struct ofw_pci_register)) {
+ return;
+ }
+
+ csr = PCIB_READ_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
+ OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
+ OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, 4);
+ csr &= ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN);
+
+ for (i = 0; i < len / sizeof(struct ofw_pci_register); i++) {
+ switch (addr[i].phys_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+ case OFW_PCI_PHYS_HI_SPACE_IO:
+ csr |= PCIM_CMD_PORTEN;
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_MEM32:
+ csr |= PCIM_CMD_MEMEN;
+ break;
+ }
+ }
+
+ PCIB_WRITE_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
+ OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
+ OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, csr, 4);
+
+ /*
+ * Create PCI interrupt-map array element. pci-mid/pci-lo
+ * aren't required, but the 'interrupts' property needs
+ * to be appended
+ */
+ npintr = 0;
+ OF_getprop(node, "interrupts", &npintr, 4);
+ paddr[0] = addr[0].phys_hi;
+ paddr[1] = 0;
+ paddr[2] = 0;
+ paddr[3] = npintr;
+
+ if (find_node_intr(node, paddr, irqs) != -1) {
+ intr = PCIB_READ_CONFIG(dev,
+ OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
+ OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
+ OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE, 2);
+ intr &= ~(0xff);
+ intr |= irqs[0] & 0xff;
+ PCIB_WRITE_CONFIG(dev,
+ OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
+ OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
+ OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE,
+ intr, 2);
+ }
+
+}
+
+static int
+find_node_intr(phandle_t node, u_int32_t *addr, u_int32_t *intr)
+{
+ phandle_t parent, iparent;
+ int len, mlen, match, i;
+ u_int32_t map[160], *mp, imask[8], maskedaddr[8], icells;
+ char name[32];
+
+ len = OF_getprop(node, "AAPL,interrupts", intr, 4);
+ if (len == 4) {
+ return (len);
+ }
+
+ parent = OF_parent(node);
+ len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
+ mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask));
+
+ if (len == -1 || mlen == -1)
+ goto nomap;
+
+ memcpy(maskedaddr, addr, mlen);
+ for (i = 0; i < mlen/4; i++)
+ maskedaddr[i] &= imask[i];
+
+ mp = map;
+ while (len > mlen) {
+ match = bcmp(maskedaddr, mp, mlen);
+ mp += mlen / 4;
+ len -= mlen;
+
+ /*
+ * We must read "#interrupt-cells" for each time because
+ * interrupt-parent may be different.
+ */
+ iparent = *mp++;
+ len -= 4;
+ if (OF_getprop(iparent, "#interrupt-cells", &icells, 4) != 4)
+ goto nomap;
+
+ /* Found. */
+ if (match == 0) {
+ bcopy(mp, intr, icells * 4);
+ return (icells * 4);
+ }
+
+ mp += icells;
+ len -= icells * 4;
+ }
+
+nomap:
+ /*
+ * If the node has no interrupt property and the parent is a PCI
+ * bridge, use the parent's interrupt. This occurs on a PCI slot.
+ */
+ bzero(name, sizeof(name));
+ OF_getprop(parent, "name", name, sizeof(name));
+ if (strcmp(name, "pci-bridge") == 0) {
+ len = OF_getprop(parent, "AAPL,interrupts", intr, 4);
+ if (len == 4) {
+ return (len);
+ }
+
+ /*
+ * XXX I don't know what is the correct local address.
+ * XXX Use the first entry for now.
+ */
+ len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
+ if (len >= 36) {
+ addr = &map[5];
+ /* XXX Use 0 for 'interrupts' for compat */
+ return (find_node_intr(parent, addr, intr));
+ }
+ }
+
+ return (-1);
+}
diff --git a/sys/powerpc/ofw/ofw_pci.h b/sys/powerpc/ofw/ofw_pci.h
new file mode 100644
index 000000000000..8d78f9189e80
--- /dev/null
+++ b/sys/powerpc/ofw/ofw_pci.h
@@ -0,0 +1,34 @@
+/*-
+ * 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$
+ */
+
+#ifndef _POWERPC_OFW_PCI_H_
+#define _POWERPC_OFW_PCI_H_
+
+phandle_t ofw_pci_find_node(device_t);
+void ofw_pci_fixup(device_t, u_int, phandle_t);
+
+#endif /* _POWERPC_OFW_PCI_H_ */
diff --git a/sys/powerpc/ofw/ofw_pcib_pci.c b/sys/powerpc/ofw/ofw_pcib_pci.c
new file mode 100644
index 000000000000..4cc73c4be34b
--- /dev/null
+++ b/sys/powerpc/ofw/ofw_pcib_pci.c
@@ -0,0 +1,117 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.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 <powerpc/ofw/ofw_pci.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
+
+#include "pcib_if.h"
+
+static int ofw_pcib_pci_probe(device_t bus);
+static int ofw_pcib_pci_attach(device_t bus);
+
+static device_method_t ofw_pcib_pci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ofw_pcib_pci_probe),
+ DEVMETHOD(device_attach, ofw_pcib_pci_attach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_read_ivar, pcib_read_ivar),
+ DEVMETHOD(bus_write_ivar, pcib_write_ivar),
+ DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_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),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, pcib_maxslots),
+ DEVMETHOD(pcib_read_config, pcib_read_config),
+ DEVMETHOD(pcib_write_config, pcib_write_config),
+ DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt),
+
+ {0, 0}
+};
+
+static devclass_t pcib_devclass;
+
+DEFINE_CLASS_0(pcib, ofw_pcib_pci_driver, ofw_pcib_pci_methods,
+ sizeof(struct pcib_softc));
+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_pci_find_node(dev) == 0) {
+ return (ENXIO);
+ }
+
+ device_set_desc(dev, "Open Firmware PCI-PCI bridge");
+ return (-1000);
+}
+
+static int
+ofw_pcib_pci_attach(device_t dev)
+{
+ phandle_t node;
+ uint32_t busrange[2];
+
+ node = ofw_pci_find_node(dev);
+ if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
+ return (ENXIO);
+
+ pcib_attach_common(dev);
+
+ ofw_pci_fixup(dev, busrange[0], node);
+
+ device_add_child(dev, "pci", -1);
+
+ return (bus_generic_attach(dev));
+}
diff --git a/sys/powerpc/ofw/ofw_syscons.c b/sys/powerpc/ofw/ofw_syscons.c
new file mode 100644
index 000000000000..1296ea6be578
--- /dev/null
+++ b/sys/powerpc/ofw/ofw_syscons.c
@@ -0,0 +1,932 @@
+/*-
+ * 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$");
+
+#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 <sys/rman.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/syscons/syscons.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <powerpc/ofw/ofw_syscons.h>
+#include <machine/nexusvar.h>
+
+static int ofwfb_ignore_mmap_checks;
+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, "relax mmap bounds checking");
+
+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_set_border_t ofwfb_set_border8;
+
+static vi_blank_display_t ofwfb_blank_display32;
+static vi_putc_t ofwfb_putc32;
+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(int attr)
+{
+ u_int retval;
+
+ 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;
+ int depth;
+ int disable;
+ int len;
+ 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);
+ 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_set_border = ofwfb_set_border8;
+ } else if (depth == 32) {
+ sc->sc_blank = ofwfb_blank_display32;
+ sc->sc_putc = ofwfb_putc32;
+ sc->sc_set_border = ofwfb_set_border32;
+ } else
+ 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));
+
+ /*
+ * XXX the physical address of the frame buffer is assumed to be
+ * BAT-mapped so it can be accessed directly
+ */
+ OF_getprop(node, "address", &sc->sc_addr, sizeof(sc->sc_addr));
+
+ /*
+ * 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) {
+ sc->sc_num_pciaddrs = len / sizeof(struct ofw_pci_register);
+ }
+
+ 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;
+ char name[64];
+ ihandle_t ih;
+ int i;
+ int cborder;
+ int font_height;
+ int retval;
+
+ sc = (struct ofwfb_softc *)adp;
+ vi = &adp->va_info;
+
+ vid_init_struct(adp, "ofwfb", -1, unit);
+
+ if (sc->sc_depth == 8) {
+ /*
+ * Install the ISO6429 colormap - older OFW systems
+ * don't do this by default
+ */
+ memset(name, 0, sizeof(name));
+ OF_package_to_path(sc->sc_node, name, sizeof(name));
+ ih = OF_open(name);
+ 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);
+ }
+ }
+
+ /* 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 */
+ adp->va_flags |= V_ADP_FONT | V_ADP_COLOR;
+
+ ofwfb_blank_display(&sc->sc_va, V_DISPLAY_ON);
+
+ 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)
+{
+
+ 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;
+ uint8_t *addr;
+
+ sc = (struct ofwfb_softc *)adp;
+ addr = (uint8_t *) sc->sc_addr;
+
+ /* Could be done a lot faster e.g. 32-bits, or Altivec'd */
+ for (i = 0; i < sc->sc_stride*sc->sc_height; i++)
+ *(addr + i) = ofwfb_background(SC_NORM_ATTR);
+
+ return (0);
+}
+
+static int
+ofwfb_blank_display32(video_adapter_t *adp, int mode)
+{
+ struct ofwfb_softc *sc;
+ int i;
+ uint32_t *addr;
+
+ sc = (struct ofwfb_softc *)adp;
+ addr = (uint32_t *) sc->sc_addr;
+
+ for (i = 0; i < (sc->sc_stride/4)*sc->sc_height; i++)
+ *(addr + i) = ofwfb_pix32(ofwfb_background(SC_NORM_ATTR));
+
+ 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_offset_t offset, vm_paddr_t *paddr,
+ int prot)
+{
+ struct ofwfb_softc *sc;
+ int i;
+
+ sc = (struct ofwfb_softc *)adp;
+
+ if (sc->sc_num_pciaddrs == 0)
+ return (ENOMEM);
+
+ /*
+ * Hack for Radeon...
+ */
+ if (ofwfb_ignore_mmap_checks) {
+ *paddr = offset;
+ return (0);
+ }
+
+ /*
+ * 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)) {
+ *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);
+ }
+
+ 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 *)((int)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;
+ 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;
+
+ 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) = ofwfb_pix32(ofwfb_background(a));
+ else
+ *(addr + j) = ofwfb_pix32(ofwfb_foreground(a));
+ }
+ 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;
+
+ /* put mouse */
+
+ return (0);
+}
+
+/*
+ * Define the syscons nexus device attachment
+ */
+static void
+ofwfb_scidentify(driver_t *driver, device_t parent)
+{
+ device_t child;
+
+ /*
+ * Add with a priority guaranteed to make it last on
+ * the device list
+ */
+ child = BUS_ADD_CHILD(parent, INT_MAX, SC_DRIVER_NAME, 0);
+ if (child != NULL)
+ nexus_set_device_type(child, "syscons");
+}
+
+static int
+ofwfb_scprobe(device_t dev)
+{
+ char *name;
+
+ name = nexus_get_name(dev);
+ if (strcmp(SC_DRIVER_NAME, name) != 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "System console");
+ return (sc_probe_unit(device_get_unit(dev),
+ device_get_flags(dev) | SC_AUTODETECT_KBD));
+}
+
+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(sc, 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;
+}
diff --git a/sys/powerpc/ofw/ofw_syscons.h b/sys/powerpc/ofw/ofw_syscons.h
new file mode 100644
index 000000000000..af33c52d6d81
--- /dev/null
+++ b/sys/powerpc/ofw/ofw_syscons.h
@@ -0,0 +1,61 @@
+/*-
+ * 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$
+ */
+
+#ifndef _OFW_SYSCONS_H_
+#define _OFW_SYSCONS_H_
+
+struct ofwfb_softc {
+ video_adapter_t sc_va;
+ struct cdev *sc_si;
+ 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_set_border_t *sc_set_border;
+
+#define OFWSC_MAXADDR 8
+ int sc_num_pciaddrs;
+ struct ofw_pci_register sc_pciaddrs[OFWSC_MAXADDR];
+};
+
+#endif
diff --git a/sys/powerpc/powermac/ata_kauai.c b/sys/powerpc/powermac/ata_kauai.c
new file mode 100644
index 000000000000..141f56ec7071
--- /dev/null
+++ b/sys/powerpc/powermac/ata_kauai.c
@@ -0,0 +1,198 @@
+/*-
+ * 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$");
+
+/*
+ * Mac 'Kauai' PCI ATA controller
+ */
+#include "opt_ata.h"
+#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/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#define ATA_KAUAI_REGOFFSET 0x2000
+
+/*
+ * 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
+
+/*
+ * Define the kauai pci bus attachment.
+ */
+static int ata_kauai_probe(device_t dev);
+static void ata_kauai_setmode(device_t parent, device_t dev);
+
+static device_method_t ata_kauai_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ata_kauai_probe),
+ DEVMETHOD(device_attach, ata_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),
+ { 0, 0 }
+};
+
+static driver_t ata_kauai_driver = {
+ "ata",
+ ata_kauai_methods,
+ sizeof(struct ata_channel),
+};
+
+DRIVER_MODULE(ata, pci, ata_kauai_driver, ata_devclass, 0, 0);
+MODULE_DEPEND(ata, ata, 1, 1, 1);
+
+/*
+ * PCI ID search table
+ */
+static struct kauai_pci_dev {
+ u_int32_t kpd_devid;
+ char *kpd_desc;
+} kauai_pci_devlist[] = {
+ { 0x0033106b, "Uninorth2 Kauai ATA Controller" },
+ { 0x003b106b, "Intrepid Kauai ATA Controller" },
+ { 0x0043106b, "K2 Kauai ATA Controller" },
+ { 0, NULL }
+};
+
+static int
+ata_kauai_probe(device_t dev)
+{
+ struct ata_channel *ch;
+ struct resource *mem;
+ u_long startp, countp;
+ u_int32_t devid;
+ int i, found, rid, status;
+
+ 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);
+
+ /*
+ * This device seems to ignore writes to the interrupt
+ * config register, resulting in interrupt resources
+ * not being attached. If this is the case, use
+ * Open Firmware to determine the irq, and then attach
+ * the resource. This allows the ATA common code to
+ * allocate the irq.
+ */
+ status = bus_get_resource(dev, SYS_RES_IRQ, 0, &startp, &countp);
+ if (status == ENOENT) {
+ int irq;
+
+ /*
+ * Aargh, hideous hack until ofw pci intr routine is
+ * exported
+ */
+ irq = 39; /* XXX */
+ bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
+
+ /*
+ * Sanity check...
+ */
+ status = bus_get_resource(dev, SYS_RES_IRQ, 0, &startp,
+ &countp);
+ if (status == ENOENT ||
+ startp != 39) {
+ printf("kauai irq not set!\n");
+ return (ENXIO);
+ }
+ }
+
+ ch = device_get_softc(dev);
+ bzero(ch, sizeof(struct ata_channel));
+
+ rid = PCIR_BARS;
+ mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (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 = mem;
+ ch->r_io[i].offset = i*ATA_KAUAI_REGGAP + ATA_KAUAI_REGOFFSET;
+ }
+ ch->r_io[ATA_CONTROL].res = mem;
+ ch->r_io[ATA_CONTROL].offset = ATA_KAUAI_ALTOFFSET;
+ ata_default_registers(dev);
+
+ ch->unit = 0;
+ ch->flags |= ATA_USE_16BIT;
+ ata_generic_hw(dev);
+
+ return (ata_probe(dev));
+}
+
+static void
+ata_kauai_setmode(device_t parent, device_t dev)
+{
+ struct ata_device *atadev = device_get_softc(dev);
+
+ /* TODO bang kauai speed register */
+ atadev->mode = ATA_PIO;
+}
diff --git a/sys/powerpc/powermac/ata_macio.c b/sys/powerpc/powermac/ata_macio.c
new file mode 100644
index 000000000000..f582a5ceef88
--- /dev/null
+++ b/sys/powerpc/powermac/ata_macio.c
@@ -0,0 +1,136 @@
+/*-
+ * 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$
+ */
+
+/*
+ * Mac-io ATA controller
+ */
+#include "opt_ata.h"
+#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>
+
+/*
+ * Offset to control registers from base
+ */
+#define ATA_MACIO_ALTOFFSET 0x160
+
+/*
+ * Define the gap between registers
+ */
+#define ATA_MACIO_REGGAP 16
+
+/*
+ * Define the macio ata bus attachment.
+ */
+static int ata_macio_probe(device_t dev);
+static void ata_macio_setmode(device_t parent, device_t dev);
+
+static device_method_t ata_macio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ata_macio_probe),
+ DEVMETHOD(device_attach, ata_attach),
+
+ /* ATA interface */
+ DEVMETHOD(ata_setmode, ata_macio_setmode),
+ { 0, 0 }
+};
+
+static driver_t ata_macio_driver = {
+ "ata",
+ ata_macio_methods,
+ sizeof(struct ata_channel),
+};
+
+DRIVER_MODULE(ata, macio, ata_macio_driver, ata_devclass, 0, 0);
+MODULE_DEPEND(ata, ata, 1, 1, 1);
+
+static int
+ata_macio_probe(device_t dev)
+{
+ const char *type = ofw_bus_get_type(dev);
+ struct ata_channel *ch;
+ struct resource *mem;
+ int rid, i;
+
+ if (strcmp(type, "ata") != 0 &&
+ strcmp(type, "ide") != 0)
+ return (ENXIO);
+
+ ch = device_get_softc(dev);
+ bzero(ch, sizeof(struct ata_channel));
+
+ rid = 0;
+ mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (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 = mem;
+ ch->r_io[i].offset = i * ATA_MACIO_REGGAP;
+ }
+ ch->r_io[ATA_CONTROL].res = mem;
+ ch->r_io[ATA_CONTROL].offset = ATA_MACIO_ALTOFFSET;
+ ata_default_registers(dev);
+
+ ch->unit = 0;
+ ch->flags |= ATA_USE_16BIT;
+ ata_generic_hw(dev);
+
+ return (ata_probe(dev));
+}
+
+static void
+ata_macio_setmode(device_t parent, device_t dev)
+{
+ struct ata_device *atadev = device_get_softc(dev);
+
+ /* TODO bang macio speed register */
+ atadev->mode = ATA_PIO;
+}
+
diff --git a/sys/powerpc/powermac/grackle.c b/sys/powerpc/powermac/grackle.c
new file mode 100644
index 000000000000..f606b655582d
--- /dev/null
+++ b/sys/powerpc/powermac/grackle.c
@@ -0,0 +1,556 @@
+/*-
+ * 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$
+ */
+
+#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/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+#include <machine/nexusvar.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"
+
+int badaddr(void *, size_t); /* XXX */
+
+/*
+ * Device interface.
+ */
+static int grackle_probe(device_t);
+static int grackle_attach(device_t);
+
+/*
+ * Bus interface.
+ */
+static int grackle_read_ivar(device_t, device_t, int,
+ uintptr_t *);
+static struct resource * grackle_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 grackle_release_resource(device_t bus, device_t child,
+ int type, int rid, struct resource *res);
+static int grackle_activate_resource(device_t bus, device_t child,
+ int type, int rid, struct resource *res);
+static int grackle_deactivate_resource(device_t bus,
+ device_t child, int type, int rid,
+ struct resource *res);
+
+
+/*
+ * pcib interface.
+ */
+static int grackle_maxslots(device_t);
+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);
+static int grackle_route_interrupt(device_t, device_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 *);
+
+/*
+ * Driver methods.
+ */
+static device_method_t grackle_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, grackle_probe),
+ DEVMETHOD(device_attach, grackle_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_read_ivar, grackle_read_ivar),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, grackle_alloc_resource),
+ DEVMETHOD(bus_release_resource, grackle_release_resource),
+ DEVMETHOD(bus_activate_resource, grackle_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, grackle_deactivate_resource),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, grackle_maxslots),
+ DEVMETHOD(pcib_read_config, grackle_read_config),
+ DEVMETHOD(pcib_write_config, grackle_write_config),
+ DEVMETHOD(pcib_route_interrupt, grackle_route_interrupt),
+
+ { 0, 0 }
+};
+
+static driver_t grackle_driver = {
+ "pcib",
+ grackle_methods,
+ sizeof(struct grackle_softc)
+};
+
+static devclass_t grackle_devclass;
+
+DRIVER_MODULE(grackle, nexus, grackle_driver, grackle_devclass, 0, 0);
+
+static int
+grackle_probe(device_t dev)
+{
+ char *type, *compatible;
+
+ type = nexus_get_device_type(dev);
+ compatible = nexus_get_compatible(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;
+ phandle_t node;
+ u_int32_t busrange[2];
+ struct grackle_range *rp, *io, *mem[2];
+ int nmem, i;
+
+ node = nexus_get_node(dev);
+ sc = device_get_softc(dev);
+
+ if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
+ return (ENXIO);
+
+ sc->sc_dev = dev;
+ sc->sc_node = node;
+ sc->sc_bus = busrange[0];
+
+ /*
+ * 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);
+
+ bzero(sc->sc_range, sizeof(sc->sc_range));
+ sc->sc_nrange = OF_getprop(node, "ranges", sc->sc_range,
+ sizeof(sc->sc_range));
+
+ if (sc->sc_nrange == -1) {
+ device_printf(dev, "could not get ranges\n");
+ return (ENXIO);
+ }
+
+ sc->sc_range[6].pci_hi = 0;
+ io = NULL;
+ nmem = 0;
+
+ for (rp = sc->sc_range; rp->pci_hi != 0; rp++) {
+ switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+ case OFW_PCI_PHYS_HI_SPACE_CONFIG:
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_IO:
+ io = rp;
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_MEM32:
+ mem[nmem] = rp;
+ nmem++;
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_MEM64:
+ break;
+ }
+ }
+
+ if (io == NULL) {
+ device_printf(dev, "can't find io range\n");
+ return (ENXIO);
+ }
+ sc->sc_io_rman.rm_type = RMAN_ARRAY;
+ sc->sc_io_rman.rm_descr = "Grackle PCI I/O Ports";
+ sc->sc_iostart = io->pci_iospace;
+ if (rman_init(&sc->sc_io_rman) != 0 ||
+ rman_manage_region(&sc->sc_io_rman, io->pci_lo,
+ io->pci_lo + io->size_lo) != 0) {
+ device_printf(dev, "failed to set up io range management\n");
+ return (ENXIO);
+ }
+
+ if (nmem == 0) {
+ device_printf(dev, "can't find mem ranges\n");
+ return (ENXIO);
+ }
+ sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+ sc->sc_mem_rman.rm_descr = "Grackle PCI Memory";
+ if (rman_init(&sc->sc_mem_rman) != 0) {
+ device_printf(dev,
+ "failed to init mem range resources\n");
+ return (ENXIO);
+ }
+ for (i = 0; i < nmem; i++) {
+ if (rman_manage_region(&sc->sc_mem_rman, mem[i]->pci_lo,
+ mem[i]->pci_lo + mem[i]->size_lo) != 0) {
+ device_printf(dev,
+ "failed to set up memory range management\n");
+ return (ENXIO);
+ }
+ }
+
+ /*
+ * Write out the correct PIC interrupt values to config space
+ * of all devices on the bus.
+ */
+ ofw_pci_fixup(dev, sc->sc_bus, sc->sc_node);
+
+ device_add_child(dev, "pci", device_get_unit(dev));
+ return (bus_generic_attach(dev));
+}
+
+static int
+grackle_maxslots(device_t dev)
+{
+
+ return (PCI_SLOTMAX);
+}
+
+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_route_interrupt(device_t bus, device_t dev, int pin)
+{
+
+ return (0);
+}
+
+static int
+grackle_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct grackle_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ *result = 0;
+ return (0);
+ case PCIB_IVAR_BUS:
+ *result = sc->sc_bus;
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static struct resource *
+grackle_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 grackle_softc *sc;
+ struct resource *rv;
+ struct rman *rm;
+ bus_space_tag_t bt;
+ 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;
+ bt = PPC_BUS_SPACE_MEM;
+ break;
+
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_io_rman;
+ bt = PPC_BUS_SPACE_IO;
+ break;
+
+ case SYS_RES_IRQ:
+ return (bus_alloc_resource(bus, type, rid, start, end, count,
+ flags));
+ break;
+
+ 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);
+ rman_set_bustag(rv, bt);
+ rman_set_bushandle(rv, rman_get_start(rv));
+
+ 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
+grackle_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
+grackle_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+ struct grackle_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) {
+ vm_offset_t start;
+
+ start = (vm_offset_t)rman_get_start(res);
+ /*
+ * For i/o-ports, convert the start address to the
+ * MPC106 PCI i/o window
+ */
+ if (type == SYS_RES_IOPORT)
+ start += sc->sc_iostart;
+
+ if (bootverbose)
+ printf("grackle mapdev: start %x, 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_bushandle(res, (u_long)p);
+ }
+
+ return (rman_activate_resource(res));
+}
+
+static int
+grackle_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
+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);
+}
+
+/*
+ * 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);
diff --git a/sys/powerpc/powermac/gracklevar.h b/sys/powerpc/powermac/gracklevar.h
new file mode 100644
index 000000000000..bb5b150e074a
--- /dev/null
+++ b/sys/powerpc/powermac/gracklevar.h
@@ -0,0 +1,69 @@
+/*-
+ * 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$
+ */
+
+#ifndef _POWERPC_POWERMAC_GRACKLEVAR_H_
+#define _POWERPC_POWERMAC_GRACKLEVAR_H_
+
+struct grackle_range {
+ u_int32_t pci_hi;
+ u_int32_t pci_mid;
+ u_int32_t pci_lo;
+ u_int32_t pci_iospace;
+ u_int32_t size_hi;
+ u_int32_t size_lo;
+};
+
+struct grackle_softc {
+ device_t sc_dev;
+ phandle_t sc_node;
+ vm_offset_t sc_addr;
+ vm_offset_t sc_data;
+ int sc_bus;
+ struct grackle_range sc_range[6];
+ int sc_nrange;
+ int sc_iostart;
+ struct rman sc_io_rman;
+ struct rman sc_mem_rman;
+ bus_space_tag_t sc_memt;
+ bus_dma_tag_t sc_dmat;
+};
+
+/*
+ * 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_ */
diff --git a/sys/powerpc/powermac/hrowpic.c b/sys/powerpc/powermac/hrowpic.c
new file mode 100644
index 000000000000..cf8a4624b58f
--- /dev/null
+++ b/sys/powerpc/powermac/hrowpic.c
@@ -0,0 +1,271 @@
+/*-
+ * 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$
+ */
+
+/*
+ * 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.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/nexusvar.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_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_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);
+ 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"));
+
+ /*
+ * 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 __unused, u_int irq __unused)
+{
+ 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_mask(device_t dev, u_int irq)
+{
+ struct hrowpic_softc *sc;
+ int bank;
+
+ sc = device_get_softc(dev);
+ hrowpic_toggle_irq(sc, irq, 0);
+ bank = (irq >= 32) ? HPIC_SECONDARY : HPIC_PRIMARY ;
+ hrowpic_write_reg(sc, HPIC_CLEAR, bank, 1U << (irq & 0x1f));
+}
+
+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);
+}
diff --git a/sys/powerpc/powermac/hrowpicvar.h b/sys/powerpc/powermac/hrowpicvar.h
new file mode 100644
index 000000000000..ac643f574d48
--- /dev/null
+++ b/sys/powerpc/powermac/hrowpicvar.h
@@ -0,0 +1,75 @@
+/*-
+ * 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$
+ */
+
+#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_ */
diff --git a/sys/powerpc/powermac/macio.c b/sys/powerpc/powermac/macio.c
new file mode 100644
index 000000000000..d3d3dd4a43fd
--- /dev/null
+++ b/sys/powerpc/powermac/macio.c
@@ -0,0 +1,542 @@
+/*-
+ * 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$
+ */
+
+/*
+ * 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 <machine/bus.h>
+#include <sys/rman.h>
+
+#include <machine/vmparam.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/pmap.h>
+
+#include <machine/resource.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;
+};
+
+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),
+
+ /* 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" },
+ { 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
+
+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 },
+ { 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)
+{
+ int intr;
+
+ if (dinfo->mdi_ninterrupts >= 5) {
+ printf("macio: device has more than 5 interrupts\n");
+ return;
+ }
+
+ if (OF_getprop(devnode, "interrupts", &intr, sizeof(intr)) == -1) {
+ if (OF_getprop(devnode, "AAPL,interrupts", &intr,
+ sizeof(intr)) == -1)
+ return;
+ }
+
+ if (intr == -1)
+ return;
+
+ resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ,
+ dinfo->mdi_ninterrupts, intr, intr, 1);
+
+ dinfo->mdi_interrupts[dinfo->mdi_ninterrupts] = intr;
+ dinfo->mdi_ninterrupts++;
+}
+
+
+static void
+macio_add_reg(phandle_t devnode, struct macio_devinfo *dinfo)
+{
+ struct macio_reg *reg;
+ int i, nreg;
+
+ nreg = OF_getprop_alloc(devnode, "reg", sizeof(*reg), (void **)&reg);
+ if (nreg == -1)
+ return;
+
+ for (i = 0; i < nreg; i++) {
+ resource_list_add(&dinfo->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];
+ int quirks;
+
+ sc = device_get_softc(dev);
+ root = sc->sc_node = OF_finddevice("mac-io");
+
+ /*
+ * Locate the device node and it's base address
+ */
+ if (OF_getprop(root, "assigned-addresses",
+ reg, sizeof(reg)) < sizeof(reg)) {
+ return (ENXIO);
+ }
+
+ sc->sc_base = reg[2];
+ sc->sc_size = MACIO_REG_SIZE;
+
+ sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+ sc->sc_mem_rman.rm_descr = "MacIO 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
+ */
+ 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);
+ 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);
+ }
+
+ 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;
+ bus_space_tag_t tagval;
+ 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;
+
+ tagval = PPC_BUS_SPACE_MEM;
+ break;
+
+ case SYS_RES_IRQ:
+ rle = resource_list_find(&dinfo->mdi_resources, SYS_RES_IRQ,
+ *rid);
+ if (rle == NULL) {
+ if (dinfo->mdi_ninterrupts >= 5) {
+ device_printf(bus,
+ "%s has more than 5 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));
+ 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);
+ rman_set_bustag(rv, tagval);
+ rman_set_bushandle(rv, rman_get_start(rv));
+
+ 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_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);
+}
diff --git a/sys/powerpc/powermac/maciovar.h b/sys/powerpc/powermac/maciovar.h
new file mode 100644
index 000000000000..e2891022ea23
--- /dev/null
+++ b/sys/powerpc/powermac/maciovar.h
@@ -0,0 +1,59 @@
+/*-
+ * 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$
+ */
+
+#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
+
+/*
+ * 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[5];
+ int mdi_ninterrupts;
+ int mdi_base;
+ struct ofw_bus_devinfo mdi_obdinfo;
+ struct resource_list mdi_resources;
+};
+
+#endif /* _MACIO_MACIOVAR_H_ */
diff --git a/sys/powerpc/powermac/openpic_macio.c b/sys/powerpc/powermac/openpic_macio.c
new file mode 100644
index 000000000000..822804e1c2ce
--- /dev/null
+++ b/sys/powerpc/powermac/openpic_macio.c
@@ -0,0 +1,97 @@
+/*-
+ * 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$");
+
+#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 <machine/intr.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/nexusvar.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"
+
+/*
+ * MacIO interface
+ */
+static int openpic_macio_probe(device_t);
+
+static device_method_t openpic_macio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, openpic_macio_probe),
+ DEVMETHOD(device_attach, openpic_attach),
+
+ /* PIC interface */
+ DEVMETHOD(pic_dispatch, openpic_dispatch),
+ DEVMETHOD(pic_enable, openpic_enable),
+ DEVMETHOD(pic_eoi, openpic_eoi),
+ DEVMETHOD(pic_mask, openpic_mask),
+ DEVMETHOD(pic_unmask, openpic_unmask),
+
+ { 0, 0 },
+};
+
+static driver_t openpic_macio_driver = {
+ "openpic",
+ openpic_macio_methods,
+ sizeof(struct openpic_softc),
+};
+
+DRIVER_MODULE(openpic, macio, openpic_macio_driver, openpic_devclass, 0, 0);
+
+static int
+openpic_macio_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);
+}
diff --git a/sys/powerpc/powermac/pswitch.c b/sys/powerpc/powermac/pswitch.c
new file mode 100644
index 000000000000..62777eb33748
--- /dev/null
+++ b/sys/powerpc/powermac/pswitch.c
@@ -0,0 +1,144 @@
+/*-
+ * 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$
+ */
+
+#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(device_get_nameunit(dev));
+ return (FILTER_HANDLED);
+}
diff --git a/sys/powerpc/powermac/uninorth.c b/sys/powerpc/powermac/uninorth.c
new file mode 100644
index 000000000000..f3b0996e5ea0
--- /dev/null
+++ b/sys/powerpc/powermac/uninorth.c
@@ -0,0 +1,600 @@
+/*-
+ * 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$
+ */
+
+#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/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+#include <machine/nexusvar.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);
+
+/*
+ * Bus interface.
+ */
+static int uninorth_read_ivar(device_t, device_t, int,
+ uintptr_t *);
+static struct resource * uninorth_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 uninorth_activate_resource(device_t bus, device_t child,
+ int type, int rid, struct resource *res);
+
+/*
+ * pcib interface.
+ */
+static int uninorth_maxslots(device_t);
+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);
+static int uninorth_route_interrupt(device_t, device_t, int);
+
+/*
+ * Local routines.
+ */
+static int uninorth_enable_config(struct uninorth_softc *, u_int,
+ u_int, u_int, u_int);
+static void unin_enable_gmac(void);
+
+/*
+ * Driver methods.
+ */
+static device_method_t uninorth_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, uninorth_probe),
+ DEVMETHOD(device_attach, uninorth_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_read_ivar, uninorth_read_ivar),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, uninorth_alloc_resource),
+ DEVMETHOD(bus_activate_resource, uninorth_activate_resource),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, uninorth_maxslots),
+ DEVMETHOD(pcib_read_config, uninorth_read_config),
+ DEVMETHOD(pcib_write_config, uninorth_write_config),
+ DEVMETHOD(pcib_route_interrupt, uninorth_route_interrupt),
+
+ { 0, 0 }
+};
+
+static driver_t uninorth_driver = {
+ "pcib",
+ uninorth_methods,
+ sizeof(struct uninorth_softc)
+};
+
+static devclass_t uninorth_devclass;
+
+DRIVER_MODULE(uninorth, nexus, uninorth_driver, uninorth_devclass, 0, 0);
+
+static int
+uninorth_probe(device_t dev)
+{
+ char *type, *compatible;
+
+ type = nexus_get_device_type(dev);
+ compatible = nexus_get_compatible(dev);
+
+ if (type == NULL || compatible == NULL)
+ return (ENXIO);
+
+ if (strcmp(type, "pci") != 0 || strcmp(compatible, "uni-north") != 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Apple UniNorth Host-PCI bridge");
+ return (0);
+}
+
+static int
+uninorth_attach(device_t dev)
+{
+ struct uninorth_softc *sc;
+ phandle_t node;
+ phandle_t child;
+ u_int32_t reg[2], busrange[2];
+ struct uninorth_range *rp, *io, *mem[2];
+ int nmem, i;
+
+ node = nexus_get_node(dev);
+ sc = device_get_softc(dev);
+
+ if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8)
+ return (ENXIO);
+
+ if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
+ return (ENXIO);
+
+ sc->sc_dev = dev;
+ sc->sc_node = node;
+ sc->sc_addr = (vm_offset_t)pmap_mapdev(reg[0] + 0x800000, PAGE_SIZE);
+ sc->sc_data = (vm_offset_t)pmap_mapdev(reg[0] + 0xc00000, PAGE_SIZE);
+ sc->sc_bus = busrange[0];
+
+ bzero(sc->sc_range, sizeof(sc->sc_range));
+ sc->sc_nrange = OF_getprop(node, "ranges", sc->sc_range,
+ sizeof(sc->sc_range));
+
+ if (sc->sc_nrange == -1) {
+ device_printf(dev, "could not get ranges\n");
+ return (ENXIO);
+ }
+
+ sc->sc_range[6].pci_hi = 0;
+ io = NULL;
+ nmem = 0;
+
+ for (rp = sc->sc_range; rp->pci_hi != 0; rp++) {
+ switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+ case OFW_PCI_PHYS_HI_SPACE_CONFIG:
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_IO:
+ io = rp;
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_MEM32:
+ mem[nmem] = rp;
+ nmem++;
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_MEM64:
+ break;
+ }
+ }
+
+ if (io == NULL) {
+ device_printf(dev, "can't find io range\n");
+ return (ENXIO);
+ }
+ sc->sc_io_rman.rm_type = RMAN_ARRAY;
+ sc->sc_io_rman.rm_descr = "UniNorth PCI I/O Ports";
+ sc->sc_iostart = io->host;
+ if (rman_init(&sc->sc_io_rman) != 0 ||
+ rman_manage_region(&sc->sc_io_rman, io->pci_lo,
+ io->pci_lo + io->size_lo - 1) != 0) {
+ device_printf(dev, "failed to set up io range management\n");
+ return (ENXIO);
+ }
+
+ if (nmem == 0) {
+ device_printf(dev, "can't find mem ranges\n");
+ return (ENXIO);
+ }
+ sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+ sc->sc_mem_rman.rm_descr = "UniNorth PCI Memory";
+ if (rman_init(&sc->sc_mem_rman) != 0) {
+ device_printf(dev,
+ "failed to init mem range resources\n");
+ return (ENXIO);
+ }
+ for (i = 0; i < nmem; i++) {
+ if (rman_manage_region(&sc->sc_mem_rman, mem[i]->pci_lo,
+ mem[i]->pci_lo + mem[i]->size_lo - 1) != 0) {
+ device_printf(dev,
+ "failed to set up memory range management\n");
+ return (ENXIO);
+ }
+ }
+
+ /*
+ * Enable the GMAC Ethernet cell if Open Firmware says it is
+ * used.
+ */
+ for (child = OF_child(node); child; child = OF_peer(child)) {
+ char compat[32];
+
+ memset(compat, 0, sizeof(compat));
+ OF_getprop(child, "compatible", compat, sizeof(compat));
+ if (strcmp(compat, "gmac") == 0) {
+ unin_enable_gmac();
+ }
+ }
+
+ /*
+ * Write out the correct PIC interrupt values to config space
+ * of all devices on the bus. This has to be done after the GEM
+ * cell is enabled above.
+ */
+ ofw_pci_fixup(dev, sc->sc_bus, node);
+
+ device_add_child(dev, "pci", device_get_unit(dev));
+ return (bus_generic_attach(dev));
+}
+
+static int
+uninorth_maxslots(device_t dev)
+{
+
+ return (PCI_SLOTMAX);
+}
+
+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_route_interrupt(device_t bus, device_t dev, int pin)
+{
+
+ return (0);
+}
+
+static int
+uninorth_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct uninorth_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 *
+uninorth_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 uninorth_softc *sc;
+ struct resource *rv;
+ struct rman *rm;
+ bus_space_tag_t bt;
+ 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;
+ bt = PPC_BUS_SPACE_MEM;
+ break;
+
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_io_rman;
+ bt = PPC_BUS_SPACE_IO;
+ break;
+
+ case SYS_RES_IRQ:
+ return (bus_alloc_resource(bus, type, rid, start, end, count,
+ flags));
+ break;
+ 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);
+ rman_set_bustag(rv, bt);
+ rman_set_bushandle(rv, rman_get_start(rv));
+
+ 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
+uninorth_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+ void *p;
+ struct uninorth_softc *sc;
+
+ 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) {
+ vm_offset_t start;
+
+ start = (vm_offset_t)rman_get_start(res);
+ /*
+ * For i/o-ports, convert the start address to the
+ * uninorth PCI i/o window
+ */
+ if (type == SYS_RES_IOPORT)
+ start += sc->sc_iostart;
+
+ if (bootverbose)
+ printf("uninorth mapdev: start %x, 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_bushandle(res, (u_long)p);
+ }
+
+ return (rman_activate_resource(res));
+}
+
+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->sc_dev),
+ device_get_unit(sc->sc_dev), "skipslot", &pass) == 0) {
+ if (pass == slot)
+ return (0);
+ }
+
+ if (sc->sc_bus == bus) {
+ /*
+ * No slots less than 11 on the primary bus
+ */
+ if (slot < 11)
+ return (0);
+
+ cfgval = (1 << slot) | (func << 8) | (reg & 0xfc);
+ } else {
+ cfgval = (bus << 16) | (slot << 11) | (func << 8) |
+ (reg & 0xfc) | 1;
+ }
+
+ do {
+ out32rb(sc->sc_addr, cfgval);
+ } while (in32rb(sc->sc_addr) != cfgval);
+
+ return (1);
+}
+
+/*
+ * Driver to swallow UniNorth host bridges from the PCI bus side.
+ */
+static int
+unhb_probe(device_t dev)
+{
+
+ if (pci_get_class(dev) == PCIC_BRIDGE &&
+ pci_get_subclass(dev) == PCIS_BRIDGE_HOST) {
+ device_set_desc(dev, "Host to PCI bridge");
+ device_quiet(dev);
+ return (-10000);
+ }
+
+ return (ENXIO);
+}
+
+static int
+unhb_attach(device_t dev)
+{
+
+ return (0);
+}
+
+static device_method_t unhb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, unhb_probe),
+ DEVMETHOD(device_attach, unhb_attach),
+
+ { 0, 0 }
+};
+
+static driver_t unhb_driver = {
+ "unhb",
+ unhb_methods,
+ 1,
+};
+static devclass_t unhb_devclass;
+
+DRIVER_MODULE(unhb, pci, unhb_driver, unhb_devclass, 0, 0);
+
+
+/*
+ * Small stub driver for the Uninorth chip itself, to allow setting
+ * of various parameters and cell enables
+ */
+static struct unin_chip_softc *uncsc;
+
+static void
+unin_enable_gmac(void)
+{
+ volatile u_int *clkreg;
+ u_int32_t tmpl;
+
+ if (uncsc == NULL)
+ panic("unin_enable_gmac: device not found");
+
+ clkreg = (void *)(uncsc->sc_addr + UNIN_CLOCKCNTL);
+ tmpl = inl(clkreg);
+ tmpl |= UNIN_CLOCKCNTL_GMAC;
+ outl(clkreg, tmpl);
+}
+
+static int
+unin_chip_probe(device_t dev)
+{
+ char *name;
+
+ name = nexus_get_name(dev);
+
+ if (name == NULL)
+ return (ENXIO);
+
+ if (strcmp(name, "uni-n") != 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Apple UniNorth System Controller");
+ return (0);
+}
+
+static int
+unin_chip_attach(device_t dev)
+{
+ phandle_t node;
+ u_int reg[2];
+
+ uncsc = device_get_softc(dev);
+ node = nexus_get_node(dev);
+
+ if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8)
+ return (ENXIO);
+
+ uncsc->sc_physaddr = reg[0];
+ uncsc->sc_size = reg[1];
+
+ /*
+ * Only map the first page, since that is where the registers
+ * of interest lie.
+ */
+ uncsc->sc_addr = (vm_offset_t) pmap_mapdev(reg[0], PAGE_SIZE);
+
+ uncsc->sc_version = *(u_int *)uncsc->sc_addr;
+ device_printf(dev, "Version %d\n", uncsc->sc_version);
+
+ return (0);
+}
+
+static device_method_t unin_chip_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, unin_chip_probe),
+ DEVMETHOD(device_attach, unin_chip_attach),
+
+ { 0, 0 }
+};
+
+static driver_t unin_chip_driver = {
+ "unin",
+ unin_chip_methods,
+ sizeof(struct unin_chip_softc)
+};
+
+static devclass_t unin_chip_devclass;
+
+DRIVER_MODULE(unin, nexus, unin_chip_driver, unin_chip_devclass, 0, 0);
+
+
+
+
diff --git a/sys/powerpc/powermac/uninorthvar.h b/sys/powerpc/powermac/uninorthvar.h
new file mode 100644
index 000000000000..d2ee8d793e3c
--- /dev/null
+++ b/sys/powerpc/powermac/uninorthvar.h
@@ -0,0 +1,74 @@
+/*-
+ * 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$
+ */
+
+#ifndef _POWERPC_POWERMAC_UNINORTHVAR_H_
+#define _POWERPC_POWERMAC_UNINORTHVAR_H_
+
+struct uninorth_range {
+ u_int32_t pci_hi;
+ u_int32_t pci_mid;
+ u_int32_t pci_lo;
+ u_int32_t host;
+ u_int32_t size_hi;
+ u_int32_t size_lo;
+};
+
+struct uninorth_softc {
+ device_t sc_dev;
+ phandle_t sc_node;
+ vm_offset_t sc_addr;
+ vm_offset_t sc_data;
+ int sc_bus;
+ struct uninorth_range sc_range[6];
+ int sc_nrange;
+ int sc_iostart;
+ struct rman sc_io_rman;
+ struct rman sc_mem_rman;
+ bus_space_tag_t sc_iot;
+ bus_space_tag_t sc_memt;
+ bus_dma_tag_t sc_dmat;
+};
+
+struct unin_chip_softc {
+ vm_offset_t sc_physaddr;
+ vm_offset_t sc_addr;
+ u_int sc_size;
+ int sc_version;
+};
+
+/*
+ * Version register
+ */
+#define UNIN_VERS 0x0
+
+/*
+ * Clock-control register
+ */
+#define UNIN_CLOCKCNTL 0x20
+#define UNIN_CLOCKCNTL_GMAC 0x2
+
+#endif /* _POWERPC_POWERMAC_UNINORTHVAR_H_ */
diff --git a/sys/powerpc/powerpc/atomic.S b/sys/powerpc/powerpc/atomic.S
new file mode 100644
index 000000000000..c6f669a6670b
--- /dev/null
+++ b/sys/powerpc/powerpc/atomic.S
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 2000, 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 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$
+ */
+
+#include <machine/asm.h>
+
+ .text
+
+ASENTRY(atomic_set_8)
+0: lwarx 0, 0, 3 /* load old value */
+ slwi 4, 4, 24 /* shift the byte so it's in the right place */
+ or 0, 0, 4 /* generate new value */
+ stwcx. 0, 0, 3 /* attempt to store */
+ bne- 0 /* loop if failed */
+ eieio /* synchronise */
+ sync
+ blr /* return */
+
+ASENTRY(atomic_clear_8)
+0: lwarx 0, 0, 3 /* load old value */
+ slwi 4, 4, 24 /* shift the byte so it's in the right place */
+ andc 0, 0, 4 /* generate new value */
+ stwcx. 0, 0, 3 /* attempt to store */
+ bne- 0 /* loop if failed */
+ eieio /* synchronise */
+ sync
+ blr /* return */
+
+ASENTRY(atomic_add_8)
+0: lwarx 9, 0, 3 /* load old value */
+ srwi 0, 9, 24 /* byte alignment */
+ add 0, 4, 0 /* calculate new value */
+ slwi 0, 9, 24 /* byte alignment */
+ clrlwi 9, 9, 8 /* clear the byte in the original word */
+ or 9, 9, 0 /* copy back in to the original word */
+ stwcx. 9, 0, 3 /* attempt to store */
+ bne- 0 /* loop if failed */
+ eieio /* synchronise */
+ sync
+ blr /* return */
+
+ASENTRY(atomic_subtract_8)
+0: lwarx 9, 0, 3 /* load old value */
+ srwi 0, 9, 24 /* byte alignment */
+ subf 0, 4, 0 /* calculate new value */
+ slwi 0, 9, 24 /* byte alignment */
+ clrlwi 9, 9, 8 /* clear the byte in the original word */
+ or 9, 9, 0 /* copy back in to the original word */
+ stwcx. 9, 0, 3 /* attempt to store */
+ bne- 0 /* loop if failed */
+ eieio /* synchronise */
+ sync
+ blr /* return */
+
+ASENTRY(atomic_set_16)
+ li 11, 3 /* mask to test for alignment */
+ andc. 11, 3, 11 /* force address to be word-aligned */
+0: lwarx 12, 0, 11 /* load old value */
+ bne 1f /* no realignment needed if it's aligned */
+ slwi 4, 4, 16 /* realign operand */
+1: or 12, 12, 4 /* calculate new value */
+ stwcx. 12, 0, 11 /* attempt to store */
+ bne- 0b /* loop if failed */
+ eieio /* synchronise */
+ sync
+ blr /* return */
+
+ASENTRY(atomic_clear_16)
+ li 11, 3 /* mask to test for alignment */
+ andc. 11, 3, 11 /* force address to be word-aligned */
+0: lwarx 12, 0, 11 /* load old value */
+ bne 1f /* no realignment needed if it's aligned */
+ slwi 4, 4, 16 /* realign operand */
+1: andc 12, 12, 4 /* calculate new value */
+ stwcx. 12, 0, 11 /* attempt to store */
+ bne- 0b /* loop if failed */
+ eieio /* synchronise */
+ sync
+ blr /* return */
+
+ASENTRY(atomic_add_16)
+ li 11, 3 /* mask to test for alignment */
+ andc. 11, 3, 11 /* force address to be word-aligned */
+0: lwarx 12, 0, 11 /* load old value */
+ bne 1f /* no realignment needed if it's aligned */
+ srwi 12, 9, 16 /* realign */
+1: add 12, 4, 12 /* calculate new value */
+ bne 2f /* no realignment needed if it's aligned */
+ slwi 12, 12, 16 /* realign */
+2: clrlwi 9, 9, 16 /* clear old value */
+ or 9, 9, 12 /* copy in new value */
+ stwcx. 12, 0, 11 /* attempt to store */
+ bne- 0b /* loop if failed */
+ eieio /* synchronise */
+ sync
+ blr /* return */
+
+ASENTRY(atomic_subtract_16)
+ li 11, 3 /* mask to test for alignment */
+ andc. 11, 3, 11 /* force address to be word-aligned */
+0: lwarx 12, 0, 11 /* load old value */
+ bne 1f /* no realignment needed if it's aligned */
+ srwi 12, 9, 16 /* realign */
+1: subf 12, 4, 12 /* calculate new value */
+ bne 2f /* no realignment needed if it's aligned */
+ slwi 12, 12, 16 /* realign */
+2: clrlwi 9, 9, 16 /* clear old value */
+ or 9, 9, 12 /* copy in new value */
+ stwcx. 12, 0, 11 /* attempt to store */
+ bne- 0 /* loop if failed */
+ eieio /* synchronise */
+ sync
+ blr /* return */
diff --git a/sys/powerpc/powerpc/autoconf.c b/sys/powerpc/powerpc/autoconf.c
new file mode 100644
index 000000000000..644932304182
--- /dev/null
+++ b/sys/powerpc/powerpc/autoconf.c
@@ -0,0 +1,84 @@
+/*-
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#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>
+
+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();
+}
+
+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 | PSL_RI);
+
+ cninit_finish();
+ cold = 0;
+}
+
+
diff --git a/sys/powerpc/powerpc/bcopy.c b/sys/powerpc/powerpc/bcopy.c
new file mode 100644
index 000000000000..af9e3bfd82db
--- /dev/null
+++ b/sys/powerpc/powerpc/bcopy.c
@@ -0,0 +1,149 @@
+/*-
+ * 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$");
+
+#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 int 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 = (int)src; /* only need low bits */
+
+ if ((t | (int)dst) & wmask) {
+ /*
+ * Try to align operands. This cannot be done
+ * unless the low bits match.
+ */
+ if ((t ^ (int)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 = (int)src;
+
+ if ((t | (int)dst) & wmask) {
+ if ((t ^ (int)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);
+}
+
diff --git a/sys/powerpc/powerpc/busdma_machdep.c b/sys/powerpc/powerpc/busdma_machdep.c
new file mode 100644
index 000000000000..5f4ad44c37bd
--- /dev/null
+++ b/sys/powerpc/powerpc/busdma_machdep.c
@@ -0,0 +1,589 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan
+ * 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 i386/busdma_machdep.c,v 1.26 2002/04/19 22:58:09 alfred
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * MacPPC bus dma support routines
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/uio.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+
+#include <machine/atomic.h>
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+
+struct bus_dma_tag {
+ bus_dma_tag_t parent;
+ bus_size_t alignment;
+ bus_size_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 bus_dmamap {
+ bus_dma_tag_t dmat;
+ void *buf; /* unmapped buffer pointer */
+ bus_size_t buflen; /* unmapped buffer length */
+ bus_dmamap_callback_t *callback;
+ void *callback_arg;
+};
+
+/*
+ * 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)
+{
+#ifdef INVARIANTS
+ panic("driver error: busdma dflt_lock called");
+#else
+ printf("DRIVER_ERROR: busdma dflt_lock called\n");
+#endif
+}
+
+/*
+ * Allocate a device specific dma_tag.
+ */
+int
+bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
+ bus_size_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;
+
+ /* Return a NULL tag on failure */
+ *dmat = NULL;
+
+ newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, M_NOWAIT);
+ if (newtag == NULL)
+ return (ENOMEM);
+
+ newtag->parent = parent;
+ newtag->alignment = alignment;
+ newtag->boundary = boundary;
+ newtag->lowaddr = trunc_page((vm_offset_t)lowaddr) + (PAGE_SIZE - 1);
+ newtag->highaddr = trunc_page((vm_offset_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);
+ }
+
+ *dmat = newtag;
+ return (error);
+}
+
+int
+bus_dma_tag_destroy(bus_dma_tag_t dmat)
+{
+ if (dmat != NULL) {
+
+ if (dmat->map_count != 0)
+ return (EBUSY);
+
+ 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;
+ }
+ }
+ return (0);
+}
+
+/*
+ * 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)
+{
+ *mapp = NULL;
+ dmat->map_count++;
+
+ return (0);
+}
+
+/*
+ * 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 (map != NULL) {
+ panic("dmamap_destroy: NULL?\n");
+ }
+ dmat->map_count--;
+ 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)
+{
+ int mflags;
+
+ if (flags & BUS_DMA_NOWAIT)
+ mflags = M_NOWAIT;
+ else
+ mflags = M_WAITOK;
+ if (flags & BUS_DMA_ZERO)
+ mflags |= M_ZERO;
+
+ *mapp = NULL;
+
+ /*
+ * 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 return an error if malloc gets it wrong.
+ */
+ if (dmat->maxsize <= PAGE_SIZE &&
+ dmat->alignment < dmat->maxsize) {
+ *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.
+ */
+ *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
+ 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul,
+ dmat->boundary);
+ }
+
+ if (*vaddr == NULL)
+ return (ENOMEM);
+
+ if ((uintptr_t)*vaddr % dmat->alignment)
+ printf("XXX: %s: alignment not respected!\n", __func__);
+
+ return (0);
+}
+
+/*
+ * Free a piece of memory and it's allocated 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 != NULL)
+ panic("bus_dmamem_free: Invalid map freed\n");
+ if (dmat->maxsize <= PAGE_SIZE &&
+ dmat->alignment < dmat->maxsize)
+ free(vaddr, M_DEVBUF);
+ else
+ contigfree(vaddr, dmat->maxsize, M_DEVBUF);
+}
+
+/*
+ * Utility function to load a linear buffer. lastaddrp holds state
+ * between invocations (for multiple-buffer loads). segp contains
+ * the starting segment on entrance, and the ending segment on exit.
+ * first indicates if this is the first invocation of this function.
+ */
+static int
+bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t segs[],
+ void *buf, bus_size_t buflen, struct thread *td,
+ int flags, vm_offset_t *lastaddrp, int *segp,
+ int first)
+{
+ bus_size_t sgsize;
+ bus_addr_t curaddr, lastaddr, baddr, bmask;
+ vm_offset_t vaddr = (vm_offset_t)buf;
+ int seg;
+ pmap_t pmap;
+
+ if (td != NULL)
+ pmap = vmspace_pmap(td->td_proc->p_vmspace);
+ else
+ pmap = NULL;
+
+ lastaddr = *lastaddrp;
+ bmask = ~(dmat->boundary - 1);
+
+ for (seg = *segp; buflen > 0 ; ) {
+ /*
+ * Get the physical address for this segment.
+ */
+ if (pmap)
+ curaddr = pmap_extract(pmap, vaddr);
+ else
+ curaddr = pmap_kextract(vaddr);
+
+ /*
+ * Compute the segment size, and adjust counts.
+ */
+ sgsize = PAGE_SIZE - ((u_long)curaddr & PAGE_MASK);
+ if (sgsize > dmat->maxsegsz)
+ sgsize = dmat->maxsegsz;
+ if (buflen < sgsize)
+ sgsize = buflen;
+
+ /*
+ * Make sure we don't cross any boundaries.
+ */
+ if (dmat->boundary > 0) {
+ baddr = (curaddr + dmat->boundary) & bmask;
+ if (sgsize > (baddr - curaddr))
+ sgsize = (baddr - curaddr);
+ }
+
+ /*
+ * Insert chunk into a segment, coalescing with
+ * the previous segment if possible.
+ */
+ if (first) {
+ segs[seg].ds_addr = curaddr;
+ segs[seg].ds_len = sgsize;
+ first = 0;
+ } else {
+ if (curaddr == lastaddr &&
+ (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)
+ break;
+ segs[seg].ds_addr = curaddr;
+ segs[seg].ds_len = sgsize;
+ }
+ }
+
+ lastaddr = curaddr + sgsize;
+ vaddr += sgsize;
+ buflen -= sgsize;
+ }
+
+ *segp = seg;
+ *lastaddrp = lastaddr;
+
+ /*
+ * Did we fit?
+ */
+ return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */
+}
+
+/*
+ * Map the buffer buf into bus space using the dmamap map.
+ */
+int
+bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
+ bus_size_t buflen, bus_dmamap_callback_t *callback,
+ void *callback_arg, int flags)
+{
+#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT
+ bus_dma_segment_t dm_segments[dmat->nsegments];
+#else
+ bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS];
+#endif
+ vm_offset_t lastaddr;
+ int error, nsegs;
+
+ if (map != NULL)
+ panic("bus_dmamap_load: Invalid map\n");
+
+ lastaddr = (vm_offset_t)0;
+ nsegs = 0;
+ error = bus_dmamap_load_buffer(dmat, dm_segments, buf, buflen,
+ NULL, flags, &lastaddr, &nsegs, 1);
+
+ if (error == 0)
+ (*callback)(callback_arg, dm_segments, nsegs + 1, 0);
+ else
+ (*callback)(callback_arg, NULL, 0, error);
+
+ return (0);
+}
+
+/*
+ * Like bus_dmamap_load(), but for mbufs.
+ */
+int
+bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0,
+ bus_dmamap_callback2_t *callback, void *callback_arg,
+ int flags)
+{
+#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT
+ bus_dma_segment_t dm_segments[dmat->nsegments];
+#else
+ bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS];
+#endif
+ int nsegs = 0, error = 0;
+
+ M_ASSERTPKTHDR(m0);
+
+ if (m0->m_pkthdr.len <= dmat->maxsize) {
+ int first = 1;
+ vm_offset_t lastaddr = 0;
+ struct mbuf *m;
+
+ for (m = m0; m != NULL && error == 0; m = m->m_next) {
+ if (m->m_len > 0) {
+ error = bus_dmamap_load_buffer(dmat,
+ dm_segments, m->m_data, m->m_len, NULL,
+ flags, &lastaddr, &nsegs, first);
+ first = 0;
+ }
+ }
+ } else {
+ error = EINVAL;
+ }
+
+ if (error) {
+ /*
+ * force "no valid mappings" on error in callback.
+ */
+ (*callback)(callback_arg, dm_segments, 0, 0, error);
+ } else {
+ (*callback)(callback_arg, dm_segments, nsegs+1,
+ m0->m_pkthdr.len, error);
+ }
+ return (error);
+}
+
+int
+bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0,
+ bus_dma_segment_t *segs, int *nsegs, int flags)
+{
+ int error = 0;
+
+ M_ASSERTPKTHDR(m0);
+
+ *nsegs = 0;
+
+ if (m0->m_pkthdr.len <= dmat->maxsize) {
+ int first = 1;
+ vm_offset_t lastaddr = 0;
+ struct mbuf *m;
+
+ for (m = m0; m != NULL && error == 0; m = m->m_next) {
+ if (m->m_len > 0) {
+ error = bus_dmamap_load_buffer(dmat,
+ segs, m->m_data, m->m_len, NULL,
+ flags, &lastaddr, nsegs, first);
+ first = 0;
+ }
+ }
+ ++*nsegs;
+ } else {
+ error = EINVAL;
+ }
+
+ return (error);
+}
+
+/*
+ * Like bus_dmamap_load(), but for uios.
+ */
+int
+bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio,
+ bus_dmamap_callback2_t *callback, void *callback_arg,
+ int flags)
+{
+ vm_offset_t lastaddr;
+#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT
+ bus_dma_segment_t dm_segments[dmat->nsegments];
+#else
+ bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS];
+#endif
+ int nsegs, i, error, first;
+ bus_size_t resid;
+ struct iovec *iov;
+ struct thread *td = NULL;
+
+ resid = uio->uio_resid;
+ iov = uio->uio_iov;
+
+ if (uio->uio_segflg == UIO_USERSPACE) {
+ td = uio->uio_td;
+ KASSERT(td != NULL,
+ ("bus_dmamap_load_uio: USERSPACE but no proc"));
+ }
+
+ first = 1;
+ nsegs = error = 0;
+ for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) {
+ /*
+ * Now at the first iovec to load. Load each iovec
+ * until we have exhausted the residual count.
+ */
+ bus_size_t minlen =
+ resid < iov[i].iov_len ? resid : iov[i].iov_len;
+ caddr_t addr = (caddr_t) iov[i].iov_base;
+
+ if (minlen > 0) {
+ error = bus_dmamap_load_buffer(dmat, dm_segments, addr,
+ minlen, td, flags, &lastaddr, &nsegs, first);
+
+ first = 0;
+
+ resid -= minlen;
+ }
+ }
+
+ if (error) {
+ /*
+ * force "no valid mappings" on error in callback.
+ */
+ (*callback)(callback_arg, dm_segments, 0, 0, error);
+ } else {
+ (*callback)(callback_arg, dm_segments, nsegs+1,
+ uio->uio_resid, error);
+ }
+
+ return (error);
+}
+
+/*
+ * Release the mapping held by map. A no-op on PowerPC.
+ */
+void
+_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+
+ return;
+}
+
+void
+_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
+{
+
+ return;
+}
diff --git a/sys/powerpc/powerpc/clock.c b/sys/powerpc/powerpc/clock.c
new file mode 100644
index 000000000000..0c01cf048911
--- /dev/null
+++ b/sys/powerpc/powerpc/clock.c
@@ -0,0 +1,318 @@
+/*-
+ * 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$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/timetc.h>
+#include <sys/interrupt.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <machine/clock.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/md_var.h>
+
+/*
+ * Initially we assume a processor with a bus frequency of 12.5 MHz.
+ */
+u_int tickspending;
+u_long ns_per_tick = 80;
+static u_long ticks_per_sec = 12500000;
+static long ticks_per_intr;
+static volatile u_long lasttb;
+
+#define DIFF19041970 2082844800
+
+static int clockinitted = 0;
+
+static timecounter_get_t decr_get_timecount;
+
+static struct timecounter decr_timecounter = {
+ decr_get_timecount, /* get_timecount */
+ 0, /* no poll_pps */
+ ~0u, /* counter_mask */
+ 0, /* frequency */
+ "decrementer" /* name */
+};
+
+void
+inittodr(time_t base)
+{
+ time_t deltat;
+ u_int rtc_time;
+ struct timespec ts;
+ phandle_t phandle;
+ ihandle_t ihandle;
+ char rtcpath[128];
+ u_int rtcsecs;
+
+ /*
+ * If we can't read from RTC, use the fs time.
+ */
+ phandle = OF_finddevice("rtc");
+ if (phandle != -1) {
+ OF_package_to_path(phandle, rtcpath, sizeof(rtcpath));
+ ihandle = OF_open(rtcpath);
+ if (ihandle != -1) {
+ if (OF_call_method("read-rtc", ihandle,
+ 0, 1, &rtcsecs))
+ printf("RTC call method error\n");
+ else {
+ ts.tv_sec = rtcsecs - DIFF19041970;
+ ts.tv_nsec = 0;
+ tc_setclock(&ts);
+ return;
+ }
+ }
+ }
+
+ {
+ ts.tv_sec = base;
+ ts.tv_nsec = 0;
+ tc_setclock(&ts);
+ return;
+ }
+ clockinitted = 1;
+ ts.tv_sec = rtc_time - DIFF19041970;
+
+ deltat = ts.tv_sec - base;
+ if (deltat < 0) {
+ deltat = -deltat;
+ }
+ if (deltat < 2 * SECDAY) {
+ tc_setclock(&ts);
+ return;
+ }
+
+ printf("WARNING: clock %s %d days",
+ ts.tv_sec < base ? "lost" : "gained", (int)(deltat / SECDAY));
+
+ printf(" -- CHECK AND RESET THE DATE!\n");
+}
+
+/*
+ * Similar to the above
+ */
+void
+resettodr()
+{
+
+}
+
+void
+decr_intr(struct trapframe *frame)
+{
+ u_long tb;
+ long tick;
+ int nticks;
+
+ /*
+ * Check whether we are initialized.
+ */
+ if (!ticks_per_intr)
+ return;
+
+ /*
+ * Based on the actual time delay since the last decrementer reload,
+ * we arrange for earlier interrupt next time.
+ */
+ __asm ("mftb %0; mfdec %1" : "=r"(tb), "=r"(tick));
+ for (nticks = 0; tick < 0; nticks++)
+ tick += ticks_per_intr;
+ mtdec(tick);
+ /*
+ * lasttb is used during microtime. Set it to the virtual
+ * start of this tick interval.
+ */
+ lasttb = tb + tick - ticks_per_intr;
+
+ nticks += tickspending;
+ tickspending = 0;
+
+ /*
+ * Reenable interrupts
+ */
+#if 0
+ msr = mfmsr();
+ mtmsr(msr | PSL_EE | PSL_RI);
+#endif
+ /*
+ * Do standard timer interrupt stuff.
+ * Do softclock stuff only on the last iteration.
+ */
+#if 0
+ while (--nticks > 0) {
+ hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+ }
+#endif
+ hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+}
+
+void
+decr_init(void)
+{
+ int qhandle, phandle;
+ char name[32];
+ unsigned int msr;
+
+ phandle = 0;
+
+ /*
+ * Get this info during autoconf? XXX
+ */
+ for (qhandle = OF_peer(0); qhandle; qhandle = phandle) {
+ if (OF_getprop(qhandle, "device_type", name, sizeof name) >= 0
+ && !strcmp(name, "cpu")
+ && OF_getprop(qhandle, "timebase-frequency",
+ &ticks_per_sec, sizeof ticks_per_sec) >= 0) {
+ /*
+ * Should check for correct CPU here? XXX
+ */
+ msr = mfmsr();
+ mtmsr(msr & ~(PSL_EE|PSL_RI));
+
+ ns_per_tick = 1000000000 / ticks_per_sec;
+ ticks_per_intr = ticks_per_sec / hz;
+ __asm __volatile ("mftb %0" : "=r"(lasttb));
+ mtdec(ticks_per_intr);
+
+ mtmsr(msr);
+
+ break;
+ }
+ if ((phandle = OF_child(qhandle)))
+ continue;
+ while (qhandle) {
+ if ((phandle = OF_peer(qhandle)))
+ break;
+ qhandle = OF_parent(qhandle);
+ }
+ }
+ if (!phandle)
+ panic("no cpu node");
+}
+
+void
+decr_tc_init(void)
+{
+ decr_timecounter.tc_frequency = ticks_per_sec;
+ tc_init(&decr_timecounter);
+}
+
+static __inline u_quad_t
+mftb(void)
+{
+ u_long scratch;
+ u_quad_t tb;
+
+ __asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw 0,%0,%1; bne 1b"
+ : "=r"(tb), "=r"(scratch));
+ return tb;
+}
+
+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();
+}
+
+/*
+ * Nothing to do.
+ */
+void
+cpu_startprofclock(void)
+{
+
+ /* Do nothing */
+}
+
+void
+cpu_stopprofclock(void)
+{
+}
+
+/*
+ * XXX Needed by syscons
+ */
+int
+sysbeep(int pitch, int period)
+{
+
+ return (0);
+}
diff --git a/sys/powerpc/powerpc/copyinout.c b/sys/powerpc/powerpc/copyinout.c
new file mode 100644
index 000000000000..4e9f77746f1a
--- /dev/null
+++ b/sys/powerpc/powerpc/copyinout.c
@@ -0,0 +1,356 @@
+/*-
+ * 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$");
+
+#include <sys/param.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>
+
+int setfault(faultbuf); /* defined in locore.S */
+
+/*
+ * Makes sure that the right segment of userspace is mapped in.
+ */
+static __inline void
+set_user_sr(register_t vsid)
+{
+
+ isync();
+ __asm __volatile ("mtsr %0,%1" :: "n"(USER_SR), "r"(vsid));
+ isync();
+}
+
+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 = PCPU_GET(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) {
+ p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK);
+
+ l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
+ if (l > len)
+ l = len;
+
+ set_user_sr(pm->pm_sr[(u_int)up >> ADDR_SR_SHFT]);
+
+ 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 = PCPU_GET(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) {
+ p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK);
+
+ l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
+ if (l > len)
+ l = len;
+
+ set_user_sr(pm->pm_sr[(u_int)up >> ADDR_SR_SHFT]);
+
+ 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)
+{
+ struct thread *td;
+ pmap_t pm;
+ faultbuf env;
+ const char *up;
+ char *kp;
+ size_t l;
+ int rv, c;
+
+ td = PCPU_GET(curthread);
+ pm = &td->td_proc->p_vmspace->vm_pmap;
+
+ if (setfault(env)) {
+ td->td_pcb->pcb_onfault = NULL;
+ return (EFAULT);
+ }
+
+ 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;
+ }
+
+ td->td_pcb->pcb_onfault = NULL;
+ return (rv);
+}
+
+int
+subyte(void *addr, int byte)
+{
+ struct thread *td;
+ pmap_t pm;
+ faultbuf env;
+ char *p;
+
+ td = PCPU_GET(curthread);
+ pm = &td->td_proc->p_vmspace->vm_pmap;
+ p = (char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
+
+ if (setfault(env)) {
+ td->td_pcb->pcb_onfault = NULL;
+ return (-1);
+ }
+
+ set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
+
+ *p = (char)byte;
+
+ td->td_pcb->pcb_onfault = NULL;
+ return (0);
+}
+
+int
+suword(void *addr, long word)
+{
+ struct thread *td;
+ pmap_t pm;
+ faultbuf env;
+ long *p;
+
+ td = PCPU_GET(curthread);
+ pm = &td->td_proc->p_vmspace->vm_pmap;
+ p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
+
+ if (setfault(env)) {
+ td->td_pcb->pcb_onfault = NULL;
+ return (-1);
+ }
+
+ set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
+
+ *p = word;
+
+ td->td_pcb->pcb_onfault = NULL;
+ return (0);
+}
+
+int
+suword32(void *addr, int32_t word)
+{
+ return (suword(addr, (long)word));
+}
+
+
+int
+fubyte(const void *addr)
+{
+ struct thread *td;
+ pmap_t pm;
+ faultbuf env;
+ u_char *p;
+ int val;
+
+ td = PCPU_GET(curthread);
+ pm = &td->td_proc->p_vmspace->vm_pmap;
+ p = (u_char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
+
+ if (setfault(env)) {
+ td->td_pcb->pcb_onfault = NULL;
+ return (-1);
+ }
+
+ set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
+
+ val = *p;
+
+ td->td_pcb->pcb_onfault = NULL;
+ return (val);
+}
+
+long
+fuword(const void *addr)
+{
+ struct thread *td;
+ pmap_t pm;
+ faultbuf env;
+ long *p, val;
+
+ td = PCPU_GET(curthread);
+ pm = &td->td_proc->p_vmspace->vm_pmap;
+ p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
+
+ if (setfault(env)) {
+ td->td_pcb->pcb_onfault = NULL;
+ return (-1);
+ }
+
+ set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
+
+ val = *p;
+
+ td->td_pcb->pcb_onfault = NULL;
+ return (val);
+}
+
+int32_t
+fuword32(const void *addr)
+{
+ return ((int32_t)fuword(addr));
+}
+
+uint32_t
+casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval)
+{
+ return (casuword((volatile u_long *)base, oldval, newval));
+}
+
+u_long
+casuword(volatile u_long *addr, u_long old, u_long new)
+{
+ struct thread *td;
+ pmap_t pm;
+ faultbuf env;
+ u_long *p, val;
+
+ td = PCPU_GET(curthread);
+ pm = &td->td_proc->p_vmspace->vm_pmap;
+ p = (u_long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
+
+ set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
+
+ if (setfault(env)) {
+ td->td_pcb->pcb_onfault = NULL;
+ return (-1);
+ }
+
+ val = *p;
+ (void) atomic_cmpset_32((volatile uint32_t *)p, old, new);
+
+ td->td_pcb->pcb_onfault = NULL;
+
+ return (val);
+}
diff --git a/sys/powerpc/powerpc/copystr.c b/sys/powerpc/powerpc/copystr.c
new file mode 100644
index 000000000000..1a159d87185b
--- /dev/null
+++ b/sys/powerpc/powerpc/copystr.c
@@ -0,0 +1,68 @@
+/*-
+ * 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$");
+
+#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;
+}
diff --git a/sys/powerpc/powerpc/cpu.c b/sys/powerpc/powerpc/cpu.c
new file mode 100644
index 000000000000..d942af6d4279
--- /dev/null
+++ b/sys/powerpc/powerpc/cpu.c
@@ -0,0 +1,385 @@
+/*-
+ * 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$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/hid.h>
+#include <machine/md_var.h>
+#include <machine/spr.h>
+
+struct cputab {
+ const char *name;
+ uint16_t version;
+ uint16_t revfmt;
+};
+#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 },
+ { "Motorola PowerPC 602", MPC602, REVFMT_DEC },
+ { "Motorola PowerPC 603", MPC603, REVFMT_MAJMIN },
+ { "Motorola PowerPC 603e", MPC603e, REVFMT_MAJMIN },
+ { "Motorola PowerPC 603ev", MPC603ev, REVFMT_MAJMIN },
+ { "Motorola PowerPC 604", MPC604, REVFMT_MAJMIN },
+ { "Motorola PowerPC 604ev", MPC604ev, REVFMT_MAJMIN },
+ { "Motorola PowerPC 620", MPC620, REVFMT_HEX },
+ { "Motorola PowerPC 750", MPC750, REVFMT_MAJMIN },
+ { "IBM PowerPC 750FX", IBM750FX, REVFMT_MAJMIN },
+ { "Motorola PowerPC 7400", MPC7400, REVFMT_MAJMIN },
+ { "Motorola PowerPC 7410", MPC7410, REVFMT_MAJMIN },
+ { "Motorola PowerPC 7450", MPC7450, REVFMT_MAJMIN },
+ { "Motorola PowerPC 7455", MPC7455, REVFMT_MAJMIN },
+ { "Motorola PowerPC 7457", MPC7457, REVFMT_MAJMIN },
+ { "Motorola PowerPC 7447A", MPC7447A, REVFMT_MAJMIN },
+ { "Motorola PowerPC 7448", MPC7448, REVFMT_MAJMIN },
+ { "Motorola PowerPC 8240", MPC8240, REVFMT_MAJMIN },
+ { "Unknown PowerPC CPU", 0, REVFMT_HEX }
+};
+
+static char model[64];
+SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, "");
+
+static register_t l2cr_config = 0;
+
+static void cpu_print_speed(void);
+static void cpu_config_l2cr(u_int, uint16_t);
+
+void
+cpu_setup(u_int cpuid)
+{
+ u_int pvr, maj, min, hid0;
+ uint16_t vers, rev, revfmt;
+ const struct cputab *cp;
+ const char *name;
+ char *bitmask;
+
+ pvr = mfpvr();
+ vers = pvr >> 16;
+ rev = pvr;
+ switch (vers) {
+ case MPC7410:
+ min = (pvr >> 0) & 0xff;
+ maj = min <= 4 ? 1 : 2;
+ 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;
+ }
+
+ hid0 = mfspr(SPR_HID0);
+
+ /*
+ * 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;
+#ifdef notyet
+ powersave = 1;
+#endif
+ 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;
+#ifdef notyet
+ powersave = 0; /* but don't use it */
+#endif
+ 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);
+
+ switch (vers) {
+ case MPC7447A:
+ case MPC7448:
+ case MPC7450:
+ case MPC7455:
+ case MPC7457:
+ bitmask = HID0_7450_BITMASK;
+ break;
+ default:
+ bitmask = HID0_BITMASK;
+ break;
+ }
+
+ switch (vers) {
+ case MPC750:
+ case IBM750FX:
+ case MPC7400:
+ case MPC7410:
+ case MPC7447A:
+ case MPC7448:
+ case MPC7450:
+ case MPC7455:
+ case MPC7457:
+ cpu_print_speed();
+ printf("\n");
+ cpu_config_l2cr(cpuid, vers);
+ break;
+
+ default:
+ printf("\n");
+ break;
+ }
+
+ printf("cpu%d: HID0 %b\n", cpuid, hid0, bitmask);
+}
+
+void
+cpu_print_speed(void)
+{
+ uint64_t cps;
+
+ mtspr(SPR_MMCR0, SPR_MMCR0_FC);
+ mtspr(SPR_PMC1, 0);
+ mtspr(SPR_MMCR0, SPR_MMCR0_PMC1SEL(PMCN_CYCLES));
+ DELAY(100000);
+ cps = (mfspr(SPR_PMC1) * 10) + 4999;
+ printf(", %lld.%02lld MHz", cps / 1000000, (cps / 10000) % 100);
+}
+
+void
+cpu_config_l2cr(u_int cpuid, uint16_t vers)
+{
+ u_int l2cr, x, msr;
+
+ l2cr = mfspr(SPR_L2CR);
+
+ /*
+ * For MP systems, the firmware may only configure the L2 cache
+ * on the first CPU. In this case, assume that the other CPUs
+ * should use the same value for L2CR.
+ */
+ if ((l2cr & L2CR_L2E) != 0 && l2cr_config == 0) {
+ l2cr_config = l2cr;
+ }
+
+ /*
+ * Configure L2 cache if not enabled.
+ */
+ if ((l2cr & L2CR_L2E) == 0 && l2cr_config != 0) {
+ l2cr = l2cr_config;
+
+ /* Disable interrupts and set the cache config bits. */
+ msr = mfmsr();
+ mtmsr(msr & ~PSL_EE);
+#ifdef ALTIVEC
+ if (cpu_altivec)
+ __asm __volatile("dssall");
+#endif
+ __asm __volatile("sync");
+ mtspr(SPR_L2CR, l2cr & ~L2CR_L2E);
+ __asm __volatile("sync");
+
+ /* Wait for L2 clock to be stable (640 L2 clocks). */
+ DELAY(100);
+
+ /* Invalidate all L2 contents. */
+ mtspr(SPR_L2CR, l2cr | L2CR_L2I);
+ do {
+ x = mfspr(SPR_L2CR);
+ } while (x & L2CR_L2IP);
+
+ /* Enable L2 cache. */
+ l2cr |= L2CR_L2E;
+ mtspr(SPR_L2CR, l2cr);
+ mtmsr(msr);
+ }
+
+ if (!bootverbose)
+ return;
+
+ printf("cpu%d: ", cpuid);
+
+ if (l2cr & L2CR_L2E) {
+ if (vers == MPC7450 ||
+ vers == MPC7455 ||
+ vers == MPC7457) {
+ u_int l3cr;
+
+ printf("256KB L2 cache");
+
+ l3cr = mfspr(SPR_L3CR);
+ if (l3cr & L3CR_L3E)
+ printf(", %cMB L3 backside cache",
+ l3cr & L3CR_L3SIZ ? '2' : '1');
+ printf("\n");
+ return;
+ }
+ if (vers == IBM750FX) {
+ printf("512KB L2 cache\n");
+ return;
+ }
+ switch (l2cr & L2CR_L2SIZ) {
+ case L2SIZ_256K:
+ printf("256KB");
+ break;
+ case L2SIZ_512K:
+ printf("512KB");
+ break;
+ case L2SIZ_1M:
+ printf("1MB");
+ break;
+ default:
+ printf("unknown size");
+ }
+ if (l2cr & L2CR_L2WT) {
+ printf(" write-through");
+ } else {
+ printf(" write-back");
+ }
+ switch (l2cr & L2CR_L2RAM) {
+ case L2RAM_FLOWTHRU_BURST:
+ printf(" flow-through synchronous burst SRAM");
+ break;
+ case L2RAM_PIPELINE_BURST:
+ printf(" pipelined synchronous burst SRAM");
+ break;
+ case L2RAM_PIPELINE_LATE:
+ printf(" pipelined synchronous late-write SRAM");
+ break;
+ default:
+ printf(" unknown type");
+ }
+
+ if (l2cr & L2CR_L2PE)
+ printf(" with parity");
+ printf(" backside cache");
+ } else
+ printf("L2 cache not enabled");
+
+ printf("\n");
+}
diff --git a/sys/powerpc/powerpc/db_disasm.c b/sys/powerpc/powerpc/db_disasm.c
new file mode 100644
index 000000000000..67f90d254401
--- /dev/null
+++ b/sys/powerpc/powerpc/db_disasm.c
@@ -0,0 +1,962 @@
+/* $FreeBSD$ */
+/* $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);
+}
diff --git a/sys/powerpc/powerpc/db_hwwatch.c b/sys/powerpc/powerpc/db_hwwatch.c
new file mode 100644
index 000000000000..a5b0a69f5a91
--- /dev/null
+++ b/sys/powerpc/powerpc/db_hwwatch.c
@@ -0,0 +1,54 @@
+/*-
+ * 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$
+ */
+#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)
+{
+}
diff --git a/sys/powerpc/powerpc/db_interface.c b/sys/powerpc/powerpc/db_interface.c
new file mode 100644
index 000000000000..3dae648d05fe
--- /dev/null
+++ b/sys/powerpc/powerpc/db_interface.c
@@ -0,0 +1,81 @@
+/* $FreeBSD$ */
+/* $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)
+{
+}
diff --git a/sys/powerpc/powerpc/db_memrw.c b/sys/powerpc/powerpc/db_memrw.c
new file mode 100644
index 000000000000..e27bc67fafe5
--- /dev/null
+++ b/sys/powerpc/powerpc/db_memrw.c
@@ -0,0 +1,110 @@
+/* $FreeBSD$ */
+/* $NetBSD: db_memrw.c,v 1.5 2001/12/27 10:25:41 dbj Exp $ */
+/* $OpenBSD: db_memrw.c,v 1.2 1996/12/28 06:21:52 rahnds 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@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.
+ */
+
+/*
+ * Interface to the debugger for virtual memory read/write.
+ * This is a simple version for kernels with writable text.
+ * For an example of read-only kernel text, see the file:
+ * sys/arch/sun3/sun3/db_memrw.c
+ *
+ * ALERT! If you want to access device registers with a
+ * specific size, then the read/write functions have to
+ * make sure to do the correct sized pointer access.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+
+#include <machine/cpu.h>
+#include <machine/db_machdep.h>
+
+#include <ddb/ddb.h>
+
+/*
+ * Read bytes from kernel address space for debugger.
+ */
+void
+db_read_bytes(addr, size, data)
+ vm_offset_t addr;
+ register size_t size;
+ register char *data;
+{
+ register char *src = (char*)addr;
+
+ if (size == 4) {
+ *((int*)data) = *((int*)src);
+ return;
+ }
+
+ if (size == 2) {
+ *((short*)data) = *((short*)src);
+ return;
+ }
+
+ while (size > 0) {
+ --size;
+ *data++ = *src++;
+ }
+}
+
+/*
+ * Write bytes to kernel address space for debugger.
+ */
+void
+db_write_bytes(addr, size, data)
+ vm_offset_t addr;
+ register size_t size;
+ register char *data;
+{
+ register char *dst = (char *)addr;
+
+ if (size == 4) {
+
+ *((int*)dst) = *((int*)data);
+
+ } else if (size == 2) {
+
+ *((short*)dst) = *((short*)data);
+
+ } else {
+
+ while (size > 0) {
+ --size;
+ *dst++ = *data++;
+ }
+
+ }
+
+ __syncicache((void *)addr, size);
+}
+
diff --git a/sys/powerpc/powerpc/db_trace.c b/sys/powerpc/powerpc/db_trace.c
new file mode 100644
index 000000000000..188e0287aab2
--- /dev/null
+++ b/sys/powerpc/powerpc/db_trace.c
@@ -0,0 +1,323 @@
+/* $FreeBSD$ */
+/* $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@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/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)
+
+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 },
+ { "dar", DB_OFFSET(dar), db_frame },
+ { "dsisr", DB_OFFSET(dsisr), db_frame },
+};
+struct db_variable *db_eregs = db_regs + sizeof (db_regs)/sizeof (db_regs[0]);
+
+extern int trapexit[];
+extern int asttrapexit[];
+extern int end[];
+
+/*
+ * register variable handling
+ */
+static int
+db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
+{
+ uint32_t *reg;
+
+ if (kdb_frame == NULL)
+ return (0);
+ reg = (uint32_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:
+ /* The saved arg values start at frame[2] */
+ args = (db_addr_t *)(stackframe + 8);
+
+ 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)
+ */
+ lr = *(db_addr_t *)(stackframe + 4) - 4;
+ if ((lr & 3) || (lr < 0x100)) {
+ db_printf("saved LR(0x%x) is invalid.", lr);
+ break;
+ }
+
+ db_printf("0x%08x: ", stackframe);
+
+ /*
+ * 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 + 4 == (db_addr_t) &trapexit) ||
+ (lr + 4 == (db_addr_t) &asttrapexit)) {
+ const char *trapstr;
+ struct trapframe *tf = (struct trapframe *)
+ (stackframe+8);
+ db_printf("%s ", tf->srr1 & PSL_PR ? "user" : "kernel");
+ switch (tf->exc) {
+ case EXC_DSI:
+ db_printf("DSI %s trap @ %#x by ",
+ tf->dsisr & DSISR_STORE ? "write" : "read",
+ tf->dar);
+ goto print_trap;
+ case EXC_ALI:
+ db_printf("ALI trap @ %#x (DSISR %#x) ",
+ tf->dar, tf->dsisr);
+ goto print_trap;
+ 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;
+ case EXC_VEC: trapstr = "VEC"; break;
+ case EXC_FPU: trapstr = "FPU"; break;
+ case EXC_FPA: trapstr = "FPA"; break;
+ case EXC_DECR: trapstr = "DECR"; break;
+ case EXC_BPT: trapstr = "BPT"; break;
+ case EXC_TRC: trapstr = "TRC"; break;
+ case EXC_RUNMODETRC: trapstr = "RUNMODETRC"; break;
+ case EXC_PERF: trapstr = "PERF"; break;
+ case EXC_SMI: trapstr = "SMI"; break;
+ case EXC_RST: trapstr = "RST"; break;
+ default: trapstr = NULL; break;
+ }
+ if (trapstr != NULL) {
+ db_printf("%s trap by ", trapstr);
+ } else {
+ db_printf("trap %#x 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("%#x: srr1=%#x\n", lr, tf->srr1);
+ } else {
+ db_printf("%s+%#x: srr1=%#x\n", symname, diff,
+ tf->srr1);
+ }
+ db_printf("%-10s r1=%#x cr=%#x xer=%#x ctr=%#x",
+ "", tf->fixreg[1], tf->cr, tf->xer, tf->ctr);
+ if (tf->exc == EXC_DSI)
+ db_printf(" dsisr=%#x", tf->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 %x", lr);
+ else
+ db_printf("at %s+%#x", symname, diff);
+ if (full)
+ /* Print all the args stored in that stackframe. */
+ db_printf("(%x, %x, %x, %x, %x, %x, %x, %x)",
+ 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));
+}
+
+void
+stack_save(struct stack *st)
+{
+ vm_offset_t callpc;
+ db_addr_t stackframe;
+
+ stack_zero(st);
+ stackframe = (db_addr_t)__builtin_frame_address(1);
+ if (stackframe < PAGE_SIZE)
+ return;
+ while (1) {
+ stackframe = *(db_addr_t *)stackframe;
+ if (stackframe < PAGE_SIZE)
+ break;
+ callpc = *(vm_offset_t *)(stackframe + 4) - 4;
+ 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 + 4 == (db_addr_t) &trapexit ||
+ callpc + 4 == (db_addr_t) &asttrapexit)
+ break;
+
+ if (stack_put(st, callpc) == -1)
+ break;
+ }
+}
+
diff --git a/sys/powerpc/powerpc/elf_machdep.c b/sys/powerpc/powerpc/elf_machdep.c
new file mode 100644
index 000000000000..ff017e13e936
--- /dev/null
+++ b/sys/powerpc/powerpc/elf_machdep.c
@@ -0,0 +1,234 @@
+/*-
+ * 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$
+ */
+
+#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 elf32_freebsd_sysvec = {
+ SYS_MAXSYSCALL,
+ sysent,
+ 0,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ __elfN(freebsd_fixup),
+ sendsig,
+ sigcode,
+ &szsigcode,
+ NULL,
+ "FreeBSD ELF32",
+ __elfN(coredump),
+ NULL,
+ MINSIGSTKSZ,
+ PAGE_SIZE,
+ VM_MIN_ADDRESS,
+ VM_MAXUSER_ADDRESS,
+ USRSTACK,
+ PS_STRINGS,
+ VM_PROT_ALL,
+ exec_copyout_strings,
+ exec_setregs,
+ NULL
+};
+
+static Elf32_Brandinfo freebsd_brand_info = {
+ ELFOSABI_FREEBSD,
+ EM_PPC,
+ "FreeBSD",
+ NULL,
+ "/libexec/ld-elf.so.1",
+ &elf32_freebsd_sysvec,
+ NULL,
+ BI_CAN_EXEC_DYN,
+ };
+
+SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &freebsd_brand_info);
+
+static Elf32_Brandinfo freebsd_brand_oinfo = {
+ ELFOSABI_FREEBSD,
+ EM_PPC,
+ "FreeBSD",
+ NULL,
+ "/usr/libexec/ld-elf.so.1",
+ &elf32_freebsd_sysvec,
+ NULL,
+ BI_CAN_EXEC_DYN,
+ };
+
+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)
+{
+}
+
+
+/* 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;
+
+ 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);
+ hwhere = (Elf_Half *) (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 */
+ addr = lookup(lf, symidx, 1);
+ if (addr == 0)
+ return -1;
+ addr += addend;
+ *where = addr;
+ break;
+
+ case R_PPC_ADDR16_LO: /* #lo(S) */
+ addr = lookup(lf, symidx, 1);
+ if (addr == 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) */
+ addr = lookup(lf, symidx, 1);
+ if (addr == 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 = 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);
+}
diff --git a/sys/powerpc/powerpc/fpu.c b/sys/powerpc/powerpc/fpu.c
new file mode 100644
index 000000000000..c4cc326da431
--- /dev/null
+++ b/sys/powerpc/powerpc/fpu.c
@@ -0,0 +1,151 @@
+/*-
+ * 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$");
+
+#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.
+ */
+ tf->srr1 |= PSL_FP;
+ if (!(pcb->pcb_flags & PCB_FPU)) {
+ memset(&pcb->pcb_fpu, 0, sizeof pcb->pcb_fpu);
+ pcb->pcb_flags |= PCB_FPU;
+ }
+
+ /*
+ * 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);
+}
+
diff --git a/sys/powerpc/powerpc/fuswintr.c b/sys/powerpc/powerpc/fuswintr.c
new file mode 100644
index 000000000000..cb5abb7b9a18
--- /dev/null
+++ b/sys/powerpc/powerpc/fuswintr.c
@@ -0,0 +1,51 @@
+/*-
+ * 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$");
+
+#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;
+}
diff --git a/sys/powerpc/powerpc/gdb_machdep.c b/sys/powerpc/powerpc/gdb_machdep.c
new file mode 100644
index 000000000000..5fbb74427391
--- /dev/null
+++ b/sys/powerpc/powerpc/gdb_machdep.c
@@ -0,0 +1,72 @@
+/*-
+ * 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$");
+
+#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/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);
+ switch (regnum) {
+ }
+ 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 (vector == EXC_TRC || vector == EXC_RUNMODETRC)
+ return (SIGTRAP);
+ return (vector);
+}
diff --git a/sys/powerpc/powerpc/genassym.c b/sys/powerpc/powerpc/genassym.c
new file mode 100644
index 000000000000..63719cc12d20
--- /dev/null
+++ b/sys/powerpc/powerpc/genassym.c
@@ -0,0 +1,154 @@
+/*-
+ * 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$
+ */
+
+#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/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(CPUSAVE_R28,CPUSAVE_R28*4);
+ASSYM(CPUSAVE_R29,CPUSAVE_R29*4);
+ASSYM(CPUSAVE_R30,CPUSAVE_R30*4);
+ASSYM(CPUSAVE_R31,CPUSAVE_R31*4);
+ASSYM(CPUSAVE_DAR,CPUSAVE_DAR*4);
+ASSYM(CPUSAVE_DSISR,CPUSAVE_DSISR*4);
+ASSYM(CPUSAVE_SRR0,CPUSAVE_SRR0*4);
+ASSYM(CPUSAVE_SRR1,CPUSAVE_SRR1*4);
+
+ASSYM(MTX_LOCK, offsetof(struct mtx, mtx_lock));
+ASSYM(MTX_RECURSECNT, offsetof(struct mtx, mtx_recurse));
+
+ASSYM(PM_KERNELSR, offsetof(struct pmap, pm_sr[KERNEL_SR]));
+ASSYM(PM_USRSR, offsetof(struct pmap, pm_sr[USER_SR]));
+ASSYM(PM_SR, offsetof(struct pmap, pm_sr));
+
+ASSYM(FSP, 8);
+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_DAR, offsetof(struct trapframe, dar));
+ASSYM(FRAME_DSISR, offsetof(struct trapframe, dsisr));
+ASSYM(FRAME_EXC, offsetof(struct trapframe, exc));
+
+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_PMR, offsetof(struct pcb, pcb_pmreal));
+ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp));
+ASSYM(PCB_LR, offsetof(struct pcb, pcb_lr));
+ASSYM(PCB_USR, offsetof(struct pcb, pcb_usr));
+ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
+ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
+ASSYM(PCB_FPU, PCB_FPU);
+
+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(MAXCOMLEN, MAXCOMLEN);
diff --git a/sys/powerpc/powerpc/in_cksum.c b/sys/powerpc/powerpc/in_cksum.c
new file mode 100644
index 000000000000..a65ed7dddfbe
--- /dev/null
+++ b/sys/powerpc/powerpc/in_cksum.c
@@ -0,0 +1,250 @@
+/* $FreeBSD$ */
+/* $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@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 ^ (int) 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);
+}
diff --git a/sys/powerpc/powerpc/interrupt.c b/sys/powerpc/powerpc/interrupt.c
new file mode 100644
index 000000000000..ff77fc8dc074
--- /dev/null
+++ b/sys/powerpc/powerpc/interrupt.c
@@ -0,0 +1,101 @@
+/*-
+ * 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$
+ */
+
+/*
+ * Interrupts are dispatched to here from locore asm
+ */
+
+#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>
+#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;
+ register_t ee;
+
+ td = curthread;
+
+ switch (framep->exc) {
+ case EXC_EXI:
+ atomic_add_int(&td->td_intr_nesting_level, 1);
+ PIC_DISPATCH(pic, framep);
+ atomic_subtract_int(&td->td_intr_nesting_level, 1);
+ break;
+
+ case EXC_DECR:
+ atomic_add_int(&td->td_intr_nesting_level, 1);
+ decr_intr(framep);
+ atomic_subtract_int(&td->td_intr_nesting_level, 1);
+ break;
+
+ default:
+ /* Re-enable interrupts if applicable. */
+ ee = framep->srr1 & PSL_EE;
+ if (ee != 0) {
+ mtmsr(mfmsr() | ee);
+ isync();
+ }
+ trap(framep);
+ }
+}
diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c
new file mode 100644
index 000000000000..7653347579f3
--- /dev/null
+++ b/sys/powerpc/powerpc/intr_machdep.c
@@ -0,0 +1,306 @@
+/*-
+ * 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$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/bus.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/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/trap.h>
+
+#include "pic_if.h"
+
+#define MAX_STRAY_LOG 5
+
+MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data");
+
+struct powerpc_intr {
+ struct intr_event *event;
+ long *cntp;
+ u_int irq;
+};
+
+static struct powerpc_intr *powerpc_intrs[INTR_VECTORS];
+static u_int nvectors; /* Allocated vectors */
+static u_int stray_count;
+
+device_t pic;
+
+static void
+intrcnt_setname(const char *name, int index)
+{
+ snprintf(intrnames + (MAXCOMLEN + 1) * index, MAXCOMLEN + 1, "%-*s",
+ MAXCOMLEN, name);
+}
+
+#ifdef INTR_FILTER
+static void
+powerpc_intr_eoi(void *arg)
+{
+ u_int irq = (uintptr_t)arg;
+
+ PIC_EOI(pic, irq);
+}
+
+static void
+powerpc_intr_mask(void *arg)
+{
+ u_int irq = (uintptr_t)arg;
+
+ PIC_MASK(pic, irq);
+}
+#endif
+
+static void
+powerpc_intr_unmask(void *arg)
+{
+ u_int irq = (uintptr_t)arg;
+
+ PIC_UNMASK(pic, irq);
+}
+
+void
+powerpc_register_pic(device_t dev)
+{
+
+ pic = dev;
+}
+
+int
+powerpc_enable_intr(void)
+{
+ struct powerpc_intr *i;
+ int vector;
+
+ for (vector = 0; vector < nvectors; vector++) {
+ i = powerpc_intrs[vector];
+ if (i == NULL)
+ continue;
+
+ PIC_ENABLE(pic, i->irq, 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;
+ u_int vector;
+ int error;
+
+ /* XXX lock */
+
+ i = NULL;
+ for (vector = 0; vector < nvectors; vector++) {
+ i = powerpc_intrs[vector];
+ if (i == NULL)
+ continue;
+ if (i->irq == irq)
+ break;
+ i = NULL;
+ }
+
+ if (i == NULL) {
+ if (nvectors >= INTR_VECTORS) {
+ /* XXX unlock */
+ return (ENOENT);
+ }
+
+ i = malloc(sizeof(*i), M_INTR, M_NOWAIT);
+ if (i == NULL) {
+ /* XXX unlock */
+ return (ENOMEM);
+ }
+ error = intr_event_create(&i->event, (void *)irq, 0,
+ powerpc_intr_unmask,
+#ifdef INTR_FILTER
+ powerpc_intr_eoi, powerpc_intr_mask,
+#endif
+ "irq%u:", irq);
+ if (error) {
+ /* XXX unlock */
+ free(i, M_INTR);
+ return (error);
+ }
+
+ vector = nvectors++;
+ powerpc_intrs[vector] = i;
+
+ i->irq = irq;
+
+ /* XXX unlock */
+
+ i->cntp = &intrcnt[vector];
+ intrcnt_setname(i->event->ie_fullname, vector);
+
+ if (!cold)
+ PIC_ENABLE(pic, i->irq, vector);
+ } else {
+ /* XXX unlock */
+ }
+
+ error = intr_event_add_handler(i->event, name, filter, handler, arg,
+ intr_priority(flags), flags, cookiep);
+ if (!error)
+ intrcnt_setname(i->event->ie_fullname, vector);
+ return (error);
+}
+
+int
+powerpc_teardown_intr(void *cookie)
+{
+
+ return (intr_event_remove_handler(cookie));
+}
+
+void
+powerpc_dispatch_intr(u_int vector, struct trapframe *tf)
+{
+ struct powerpc_intr *i;
+ struct intr_event *ie;
+#ifndef INTR_FILTER
+ struct intr_handler *ih;
+ int error, sched, ret;
+#endif
+
+ i = powerpc_intrs[vector];
+ if (i == NULL)
+ goto stray;
+
+ (*i->cntp)++;
+
+ ie = i->event;
+ KASSERT(ie != NULL, ("%s: interrupt without an event", __func__));
+
+#ifdef INTR_FILTER
+ if (intr_event_handle(ie, tf) != 0) {
+ PIC_MASK(pic, i->irq);
+ log(LOG_ERR, "stray irq%u\n", i->irq);
+ }
+#else
+ if (TAILQ_EMPTY(&ie->ie_handlers))
+ goto stray;
+
+ /*
+ * Execute all fast interrupt handlers directly without Giant. Note
+ * that this means that any fast interrupt handler must be MP safe.
+ */
+ ret = 0;
+ sched = 0;
+ critical_enter();
+ TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
+ if (ih->ih_filter == NULL) {
+ sched = 1;
+ continue;
+ }
+ CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
+ ih->ih_filter, ih->ih_argument, ih->ih_name);
+ ret = ih->ih_filter(ih->ih_argument);
+ /*
+ * Wrapper handler special case: see
+ * i386/intr_machdep.c::intr_execute_handlers()
+ */
+ if (!sched) {
+ if (ret == FILTER_SCHEDULE_THREAD)
+ sched = 1;
+ }
+ }
+
+ if (sched) {
+ PIC_MASK(pic, i->irq);
+ error = intr_event_schedule_thread(ie);
+ KASSERT(error == 0, ("%s: impossible stray interrupt",
+ __func__));
+ } else
+ PIC_EOI(pic, i->irq);
+ critical_exit();
+#endif
+ return;
+
+stray:
+ stray_count++;
+ if (stray_count <= MAX_STRAY_LOG) {
+ printf("stray irq %d\n", i->irq);
+ if (stray_count >= MAX_STRAY_LOG) {
+ printf("got %d stray interrupts, not logging anymore\n",
+ MAX_STRAY_LOG);
+ }
+ }
+ if (i != NULL)
+ PIC_MASK(pic, i->irq);
+}
diff --git a/sys/powerpc/powerpc/locore.S b/sys/powerpc/powerpc/locore.S
new file mode 100644
index 000000000000..1a3c0bbaceeb
--- /dev/null
+++ b/sys/powerpc/powerpc/locore.S
@@ -0,0 +1,208 @@
+/* $FreeBSD$ */
+/* $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/sr.h>
+#include <machine/spr.h>
+#include <machine/psl.h>
+#include <machine/asm.h>
+
+/* Locate the per-CPU data structure */
+#define GET_CPUINFO(r) \
+ mfsprg0 r
+
+/*
+ * Globals
+ */
+ .data
+GLOBAL(tmpstk)
+ .space 8208
+GLOBAL(esym)
+ .long 0 /* end of symbol table */
+
+GLOBAL(ofmsr)
+ .long 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
+
+GLOBAL(powersave)
+ .long 0
+
+#define INTSTK 16384 /* 16K interrupt stack */
+#define INTRCNT_COUNT 256 /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
+GLOBAL(intrnames)
+ .space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+GLOBAL(eintrnames)
+ .align 4
+GLOBAL(intrcnt)
+ .space INTRCNT_COUNT * 4 * 2
+GLOBAL(eintrcnt)
+
+/*
+ * File-scope for locore.S
+ */
+idle_u:
+ .long 0 /* fake uarea during idle after exit */
+openfirmware_entry:
+ .long 0 /* Open Firmware entry point */
+srsave:
+ .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+/*
+ * This symbol is here for the benefit of kvm_mkdb, and is supposed to
+ * mark the start of kernel text.
+ */
+ .text
+ .globl kernel_text
+kernel_text:
+
+/*
+ * Startup entry. Note, this must be the first thing in the text
+ * segment!
+ */
+ .text
+ .globl __start
+__start:
+#ifdef FIRMWORKSBUGS
+ mfmsr 0
+ andi. 0,0,PSL_IR|PSL_DR
+ beq 1f
+
+ bl ofwr_init
+1:
+#endif
+ 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@ha
+ stw 5,openfirmware_entry@l(8) /* save client interface handler */
+ mr 3,5
+
+ lis 1,tmpstk@ha
+ addi 1,1,tmpstk@l
+ addi 1,1,8192
+
+ mfmsr 0
+ lis 9,ofmsr@ha
+ stwu 0,ofmsr@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_init
+
+ lis 4,end@ha
+ addi 4,4,end@l
+ mr 5,4
+
+ lis 3,kernel_text@ha
+ addi 3,3,kernel_text@l
+
+ /* Restore the argument pointer and length */
+ mr 6,20
+ mr 7,21
+
+ bl powerpc_init
+ 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,PC_CURTHREAD(4)
+ lwz 4,TD_PCB(4)
+ 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/powerpc/trap_subr.S>
diff --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c
new file mode 100644
index 000000000000..ed0ff8339abc
--- /dev/null
+++ b/sys/powerpc/powerpc/machdep.c
@@ -0,0 +1,995 @@
+/*-
+ * 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$");
+
+#include "opt_compat.h"
+#include "opt_ddb.h"
+#include "opt_kstack_pages.h"
+#include "opt_msgbuf.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/signalvar.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/bat.h>
+#include <machine/cpu.h>
+#include <machine/elf.h>
+#include <machine/fpu.h>
+#include <machine/md_var.h>
+#include <machine/metadata.h>
+#include <machine/mmuvar.h>
+#include <machine/pcb.h>
+#include <machine/powerpc.h>
+#include <machine/reg.h>
+#include <machine/sigframe.h>
+#include <machine/trap.h>
+#include <machine/vmparam.h>
+
+#include <ddb/ddb.h>
+
+#include <dev/ofw/openfirm.h>
+
+#ifdef DDB
+extern vm_offset_t ksym_start, ksym_end;
+#endif
+
+int cold = 1;
+
+struct pcpu __pcpu[MAXCPU];
+struct trapframe frame0;
+
+vm_offset_t kstack0;
+vm_offset_t kstack0_phys;
+
+char machine[] = "powerpc";
+SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
+
+static int cacheline_size = CACHELINESIZE;
+SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
+ CTLFLAG_RD, &cacheline_size, 0, "");
+
+static void cpu_startup(void *);
+SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
+
+void powerpc_init(u_int, u_int, u_int, void *);
+
+int save_ofw_mapping(void);
+int restore_ofw_mapping(void);
+
+void install_extint(void (*)(void));
+
+int setfault(faultbuf); /* defined in locore.S */
+
+static int grab_mcontext(struct thread *, mcontext_t *, int);
+
+void asm_panic(char *);
+
+long Maxmem = 0;
+long realmem = 0;
+
+struct pmap ofw_pmap;
+extern int ofmsr;
+
+struct bat battable[16];
+
+struct kva_md_info kmi;
+
+void setPQL2(int *const size, int *const ways);
+
+void
+setPQL2(int *const size, int *const ways)
+{
+ return;
+}
+
+static void
+powerpc_ofw_shutdown(void *junk, int howto)
+{
+ if (howto & RB_HALT) {
+ OF_halt();
+ }
+ OF_reboot();
+}
+
+static void
+cpu_startup(void *dummy)
+{
+
+ /*
+ * Initialise the decrementer-based clock.
+ */
+ decr_init();
+
+ /*
+ * Good {morning,afternoon,evening,night}.
+ */
+ cpu_setup(PCPU_GET(cpuid));
+
+ /* startrtclock(); */
+#ifdef PERFMON
+ perfmon_init();
+#endif
+ printf("real memory = %ld (%ld MB)\n", ptoa(physmem),
+ ptoa(physmem) / 1048576);
+ realmem = physmem;
+
+ /*
+ * 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) {
+ int size1 = phys_avail[indx + 1] - phys_avail[indx];
+
+ printf("0x%08x - 0x%08x, %d bytes (%d pages)\n",
+ 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();
+
+ EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0,
+ SHUTDOWN_PRI_LAST);
+
+#ifdef SMP
+ /*
+ * OK, enough kmem_alloc/malloc state should be up, lets get on with it!
+ */
+ mp_start(); /* fire up the secondaries */
+ mp_announce();
+#endif /* SMP */
+}
+
+extern char kernel_text[], _end[];
+
+extern void *trapcode, *trapsize;
+extern void *alitrap, *alisize;
+extern void *dsitrap, *dsisize;
+extern void *decrint, *decrsize;
+extern void *extint, *extsize;
+extern void *dblow, *dbsize;
+extern void *vectrap, *vectrapsize;
+
+void
+powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
+{
+ struct pcpu *pc;
+ vm_offset_t end, off;
+ void *kmdp;
+ char *env;
+
+ end = 0;
+ kmdp = NULL;
+
+ /*
+ * 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 *);
+ end = 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_linkup(&proc0, &thread0);
+ thread0.td_frame = &frame0;
+
+ /*
+ * Set up per-cpu data.
+ */
+ pc = &__pcpu[0];
+ pcpu_init(pc, 0, sizeof(struct pcpu));
+ pc->pc_curthread = &thread0;
+ pc->pc_curpcb = thread0.td_pcb;
+ pc->pc_cpuid = 0;
+
+ __asm __volatile("mtsprg 0, %0" :: "r"(pc));
+
+ mutex_init();
+
+ /*
+ * 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");
+ }
+
+ kdb_init();
+
+ kobj_machdep_init();
+
+ /*
+ * XXX: Initialize the interrupt tables.
+ * Disable translation in case the vector area
+ * hasn't been mapped (G5)
+ */
+ mtmsr(mfmsr() & ~(PSL_IR | PSL_DR));
+ isync();
+ bcopy(&trapcode, (void *)EXC_RST, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_MCHK, (size_t)&trapsize);
+ bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
+ bcopy(&trapcode, (void *)EXC_ISI, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize);
+ bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize);
+ bcopy(&trapcode, (void *)EXC_PGM, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_FPA, (size_t)&trapsize);
+ bcopy(&vectrap, (void *)EXC_VEC, (size_t)&vectrapsize);
+ bcopy(&trapcode, (void *)EXC_VECAST, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize);
+ bcopy(&trapcode, (void *)EXC_BPT, (size_t)&trapsize);
+#ifdef KDB
+ bcopy(&dblow, (void *)EXC_RST, (size_t)&dbsize);
+ bcopy(&dblow, (void *)EXC_MCHK, (size_t)&dbsize);
+ bcopy(&dblow, (void *)EXC_PGM, (size_t)&dbsize);
+ bcopy(&dblow, (void *)EXC_TRC, (size_t)&dbsize);
+ bcopy(&dblow, (void *)EXC_BPT, (size_t)&dbsize);
+#endif
+ __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
+
+ /*
+ * Make sure translation has been enabled
+ */
+ mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI);
+ isync();
+
+ /*
+ * Initialise virtual memory.
+ */
+ pmap_mmu_install(MMU_TYPE_OEA, 0); /* XXX temporary */
+ pmap_bootstrap(startkernel, endkernel);
+
+ /*
+ * 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_kstack = kstack0;
+ thread0.td_pcb = (struct pcb *)
+ (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
+
+ /*
+ * Map and initialise the message buffer.
+ */
+ for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
+ pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off);
+ msgbufinit(msgbufp, MSGBUF_SIZE);
+
+#ifdef KDB
+ if (boothowto & RB_KDB)
+ kdb_enter("Boot flags requested debugger");
+#endif
+}
+
+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
+sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
+{
+ struct trapframe *tf;
+ struct sigframe *sfp;
+ struct sigacts *psp;
+ struct sigframe sf;
+ struct thread *td;
+ struct proc *p;
+ int oonstack, rndfsize;
+ int sig;
+ int code;
+
+ td = curthread;
+ p = td->td_proc;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ sig = ksi->ksi_signo;
+ code = ksi->ksi_code;
+ psp = p->p_sigacts;
+ mtx_assert(&psp->ps_mtx, MA_OWNED);
+ tf = td->td_frame;
+ oonstack = sigonstack(tf->fixreg[1]);
+
+ rndfsize = ((sizeof(sf) + 15) / 16) * 16;
+
+ CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
+ catcher, sig);
+
+ /*
+ * 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;
+
+ /*
+ * Allocate and validate space for the signal handler context.
+ */
+ if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
+ SIGISMEMBER(psp->ps_sigonstack, sig)) {
+ sfp = (struct sigframe *)(td->td_sigstk.ss_sp +
+ td->td_sigstk.ss_size - rndfsize);
+ } else {
+ sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize);
+ }
+
+ /*
+ * Translate the signal if appropriate (Linux emu ?)
+ */
+ if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
+ sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
+
+ /*
+ * 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)sfp;
+ tf->fixreg[FIRSTARG] = sig;
+ tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc;
+ if (SIGISMEMBER(psp->ps_siginfo, sig)) {
+ /*
+ * Signal handler installed with SA_SIGINFO.
+ */
+ tf->fixreg[FIRSTARG+1] = (register_t)&sfp->sf_si;
+
+ /*
+ * Fill siginfo structure.
+ */
+ sf.sf_si = ksi->ksi_info;
+ sf.sf_si.si_signo = sig;
+ sf.sf_si.si_addr = (void *) ((tf->exc == EXC_DSI) ?
+ tf->dar : tf->srr0);
+ } else {
+ /* Old FreeBSD-style arguments. */
+ tf->fixreg[FIRSTARG+1] = code;
+ tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ?
+ tf->dar : tf->srr0;
+ }
+ mtx_unlock(&psp->ps_mtx);
+ PROC_UNLOCK(p);
+
+ tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
+
+ /*
+ * copy the frame out to userland.
+ */
+ if (copyout(&sf, sfp, sizeof(*sfp)) != 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
+sigreturn(struct thread *td, struct sigreturn_args *uap)
+{
+ struct proc *p;
+ 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);
+
+ p = td->td_proc;
+ PROC_LOCK(p);
+ td->td_sigmask = uc.uc_sigmask;
+ SIG_CANTMASK(td->td_sigmask);
+ signotify(td);
+ PROC_UNLOCK(p);
+
+ 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 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_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));
+ }
+
+ /* XXX Altivec context ? */
+
+ 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, const mcontext_t *mcp)
+{
+ struct pcb *pcb;
+ struct trapframe *tf;
+
+ 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);
+ }
+
+ memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
+
+ if (mcp->mc_flags & _MC_FP_VALID) {
+ if ((pcb->pcb_flags & PCB_FPU) != PCB_FPU) {
+ critical_enter();
+ enable_fpu(td);
+ critical_exit();
+ }
+ memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double));
+ memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double));
+ }
+
+ /* XXX Altivec context? */
+
+ return (0);
+}
+
+void
+cpu_boot(int howto)
+{
+}
+
+void
+cpu_initclocks(void)
+{
+
+ decr_tc_init();
+}
+
+/* Get current clock frequency for the given cpu id. */
+int
+cpu_est_clockrate(int cpu_id, uint64_t *rate)
+{
+
+ return (ENXIO);
+}
+
+/*
+ * Shutdown the CPU as much as possible.
+ */
+void
+cpu_halt(void)
+{
+
+ OF_exit();
+}
+
+void
+cpu_idle(void)
+{
+ /* TODO: Insert code to halt (until next interrupt) */
+
+#ifdef INVARIANTS
+ if ((mfmsr() & PSL_EE) != PSL_EE) {
+ struct thread *td = curthread;
+ printf("td msr %x\n", td->td_md.md_saved_msr);
+ panic("ints disabled in idleproc!");
+ }
+#endif
+}
+
+/*
+ * Set set up registers on exec.
+ */
+void
+exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
+{
+ struct trapframe *tf;
+ struct ps_strings arginfo;
+
+ tf = trapframe(td);
+ bzero(tf, sizeof *tf);
+ tf->fixreg[1] = -roundup(-stack + 8, 16);
+
+ /*
+ * XXX Machine-independent code has already copied arguments and
+ * XXX environment to userland. Get them back here.
+ */
+ (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo));
+
+ /*
+ * 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.
+ */
+ /*
+ * 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] = arginfo.ps_nargvstr;
+ td->td_retval[1] = (register_t)arginfo.ps_argvstr;
+ tf->fixreg[3] = arginfo.ps_nargvstr;
+ tf->fixreg[4] = (register_t)arginfo.ps_argvstr;
+ tf->fixreg[5] = (register_t)arginfo.ps_envstr;
+ tf->fixreg[6] = 0; /* auxillary vector */
+ tf->fixreg[7] = 0; /* termination vector */
+ tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */
+
+ tf->srr0 = entry;
+ tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
+ td->td_pcb->pcb_flags = 0;
+}
+
+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_FPU) == 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;
+ if ((pcb->pcb_flags & PCB_FPU) == 0)
+ enable_fpu(td);
+ memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg));
+
+ return (0);
+}
+
+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);
+}
+
+/*
+ * Initialise a struct pcpu.
+ */
+void
+cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
+{
+
+}
+
+void
+spinlock_enter(void)
+{
+ struct thread *td;
+
+ td = curthread;
+ if (td->td_md.md_spinlock_count == 0)
+ td->td_md.md_saved_msr = intr_disable();
+ td->td_md.md_spinlock_count++;
+ critical_enter();
+}
+
+void
+spinlock_exit(void)
+{
+ struct thread *td;
+
+ td = curthread;
+ critical_exit();
+ td->td_md.md_spinlock_count--;
+ if (td->td_md.md_spinlock_count == 0)
+ intr_restore(td->td_md.md_saved_msr);
+}
+
+/*
+ * kcopy(const void *src, void *dst, size_t len);
+ *
+ * Copy len bytes from src to dst, aborting if we encounter a fatal
+ * page fault.
+ *
+ * kcopy() _must_ save and restore the old fault handler since it is
+ * called by uiomove(), which may be in the path of servicing a non-fatal
+ * page fault.
+ */
+int
+kcopy(const void *src, void *dst, size_t len)
+{
+ struct thread *td;
+ faultbuf env, *oldfault;
+ int rv;
+
+ td = PCPU_GET(curthread);
+ oldfault = td->td_pcb->pcb_onfault;
+ if ((rv = setfault(env)) != 0) {
+ td->td_pcb->pcb_onfault = oldfault;
+ return rv;
+ }
+
+ memcpy(dst, src, len);
+
+ td->td_pcb->pcb_onfault = oldfault;
+ return (0);
+}
+
+void
+asm_panic(char *pstr)
+{
+ panic(pstr);
+}
+
+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);
+}
diff --git a/sys/powerpc/powerpc/mem.c b/sys/powerpc/powerpc/mem.c
new file mode 100644
index 000000000000..340fa82a8eb5
--- /dev/null
+++ b/sys/powerpc/powerpc/mem.c
@@ -0,0 +1,181 @@
+/*-
+ * 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$");
+
+/*
+ * 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/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 <machine/memdev.h>
+
+struct mem_range_softc mem_range_softc;
+
+/* 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;
+ 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 (minor(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)
+ && pmap_dev_direct_mapped(v, cnt)) {
+ error = EFAULT;
+ break;
+ }
+
+ uiomove((void *)v, cnt, uio);
+ break;
+ }
+ else if (minor(dev) == CDEV_MINOR_KMEM) {
+ va = uio->uio_offset;
+
+ if ((va < VM_MIN_KERNEL_ADDRESS)
+ || (va > VM_MAX_KERNEL_ADDRESS))
+ 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_offset_t offset, vm_paddr_t *paddr, int prot)
+{
+ /*
+ * /dev/mem is the only one that makes sense through this
+ * interface. For /dev/kmem any physaddr we return here
+ * could be transient and hence incorrect or invalid at
+ * a later time.
+ */
+ if (minor(dev) != CDEV_MINOR_MEM)
+ return (-1);
+
+ /* Only direct-mapped addresses. */
+ if (mem_valid(offset, 0)
+ && pmap_dev_direct_mapped(offset, 0))
+ return (EFAULT);
+
+ *paddr = offset;
+
+ return (0);
+}
+
+void
+dev_mem_md_init(void)
+{
+}
diff --git a/sys/powerpc/powerpc/mmu_if.m b/sys/powerpc/powerpc/mmu_if.m
new file mode 100644
index 000000000000..0fc546fb14b2
--- /dev/null
+++ b/sys/powerpc/powerpc/mmu_if.m
@@ -0,0 +1,768 @@
+#-
+# 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$
+#
+
+#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)
+ {
+ return (0);
+ }
+
+ static void mmu_null_deactivate(struct thread *td)
+ {
+ return;
+ }
+
+ static vm_offset_t mmu_null_addr_hint(mmu_t mmu, vm_object_t object,
+ vm_offset_t va, vm_size_t size)
+ {
+ return (va);
+ }
+};
+
+
+/**
+ * @brief Change the wiring attribute for the page in the given physical
+ * map and virtual address.
+ *
+ * @param _pmap physical map of page
+ * @param _va page virtual address
+ * @param _wired TRUE to increment wired count, FALSE to decrement
+ */
+METHOD void change_wiring {
+ mmu_t _mmu;
+ pmap_t _pmap;
+ vm_offset_t _va;
+ boolean_t _wired;
+};
+
+
+/**
+ * @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 'referenced' bit on the given physical page
+ *
+ * @param _pg physical page
+ */
+METHOD void clear_reference {
+ 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;
+};
+
+
+/**
+ * @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 _wired TRUE if page will be wired
+ */
+METHOD void enter {
+ mmu_t _mmu;
+ pmap_t _pmap;
+ vm_offset_t _va;
+ vm_page_t _p;
+ vm_prot_t _prot;
+ boolean_t _wired;
+};
+
+
+/**
+ * @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 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 boolean_t 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 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 PG_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 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. This routine is
+ * optional and is an optimisation: the mincore code will call is_modified
+ * and ts_referenced if no result is returned.
+ *
+ * @param _pmap physical map
+ * @param _addr page virtual 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;
+} 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 _addr initial guess at virtual address
+ * @param _size size of virtual address range
+ */
+METHOD vm_offset_t addr_hint {
+ mmu_t _mmu;
+ vm_object_t _obj;
+ vm_offset_t _addr;
+ vm_size_t _size;
+} DEFAULT mmu_null_addr_hint;
+
+
+
+
+/**
+ * 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 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_offset_t _pa;
+ vm_size_t _size;
+};
+
+
+/**
+ * @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_offset_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_offset_t _pa;
+};
+
+
+/**
+ * @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_offset_t _pa;
+ vm_size_t _size;
+};
+
+
+/**
+ * @brief Evaluate if a physical page has an executable mapping
+ *
+ * @param _pg physical page
+ *
+ * @retval bool TRUE if a physical mapping exists for the given page.
+ */
+METHOD boolean_t page_executable {
+ mmu_t _mmu;
+ vm_page_t _pg;
+};
+
diff --git a/sys/powerpc/powerpc/mmu_oea.c b/sys/powerpc/powerpc/mmu_oea.c
new file mode 100644
index 000000000000..d1a0faa9d50f
--- /dev/null
+++ b/sys/powerpc/powerpc/mmu_oea.c
@@ -0,0 +1,2522 @@
+/*-
+ * 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@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.
+ * 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.
+ */
+/*-
+ * 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$");
+
+/*
+ * Manages physical address maps.
+ *
+ * In addition to hardware address maps, this module is called upon to
+ * provide software-use-only maps which may or may not be stored in the
+ * same form as hardware maps. These pseudo-maps are used to store
+ * intermediate results from copy operations to and from address spaces.
+ *
+ * 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/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 <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/vm_pager.h>
+#include <vm/uma.h>
+
+#include <machine/cpu.h>
+#include <machine/powerpc.h>
+#include <machine/bat.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/psl.h>
+#include <machine/pte.h>
+#include <machine/sr.h>
+#include <machine/mmuvar.h>
+
+#include "mmu_if.h"
+
+#define MOEA_DEBUG
+
+#define TODO panic("%s: not implemented", __func__);
+
+#define TLBIE(va) __asm __volatile("tlbie %0" :: "r"(va))
+#define TLBSYNC() __asm __volatile("tlbsync");
+#define SYNC() __asm __volatile("sync");
+#define EIEIO() __asm __volatile("eieio");
+
+#define VSID_MAKE(sr, hash) ((sr) | (((hash) & 0xfffff) << 4))
+#define VSID_TO_SR(vsid) ((vsid) & 0xf)
+#define VSID_TO_HASH(vsid) (((vsid) >> 4) & 0xfffff)
+
+#define PVO_PTEGIDX_MASK 0x007 /* which PTEG slot */
+#define PVO_PTEGIDX_VALID 0x008 /* slot is valid */
+#define PVO_WIRED 0x010 /* PVO entry is wired */
+#define PVO_MANAGED 0x020 /* PVO entry is managed */
+#define PVO_EXECUTABLE 0x040 /* PVO entry is executable */
+#define PVO_BOOTSTRAP 0x080 /* PVO entry allocated during
+ bootstrap */
+#define PVO_FAKE 0x100 /* fictitious phys page */
+#define PVO_VADDR(pvo) ((pvo)->pvo_vaddr & ~ADDR_POFF)
+#define PVO_ISEXECUTABLE(pvo) ((pvo)->pvo_vaddr & PVO_EXECUTABLE)
+#define PVO_ISFAKE(pvo) ((pvo)->pvo_vaddr & PVO_FAKE)
+#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 MOEA_PVO_CHECK(pvo)
+
+struct ofw_map {
+ vm_offset_t om_va;
+ vm_size_t om_len;
+ vm_offset_t om_pa;
+ u_int om_mode;
+};
+
+/*
+ * Map of physical memory regions.
+ */
+static struct mem_region *regions;
+static struct mem_region *pregions;
+u_int phys_avail_count;
+int regions_sz, pregions_sz;
+static struct ofw_map *translations;
+
+extern struct pmap ofw_pmap;
+
+
+
+/*
+ * Lock for the pteg and pvo tables.
+ */
+struct mtx moea_table_mutex;
+
+/*
+ * 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 */
+struct pvo_head moea_pvo_unmanaged =
+ LIST_HEAD_INITIALIZER(moea_pvo_unmanaged); /* list of unmanaged pages */
+
+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, "");
+
+struct pvo_entry *moea_pvo_zeropage;
+struct mtx moea_pvo_zeropage_mtx;
+
+vm_offset_t moea_rkva_start = VM_MIN_KERNEL_ADDRESS;
+u_int moea_rkva_count = 4;
+
+/*
+ * 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 void moea_enter_locked(pmap_t, vm_offset_t, vm_page_t,
+ vm_prot_t, boolean_t);
+static struct pvo_entry *moea_rkva_alloc(mmu_t);
+static void moea_pa_map(struct pvo_entry *, vm_offset_t,
+ struct pte *, int *);
+static void moea_pa_unmap(struct pvo_entry *, struct pte *, int *);
+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, int *);
+static void moea_kremove(mmu_t, vm_offset_t);
+static void tlbia(void);
+int moea_pte_spill(vm_offset_t);
+
+/*
+ * Kernel MMU interface
+ */
+void moea_change_wiring(mmu_t, pmap_t, vm_offset_t, boolean_t);
+void moea_clear_modify(mmu_t, vm_page_t);
+void moea_clear_reference(mmu_t, vm_page_t);
+void moea_copy_page(mmu_t, vm_page_t, vm_page_t);
+void moea_enter(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t, boolean_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_ts_referenced(mmu_t, vm_page_t);
+vm_offset_t moea_map(mmu_t, vm_offset_t *, vm_offset_t, vm_offset_t, int);
+boolean_t moea_page_exists_quick(mmu_t, pmap_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_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_bootstrap(mmu_t, vm_offset_t, vm_offset_t);
+void *moea_mapdev(mmu_t, vm_offset_t, vm_size_t);
+void moea_unmapdev(mmu_t, vm_offset_t, vm_size_t);
+vm_offset_t moea_kextract(mmu_t, vm_offset_t);
+void moea_kenter(mmu_t, vm_offset_t, vm_offset_t);
+boolean_t moea_dev_direct_mapped(mmu_t, vm_offset_t, vm_size_t);
+boolean_t moea_page_executable(mmu_t, vm_page_t);
+
+static mmu_method_t moea_methods[] = {
+ MMUMETHOD(mmu_change_wiring, moea_change_wiring),
+ MMUMETHOD(mmu_clear_modify, moea_clear_modify),
+ MMUMETHOD(mmu_clear_reference, moea_clear_reference),
+ MMUMETHOD(mmu_copy_page, moea_copy_page),
+ 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_ts_referenced, moea_ts_referenced),
+ MMUMETHOD(mmu_map, moea_map),
+ MMUMETHOD(mmu_page_exists_quick,moea_page_exists_quick),
+ 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_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),
+
+ /* Internal interfaces */
+ MMUMETHOD(mmu_bootstrap, moea_bootstrap),
+ MMUMETHOD(mmu_mapdev, moea_mapdev),
+ MMUMETHOD(mmu_unmapdev, moea_unmapdev),
+ MMUMETHOD(mmu_kextract, moea_kextract),
+ MMUMETHOD(mmu_kenter, moea_kenter),
+ MMUMETHOD(mmu_dev_direct_mapped,moea_dev_direct_mapped),
+ MMUMETHOD(mmu_page_executable, moea_page_executable),
+
+ { 0, 0 }
+};
+
+static mmu_def_t oea_mmu = {
+ MMU_TYPE_OEA,
+ moea_methods,
+ 0
+};
+MMU_DEF(oea_mmu);
+
+
+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 *
+pa_to_pvoh(vm_offset_t pa, vm_page_t *pg_p)
+{
+ struct vm_page *pg;
+
+ pg = PHYS_TO_VM_PAGE(pa);
+
+ if (pg_p != NULL)
+ *pg_p = pg;
+
+ if (pg == NULL)
+ return (&moea_pvo_unmanaged);
+
+ return (&pg->md.mdpg_pvoh);
+}
+
+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)
+{
+
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ 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)
+{
+
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ 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);
+ EIEIO();
+ TLBSYNC();
+ SYNC();
+}
+
+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 havce
+ * 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;
+ 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.
+ */
+ SYNC();
+
+ /*
+ * Invalidate the pte.
+ */
+ pt->pte_hi &= ~PTE_VALID;
+
+ SYNC();
+ TLBIE(va);
+ EIEIO();
+ TLBSYNC();
+ SYNC();
+
+ /*
+ * 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 mr_cmp(const void *a, const void *b);
+static int om_cmp(const void *a, const void *b);
+
+static int
+mr_cmp(const void *a, const void *b)
+{
+ const struct mem_region *regiona;
+ const struct mem_region *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);
+}
+
+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_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
+{
+ ihandle_t mmui;
+ phandle_t chosen, mmu;
+ int sz;
+ int i, j;
+ int ofw_mappings;
+ vm_size_t size, physsz, hwphyssz;
+ vm_offset_t pa, va, off;
+ u_int batl, batu;
+
+ /*
+ * 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.
+ */
+ batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs);
+ batl = BATL(0x00000000, BAT_M, BAT_PP_RW);
+ __asm (".balign 32; \n"
+ "mtibatu 0,%0; mtibatl 0,%1; isync; \n"
+ "mtdbatu 0,%0; mtdbatl 0,%1; isync"
+ :: "r"(batu), "r"(batl));
+
+#if 0
+ /* map frame buffer */
+ batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs);
+ batl = BATL(0x90000000, BAT_I|BAT_G, BAT_PP_RW);
+ __asm ("mtdbatu 1,%0; mtdbatl 1,%1; isync"
+ :: "r"(batu), "r"(batl));
+#endif
+
+#if 1
+ /* map pci space */
+ batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs);
+ batl = BATL(0x80000000, BAT_I|BAT_G, BAT_PP_RW);
+ __asm ("mtdbatu 1,%0; mtdbatl 1,%1; isync"
+ :: "r"(batu), "r"(batl));
+#endif
+
+ /*
+ * Set the start and end of kva.
+ */
+ virtual_avail = VM_MIN_KERNEL_ADDRESS;
+ virtual_end = VM_MAX_KERNEL_ADDRESS;
+
+ mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
+ CTR0(KTR_PMAP, "moea_bootstrap: physical memory");
+
+ qsort(pregions, pregions_sz, sizeof(*pregions), mr_cmp);
+ 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");
+ qsort(regions, regions_sz, sizeof(*regions), mr_cmp);
+ 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;
+ }
+ 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);
+
+ /*
+ * Allocate the message buffer.
+ */
+ msgbuf_phys = moea_bootstrap_alloc(MSGBUF_SIZE, 0);
+
+ /*
+ * 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;
+
+ /*
+ * Set up the Open Firmware pmap and add it's mappings.
+ */
+ moea_pinit(mmup, &ofw_pmap);
+ ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT;
+ ofw_pmap.pm_sr[KERNEL2_SR] = KERNEL2_SEGMENT;
+ if ((chosen = OF_finddevice("/chosen")) == -1)
+ panic("moea_bootstrap: can't find /chosen");
+ OF_getprop(chosen, "mmu", &mmui, 4);
+ if ((mmu = OF_instance_to_package(mmui)) == -1)
+ panic("moea_bootstrap: can't get mmu package");
+ if ((sz = OF_getproplen(mmu, "translations")) == -1)
+ panic("moea_bootstrap: can't get ofw translation count");
+ 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, ofw_mappings = 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) {
+ struct vm_page m;
+
+ m.phys_addr = translations[i].om_pa + off;
+ PMAP_LOCK(&ofw_pmap);
+ moea_enter_locked(&ofw_pmap,
+ translations[i].om_va + off, &m,
+ VM_PROT_ALL, 1);
+ PMAP_UNLOCK(&ofw_pmap);
+ ofw_mappings++;
+ }
+ }
+#ifdef SMP
+ TLBSYNC();
+#endif
+
+ /*
+ * 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;
+ }
+ kernel_pmap->pm_sr[KERNEL_SR] = KERNEL_SEGMENT;
+ kernel_pmap->pm_sr[KERNEL2_SR] = KERNEL2_SEGMENT;
+ kernel_pmap->pm_active = ~0;
+
+ /*
+ * 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, 0);
+ kstack0_phys = pa;
+ kstack0 = virtual_avail + (KSTACK_GUARD_PAGES * PAGE_SIZE);
+ CTR2(KTR_PMAP, "moea_bootstrap: kstack0 at %#x (%#x)", kstack0_phys,
+ kstack0);
+ virtual_avail += (KSTACK_PAGES + KSTACK_GUARD_PAGES) * PAGE_SIZE;
+ for (i = 0; i < KSTACK_PAGES; i++) {
+ pa = kstack0_phys + i * PAGE_SIZE;
+ va = kstack0 + i * PAGE_SIZE;
+ moea_kenter(mmup, va, pa);
+ TLBIE(va);
+ }
+
+ /*
+ * Calculate the last available physical address.
+ */
+ for (i = 0; phys_avail[i + 2] != 0; i += 2)
+ ;
+ Maxmem = powerpc_btop(phys_avail[i + 1]);
+
+ /*
+ * Allocate virtual address space for the message buffer.
+ */
+ msgbufp = (struct msgbuf *)virtual_avail;
+ virtual_avail += round_page(MSGBUF_SIZE);
+
+ /*
+ * Initialize hardware.
+ */
+ for (i = 0; i < 16; i++) {
+ mtsrin(i << ADDR_SR_SHFT, EMPTY_SEGMENT);
+ }
+ __asm __volatile ("mtsr %0,%1"
+ :: "n"(KERNEL_SR), "r"(KERNEL_SEGMENT));
+ __asm __volatile ("mtsr %0,%1"
+ :: "n"(KERNEL2_SR), "r"(KERNEL2_SEGMENT));
+ __asm __volatile ("sync; mtsdr1 %0; isync"
+ :: "r"((u_int)moea_pteg_table | (moea_pteg_mask >> 10)));
+ tlbia();
+
+ pmap_bootstrapped++;
+}
+
+/*
+ * 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;
+
+ if ((pmr = (pmap_t)moea_kextract(mmu, (vm_offset_t)pm)) == NULL)
+ pmr = pm;
+
+ pm->pm_active |= PCPU_GET(cpumask);
+ PCPU_SET(curpmap, pmr);
+}
+
+void
+moea_deactivate(mmu_t mmu, struct thread *td)
+{
+ pmap_t pm;
+
+ pm = &td->td_proc->p_vmspace->vm_pmap;
+ pm->pm_active &= ~(PCPU_GET(cpumask));
+ PCPU_SET(curpmap, NULL);
+}
+
+void
+moea_change_wiring(mmu_t mmu, pmap_t pm, vm_offset_t va, boolean_t wired)
+{
+ struct pvo_entry *pvo;
+
+ PMAP_LOCK(pm);
+ pvo = moea_pvo_find_va(pm, va & ~ADDR_POFF, NULL);
+
+ if (pvo != NULL) {
+ if (wired) {
+ if ((pvo->pvo_vaddr & PVO_WIRED) == 0)
+ pm->pm_stats.wired_count++;
+ pvo->pvo_vaddr |= PVO_WIRED;
+ } else {
+ if ((pvo->pvo_vaddr & PVO_WIRED) != 0)
+ pm->pm_stats.wired_count--;
+ pvo->pvo_vaddr &= ~PVO_WIRED;
+ }
+ }
+ 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);
+
+ kcopy((void *)src, (void *)dst, PAGE_SIZE);
+}
+
+/*
+ * 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 pa = VM_PAGE_TO_PHYS(m);
+ caddr_t va;
+
+ if (pa < SEGMENT_LENGTH) {
+ va = (caddr_t) pa;
+ } else if (moea_initialized) {
+ if (moea_pvo_zeropage == NULL) {
+ moea_pvo_zeropage = moea_rkva_alloc(mmu);
+ mtx_init(&moea_pvo_zeropage_mtx, "pvo zero page",
+ NULL, MTX_DEF);
+ }
+ mtx_lock(&moea_pvo_zeropage_mtx);
+ moea_pa_map(moea_pvo_zeropage, pa, NULL, NULL);
+ va = (caddr_t)PVO_VADDR(moea_pvo_zeropage);
+ } else {
+ panic("moea_zero_page: can't zero pa %#x", pa);
+ }
+
+ bzero(va, PAGE_SIZE);
+
+ if (pa >= SEGMENT_LENGTH) {
+ moea_pa_unmap(moea_pvo_zeropage, NULL, NULL);
+ mtx_unlock(&moea_pvo_zeropage_mtx);
+ }
+}
+
+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);
+ caddr_t va;
+
+ if (pa < SEGMENT_LENGTH) {
+ va = (caddr_t) pa;
+ } else if (moea_initialized) {
+ if (moea_pvo_zeropage == NULL) {
+ moea_pvo_zeropage = moea_rkva_alloc(mmu);
+ mtx_init(&moea_pvo_zeropage_mtx, "pvo zero page",
+ NULL, MTX_DEF);
+ }
+ mtx_lock(&moea_pvo_zeropage_mtx);
+ moea_pa_map(moea_pvo_zeropage, pa, NULL, NULL);
+ va = (caddr_t)PVO_VADDR(moea_pvo_zeropage);
+ } else {
+ panic("moea_zero_page: can't zero pa %#x", pa);
+ }
+
+ bzero(va + off, size);
+
+ if (pa >= SEGMENT_LENGTH) {
+ moea_pa_unmap(moea_pvo_zeropage, NULL, NULL);
+ mtx_unlock(&moea_pvo_zeropage_mtx);
+ }
+}
+
+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.
+ */
+void
+moea_enter(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
+ boolean_t wired)
+{
+
+ vm_page_lock_queues();
+ PMAP_LOCK(pmap);
+ moea_enter_locked(pmap, va, m, prot, wired);
+ vm_page_unlock_queues();
+ PMAP_UNLOCK(pmap);
+}
+
+/*
+ * 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 void
+moea_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
+ boolean_t wired)
+{
+ struct pvo_head *pvo_head;
+ uma_zone_t zone;
+ vm_page_t pg;
+ u_int pte_lo, pvo_flags, was_exec, i;
+ int error;
+
+ if (!moea_initialized) {
+ pvo_head = &moea_pvo_kunmanaged;
+ zone = moea_upvo_zone;
+ pvo_flags = 0;
+ pg = NULL;
+ was_exec = PTE_EXEC;
+ } else {
+ pvo_head = vm_page_to_pvoh(m);
+ pg = m;
+ zone = moea_mpvo_zone;
+ pvo_flags = PVO_MANAGED;
+ was_exec = 0;
+ }
+ if (pmap_bootstrapped)
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+
+ /* XXX change the pvo head for fake pages */
+ if ((m->flags & PG_FICTITIOUS) == PG_FICTITIOUS)
+ pvo_head = &moea_pvo_kunmanaged;
+
+ /*
+ * If this is a managed page, and it's the first reference to the page,
+ * clear the execness of the page. Otherwise fetch the execness.
+ */
+ if ((pg != NULL) && ((m->flags & PG_FICTITIOUS) == 0)) {
+ if (LIST_EMPTY(pvo_head)) {
+ moea_attr_clear(pg, PTE_EXEC);
+ } else {
+ was_exec = moea_attr_fetch(pg) & PTE_EXEC;
+ }
+ }
+
+ /*
+ * 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 ((VM_PAGE_TO_PHYS(m) >= pregions[i].mr_start) &&
+ (VM_PAGE_TO_PHYS(m) <
+ (pregions[i].mr_start + pregions[i].mr_size))) {
+ pte_lo &= ~(PTE_I | PTE_G);
+ break;
+ }
+ }
+
+ if (prot & VM_PROT_WRITE) {
+ pte_lo |= PTE_BW;
+ if (pmap_bootstrapped)
+ vm_page_flag_set(m, PG_WRITEABLE);
+ } else
+ pte_lo |= PTE_BR;
+
+ if (prot & VM_PROT_EXECUTE)
+ pvo_flags |= PVO_EXECUTABLE;
+
+ if (wired)
+ pvo_flags |= PVO_WIRED;
+
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ pvo_flags |= PVO_FAKE;
+
+ 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 if this page is
+ * mapped executable and cacheable and was not previously mapped (or
+ * was not mapped executable).
+ */
+ if (error == 0 && (pvo_flags & PVO_EXECUTABLE) &&
+ (pte_lo & PTE_I) == 0 && was_exec == 0) {
+ /*
+ * Flush the real memory from the cache.
+ */
+ moea_syncicache(VM_PAGE_TO_PHYS(m), PAGE_SIZE);
+ if (pg != NULL)
+ moea_attr_save(pg, PTE_EXEC);
+ }
+
+ /* XXX syncicache always until problems are sorted */
+ moea_syncicache(VM_PAGE_TO_PHYS(m), PAGE_SIZE);
+}
+
+/*
+ * 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;
+
+ psize = atop(end - start);
+ m = m_start;
+ 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), FALSE);
+ m = TAILQ_NEXT(m, listq);
+ }
+ 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)
+{
+
+ PMAP_LOCK(pm);
+ moea_enter_locked(pm, va, m, prot & (VM_PROT_READ | VM_PROT_EXECUTE),
+ FALSE);
+ 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_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;
+
+ m = NULL;
+ vm_page_lock_queues();
+ PMAP_LOCK(pmap);
+ pvo = moea_pvo_find_va(pmap, va & ~ADDR_POFF, NULL);
+ if (pvo != NULL && (pvo->pvo_pte.pte_hi & PTE_VALID) &&
+ ((pvo->pvo_pte.pte_lo & PTE_PP) == PTE_RW ||
+ (prot & VM_PROT_WRITE) == 0)) {
+ m = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte_lo & PTE_RPGN);
+ vm_page_hold(m);
+ }
+ vm_page_unlock_queues();
+ PMAP_UNLOCK(pmap);
+ return (m);
+}
+
+void
+moea_init(mmu_t mmu)
+{
+
+ CTR0(KTR_PMAP, "moea_init");
+
+ 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_modified(mmu_t mmu, vm_page_t m)
+{
+
+ if ((m->flags & (PG_FICTITIOUS |PG_UNMANAGED)) != 0)
+ return (FALSE);
+
+ return (moea_query_bit(m, PTE_CHG));
+}
+
+void
+moea_clear_reference(mmu_t mmu, vm_page_t m)
+{
+
+ if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0)
+ return;
+ moea_clear_bit(m, PTE_REF, NULL);
+}
+
+void
+moea_clear_modify(mmu_t mmu, vm_page_t m)
+{
+
+ if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0)
+ return;
+ moea_clear_bit(m, PTE_CHG, NULL);
+}
+
+/*
+ * 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;
+
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
+ (m->flags & PG_WRITEABLE) == 0)
+ return;
+ lo = moea_attr_fetch(m);
+ SYNC();
+ LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+ pmap = pvo->pvo_pmap;
+ PMAP_LOCK(pmap);
+ if ((pvo->pvo_pte.pte_lo & PTE_PP) != PTE_BR) {
+ pt = moea_pvo_to_pte(pvo, -1);
+ pvo->pvo_pte.pte_lo &= ~PTE_PP;
+ pvo->pvo_pte.pte_lo |= PTE_BR;
+ if (pt != NULL) {
+ moea_pte_synch(pt, &pvo->pvo_pte);
+ lo |= pvo->pvo_pte.pte_lo;
+ pvo->pvo_pte.pte_lo &= ~PTE_CHG;
+ moea_pte_change(pt, &pvo->pvo_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_flag_clear(m, PG_WRITEABLE);
+}
+
+/*
+ * 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.
+ */
+boolean_t
+moea_ts_referenced(mmu_t mmu, vm_page_t m)
+{
+ int count;
+
+ if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0)
+ return (0);
+
+ count = moea_clear_bit(m, PTE_REF, NULL);
+
+ return (count);
+}
+
+/*
+ * Map a wired page into kernel virtual address space.
+ */
+void
+moea_kenter(mmu_t mmu, vm_offset_t va, vm_offset_t pa)
+{
+ u_int pte_lo;
+ int error;
+ int i;
+
+#if 0
+ if (va < VM_MIN_KERNEL_ADDRESS)
+ panic("moea_kenter: attempt to enter non-kernel address %#x",
+ va);
+#endif
+
+ 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_I | PTE_G);
+ break;
+ }
+ }
+
+ 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);
+
+ /*
+ * Flush the real memory from the instruction cache.
+ */
+ if ((pte_lo & (PTE_I | PTE_G)) == 0) {
+ moea_syncicache(pa, PAGE_SIZE);
+ }
+ PMAP_UNLOCK(kernel_pmap);
+}
+
+/*
+ * Extract the physical page address associated with the given kernel virtual
+ * address.
+ */
+vm_offset_t
+moea_kextract(mmu_t mmu, vm_offset_t va)
+{
+ struct pvo_entry *pvo;
+ vm_paddr_t pa;
+
+#ifdef UMA_MD_SMALL_ALLOC
+ /*
+ * Allow direct mappings
+ */
+ if (va < VM_MIN_KERNEL_ADDRESS) {
+ return (va);
+ }
+#endif
+
+ 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_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_offset_t pa_start,
+ vm_offset_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;
+
+ if (!moea_initialized || (m->flags & PG_FICTITIOUS))
+ return FALSE;
+
+ loops = 0;
+ LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+ if (pvo->pvo_pmap == pmap)
+ return (TRUE);
+ if (++loops >= 16)
+ break;
+ }
+
+ return (FALSE);
+}
+
+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"));
+ PMAP_LOCK_INIT(pmap);
+
+ entropy = 0;
+ __asm __volatile("mftb %0" : "=r"(entropy));
+
+ /*
+ * 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[i]) - 1;
+ mask = 1 << i;
+ hash &= 0xfffff & ~(VSID_NBPW - 1);
+ hash |= i;
+ }
+ moea_vsid_bitmap[n] |= mask;
+ for (i = 0; i < 16; i++)
+ pmap->pm_sr[i] = VSID_MAKE(i, hash);
+ return;
+ }
+
+ panic("moea_pinit: out of segments");
+}
+
+/*
+ * Initialize the pmap associated with process 0.
+ */
+void
+moea_pinit0(mmu_t mmu, pmap_t 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;
+ struct pte *pt;
+ int pteidx;
+
+ CTR4(KTR_PMAP, "moea_protect: pm=%p sva=%#x eva=%#x prot=%#x", pm, sva,
+ eva, prot);
+
+
+ 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;
+ }
+
+ vm_page_lock_queues();
+ PMAP_LOCK(pm);
+ for (; sva < eva; sva += PAGE_SIZE) {
+ pvo = moea_pvo_find_va(pm, sva, &pteidx);
+ if (pvo == NULL)
+ continue;
+
+ if ((prot & VM_PROT_EXECUTE) == 0)
+ pvo->pvo_vaddr &= ~PVO_EXECUTABLE;
+
+ /*
+ * Grab the PTE pointer before we diddle with the cached PTE
+ * copy.
+ */
+ pt = moea_pvo_to_pte(pvo, pteidx);
+ /*
+ * Change the protection of the page.
+ */
+ pvo->pvo_pte.pte_lo &= ~PTE_PP;
+ pvo->pvo_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, pvo->pvo_vaddr);
+ mtx_unlock(&moea_table_mutex);
+ }
+ }
+ vm_page_unlock_queues();
+ 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");
+
+ idx = VSID_TO_HASH(pmap->pm_sr[0]) & (NPMAPS-1);
+ mask = 1 << (idx % VSID_NBPW);
+ idx /= VSID_NBPW;
+ moea_vsid_bitmap[idx] &= ~mask;
+ PMAP_LOCK_DESTROY(pmap);
+}
+
+/*
+ * 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;
+ int pteidx;
+
+ vm_page_lock_queues();
+ PMAP_LOCK(pm);
+ for (; sva < eva; sva += PAGE_SIZE) {
+ pvo = moea_pvo_find_va(pm, sva, &pteidx);
+ if (pvo != NULL) {
+ moea_pvo_remove(pvo, pteidx);
+ }
+ }
+ PMAP_UNLOCK(pm);
+ vm_page_unlock_queues();
+}
+
+/*
+ * 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;
+
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+
+ 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);
+
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+ pmap = pvo->pvo_pmap;
+ PMAP_LOCK(pmap);
+ moea_pvo_remove(pvo, -1);
+ PMAP_UNLOCK(pmap);
+ }
+ vm_page_flag_clear(m, PG_WRITEABLE);
+}
+
+/*
+ * 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");
+}
+
+/*
+ * Return an unmapped pvo for a kernel virtual address.
+ * Used by pmap functions that operate on physical pages.
+ */
+static struct pvo_entry *
+moea_rkva_alloc(mmu_t mmu)
+{
+ struct pvo_entry *pvo;
+ struct pte *pt;
+ vm_offset_t kva;
+ int pteidx;
+
+ if (moea_rkva_count == 0)
+ panic("moea_rkva_alloc: no more reserved KVAs");
+
+ kva = moea_rkva_start + (PAGE_SIZE * --moea_rkva_count);
+ moea_kenter(mmu, kva, 0);
+
+ pvo = moea_pvo_find_va(kernel_pmap, kva, &pteidx);
+
+ if (pvo == NULL)
+ panic("moea_kva_alloc: moea_pvo_find_va failed");
+
+ pt = moea_pvo_to_pte(pvo, pteidx);
+
+ if (pt == NULL)
+ panic("moea_kva_alloc: moea_pvo_to_pte failed");
+
+ moea_pte_unset(pt, &pvo->pvo_pte, pvo->pvo_vaddr);
+ mtx_unlock(&moea_table_mutex);
+ PVO_PTEGIDX_CLR(pvo);
+
+ moea_pte_overflow++;
+
+ return (pvo);
+}
+
+static void
+moea_pa_map(struct pvo_entry *pvo, vm_offset_t pa, struct pte *saved_pt,
+ int *depth_p)
+{
+ struct pte *pt;
+
+ /*
+ * If this pvo already has a valid pte, we need to save it so it can
+ * be restored later. We then just reload the new PTE over the old
+ * slot.
+ */
+ if (saved_pt != NULL) {
+ pt = moea_pvo_to_pte(pvo, -1);
+
+ if (pt != NULL) {
+ moea_pte_unset(pt, &pvo->pvo_pte, pvo->pvo_vaddr);
+ mtx_unlock(&moea_table_mutex);
+ PVO_PTEGIDX_CLR(pvo);
+ moea_pte_overflow++;
+ }
+
+ *saved_pt = pvo->pvo_pte;
+
+ pvo->pvo_pte.pte_lo &= ~PTE_RPGN;
+ }
+
+ pvo->pvo_pte.pte_lo |= pa;
+
+ if (!moea_pte_spill(pvo->pvo_vaddr))
+ panic("moea_pa_map: could not spill pvo %p", pvo);
+
+ if (depth_p != NULL)
+ (*depth_p)++;
+}
+
+static void
+moea_pa_unmap(struct pvo_entry *pvo, struct pte *saved_pt, int *depth_p)
+{
+ struct pte *pt;
+
+ pt = moea_pvo_to_pte(pvo, -1);
+
+ if (pt != NULL) {
+ moea_pte_unset(pt, &pvo->pvo_pte, pvo->pvo_vaddr);
+ mtx_unlock(&moea_table_mutex);
+ PVO_PTEGIDX_CLR(pvo);
+ moea_pte_overflow++;
+ }
+
+ pvo->pvo_pte.pte_lo &= ~PTE_RPGN;
+
+ /*
+ * If there is a saved PTE and it's valid, restore it and return.
+ */
+ if (saved_pt != NULL && (saved_pt->pte_lo & PTE_RPGN) != 0) {
+ if (depth_p != NULL && --(*depth_p) == 0)
+ panic("moea_pa_unmap: restoring but depth == 0");
+
+ pvo->pvo_pte = *saved_pt;
+
+ if (!moea_pte_spill(pvo->pvo_vaddr))
+ panic("moea_pa_unmap: could not spill pvo %p", pvo);
+ }
+}
+
+static void
+moea_syncicache(vm_offset_t pa, vm_size_t len)
+{
+ __syncicache((void *)pa, len);
+}
+
+static void
+tlbia(void)
+{
+ caddr_t i;
+
+ SYNC();
+ for (i = 0; i < (caddr_t)0x00040000; i += 0x00001000) {
+ TLBIE(i);
+ EIEIO();
+ }
+ TLBSYNC();
+ SYNC();
+}
+
+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_lo & PTE_RPGN) == pa &&
+ (pvo->pvo_pte.pte_lo & PTE_PP) ==
+ (pte_lo & PTE_PP)) {
+ mtx_unlock(&moea_table_mutex);
+ 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 & VM_PROT_EXECUTE)
+ pvo->pvo_vaddr |= PVO_EXECUTABLE;
+ 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;
+ if (flags & PVO_FAKE)
+ pvo->pvo_vaddr |= PVO_FAKE;
+
+ moea_pte_create(&pvo->pvo_pte, sr, va, pa | pte_lo);
+
+ /*
+ * 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_lo & PVO_WIRED)
+ pm->pm_stats.wired_count++;
+ pm->pm_stats.resident_count++;
+
+ /*
+ * We hope this succeeds but it isn't required.
+ */
+ i = moea_pte_insert(ptegidx, &pvo->pvo_pte);
+ 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, 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_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_FAKE)) == PVO_MANAGED) {
+ struct vm_page *pg;
+
+ pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte_lo & PTE_RPGN);
+ if (pg != NULL) {
+ moea_attr_save(pg, pvo->pvo_pte.pte_lo &
+ (PTE_REF | PTE_CHG));
+ }
+ }
+
+ /*
+ * Remove this PVO from the PV list.
+ */
+ LIST_REMOVE(pvo, pvo_vlink);
+
+ /*
+ * 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_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_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_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_hi & ~PTE_VALID)) == PTE_VALID) {
+ if ((pvo->pvo_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_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_hi & PTE_VALID) {
+ panic("moea_pvo_to_pte: pvo %p has invalid pte %p in "
+ "moea_pteg_table but valid in pvo", pvo, pt);
+ }
+
+ 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.
+ */
+ MOEA_PVO_CHECK(pvo);
+ if (source_pvo == NULL &&
+ moea_pte_match(&pvo->pvo_pte, sr, addr,
+ pvo->pvo_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);
+
+ if (j >= 0) {
+ PVO_PTEGIDX_SET(pvo, j);
+ moea_pte_overflow--;
+ MOEA_PVO_CHECK(pvo);
+ 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)) {
+ 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) {
+ MOEA_PVO_CHECK(pvo);
+ /*
+ * 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)) {
+ 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_hi &= ~PTE_HID;
+
+ moea_pte_unset(pt, &victim_pvo->pvo_pte, victim_pvo->pvo_vaddr);
+ moea_pte_set(pt, &source_pvo->pvo_pte);
+
+ PVO_PTEGIDX_CLR(victim_pvo);
+ PVO_PTEGIDX_SET(source_pvo, i);
+ moea_pte_replacements++;
+
+ MOEA_PVO_CHECK(victim_pvo);
+ MOEA_PVO_CHECK(source_pvo);
+
+ mtx_unlock(&moea_table_mutex);
+ return (1);
+}
+
+static int
+moea_pte_insert(u_int ptegidx, struct pte *pvo_pt)
+{
+ struct pte *pt;
+ int i;
+
+ 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);
+ }
+ }
+
+ panic("moea_pte_insert: overflow");
+ return (-1);
+}
+
+static boolean_t
+moea_query_bit(vm_page_t m, int ptebit)
+{
+ struct pvo_entry *pvo;
+ struct pte *pt;
+
+#if 0
+ if (moea_attr_fetch(m) & ptebit)
+ return (TRUE);
+#endif
+
+ LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+
+ /*
+ * See if we saved the bit off. If so, cache it and return
+ * success.
+ */
+ if (pvo->pvo_pte.pte_lo & ptebit) {
+ moea_attr_save(m, ptebit);
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+ 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.
+ */
+ SYNC();
+ LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+
+ /*
+ * 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);
+ mtx_unlock(&moea_table_mutex);
+ if (pvo->pvo_pte.pte_lo & ptebit) {
+ moea_attr_save(m, ptebit);
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+ return (TRUE);
+ }
+ }
+ }
+
+ return (FALSE);
+}
+
+static u_int
+moea_clear_bit(vm_page_t m, int ptebit, int *origbit)
+{
+ u_int count;
+ struct pvo_entry *pvo;
+ struct pte *pt;
+ int rv;
+
+ /*
+ * Clear the cached value.
+ */
+ rv = moea_attr_fetch(m);
+ 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.
+ */
+ 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) {
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+ pt = moea_pvo_to_pte(pvo, -1);
+ if (pt != NULL) {
+ moea_pte_synch(pt, &pvo->pvo_pte);
+ if (pvo->pvo_pte.pte_lo & ptebit) {
+ count++;
+ moea_pte_clear(pt, PVO_VADDR(pvo), ptebit);
+ }
+ mtx_unlock(&moea_table_mutex);
+ }
+ rv |= pvo->pvo_pte.pte_lo;
+ pvo->pvo_pte.pte_lo &= ~ptebit;
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+ }
+
+ if (origbit != NULL) {
+ *origbit = rv;
+ }
+
+ 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_offset_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);
+}
+
+boolean_t
+moea_page_executable(mmu_t mmu, vm_page_t pg)
+{
+ return ((moea_attr_fetch(pg) & PTE_EXEC) == PTE_EXEC);
+}
+
+/*
+ * 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_offset_t pa, vm_size_t size)
+{
+ vm_offset_t va, tmpva, ppa, offset;
+ int i;
+
+ ppa = trunc_page(pa);
+ offset = pa & PAGE_MASK;
+ size = roundup(offset + size, PAGE_SIZE);
+
+ GIANT_REQUIRED;
+
+ /*
+ * 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 = kmem_alloc_nofault(kernel_map, size);
+ if (!va)
+ panic("moea_mapdev: Couldn't alloc kernel virtual memory");
+
+ for (tmpva = va; size > 0;) {
+ moea_kenter(mmu, tmpva, ppa);
+ TLBIE(tmpva); /* XXX or should it be invalidate-all ? */
+ 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 <= VM_MAX_KERNEL_ADDRESS)) {
+ base = trunc_page(va);
+ offset = va & PAGE_MASK;
+ size = roundup(offset + size, PAGE_SIZE);
+ kmem_free(kernel_map, base, size);
+ }
+}
diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c
new file mode 100644
index 000000000000..f76eedf58e3a
--- /dev/null
+++ b/sys/powerpc/powerpc/mp_machdep.c
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2000 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$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ktr.h>
+#include <sys/proc.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/kernel.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+
+#include <machine/atomic.h>
+#include <machine/pmap.h>
+
+int boot_cpu_id;
+
+void
+cpu_mp_setmaxid(void)
+{
+}
+
+int
+cpu_mp_probe(void)
+{
+ all_cpus = 1; /* needed for MB init code */
+ return 0;
+}
+
+void
+cpu_mp_start(void)
+{
+}
+
+void
+cpu_mp_announce(void)
+{
+}
diff --git a/sys/powerpc/powerpc/nexus.c b/sys/powerpc/powerpc/nexus.c
new file mode 100644
index 000000000000..e31ef61a813c
--- /dev/null
+++ b/sys/powerpc/powerpc/nexus.c
@@ -0,0 +1,487 @@
+/*-
+ * 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.
+ */
+/*-
+ * Copyright 2001 by Thomas Moestl <tmm@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.
+ *
+ * from: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09
+ *
+ * $FreeBSD$
+ */
+#include "opt_psim.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/frame.h>
+#include <machine/intr_machdep.h>
+#include <machine/nexusvar.h>
+#include <machine/resource.h>
+
+#include <sys/rman.h>
+
+#include "ofw_bus_if.h"
+#include "pic_if.h"
+
+/*
+ * The nexus (which is a pseudo-bus actually) iterates over the nodes that
+ * exist in Open Firmware and adds them as devices to this bus so that drivers
+ * can be attached to them.
+ *
+ * Maybe this code should get into dev/ofw to some extent, as some of it should
+ * work for all Open Firmware based machines...
+ */
+
+static MALLOC_DEFINE(M_NEXUS, "nexus", "nexus device information");
+
+struct nexus_devinfo {
+ phandle_t ndi_node;
+ /* Some common properties. */
+ const char *ndi_name;
+ const char *ndi_device_type;
+ const char *ndi_compatible;
+};
+
+struct nexus_softc {
+ struct rman sc_rman;
+};
+
+/*
+ * Device interface
+ */
+static int nexus_probe(device_t);
+static void nexus_probe_nomatch(device_t, device_t);
+
+/*
+ * Bus interface
+ */
+static device_t nexus_add_child(device_t, int, const char *, int);
+static int nexus_read_ivar(device_t, device_t, int, uintptr_t *);
+static int nexus_write_ivar(device_t, device_t, int, uintptr_t);
+static int nexus_setup_intr(device_t, device_t, struct resource *, int,
+ driver_filter_t *, driver_intr_t *, void *, void **);
+static int nexus_teardown_intr(device_t, device_t, struct resource *,
+ void *);
+static struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
+ u_long, u_long, u_long, u_int);
+static int nexus_activate_resource(device_t, device_t, int, int,
+ struct resource *);
+static int nexus_deactivate_resource(device_t, device_t, int, int,
+ struct resource *);
+static int nexus_release_resource(device_t, device_t, int, int,
+ struct resource *);
+
+static phandle_t nexus_ofw_get_node(device_t, device_t);
+static const char *nexus_ofw_get_name(device_t, device_t);
+static const char *nexus_ofw_get_type(device_t, device_t);
+static const char *nexus_ofw_get_compat(device_t, device_t);
+
+/*
+ * Local routines
+ */
+static device_t nexus_device_from_node(device_t, phandle_t);
+
+static device_method_t nexus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, nexus_probe),
+ DEVMETHOD(device_attach, bus_generic_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. Resource management is business of the children... */
+ DEVMETHOD(bus_add_child, nexus_add_child),
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch),
+ DEVMETHOD(bus_read_ivar, nexus_read_ivar),
+ DEVMETHOD(bus_write_ivar, nexus_write_ivar),
+ DEVMETHOD(bus_setup_intr, nexus_setup_intr),
+ DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
+ DEVMETHOD(bus_activate_resource, nexus_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
+ DEVMETHOD(bus_release_resource, nexus_release_resource),
+
+ /* OFW bus interface */
+ DEVMETHOD(ofw_bus_get_node, nexus_ofw_get_node),
+ DEVMETHOD(ofw_bus_get_name, nexus_ofw_get_name),
+ DEVMETHOD(ofw_bus_get_type, nexus_ofw_get_type),
+ DEVMETHOD(ofw_bus_get_compat, nexus_ofw_get_compat),
+
+ { 0, 0 }
+};
+
+static driver_t nexus_driver = {
+ "nexus",
+ nexus_methods,
+ sizeof(struct nexus_softc),
+};
+
+static devclass_t nexus_devclass;
+
+DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
+
+static int
+nexus_probe(device_t dev)
+{
+ phandle_t root;
+ phandle_t child;
+ struct nexus_softc *sc;
+ u_long start, end;
+
+ if ((root = OF_peer(0)) == -1)
+ panic("nexus_probe: OF_peer failed.");
+
+ sc = device_get_softc(dev);
+
+ start = 0;
+ end = INTR_VECTORS - 1;
+
+ sc->sc_rman.rm_start = start;
+ sc->sc_rman.rm_end = end;
+ sc->sc_rman.rm_type = RMAN_ARRAY;
+ sc->sc_rman.rm_descr = "Interrupt request lines";
+ if (rman_init(&sc->sc_rman) ||
+ rman_manage_region(&sc->sc_rman, start, end))
+ panic("nexus_probe IRQ rman");
+
+ /*
+ * Allow devices to identify
+ */
+ bus_generic_probe(dev);
+
+ /*
+ * Now walk the OFW tree to locate top-level devices
+ */
+ for (child = OF_child(root); child != 0; child = OF_peer(child)) {
+ if (child == -1)
+ panic("nexus_probe(): OF_child failed.");
+ (void)nexus_device_from_node(dev, child);
+
+ }
+ device_set_desc(dev, "Open Firmware Nexus device");
+ return (0);
+}
+
+static void
+nexus_probe_nomatch(device_t dev, device_t child)
+{
+ char *name, *type;
+
+ if (BUS_READ_IVAR(dev, child, NEXUS_IVAR_NAME,
+ (uintptr_t *)&name) != 0 ||
+ BUS_READ_IVAR(dev, child, NEXUS_IVAR_DEVICE_TYPE,
+ (uintptr_t *)&type) != 0)
+ return;
+
+ if (type == NULL)
+ type = "(unknown)";
+
+ if (bootverbose)
+ device_printf(dev, "<%s>, type %s (no driver attached)\n",
+ name, type);
+}
+
+static device_t
+nexus_add_child(device_t dev, int order, const char *name, int unit)
+{
+ device_t child;
+ struct nexus_devinfo *dinfo;
+
+ child = device_add_child_ordered(dev, order, name, unit);
+ if (child == NULL)
+ return (NULL);
+
+ dinfo = malloc(sizeof(struct nexus_devinfo), M_NEXUS, M_NOWAIT|M_ZERO);
+ if (dinfo == NULL)
+ return (NULL);
+
+ dinfo->ndi_node = -1;
+ dinfo->ndi_name = name;
+ device_set_ivars(child, dinfo);
+
+ return (child);
+}
+
+
+static int
+nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct nexus_devinfo *dinfo;
+
+ if ((dinfo = device_get_ivars(child)) == 0)
+ return (ENOENT);
+ switch (which) {
+ case NEXUS_IVAR_NODE:
+ *result = dinfo->ndi_node;
+ break;
+ case NEXUS_IVAR_NAME:
+ *result = (uintptr_t)dinfo->ndi_name;
+ break;
+ case NEXUS_IVAR_DEVICE_TYPE:
+ *result = (uintptr_t)dinfo->ndi_device_type;
+ break;
+ case NEXUS_IVAR_COMPATIBLE:
+ *result = (uintptr_t)dinfo->ndi_compatible;
+ break;
+ default:
+ return (ENOENT);
+ }
+ return 0;
+}
+
+static int
+nexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct nexus_devinfo *dinfo;
+
+ if ((dinfo = device_get_ivars(child)) == 0)
+ return (ENOENT);
+
+ switch (which) {
+ case NEXUS_IVAR_NAME:
+ return (EINVAL);
+
+ /* Identified devices may want to set these */
+ case NEXUS_IVAR_NODE:
+ dinfo->ndi_node = (phandle_t)value;
+ break;
+
+ case NEXUS_IVAR_DEVICE_TYPE:
+ dinfo->ndi_device_type = (char *)value;
+ break;
+
+ default:
+ return (ENOENT);
+ }
+ return 0;
+}
+
+static int
+nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
+ driver_filter_t *filter, driver_intr_t *ihand, void *arg, void **cookiep)
+{
+ driver_t *driver;
+ int error;
+
+ /* somebody tried to setup an irq that failed to allocate! */
+ if (res == NULL)
+ panic("nexus_setup_intr: NULL irq resource!");
+
+ *cookiep = 0;
+ if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
+ flags |= INTR_EXCL;
+
+ driver = device_get_driver(child);
+
+ /*
+ * We depend here on rman_activate_resource() being idempotent.
+ */
+ error = rman_activate_resource(res);
+ if (error)
+ return (error);
+
+ error = powerpc_setup_intr(device_get_nameunit(child),
+ rman_get_start(res), filter, ihand, arg, flags, cookiep);
+
+ return (error);
+}
+
+static int
+nexus_teardown_intr(device_t dev, device_t child, struct resource *res,
+ void *cookie)
+{
+
+ return (powerpc_teardown_intr(cookie));
+}
+
+/*
+ * Allocate resources at the behest of a child. This only handles interrupts,
+ * since I/O resources are handled by child busses.
+ */
+static struct resource *
+nexus_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 nexus_softc *sc;
+ struct resource *rv;
+
+ if (type != SYS_RES_IRQ) {
+ device_printf(bus, "unknown resource request from %s\n",
+ device_get_nameunit(child));
+ return (NULL);
+ }
+
+ if (count == 0 || start + count - 1 != end) {
+ device_printf(bus, "invalid IRQ allocation from %s\n",
+ device_get_nameunit(child));
+ return (NULL);
+ }
+
+ sc = device_get_softc(bus);
+
+ rv = rman_reserve_resource(&sc->sc_rman, start, end, count,
+ flags, child);
+ if (rv == NULL) {
+ device_printf(bus, "IRQ allocation failed for %s\n",
+ device_get_nameunit(child));
+ } else
+ rman_set_rid(rv, *rid);
+
+ return (rv);
+}
+
+static int
+nexus_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+
+ /* Not much to be done yet... */
+ return (rman_activate_resource(res));
+}
+
+static int
+nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+
+ /* Not much to be done yet... */
+ return (rman_deactivate_resource(res));
+}
+
+static int
+nexus_release_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+
+ if (type != SYS_RES_IRQ) {
+ device_printf(bus, "unknown resource request from %s\n",
+ device_get_nameunit(child));
+ return (EINVAL);
+ }
+
+ return (rman_release_resource(res));
+}
+
+static device_t
+nexus_device_from_node(device_t parent, phandle_t node)
+{
+ device_t cdev;
+ struct nexus_devinfo *dinfo;
+ char *name, *type, *compatible;
+
+ OF_getprop_alloc(node, "name", 1, (void **)&name);
+ OF_getprop_alloc(node, "device_type", 1, (void **)&type);
+ OF_getprop_alloc(node, "compatible", 1, (void **)&compatible);
+ cdev = device_add_child(parent, NULL, -1);
+ if (cdev != NULL) {
+ dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK);
+ dinfo->ndi_node = node;
+ dinfo->ndi_name = name;
+ dinfo->ndi_device_type = type;
+ dinfo->ndi_compatible = compatible;
+ device_set_ivars(cdev, dinfo);
+ } else
+ free(name, M_OFWPROP);
+
+ return (cdev);
+}
+
+static const char *
+nexus_ofw_get_name(device_t bus, device_t dev)
+{
+ struct nexus_devinfo *dinfo;
+
+ if ((dinfo = device_get_ivars(dev)) == NULL)
+ return (NULL);
+
+ return (dinfo->ndi_name);
+}
+
+static phandle_t
+nexus_ofw_get_node(device_t bus, device_t dev)
+{
+ struct nexus_devinfo *dinfo;
+
+ if ((dinfo = device_get_ivars(dev)) == NULL)
+ return (0);
+
+ return (dinfo->ndi_node);
+}
+
+static const char *
+nexus_ofw_get_type(device_t bus, device_t dev)
+{
+ struct nexus_devinfo *dinfo;
+
+ if ((dinfo = device_get_ivars(dev)) == NULL)
+ return (NULL);
+
+ return (dinfo->ndi_device_type);
+}
+
+static const char *
+nexus_ofw_get_compat(device_t bus, device_t dev)
+{
+ struct nexus_devinfo *dinfo;
+
+ if ((dinfo = device_get_ivars(dev)) == NULL)
+ return (NULL);
+
+ return (dinfo->ndi_compatible);
+}
diff --git a/sys/powerpc/powerpc/ofw_machdep.c b/sys/powerpc/powerpc/ofw_machdep.c
new file mode 100644
index 000000000000..d63236f9bda8
--- /dev/null
+++ b/sys/powerpc/powerpc/ofw_machdep.c
@@ -0,0 +1,436 @@
+/*-
+ * 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$");
+
+#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/stat.h>
+
+#include <net/ethernet.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_page.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+#include <machine/powerpc.h>
+#include <machine/ofw_machdep.h>
+#include <powerpc/ofw/ofw_pci.h>
+
+#define OFMEM_REGIONS 32
+static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3];
+static struct mem_region OFfree[OFMEM_REGIONS + 3];
+
+extern register_t ofmsr[5];
+extern struct pcpu __pcpu[MAXCPU];
+extern struct pmap ofw_pmap;
+static int (*ofwcall)(void *);
+
+/*
+ * Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback.
+ */
+register_t ofw_sprg0_save;
+
+static __inline void
+ofw_sprg_prepare(void)
+{
+ /*
+ * 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)
+{
+ /*
+ * 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));
+}
+
+/*
+ * 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)
+{
+ int end;
+ end = imax(to->mr_start + to->mr_size, from->mr_start + from->mr_size);
+ to->mr_start = imin(from->mr_start, to->mr_start);
+ to->mr_size = end - to->mr_start;
+}
+
+/*
+ * 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
+mem_regions(struct mem_region **memp, int *memsz,
+ struct mem_region **availp, int *availsz)
+{
+ int phandle;
+ int asz, msz, fsz;
+ int i, j;
+ int still_merging;
+
+ /*
+ * Get memory.
+ */
+ if ((phandle = OF_finddevice("/memory")) == -1
+ || (msz = OF_getprop(phandle, "reg",
+ OFmem, sizeof OFmem[0] * OFMEM_REGIONS))
+ <= 0
+ || (asz = OF_getprop(phandle, "available",
+ OFavail, sizeof OFavail[0] * OFMEM_REGIONS))
+ <= 0)
+ panic("no memory?");
+ *memp = OFmem;
+ *memsz = msz / sizeof(struct mem_region);
+
+ /*
+ * OFavail may have overlapping regions - collapse these
+ * and copy out remaining regions to OFfree
+ */
+ asz /= sizeof(struct mem_region);
+ do {
+ still_merging = FALSE;
+ for (i = 0; i < asz; i++) {
+ if (OFavail[i].mr_size == 0)
+ continue;
+ for (j = i+1; j < asz; j++) {
+ if (OFavail[j].mr_size == 0)
+ continue;
+ if (memr_overlap(&OFavail[j], &OFavail[i])) {
+ memr_merge(&OFavail[j], &OFavail[i]);
+ /* mark inactive */
+ OFavail[j].mr_size = 0;
+ still_merging = TRUE;
+ }
+ }
+ }
+ } while (still_merging == TRUE);
+
+ /* evict inactive ranges */
+ for (i = 0, fsz = 0; i < asz; i++) {
+ if (OFavail[i].mr_size != 0) {
+ OFfree[fsz] = OFavail[i];
+ fsz++;
+ }
+ }
+
+ *availp = OFfree;
+ *availsz = fsz;
+}
+
+void
+set_openfirm_callback(int (*openfirm)(void *))
+{
+
+ ofwcall = openfirm;
+}
+
+int
+openfirmware(void *args)
+{
+ long oldmsr;
+ int result;
+ u_int srsave[16];
+ u_int i;
+
+ __asm __volatile( "\t"
+ "sync\n\t"
+ "mfmsr %0\n\t"
+ "mtmsr %1\n\t"
+ "isync\n"
+ : "=r" (oldmsr)
+ : "r" (ofmsr[0])
+ );
+
+ ofw_sprg_prepare();
+
+ if (pmap_bootstrapped) {
+ /*
+ * Swap the kernel's address space with Open Firmware's
+ */
+ for (i = 0; i < 16; i++) {
+ srsave[i] = mfsrin(i << ADDR_SR_SHFT);
+ mtsrin(i << ADDR_SR_SHFT, ofw_pmap.pm_sr[i]);
+ }
+
+ /*
+ * Clear battable[] translations
+ */
+ __asm __volatile("mtdbatu 2, %0\n"
+ "mtdbatu 3, %0" : : "r" (0));
+ isync();
+ }
+
+ result = ofwcall(args);
+
+ if (pmap_bootstrapped) {
+ /*
+ * Restore the kernel's addr space. The isync() doesn;t
+ * work outside the loop unless mtsrin() is open-coded
+ * in an asm statement :(
+ */
+ for (i = 0; i < 16; i++) {
+ mtsrin(i << ADDR_SR_SHFT, srsave[i]);
+ isync();
+ }
+ }
+
+ ofw_sprg_restore();
+
+ __asm( "\t"
+ "mtmsr %0\n\t"
+ "isync\n"
+ : : "r" (oldmsr)
+ );
+
+ return (result);
+}
+
+void
+OF_halt()
+{
+ int retval; /* dummy, this may not be needed */
+
+ OF_interpret("shut-down", 1, &retval);
+ for (;;); /* just in case */
+}
+
+void
+OF_reboot()
+{
+ int retval; /* dummy, this may not be needed */
+
+ OF_interpret("reset-all", 1, &retval);
+ for (;;); /* just in case */
+}
+
+void
+OF_getetheraddr(device_t dev, u_char *addr)
+{
+ phandle_t node;
+
+ node = ofw_pci_find_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 name[16];
+ 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, "name", name, sizeof(name));
+ if (res != -1) {
+ name[sizeof(name) - 1] = '\0';
+ pci = (strcmp(name, "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;
+ 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);
+
+ /* Get the requested register. */
+ OF_get_addr_props(bridge, &naddr, &nsize, &pci);
+ 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;
+ 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);
+ 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);
+ }
+
+ /* Default to memory mapped I/O. */
+ *tag = PPC_BUS_SPACE_MEM;
+ if (spc == OFW_PCI_PHYS_HI_SPACE_IO)
+ *tag = PPC_BUS_SPACE_IO;
+ return (bus_space_map(*tag, addr, size, 0, handle));
+}
+
+int
+mem_valid(vm_offset_t addr, int len)
+{
+ int i;
+
+ for (i = 0; i < OFMEM_REGIONS; i++)
+ if ((addr >= OFmem[i].mr_start)
+ && (addr + len < OFmem[i].mr_start + OFmem[i].mr_size))
+ return (0);
+
+ return (EFAULT);
+}
diff --git a/sys/powerpc/powerpc/ofwmagic.S b/sys/powerpc/powerpc/ofwmagic.S
new file mode 100644
index 000000000000..55af6d254440
--- /dev/null
+++ b/sys/powerpc/powerpc/ofwmagic.S
@@ -0,0 +1,75 @@
+/* $FreeBSD$ */
+/* $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.
+ * 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.
+ */
+
+/*
+ * 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
diff --git a/sys/powerpc/powerpc/openpic.c b/sys/powerpc/powerpc/openpic.c
new file mode 100644
index 000000000000..c6a086380eb9
--- /dev/null
+++ b/sys/powerpc/powerpc/openpic.c
@@ -0,0 +1,238 @@
+/*-
+ * 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$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/intr.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 __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 cpu, int pri)
+{
+ uint32_t x;
+
+ x = openpic_read(sc, OPENPIC_CPU_PRIORITY(cpu));
+ x &= ~OPENPIC_CPU_PRIORITY_MASK;
+ x |= pri;
+ openpic_write(sc, OPENPIC_CPU_PRIORITY(cpu), x);
+}
+
+int
+openpic_attach(device_t dev)
+{
+ struct openpic_softc *sc;
+ u_int 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);
+
+ 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
+ */
+ if (sc->sc_psim)
+ sc->sc_nirq--;
+
+ if (bootverbose)
+ device_printf(dev,
+ "Version %s, supports %d CPUs and %d irqs\n",
+ sc->sc_version, sc->sc_ncpu, sc->sc_nirq);
+
+ /* disable all interrupts */
+ for (irq = 0; irq < sc->sc_nirq; irq++)
+ openpic_write(sc, OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
+
+ openpic_set_priority(sc, 0, 15);
+
+ /* 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);
+
+ for (irq = 0; irq < sc->sc_nirq; irq++) {
+ x = irq; /* irq == vector. */
+ x |= OPENPIC_IMASK;
+ x |= OPENPIC_POLARITY_POSITIVE;
+ x |= OPENPIC_SENSE_LEVEL;
+ x |= 8 << OPENPIC_PRIORITY_SHIFT;
+ openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+ }
+
+ /* XXX IPI */
+ /* XXX set spurious intr vector */
+
+ openpic_set_priority(sc, 0, 0);
+
+ /* clear all pending interrupts */
+ for (irq = 0; irq < sc->sc_nirq; irq++) {
+ (void)openpic_read(sc, OPENPIC_IACK(0));
+ openpic_write(sc, OPENPIC_EOI(0), 0);
+ }
+
+ powerpc_register_pic(dev);
+
+ return (0);
+}
+
+/*
+ * PIC I/F methods
+ */
+
+void
+openpic_dispatch(device_t dev, struct trapframe *tf)
+{
+ struct openpic_softc *sc;
+ u_int vector;
+
+ sc = device_get_softc(dev);
+ while (1) {
+ vector = openpic_read(sc, OPENPIC_IACK(0));
+ 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);
+ x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
+ x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
+ x |= vector;
+ openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+}
+
+void
+openpic_eoi(device_t dev, u_int irq __unused)
+{
+ struct openpic_softc *sc;
+
+ sc = device_get_softc(dev);
+ openpic_write(sc, OPENPIC_EOI(0), 0);
+}
+
+void
+openpic_mask(device_t dev, u_int irq)
+{
+ struct openpic_softc *sc;
+ uint32_t x;
+
+ sc = device_get_softc(dev);
+ x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
+ x |= OPENPIC_IMASK;
+ openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+ openpic_write(sc, OPENPIC_EOI(0), 0);
+}
+
+void
+openpic_unmask(device_t dev, u_int irq)
+{
+ struct openpic_softc *sc;
+ uint32_t x;
+
+ sc = device_get_softc(dev);
+ x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
+ x &= ~OPENPIC_IMASK;
+ openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+}
diff --git a/sys/powerpc/powerpc/pic_if.m b/sys/powerpc/powerpc/pic_if.m
new file mode 100644
index 000000000000..9db9c1667a12
--- /dev/null
+++ b/sys/powerpc/powerpc/pic_if.m
@@ -0,0 +1,59 @@
+#-
+# 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$
+#
+
+#include <sys/bus.h>
+#include <machine/frame.h>
+
+INTERFACE pic;
+
+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 mask {
+ device_t dev;
+ u_int irq;
+};
+
+METHOD void unmask {
+ device_t dev;
+ u_int irq;
+};
diff --git a/sys/powerpc/powerpc/pmap_dispatch.c b/sys/powerpc/powerpc/pmap_dispatch.c
new file mode 100644
index 000000000000..92ac5148a404
--- /dev/null
+++ b/sys/powerpc/powerpc/pmap_dispatch.c
@@ -0,0 +1,382 @@
+/*-
+ * 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$");
+
+/*
+ * 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 kobj_machdep_init() be called before
+ * pmap_bootstrap() to allow the kobj subsystem to initialise. This
+ * in turn requires that mutex_init() has been called.
+ */
+
+#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 <machine/mmuvar.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;
+
+void
+pmap_change_wiring(pmap_t pmap, vm_offset_t va, boolean_t wired)
+{
+ MMU_CHANGE_WIRING(mmu_obj, pmap, va, wired);
+}
+
+void
+pmap_clear_modify(vm_page_t m)
+{
+ MMU_CLEAR_MODIFY(mmu_obj, m);
+}
+
+void
+pmap_clear_reference(vm_page_t m)
+{
+ MMU_CLEAR_REFERENCE(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)
+{
+ 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)
+{
+ MMU_COPY_PAGE(mmu_obj, src, dst);
+}
+
+void
+pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t p, vm_prot_t prot,
+ boolean_t wired)
+{
+ MMU_ENTER(mmu_obj, pmap, va, p, prot, wired);
+}
+
+void
+pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
+ vm_page_t m_start, vm_prot_t 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)
+{
+ MMU_ENTER_QUICK(mmu_obj, pmap, va, m, prot);
+}
+
+vm_paddr_t
+pmap_extract(pmap_t pmap, vm_offset_t 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)
+{
+ return (MMU_EXTRACT_AND_HOLD(mmu_obj, pmap, va, prot));
+}
+
+void
+pmap_growkernel(vm_offset_t va)
+{
+ MMU_GROWKERNEL(mmu_obj, va);
+}
+
+void
+pmap_init(void)
+{
+ MMU_INIT(mmu_obj);
+}
+
+boolean_t
+pmap_is_modified(vm_page_t m)
+{
+ return (MMU_IS_MODIFIED(mmu_obj, m));
+}
+
+boolean_t
+pmap_is_prefaultable(pmap_t pmap, vm_offset_t va)
+{
+ return (MMU_IS_PREFAULTABLE(mmu_obj, pmap, va));
+}
+
+boolean_t
+pmap_ts_referenced(vm_page_t 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)
+{
+ 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)
+{
+ MMU_OBJECT_INIT_PT(mmu_obj, pmap, addr, object, pindex, size);
+}
+
+boolean_t
+pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
+{
+ return (MMU_PAGE_EXISTS_QUICK(mmu_obj, pmap, m));
+}
+
+void
+pmap_page_init(vm_page_t m)
+{
+ MMU_PAGE_INIT(mmu_obj, m);
+}
+
+void
+pmap_pinit(pmap_t pmap)
+{
+ MMU_PINIT(mmu_obj, pmap);
+}
+
+void
+pmap_pinit0(pmap_t pmap)
+{
+ MMU_PINIT0(mmu_obj, pmap);
+}
+
+void
+pmap_protect(pmap_t pmap, vm_offset_t start, vm_offset_t end, vm_prot_t prot)
+{
+ MMU_PROTECT(mmu_obj, pmap, start, end, prot);
+}
+
+void
+pmap_qenter(vm_offset_t start, vm_page_t *m, int count)
+{
+ MMU_QENTER(mmu_obj, start, m, count);
+}
+
+void
+pmap_qremove(vm_offset_t start, int count)
+{
+ MMU_QREMOVE(mmu_obj, start, count);
+}
+
+void
+pmap_release(pmap_t pmap)
+{
+ MMU_RELEASE(mmu_obj, pmap);
+}
+
+void
+pmap_remove(pmap_t pmap, vm_offset_t start, vm_offset_t end)
+{
+ MMU_REMOVE(mmu_obj, pmap, start, end);
+}
+
+void
+pmap_remove_all(vm_page_t m)
+{
+ MMU_REMOVE_ALL(mmu_obj, m);
+}
+
+void
+pmap_remove_pages(pmap_t pmap)
+{
+ MMU_REMOVE_PAGES(mmu_obj, pmap);
+}
+
+void
+pmap_remove_write(vm_page_t m)
+{
+ MMU_REMOVE_WRITE(mmu_obj, m);
+}
+
+void
+pmap_zero_page(vm_page_t m)
+{
+ MMU_ZERO_PAGE(mmu_obj, m);
+}
+
+void
+pmap_zero_page_area(vm_page_t m, int off, int size)
+{
+ MMU_ZERO_PAGE_AREA(mmu_obj, m, off, size);
+}
+
+void
+pmap_zero_page_idle(vm_page_t m)
+{
+ MMU_ZERO_PAGE_IDLE(mmu_obj, m);
+}
+
+int
+pmap_mincore(pmap_t pmap, vm_offset_t addr)
+{
+ return (MMU_MINCORE(mmu_obj, pmap, addr));
+}
+
+void
+pmap_activate(struct thread *td)
+{
+ MMU_ACTIVATE(mmu_obj, td);
+}
+
+void
+pmap_deactivate(struct thread *td)
+{
+ MMU_DEACTIVATE(mmu_obj, td);
+}
+
+vm_offset_t
+pmap_addr_hint(vm_object_t obj, vm_offset_t addr, vm_size_t size)
+{
+ return (MMU_ADDR_HINT(mmu_obj, obj, 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((kobj_t)mmu_obj, mmu_def_impl);
+
+ MMU_BOOTSTRAP(mmu_obj, start, end);
+}
+
+void *
+pmap_mapdev(vm_offset_t pa, vm_size_t size)
+{
+ return (MMU_MAPDEV(mmu_obj, pa, size));
+}
+
+void
+pmap_unmapdev(vm_offset_t va, vm_size_t size)
+{
+ MMU_UNMAPDEV(mmu_obj, va, size);
+}
+
+vm_offset_t
+pmap_kextract(vm_offset_t va)
+{
+ return (MMU_KEXTRACT(mmu_obj, va));
+}
+
+void
+pmap_kenter(vm_offset_t va, vm_offset_t pa)
+{
+ MMU_KENTER(mmu_obj, va, pa);
+}
+
+boolean_t
+pmap_dev_direct_mapped(vm_offset_t pa, vm_size_t size)
+{
+ return (MMU_DEV_DIRECT_MAPPED(mmu_obj, pa, size));
+}
+
+boolean_t
+pmap_page_executable(vm_page_t pg)
+{
+ return (MMU_PAGE_EXECUTABLE(mmu_obj, pg));
+}
+
+/*
+ * 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) {
+ curr_prio = prio;
+ mmu_def_impl = mmup;
+ return (TRUE);
+ }
+ }
+
+ return (FALSE);
+}
diff --git a/sys/powerpc/powerpc/sc_machdep.c b/sys/powerpc/powerpc/sc_machdep.c
new file mode 100644
index 000000000000..a81ffddbb211
--- /dev/null
+++ b/sys/powerpc/powerpc/sc_machdep.c
@@ -0,0 +1,90 @@
+/*-
+ * 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$");
+
+#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);
+}
diff --git a/sys/powerpc/powerpc/setjmp.S b/sys/powerpc/powerpc/setjmp.S
new file mode 100644
index 000000000000..b372e40e3ff0
--- /dev/null
+++ b/sys/powerpc/powerpc/setjmp.S
@@ -0,0 +1,103 @@
+/* $FreeBSD$ */
+/* 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) */
+
+#define JMP_r1 0x04
+#define JMP_r14 0x08
+#define JMP_r15 0x0c
+#define JMP_r16 0x10
+#define JMP_r17 0x14
+#define JMP_r18 0x18
+#define JMP_r19 0x1c
+#define JMP_r20 0x20
+#define JMP_r21 0x24
+#define JMP_r22 0x28
+#define JMP_r23 0x2c
+#define JMP_r24 0x30
+#define JMP_r25 0x34
+#define JMP_r26 0x38
+#define JMP_r27 0x3c
+#define JMP_r28 0x40
+#define JMP_r29 0x44
+#define JMP_r30 0x48
+#define JMP_r31 0x4c
+#define JMP_lr 0x50
+#define JMP_cr 0x54
+#define JMP_ctr 0x58
+#define JMP_xer 0x5c
+#define JMP_sig 0x60
+
+
+.globl setjmp
+setjmp:
+ stw 31, JMP_r31(3)
+ /* r1, r14-r30 */
+ stw 1, JMP_r1 (3)
+ stw 14, JMP_r14(3)
+ stw 15, JMP_r15(3)
+ stw 16, JMP_r16(3)
+ stw 17, JMP_r17(3)
+ stw 18, JMP_r18(3)
+ stw 19, JMP_r19(3)
+ stw 20, JMP_r20(3)
+ stw 21, JMP_r21(3)
+ stw 22, JMP_r22(3)
+ stw 23, JMP_r23(3)
+ stw 24, JMP_r24(3)
+ stw 25, JMP_r25(3)
+ stw 26, JMP_r26(3)
+ stw 27, JMP_r27(3)
+ stw 28, JMP_r28(3)
+ stw 29, JMP_r29(3)
+ stw 30, JMP_r30(3)
+ /* cr, lr, ctr, xer */
+ mfcr 0
+ stw 0, JMP_cr(3)
+ mflr 0
+ stw 0, JMP_lr(3)
+ mfctr 0
+ stw 0, JMP_ctr(3)
+ mfxer 0
+ stw 0, JMP_xer(3)
+ /* f14-f31, fpscr */
+ li 3, 0
+ blr
+
+
+.extern sigsetmask
+.globl longjmp
+longjmp:
+ lwz 31, JMP_r31(3)
+ /* r1, r14-r30 */
+ lwz 1, JMP_r1 (3)
+ lwz 14, JMP_r14(3)
+ lwz 15, JMP_r15(3)
+ lwz 16, JMP_r16(3)
+ lwz 17, JMP_r17(3)
+ lwz 18, JMP_r18(3)
+ lwz 19, JMP_r19(3)
+ lwz 20, JMP_r20(3)
+ lwz 21, JMP_r21(3)
+ lwz 22, JMP_r22(3)
+ lwz 23, JMP_r23(3)
+ lwz 24, JMP_r24(3)
+ lwz 25, JMP_r25(3)
+ lwz 26, JMP_r26(3)
+ lwz 27, JMP_r27(3)
+ lwz 28, JMP_r28(3)
+ lwz 29, JMP_r29(3)
+ lwz 30, JMP_r30(3)
+ /* cr, lr, ctr, xer */
+ lwz 0, JMP_cr(3)
+ mtcr 0
+ lwz 0, JMP_lr(3)
+ mtlr 0
+ lwz 0, JMP_ctr(3)
+ mtctr 0
+ lwz 0, JMP_xer(3)
+ mtxer 0
+ /* f14-f31, fpscr */
+ mr 3, 4
+ blr
diff --git a/sys/powerpc/powerpc/sigcode.S b/sys/powerpc/powerpc/sigcode.S
new file mode 100644
index 000000000000..af0ed49e153b
--- /dev/null
+++ b/sys/powerpc/powerpc/sigcode.S
@@ -0,0 +1,59 @@
+/* $FreeBSD$ */
+/* $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(sigcode),CNAME(szsigcode)
+CNAME(sigcode):
+ addi 1,1,-16 /* reserved space for callee */
+ blrl
+ addi 3,1,16+SF_UC /* restore sp, and get &frame->sf_uc */
+ li 0,SYS_sigreturn
+ sc /* sigreturn(scp) */
+ li 0,SYS_exit
+ sc /* exit(errno) */
+endsigcode:
+
+ .data
+CNAME(szsigcode):
+ .long endsigcode - CNAME(sigcode)
diff --git a/sys/powerpc/powerpc/suswintr.c b/sys/powerpc/powerpc/suswintr.c
new file mode 100644
index 000000000000..0252201e8a4b
--- /dev/null
+++ b/sys/powerpc/powerpc/suswintr.c
@@ -0,0 +1,51 @@
+/*-
+ * 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$");
+
+#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;
+}
diff --git a/sys/powerpc/powerpc/swtch.S b/sys/powerpc/powerpc/swtch.S
new file mode 100644
index 000000000000..038e788b9175
--- /dev/null
+++ b/sys/powerpc/powerpc/swtch.S
@@ -0,0 +1,154 @@
+/* $FreeBSD$ */
+/* $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/sr.h>
+#include <machine/psl.h>
+#include <machine/asm.h>
+
+/*
+ * void cpu_switch(struct thread *old, struct thread *new)
+ *
+ * Switch to a new thread saving the current state in the old thread.
+ */
+ENTRY(cpu_switch)
+ lwz %r5,TD_PCB(%r3) /* Get the old thread's PCB ptr */
+
+ mr %r12,%r2
+ stmw %r12,PCB_CONTEXT(%r5) /* Save the non-volatile GP regs.
+ These can now be used for scratch */
+
+ mfcr %r16 /* Save the condition register */
+ stw %r16,PCB_CR(%r5)
+ mflr %r16 /* Save the link register */
+ stw %r16,PCB_LR(%r5)
+ mfsr %r16,USER_SR /* Save USER_SR for copyin/out */
+ isync
+ stw %r16,PCB_USR(%r5)
+ stw %r1,PCB_SP(%r5) /* Save the stack pointer */
+
+ mr %r14,%r3 /* Copy the old thread ptr... */
+ mr %r15,%r4 /* and the new thread ptr in scratch */
+
+ lwz %r6,PCB_FLAGS(%r5) /* Save FPU context if needed */
+ andi. %r6, %r6, PCB_FPU
+ beq .L1
+ bl save_fpu
+ mr %r3,%r14 /* restore old thread ptr */
+.L1:
+ bl pmap_deactivate /* Deactivate the current pmap */
+
+ mr %r3,%r15 /* Get new thread ptr */
+ bl pmap_activate /* Activate the new address space */
+
+ mfsprg %r7,0 /* Get the pcpu pointer */
+ stw %r15,PC_CURTHREAD(%r7) /* Store new current thread */
+ lwz %r17,TD_PCB(%r15) /* Store new current PCB */
+ stw %r17,PC_CURPCB(%r7)
+
+ lwz %r6, PCB_FLAGS(%r17) /* Restore FPU context if needed */
+ andi. %r6, %r6, PCB_FPU
+ beq .L2
+ mr %r3,%r15 /* Pass curthread to enable_fpu */
+ bl enable_fpu
+
+ /* thread to restore is in r3 */
+.L2:
+ mr %r3,%r17 /* Recover PCB ptr */
+ lmw %r12,PCB_CONTEXT(%r3) /* Load the non-volatile GP regs */
+ mr %r2,%r12
+ lwz %r5,PCB_CR(%r3) /* Load the condition register */
+ mtcr %r5
+ lwz %r5,PCB_LR(%r3) /* Load the link register */
+ mtlr %r5
+ lwz %r5,PCB_USR(%r3) /* Load the USER_SR segment reg */
+ mtsr USER_SR,%r5
+ isync
+ lwz %r1,PCB_SP(%r3) /* Load the stack pointer */
+ blr
+
+/*
+ * savectx(pcb)
+ * Update pcb, saving current processor state
+ */
+ENTRY(savectx)
+ mr %r12,%r2
+ stmw %r12,PCB_CONTEXT(%r3) /* Save the non-volatile GP regs */
+ mfcr %r4 /* Save the condition register */
+ stw %r4,PCB_CONTEXT(%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
diff --git a/sys/powerpc/powerpc/syncicache.c b/sys/powerpc/powerpc/syncicache.c
new file mode 100644
index 000000000000..3d4f732e72bf
--- /dev/null
+++ b/sys/powerpc/powerpc/syncicache.c
@@ -0,0 +1,96 @@
+/*-
+ * 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 $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#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/md_var.h>
+
+#if defined(_KERNEL) || defined(_STANDALONE)
+#ifndef CACHELINESIZE
+#error "Must know the size of a cache line"
+#endif
+#else
+static void getcachelinesize(void);
+
+static int _cachelinesize;
+#define CACHELINESIZE _cachelinesize
+
+static void
+getcachelinesize()
+{
+ static int cachemib[] = { CTL_MACHDEP, CPU_CACHELINE };
+ int clen;
+
+ clen = sizeof(_cachelinesize);
+
+ if (sysctl(cachemib, sizeof(cachemib) / sizeof(cachemib[0]),
+ &_cachelinesize, &clen, NULL, 0) < 0 || !_cachelinesize) {
+ abort();
+ }
+}
+#endif
+
+void
+__syncicache(void *from, int len)
+{
+ int l, off;
+ char *p;
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ if (!_cachelinesize)
+ getcachelinesize();
+#endif
+ off = (u_int)from & (CACHELINESIZE - 1);
+ l = len += off;
+ p = (char *)from - off;
+ do {
+ __asm __volatile ("dcbst 0,%0" :: "r"(p));
+ p += CACHELINESIZE;
+ } while ((l -= CACHELINESIZE) > 0);
+ __asm __volatile ("sync");
+ p = (char *)from - off;
+ do {
+ __asm __volatile ("icbi 0,%0" :: "r"(p));
+ p += CACHELINESIZE;
+ } while ((len -= CACHELINESIZE) > 0);
+ __asm __volatile ("sync; isync");
+}
diff --git a/sys/powerpc/powerpc/sys_machdep.c b/sys/powerpc/powerpc/sys_machdep.c
new file mode 100644
index 000000000000..86e6e077c3f4
--- /dev/null
+++ b/sys/powerpc/powerpc/sys_machdep.c
@@ -0,0 +1,39 @@
+/*-
+ * 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$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/sysproto.h>
+
+int
+sysarch(struct thread *td, struct sysarch_args *uap)
+{
+
+ return (EINVAL);
+}
diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c
new file mode 100644
index 000000000000..a5ab7ebbffb2
--- /dev/null
+++ b/sys/powerpc/powerpc/trap.c
@@ -0,0 +1,681 @@
+/*-
+ * 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$");
+
+#include "opt_ktrace.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/uio.h>
+#include <sys/signalvar.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+#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/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);
+
+static __inline void setusr(u_int);
+
+int setfault(faultbuf); /* defined in locore.S */
+
+/* Why are these not defined in a header? */
+int badaddr(void *, size_t);
+int badaddr_read(void *, size_t, int *);
+
+extern char *syscallnames[];
+
+struct powerpc_exception {
+ u_int vector;
+ char *name;
+};
+
+static struct powerpc_exception powerpc_exceptions[] = {
+ { 0x0100, "system reset" },
+ { 0x0200, "machine check" },
+ { 0x0300, "data storage interrupt" },
+ { 0x0400, "instruction storage interrupt" },
+ { 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;
+ int sig, type, user;
+ u_int ucode;
+ ksiginfo_t ksi;
+
+ PCPU_INC(cnt.v_trap);
+
+ td = PCPU_GET(curthread);
+ p = td->td_proc;
+
+ type = ucode = frame->exc;
+ sig = 0;
+ user = frame->srr1 & PSL_PR;
+
+ CTR3(KTR_TRAP, "trap: %s type=%s (%s)", p->p_comm,
+ trapname(type), user ? "user" : "kernel");
+
+ 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;
+ break;
+
+ case EXC_DSI:
+ case EXC_ISI:
+ sig = trap_pfault(frame, 1);
+ 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;
+
+#ifdef ALTIVEC
+ case EXC_VEC:
+ if ((vecthread = PCPU_GET(vecthread)) != NULL) {
+ KASSERT(vecthread != td,
+ ("altivec already enabled"));
+ save_vec(vecthread);
+ }
+ PCPU_SET(vecthread, td);
+ td->td_pcb->pcb_veccpu = PCPU_GET(cpuid);
+ enable_vec(td);
+ frame->srr1 |= PSL_VEC;
+ break;
+#else
+ case EXC_VEC:
+ case EXC_VECAST:
+ sig = SIGILL;
+ break;
+#endif /* ALTIVEC */
+
+ case EXC_ALI:
+ if (fix_unaligned(td, frame) != 0)
+ sig = SIGBUS;
+ else
+ frame->srr0 += 4;
+ break;
+
+ case EXC_PGM:
+ /* XXX temporarily */
+ /* XXX: Magic Number? */
+ if (frame->srr1 & 0x0002000)
+ sig = SIGTRAP;
+ else
+ sig = SIGILL;
+ 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_DSI:
+ if (trap_pfault(frame, 0) == 0)
+ return;
+ break;
+ case EXC_MCHK:
+ if (handle_onfault(frame))
+ return;
+ break;
+ default:
+ break;
+ }
+ trap_fatal(frame);
+ }
+
+#ifdef ALTIVEC
+ if (td != PCPU_GET(vecthread) ||
+ td->td_pcb->pcb_veccpu != PCPU_GET(cpuid))
+ frame->srr1 &= ~PSL_VEC;
+#endif /* ALTIVEC */
+
+ 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);
+ mtx_assert(&Giant, MA_NOTOWNED);
+}
+
+static void
+trap_fatal(struct trapframe *frame)
+{
+
+ printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR));
+#ifdef KDB
+ if ((debugger_on_panic || kdb_active) &&
+ kdb_trap(frame->exc, 0, frame))
+ 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 >> 8,
+ trapname(vector));
+ switch (vector) {
+ case EXC_DSI:
+ printf(" virtual address = 0x%x\n", frame->dar);
+ break;
+ case EXC_ISI:
+ printf(" virtual address = 0x%x\n", frame->srr0);
+ break;
+ }
+ printf(" srr0 = 0x%x\n", frame->srr0);
+ printf(" srr1 = 0x%x\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)[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);
+}
+
+void
+syscall(struct trapframe *frame)
+{
+ caddr_t params;
+ struct sysent *callp;
+ struct thread *td;
+ struct proc *p;
+ int error, n;
+ size_t narg;
+ register_t args[10];
+ u_int code;
+
+ td = PCPU_GET(curthread);
+ p = td->td_proc;
+
+ PCPU_INC(cnt.v_syscall);
+
+#ifdef KSE
+ if (p->p_flag & P_SA)
+ thread_user_enter(td);
+#endif
+
+ code = frame->fixreg[0];
+ params = (caddr_t)(frame->fixreg + FIRSTARG);
+ n = NARGREG;
+
+ if (p->p_sysent->sv_prepsyscall) {
+ /*
+ * The prep code is MP aware.
+ */
+ (*p->p_sysent->sv_prepsyscall)(frame, args, &code, &params);
+ } else if (code == SYS_syscall) {
+ /*
+ * code is first argument,
+ * followed by actual args.
+ */
+ code = *(u_int *) params;
+ params += sizeof(register_t);
+ n -= 1;
+ } else if (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);
+ code = *(u_int *) params;
+ params += sizeof(register_t);
+ n -= 2;
+ }
+
+ if (p->p_sysent->sv_mask)
+ code &= p->p_sysent->sv_mask;
+
+ if (code >= p->p_sysent->sv_size)
+ callp = &p->p_sysent->sv_table[0];
+ else
+ callp = &p->p_sysent->sv_table[code];
+
+ narg = callp->sy_narg;
+
+ if (narg > n) {
+ bcopy(params, args, n * sizeof(register_t));
+ error = copyin(MOREARGS(frame->fixreg[1]), args + n,
+ (narg - n) * sizeof(register_t));
+ params = (caddr_t)args;
+ } else
+ error = 0;
+
+ CTR5(KTR_SYSC, "syscall: p=%s %s(%x %x %x)", p->p_comm,
+ syscallnames[code],
+ frame->fixreg[FIRSTARG],
+ frame->fixreg[FIRSTARG+1],
+ frame->fixreg[FIRSTARG+2]);
+
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_SYSCALL))
+ ktrsyscall(code, narg, (register_t *)params);
+#endif
+
+ td->td_syscalls++;
+
+ if (error == 0) {
+ td->td_retval[0] = 0;
+ td->td_retval[1] = frame->fixreg[FIRSTARG + 1];
+
+ STOPEVENT(p, S_SCE, narg);
+
+ PTRACESTOP_SC(p, td, S_PT_SCE);
+
+ AUDIT_SYSCALL_ENTER(code, td);
+ error = (*callp->sy_call)(td, params);
+ AUDIT_SYSCALL_EXIT(error, td);
+
+ CTR3(KTR_SYSC, "syscall: p=%s %s ret=%x", p->p_comm,
+ syscallnames[code], td->td_retval[0]);
+ }
+ switch (error) {
+ case 0:
+ if (frame->fixreg[0] == SYS___syscall &&
+ code != SYS_freebsd6_lseek && code != SYS_lseek) {
+ /*
+ * 64-bit return, 32-bit syscall. Fixup byte order
+ */
+ frame->fixreg[FIRSTARG] = 0;
+ frame->fixreg[FIRSTARG + 1] = td->td_retval[0];
+ } else {
+ frame->fixreg[FIRSTARG] = td->td_retval[0];
+ frame->fixreg[FIRSTARG + 1] = td->td_retval[1];
+ }
+ /* XXX: Magic number */
+ frame->cr &= ~0x10000000;
+ break;
+ case ERESTART:
+ /*
+ * Set user's pc back to redo the system call.
+ */
+ frame->srr0 -= 4;
+ break;
+ case EJUSTRETURN:
+ /* nothing to do */
+ break;
+ default:
+ if (p->p_sysent->sv_errsize) {
+ if (error >= p->p_sysent->sv_errsize)
+ error = -1; /* XXX */
+ else
+ error = p->p_sysent->sv_errtbl[error];
+ }
+ frame->fixreg[FIRSTARG] = error;
+ /* XXX: Magic number: Carry Flag Equivalent? */
+ frame->cr |= 0x10000000;
+ break;
+ }
+
+ /*
+ * Check for misbehavior.
+ */
+ WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
+ KASSERT(td->td_critnest == 0,
+ ("System call %s returning in a critical section",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"));
+ KASSERT(td->td_locks == 0,
+ ("System call %s returning with %d locks held",
+ (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???",
+ td->td_locks));
+
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_SYSRET))
+ ktrsysret(code, error, td->td_retval[0]);
+#endif
+
+ /*
+ * Does the comment in the i386 code about errno apply here?
+ */
+ STOPEVENT(p, S_SCX, code);
+
+ PTRACESTOP_SC(p, td, S_PT_SCX);
+}
+
+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;
+ u_int user_sr;
+
+ td = curthread;
+ p = td->td_proc;
+ if (frame->exc == EXC_ISI) {
+ eva = frame->srr0;
+ ftype = VM_PROT_READ | VM_PROT_EXECUTE;
+ } else {
+ eva = frame->dar;
+ if (frame->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_SR) {
+ if (p->p_vmspace == NULL)
+ return (SIGSEGV);
+
+ __asm ("mfsr %0, %1"
+ : "=r"(user_sr)
+ : "K"(USER_SR));
+ eva &= ADDR_PIDX | ADDR_POFF;
+ eva |= user_sr << ADDR_SR_SHFT;
+ 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,
+ (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY
+ : 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 (SIGSEGV);
+}
+
+static __inline void
+setusr(u_int content)
+{
+ __asm __volatile ("isync; mtsr %0,%1; isync"
+ :: "n"(USER_SR), "r"(content));
+}
+
+int
+badaddr(void *addr, size_t size)
+{
+ return (badaddr_read(addr, size, NULL));
+}
+
+int
+badaddr_read(void *addr, size_t size, int *rptr)
+{
+ struct thread *td;
+ faultbuf env;
+ int x;
+
+ /* Get rid of any stale machine checks that have been waiting. */
+ __asm __volatile ("sync; isync");
+
+ td = PCPU_GET(curthread);
+
+ if (setfault(env)) {
+ td->td_pcb->pcb_onfault = 0;
+ __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 (%d)", size);
+ }
+
+ /* Make sure we took the machine check, if we caused one. */
+ __asm __volatile ("sync; isync");
+
+ td->td_pcb->pcb_onfault = 0;
+ __asm __volatile ("sync"); /* To be sure. */
+
+ /* Use the value to avoid reorder. */
+ if (rptr)
+ *rptr = x;
+
+ return (0);
+}
+
+/*
+ * 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->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;
+ }
+
+ return -1;
+}
diff --git a/sys/powerpc/powerpc/trap_subr.S b/sys/powerpc/powerpc/trap_subr.S
new file mode 100644
index 000000000000..06ed891406f9
--- /dev/null
+++ b/sys/powerpc/powerpc/trap_subr.S
@@ -0,0 +1,540 @@
+/* $FreeBSD$ */
+/* $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/powerpc/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; \
+ lwz sr,12*4(pmap); mtsr 12,sr; \
+ 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)
+
+/*
+ * 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@l(pmap); \
+ RESTORE_SRS(pmap,sr)
+
+/*
+ * FRAME_SETUP assumes:
+ * SPRG1 SP (1)
+ * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps)
+ * r28 LR
+ * r29 CR
+ * r30 scratch
+ * r31 scratch
+ * r1 kernel stack
+ * LR trap type (from calling address, mask with 0xff00)
+ * 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_DAR)(%r2); /* saved DAR */ \
+ lwz %r29,(savearea+CPUSAVE_DSISR)(%r2);/* saved DSISR */ \
+ lwz %r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */ \
+ lwz %r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */ \
+ mfxer %r3; \
+ mfctr %r4; \
+ mflr %r5; \
+ andi. %r5,%r5,0xff00; /* convert LR to exc # */ \
+ 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_DAR+8(1); \
+ stw %r29,FRAME_DSISR+8(1); /* save dsisr/srr0/srr1 */ \
+ stw %r30,FRAME_SRR0+8(1); \
+ stw %r31,FRAME_SRR1+8(1)
+
+#define FRAME_LEAVE(savearea) \
+/* 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_EE|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 */ \
+ mtsrr1 %r3; \
+ mfsprg2 %r2; /* restore r2 & r3 */ \
+ mfsprg3 %r3
+
+#ifdef KDB
+/*
+ * Define the kdb debugger stack
+ */
+ .data
+GLOBAL(dbstk)
+ .space INTSTK+8 /* kdb stack */
+#endif
+
+/*
+ * This code gets copied to all the trap vectors
+ * (except ISI/DSI, ALI, and the interrupts)
+ */
+ .text
+ .globl CNAME(trapcode),CNAME(trapsize)
+CNAME(trapcode):
+ 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)
+ mfsprg1 %r1 /* restore SP, in case of branch */
+ mflr %r28 /* save LR */
+ mfcr %r29 /* save CR */
+/* Test whether we already had PR set */
+ mfsrr1 %r31
+ mtcr %r31
+ bla s_trap /* LR & 0xff00 is exception # */
+CNAME(trapsize) = .-CNAME(trapcode)
+
+/*
+ * 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_DAR)(%r1)
+ stw %r31,(PC_TEMPSAVE+CPUSAVE_DSISR)(%r1)
+ mfsprg1 %r1 /* restore SP, in case of branch */
+ mflr %r28 /* save LR */
+ mfcr %r29 /* save CR */
+/* Test whether we already had PR set */
+ mfsrr1 %r31
+ mtcr %r31
+ bla s_trap /* LR & 0xff00 is exception # */
+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)
+ 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@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:
+ 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_DAR)(%r1)
+ stw %r31,(PC_TEMPSAVE+CPUSAVE_DSISR)(%r1)
+
+#ifdef KDB
+ /* Try and detect a kernel stack overflow */
+ mfsrr1 %r31
+ mtcr %r31
+ bt 17,realtrap /* branch is user mode */
+ mfsprg1 %r31 /* get old SP */
+ 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_DAR)(%r1) /* get DAR */
+ stw %r30,(PC_DBSAVE +CPUSAVE_DAR)(%r1) /* save DAR */
+ lwz %r30,(PC_TEMPSAVE+CPUSAVE_DSISR)(%r1) /* get DSISR */
+ lwz %r30,(PC_DBSAVE +CPUSAVE_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 */
+ lis %r1,dbstk+INTSTK@ha /* get new SP */
+ addi %r1,%r1,dbstk+INTSTK@l
+ 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) */
+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)
+/* 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@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, PC_CURTHREAD(%r3) /* deref to get curthread */
+ lwz %r4, TD_FLAGS(%r4) /* 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@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)
+ rfi
+
+/*
+ * Temporary: vector-unavailable traps are directed to vector-assist traps
+ */
+ .globl CNAME(vectrap),CNAME(vectrapsize)
+CNAME(vectrap):
+ ba EXC_VECAST
+CNAME(vectrapsize) = .-CNAME(vectrap)
+
+#if defined(KDB)
+/*
+ * Deliberate entry to dbtrap
+ */
+ .globl CNAME(ppc_db_trap)
+CNAME(ppc_db_trap):
+ 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:
+ 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)
+ mtlr %r31
+ mfsprg1 %r1
+ b realtrap
+dbleave:
+ FRAME_LEAVE(PC_DBSAVE)
+ 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
+ GET_CPUINFO(%r1)
+ bf 17,1f /* branch if privileged */
+ stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) /* free r28 */
+ mfsprg2 %r28 /* r29 holds cr ... */
+ stw %r28,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) /* free r29 */
+ stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) /* free r30 */
+ stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) /* free r31 */
+ mflr %r28 /* save LR */
+ bla u_trap
+1:
+ 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 */
+ lis %r1,dbstk+INTSTK@ha /* get new SP */
+ addi %r1,%r1,dbstk+INTSTK@l
+ bla dbtrap
+CNAME(dbsize) = .-CNAME(dblow)
+#endif /* KDB */
diff --git a/sys/powerpc/powerpc/uio_machdep.c b/sys/powerpc/powerpc/uio_machdep.c
new file mode 100644
index 000000000000..070ad9871c5d
--- /dev/null
+++ b/sys/powerpc/powerpc/uio_machdep.c
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2004 Alan L. Cox <alc@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.
+ * 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.
+ *
+ * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+#include <machine/md_var.h>
+#include <machine/vmparam.h>
+
+/*
+ * Implement uiomove(9) from physical memory using the direct map 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;
+ size_t cnt;
+ int error = 0;
+ int save = 0;
+
+ 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);
+ cp = (char *)VM_PAGE_TO_PHYS(ma[offset >> PAGE_SHIFT]) +
+ page_offset;
+ switch (uio->uio_segflg) {
+ case UIO_USERSPACE:
+ if (ticks - PCPU_GET(switchticks) >= hogticks)
+ uio_yield();
+ if (uio->uio_rw == UIO_READ)
+ error = copyout(cp, iov->iov_base, cnt);
+ else
+ error = copyin(iov->iov_base, cp, cnt);
+ if (error)
+ goto out;
+ if (uio->uio_rw == UIO_WRITE &&
+ pmap_page_executable(ma[offset >> PAGE_SHIFT]))
+ __syncicache(cp, cnt);
+ 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;
+ }
+ 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);
+}
diff --git a/sys/powerpc/powerpc/uma_machdep.c b/sys/powerpc/powerpc/uma_machdep.c
new file mode 100644
index 000000000000..89d092a00843
--- /dev/null
+++ b/sys/powerpc/powerpc/uma_machdep.c
@@ -0,0 +1,91 @@
+/*-
+ * 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$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.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_pageout.h>
+#include <vm/uma.h>
+#include <vm/uma_int.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, int bytes, u_int8_t *flags, int wait)
+{
+ static vm_pindex_t color;
+ void *va;
+ vm_page_t m;
+ int pflags;
+
+ *flags = UMA_SLAB_PRIV;
+ if ((wait & (M_NOWAIT|M_USE_RESERVE)) == M_NOWAIT)
+ pflags = VM_ALLOC_INTERRUPT | VM_ALLOC_WIRED;
+ else
+ pflags = VM_ALLOC_SYSTEM | VM_ALLOC_WIRED;
+ if (wait & M_ZERO)
+ pflags |= VM_ALLOC_ZERO;
+
+ for (;;) {
+ m = vm_page_alloc(NULL, color++, 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 ((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, int size, u_int8_t flags)
+{
+ vm_page_t m;
+
+ m = PHYS_TO_VM_PAGE((u_int32_t)mem);
+ m->wire_count--;
+ vm_page_free(m);
+ atomic_subtract_int(&cnt.v_wire_count, 1);
+ atomic_subtract_int(&hw_uma_mdpages, 1);
+}
diff --git a/sys/powerpc/powerpc/vm_machdep.c b/sys/powerpc/powerpc/vm_machdep.c
new file mode 100644
index 000000000000..1b58c1ec6b1d
--- /dev/null
+++ b/sys/powerpc/powerpc/vm_machdep.c
@@ -0,0 +1,364 @@
+/*-
+ * 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$
+ */
+/*-
+ * 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@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/unistd.h>
+
+#include <machine/cpu.h>
+#include <machine/fpu.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+#include <machine/powerpc.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>
+
+/*
+ * 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 proc *p1;
+ 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=%08x p2=%08x flags=%x", (u_int)td1, (u_int)p2, flags);
+
+ if ((flags & RFPROC) == 0)
+ return;
+
+ p1 = td1->td_proc;
+
+ pcb = (struct pcb *)((td2->td_kstack +
+ td2->td_kstack_pages * PAGE_SIZE - sizeof(struct pcb)) & ~0x2fU);
+ 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));
+ 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;
+ pcb->pcb_lr = (register_t)fork_trampoline;
+ pcb->pcb_usr = kernel_pmap->pm_sr[USER_SR];
+
+ /* 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(td, func, arg)
+ struct thread *td;
+ void (*func)(void *);
+ void *arg;
+{
+ struct callframe *cf;
+
+ CTR3(KTR_PROC, "cpu_set_fork_handler: called with td=%08x func=%08x arg=%08x",
+ (u_int)td, (u_int)func, (u_int)arg);
+
+ cf = (struct callframe *)td->td_pcb->pcb_sp;
+
+ cf->cf_func = (register_t)func;
+ cf->cf_arg0 = (register_t)arg;
+}
+
+void
+cpu_exit(td)
+ register struct thread *td;
+{
+}
+
+/* Temporary helper */
+void
+cpu_throw(struct thread *old, struct thread *new)
+{
+
+ cpu_switch(old, new, NULL);
+ panic("cpu_throw() didn't");
+}
+
+/*
+ * Reset back to firmware.
+ */
+void
+cpu_reset()
+{
+ OF_reboot();
+}
+
+/*
+ * Allocate an sf_buf for the given vm_page. On this machine, however, there
+ * is no sf_buf object. Instead, an opaque pointer to the given vm_page is
+ * returned.
+ */
+struct sf_buf *
+sf_buf_alloc(struct vm_page *m, int pri)
+{
+
+ return ((struct sf_buf *)m);
+}
+
+/*
+ * Free the sf_buf. In fact, do nothing because there are no resources
+ * associated with the sf_buf.
+ */
+void
+sf_buf_free(struct sf_buf *sf)
+{
+}
+
+/*
+ * Software interrupt handler for queued VM system processing.
+ */
+void
+swi_vm(void *dummy)
+{
+#if 0 /* XXX: Don't have busdma stuff yet */
+ if (busdma_swi_pending != 0)
+ busdma_swi();
+#endif
+}
+
+/*
+ * 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(addr)
+ vm_offset_t addr;
+{
+ /*
+ * stuff other tests for known memory-mapped devices (PCI?)
+ * here
+ */
+
+ return 1;
+}
+
+/*
+ * KSE functions
+ */
+void
+cpu_thread_exit(struct thread *td)
+{
+}
+
+void
+cpu_thread_clean(struct thread *td)
+{
+}
+
+void
+cpu_thread_setup(struct thread *td)
+{
+ struct pcb *pcb;
+
+ pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
+ sizeof(struct pcb)) & ~0x2fU);
+ td->td_pcb = pcb;
+ td->td_frame = (struct trapframe *)pcb - 1;
+}
+
+void
+cpu_thread_swapin(struct thread *td)
+{
+}
+
+void
+cpu_thread_swapout(struct thread *td)
+{
+}
+
+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;
+ pcb2->pcb_lr = (register_t)fork_trampoline;
+ pcb2->pcb_usr = kernel_pmap->pm_sr[USER_SR];
+
+ /* 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;
+ uint32_t sp;
+
+ tf = td->td_frame;
+ /* align stack and alloc space for frame ptr and saved LR */
+ sp = ((uint32_t)stack->ss_sp + stack->ss_size
+ - 2*sizeof(u_int32_t)) & ~0x1f;
+ bzero(tf, sizeof(struct trapframe));
+
+ tf->fixreg[1] = (register_t)sp;
+ tf->fixreg[3] = (register_t)arg;
+ tf->srr0 = (register_t)entry;
+ tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
+ td->td_pcb->pcb_flags = 0;
+
+ td->td_retval[0] = (register_t)entry;
+ td->td_retval[1] = 0;
+}
+
+int
+cpu_set_user_tls(struct thread *td, void *tls_base)
+{
+
+ td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008;
+ return (0);
+}
diff --git a/sys/powerpc/psim/ata_iobus.c b/sys/powerpc/psim/ata_iobus.c
new file mode 100644
index 000000000000..f9b4a56ba361
--- /dev/null
+++ b/sys/powerpc/psim/ata_iobus.c
@@ -0,0 +1,257 @@
+/*-
+ * 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$
+ */
+
+/*
+ * PSIM local bus ATA controller
+ */
+#include "opt_ata.h"
+#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),
+
+ { 0, 0 }
+};
+
+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, 0, 0);
+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",
+ devclass_find_free_unit(ata_devclass, 0));
+
+ 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 void ata_iobus_sub_setmode(device_t parent, device_t dev);
+
+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),
+ { 0, 0 }
+};
+
+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, 0, 0);
+
+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 void
+ata_iobus_sub_setmode(device_t parent, device_t dev)
+{
+ struct ata_device *atadev = device_get_softc(dev);
+
+ /* Only ever PIO mode here... */
+ atadev->mode = ATA_PIO;
+}
diff --git a/sys/powerpc/psim/iobus.c b/sys/powerpc/psim/iobus.c
new file mode 100644
index 000000000000..30cbeed7cedf
--- /dev/null
+++ b/sys/powerpc/psim/iobus.c
@@ -0,0 +1,416 @@
+/*-
+ * 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$
+ */
+
+/*
+ * PSIM 'iobus' local bus. Should be set up in the device tree like:
+ *
+ * /iobus@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/openfirm.h>
+
+#include <machine/vmparam.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/pmap.h>
+
+#include <machine/resource.h>
+#include <machine/nexusvar.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, nexus, iobus_driver, iobus_devclass, 0, 0);
+
+static int
+iobus_probe(device_t dev)
+{
+ char *type = nexus_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 = nexus_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;
+ bus_space_tag_t tagval;
+
+ 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;
+ tagval = PPC_BUS_SPACE_MEM;
+ break;
+ case SYS_RES_IRQ:
+ return (bus_alloc_resource(bus, type, rid, start, end, count,
+ flags));
+ break;
+ 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);
+ rman_set_bustag(rv, tagval);
+ rman_set_bushandle(rv, rman_get_start(rv));
+
+ 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_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));
+}
diff --git a/sys/powerpc/psim/iobusvar.h b/sys/powerpc/psim/iobusvar.h
new file mode 100644
index 000000000000..1ab7f7eaed90
--- /dev/null
+++ b/sys/powerpc/psim/iobusvar.h
@@ -0,0 +1,66 @@
+/*-
+ * 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$
+ */
+
+#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_ */
diff --git a/sys/powerpc/psim/openpic_iobus.c b/sys/powerpc/psim/openpic_iobus.c
new file mode 100644
index 000000000000..a3a69d318c2d
--- /dev/null
+++ b/sys/powerpc/psim/openpic_iobus.c
@@ -0,0 +1,106 @@
+/*-
+ * 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$");
+
+#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.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/nexusvar.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 device_method_t openpic_iobus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, openpic_iobus_probe),
+ DEVMETHOD(device_attach, openpic_attach),
+
+ /* PIC interface */
+ DEVMETHOD(pic_dispatch, openpic_dispatch),
+ DEVMETHOD(pic_enable, openpic_enable),
+ DEVMETHOD(pic_eoi, openpic_eoi),
+ 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)
+{
+ 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);
+ return (0);
+}
diff --git a/sys/powerpc/psim/psim-tree b/sys/powerpc/psim/psim-tree
new file mode 100644
index 000000000000..62391c5ed950
--- /dev/null
+++ b/sys/powerpc/psim/psim-tree
@@ -0,0 +1,90 @@
+# $FreeBSD$
+#
+# 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@0x70000000/ide@1/disk@0
+
+#
+# CPU definition. The phandle property is to help nexus.c locate the
+# interrupt controller.
+#
+/cpus/cpu@0
+
+#
+# disk file, done via phb. maybe there's a simpler way.
+#
+/phb@0x70000000
+ ./device_type "pci
+ ./name "pci
+ ./#address-cells 3
+ ./#size-cells 2
+ ./ranges ni0,0,0,0 0xc0000000 0x10000
+
+/phb@0x70000000/ide@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@0x70000000/ide@1/disk@0/file "../image.iso
+
+#
+# I/O Bus
+#
+/iobus@0x90000000
+ ./name psim-iobus
+ ./reg 0x90000000 0x20000000
+
+#
+# OpenPIC
+#
+/iobus@0x90000000/opic@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@0x0
+
+#
+# IDE1
+#
+#/iobus@0x90000000/ide@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@0x90000000/ide@0x90052000 > a irq12 /iobus/opic
diff --git a/sys/powerpc/psim/uart_iobus.c b/sys/powerpc/psim/uart_iobus.c
new file mode 100644
index 000000000000..1768338b9952
--- /dev/null
+++ b/sys/powerpc/psim/uart_iobus.c
@@ -0,0 +1,87 @@
+/*-
+ * 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$
+ */
+
+/*
+ * 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);