summaryrefslogtreecommitdiffstats
path: root/arch/sparc64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64')
-rw-r--r--arch/sparc64/Makefile4
-rw-r--r--arch/sparc64/config.in18
-rw-r--r--arch/sparc64/defconfig45
-rw-r--r--arch/sparc64/kernel/Makefile39
-rw-r--r--arch/sparc64/kernel/auxio.c14
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c55
-rw-r--r--arch/sparc64/kernel/binfmt_elf32.c2
-rw-r--r--arch/sparc64/kernel/cpu.c6
-rw-r--r--arch/sparc64/kernel/devices.c11
-rw-r--r--arch/sparc64/kernel/ebus.c221
-rw-r--r--arch/sparc64/kernel/entry.S178
-rw-r--r--arch/sparc64/kernel/etrap.S10
-rw-r--r--arch/sparc64/kernel/idprom.c6
-rw-r--r--arch/sparc64/kernel/init_task.c1
-rw-r--r--arch/sparc64/kernel/ioctl32.c14
-rw-r--r--arch/sparc64/kernel/irq.c157
-rw-r--r--arch/sparc64/kernel/pci.c339
-rw-r--r--arch/sparc64/kernel/pci_common.c651
-rw-r--r--arch/sparc64/kernel/pci_impl.h166
-rw-r--r--arch/sparc64/kernel/pci_iommu.c510
-rw-r--r--arch/sparc64/kernel/pci_psycho.c1606
-rw-r--r--arch/sparc64/kernel/pci_sabre.c1487
-rw-r--r--arch/sparc64/kernel/power.c105
-rw-r--r--arch/sparc64/kernel/process.c256
-rw-r--r--arch/sparc64/kernel/psycho.c2619
-rw-r--r--arch/sparc64/kernel/ptrace.c52
-rw-r--r--arch/sparc64/kernel/rtrap.S39
-rw-r--r--arch/sparc64/kernel/semaphore.c129
-rw-r--r--arch/sparc64/kernel/setup.c31
-rw-r--r--arch/sparc64/kernel/signal.c203
-rw-r--r--arch/sparc64/kernel/signal32.c142
-rw-r--r--arch/sparc64/kernel/smp.c115
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c6
-rw-r--r--arch/sparc64/kernel/starfire.c12
-rw-r--r--arch/sparc64/kernel/sys_sparc.c102
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c141
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c26
-rw-r--r--arch/sparc64/kernel/systbls.S14
-rw-r--r--arch/sparc64/kernel/time.c162
-rw-r--r--arch/sparc64/kernel/trampoline.S4
-rw-r--r--arch/sparc64/kernel/traps.c186
-rw-r--r--arch/sparc64/kernel/ttable.S6
-rw-r--r--arch/sparc64/kernel/unaligned.c50
-rw-r--r--arch/sparc64/kernel/winfixup.S206
-rw-r--r--arch/sparc64/lib/PeeCeeI.c139
-rw-r--r--arch/sparc64/lib/VIScopy.S10
-rw-r--r--arch/sparc64/lib/VIScsum.S4
-rw-r--r--arch/sparc64/lib/VISsave.S38
-rw-r--r--arch/sparc64/lib/atomic.S6
-rw-r--r--arch/sparc64/lib/blockops.S6
-rw-r--r--arch/sparc64/lib/checksum.S2
-rw-r--r--arch/sparc64/lib/debuglocks.c4
-rw-r--r--arch/sparc64/lib/rwlock.S6
-rw-r--r--arch/sparc64/math-emu/.cvsignore2
-rw-r--r--arch/sparc64/math-emu/Makefile9
-rw-r--r--arch/sparc64/math-emu/double.h197
-rw-r--r--arch/sparc64/math-emu/extended.h388
-rw-r--r--arch/sparc64/math-emu/fabsq.c13
-rw-r--r--arch/sparc64/math-emu/faddd.c23
-rw-r--r--arch/sparc64/math-emu/faddq.c23
-rw-r--r--arch/sparc64/math-emu/fadds.c23
-rw-r--r--arch/sparc64/math-emu/fcmpeq.c39
-rw-r--r--arch/sparc64/math-emu/fcmpq.c39
-rw-r--r--arch/sparc64/math-emu/fdivd.c23
-rw-r--r--arch/sparc64/math-emu/fdivq.c23
-rw-r--r--arch/sparc64/math-emu/fdivs.c24
-rw-r--r--arch/sparc64/math-emu/fdmulq.c26
-rw-r--r--arch/sparc64/math-emu/fdtoi.c25
-rw-r--r--arch/sparc64/math-emu/fdtoq.c23
-rw-r--r--arch/sparc64/math-emu/fdtos.c23
-rw-r--r--arch/sparc64/math-emu/fdtox.c25
-rw-r--r--arch/sparc64/math-emu/fitoq.c22
-rw-r--r--arch/sparc64/math-emu/fmovq.c13
-rw-r--r--arch/sparc64/math-emu/fmuld.c23
-rw-r--r--arch/sparc64/math-emu/fmulq.c23
-rw-r--r--arch/sparc64/math-emu/fmuls.c23
-rw-r--r--arch/sparc64/math-emu/fnegq.c13
-rw-r--r--arch/sparc64/math-emu/fqtod.c23
-rw-r--r--arch/sparc64/math-emu/fqtoi.c25
-rw-r--r--arch/sparc64/math-emu/fqtos.c23
-rw-r--r--arch/sparc64/math-emu/fqtox.c25
-rw-r--r--arch/sparc64/math-emu/fsmuld.c26
-rw-r--r--arch/sparc64/math-emu/fsqrtd.c22
-rw-r--r--arch/sparc64/math-emu/fsqrtq.c22
-rw-r--r--arch/sparc64/math-emu/fsqrts.c22
-rw-r--r--arch/sparc64/math-emu/fstod.c23
-rw-r--r--arch/sparc64/math-emu/fstoi.c25
-rw-r--r--arch/sparc64/math-emu/fstoq.c23
-rw-r--r--arch/sparc64/math-emu/fstox.c25
-rw-r--r--arch/sparc64/math-emu/fsubd.c25
-rw-r--r--arch/sparc64/math-emu/fsubq.c25
-rw-r--r--arch/sparc64/math-emu/fsubs.c25
-rw-r--r--arch/sparc64/math-emu/fxtoq.c22
-rw-r--r--arch/sparc64/math-emu/math.c423
-rw-r--r--arch/sparc64/math-emu/op-1.h297
-rw-r--r--arch/sparc64/math-emu/op-2.h513
-rw-r--r--arch/sparc64/math-emu/op-4.h661
-rw-r--r--arch/sparc64/math-emu/op-8.h103
-rw-r--r--arch/sparc64/math-emu/op-common.h760
-rw-r--r--arch/sparc64/math-emu/quad.h205
-rw-r--r--arch/sparc64/math-emu/sfp-machine.h15
-rw-r--r--arch/sparc64/math-emu/single.h110
-rw-r--r--arch/sparc64/math-emu/soft-fp.h176
-rw-r--r--arch/sparc64/mm/asyncd.c12
-rw-r--r--arch/sparc64/mm/fault.c64
-rw-r--r--arch/sparc64/mm/generic.c5
-rw-r--r--arch/sparc64/mm/init.c59
-rw-r--r--arch/sparc64/mm/ultra.S29
-rw-r--r--arch/sparc64/prom/bootstr.c6
-rw-r--r--arch/sparc64/prom/init.c4
-rw-r--r--arch/sparc64/prom/memory.c8
-rw-r--r--arch/sparc64/prom/misc.c50
-rw-r--r--arch/sparc64/prom/p1275.c10
-rw-r--r--arch/sparc64/prom/ranges.c48
-rw-r--r--arch/sparc64/solaris/ioctl.c6
-rw-r--r--arch/sparc64/solaris/misc.c2
-rw-r--r--arch/sparc64/solaris/socksys.c6
-rw-r--r--arch/sparc64/solaris/timod.c6
-rw-r--r--arch/sparc64/vmlinux.lds9
119 files changed, 6823 insertions, 8571 deletions
diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile
index 4df9bc0f5..1216a3a4f 100644
--- a/arch/sparc64/Makefile
+++ b/arch/sparc64/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.37 1999/06/04 13:29:10 jj Exp $
+# $Id: Makefile,v 1.40 1999/08/19 02:31:57 davem Exp $
# sparc64/Makefile
#
# Makefile for the architecture dependent flags and dependencies on the
@@ -15,7 +15,7 @@ SHELL =/bin/bash
CC := sparc64-linux-gcc -D__KERNEL__ -I$(TOPDIR)/include
CC_HAS_ARGS := $(shell if echo "$(CC)" | grep '\(__KERNEL__\| \)' > /dev/null; then echo y; else echo n; fi)
-IS_EGCS := $(shell if $(CC) -c -m64 -mcmodel=medlow -o _tmp.o arch/sparc64/math-emu/fnegq.c >/dev/null 2>&1; then echo y; else echo n; fi; rm -f _tmp.o)
+IS_EGCS := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
ifneq ($(CC_HAS_ARGS),y)
diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in
index e03e9b427..cf8af1a78 100644
--- a/arch/sparc64/config.in
+++ b/arch/sparc64/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.67 1999/05/01 09:17:37 davem Exp $
+# $Id: config.in,v 1.78 1999/09/06 01:17:28 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
@@ -36,6 +36,7 @@ endmenu
# Global things across all Sun machines.
define_bool CONFIG_SBUS y
define_bool CONFIG_SBUSCHAR y
+define_bool CONFIG_BUSMOUSE y
define_bool CONFIG_SUN_MOUSE y
define_bool CONFIG_SERIAL y
define_bool CONFIG_SUN_SERIAL y
@@ -49,9 +50,6 @@ source drivers/sbus/char/Config.in
source drivers/sbus/audio/Config.in
tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS
-if [ "$CONFIG_PCI" = "y" ]; then
- bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
-fi
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
@@ -66,10 +64,9 @@ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'Solaris binary emulation' CONFIG_SOLARIS_EMUL
fi
-
+source drivers/parport/Config.in
+dep_tristate ' Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
if [ "$CONFIG_PCI" = "y" ]; then
- source drivers/misc/Config.in
- dep_tristate ' Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
tristate 'SUNW,envctrl support' CONFIG_ENVCTRL
fi
endmenu
@@ -105,7 +102,8 @@ if [ "$CONFIG_PCI" = "y" ]; then
dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE
define_bool CONFIG_BLK_DEV_IDEPCI y
define_bool CONFIG_BLK_DEV_IDEDMA y
- define_bool CONFIG_IDEDMA_PCI_AUTO y
+ define_bool CONFIG_IDEDMA_AUTO y
+ define_bool IDEDMA_NEW_DRIVE_LISTINGS y
define_bool CONFIG_BLK_DEV_NS87415 y
define_bool CONFIG_BLK_DEV_CMD646 y
fi
@@ -206,6 +204,10 @@ if [ "$CONFIG_NET" = "y" ]; then
if [ "$CONFIG_PCI" = "y" ]; then
tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
+ tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139
+ tristate 'PCI NE2000 support' CONFIG_NE2K_PCI
+ tristate 'EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
+ tristate 'Adaptec Starfire support' CONFIG_ADAPTEC_STARFIRE
fi
# bool 'FDDI driver support' CONFIG_FDDI
# if [ "$CONFIG_FDDI" = "y" ]; then
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 6d865228d..53a69e509 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -27,6 +27,7 @@ CONFIG_VT_CONSOLE=y
CONFIG_PROM_CONSOLE=y
CONFIG_FB=y
CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CLGEN is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_MATROX is not set
CONFIG_FB_ATY=y
@@ -49,6 +50,7 @@ CONFIG_FONT_SUN8x16=y
# CONFIG_FBCON_FONTS is not set
CONFIG_SBUS=y
CONFIG_SBUSCHAR=y
+CONFIG_BUSMOUSE=y
CONFIG_SUN_MOUSE=y
CONFIG_SERIAL=y
CONFIG_SUN_SERIAL=y
@@ -69,6 +71,7 @@ CONFIG_OBP_FLASH=m
# CONFIG_SUN_BPP is not set
# CONFIG_SUN_VIDEOPIX is not set
CONFIG_SUN_AURORA=m
+# CONFIG_TADPOLE_TS102_UCTRL is not set
CONFIG_APM_RTC_IS_GMT=y
# CONFIG_RTC is not set
@@ -81,7 +84,6 @@ CONFIG_SPARCAUDIO_CS4231=y
# CONFIG_SPARCAUDIO_DBRI is not set
# CONFIG_SPARCAUDIO_DUMMY is not set
CONFIG_SUN_OPENPROMFS=m
-CONFIG_PCI_OLD_PROC=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
@@ -93,12 +95,14 @@ CONFIG_BINFMT_ELF32=y
CONFIG_BINFMT_MISC=m
CONFIG_SOLARIS_EMUL=m
CONFIG_PARPORT=m
-# CONFIG_PARPORT_PC is not set
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_FIFO=y
# CONFIG_PARPORT_AMIGA is not set
# CONFIG_PARPORT_MFC3 is not set
# CONFIG_PARPORT_ATARI is not set
+# CONFIG_PARPORT_SUNBPP is not set
# CONFIG_PARPORT_OTHER is not set
-# CONFIG_PARPORT_1284 is not set
+CONFIG_PARPORT_1284=y
CONFIG_PRINTER=m
CONFIG_ENVCTRL=m
@@ -106,11 +110,7 @@ CONFIG_ENVCTRL=m
# Floppy, IDE, and other block devices
#
CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=m
-CONFIG_MD_STRIPED=m
-CONFIG_MD_MIRRORING=m
-CONFIG_MD_RAID5=m
+# CONFIG_BLK_DEV_MD is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_BLK_DEV_LOOP=m
@@ -123,7 +123,8 @@ CONFIG_BLK_DEV_IDEFLOPPY=m
# CONFIG_BLK_DEV_IDESCSI is not set
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_IDEDMA_AUTO=y
+IDEDMA_NEW_DRIVE_LISTINGS=y
CONFIG_BLK_DEV_NS87415=y
CONFIG_BLK_DEV_CMD646=y
@@ -131,8 +132,9 @@ CONFIG_BLK_DEV_CMD646=y
# Networking options
#
CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
# CONFIG_NETLINK is not set
-# CONFIG_FIREWALL is not set
+# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -148,10 +150,11 @@ CONFIG_INET=y
#
# (it is safe to leave these untouched)
#
-CONFIG_INET_RARP=m
CONFIG_SKB_LARGE=y
CONFIG_IPV6=m
# CONFIG_IPV6_EUI64 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
#
#
@@ -172,7 +175,6 @@ CONFIG_DECNET_RAW=y
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
# CONFIG_NET_HW_FLOWCONTROL is not set
-# CONFIG_CPU_IS_SLOW is not set
#
# QoS and/or fair queueing
@@ -256,6 +258,10 @@ CONFIG_SUNQE=m
CONFIG_MYRI_SBUS=m
CONFIG_DE4X5=m
CONFIG_VORTEX=m
+CONFIG_RTL8139=m
+CONFIG_NE2K_PCI=m
+CONFIG_EEXPRESS_PRO100=m
+CONFIG_ADAPTEC_STARFIRE=m
#
# Unix 98 PTY support
@@ -284,6 +290,8 @@ CONFIG_VFAT_FS=m
CONFIG_EFS_FS=m
CONFIG_ISO9660_FS=m
# CONFIG_JOLIET is not set
+CONFIG_UDF_FS=m
+# CONFIG_UDF_RW is not set
CONFIG_MINIX_FS=m
# CONFIG_NTFS_FS is not set
CONFIG_HPFS_FS=m
@@ -319,13 +327,13 @@ CONFIG_NCP_FS=m
#
# Partition Types
#
-CONFIG_BSD_DISKLABEL=y
-# CONFIG_MAC_PARTITION is not set
-CONFIG_SMD_DISKLABEL=y
-CONFIG_SOLARIS_X86_PARTITION=y
-# CONFIG_SGI_DISKLABEL is not set
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
-CONFIG_AMIGA_PARTITION=y
+# CONFIG_SGI_PARTITION is not set
+CONFIG_SUN_PARTITION=y
CONFIG_NLS=y
#
@@ -356,6 +364,7 @@ CONFIG_NLS=y
# CONFIG_NLS_ISO8859_7 is not set
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index 6934dda6e..34f52698e 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.43 1999/01/02 16:45:53 davem Exp $
+# $Id: Makefile,v 1.46 1999/08/31 04:39:34 davem Exp $
# Makefile for the linux kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
@@ -20,7 +20,9 @@ O_OBJS := process.o setup.o cpu.o idprom.o \
traps.o devices.o auxio.o ioport.o \
irq.o ptrace.o time.o sys_sparc.o signal.o \
unaligned.o sys_sunos32.o sunos_ioctl32.o \
- central.o psycho.o starfire.o
+ central.o pci.o pci_common.o pci_iommu.o \
+ pci_psycho.o pci_sabre.o starfire.o semaphore.o \
+ power.o
OX_OBJS := sparc64_ksyms.o
ifdef CONFIG_PCI
@@ -61,12 +63,16 @@ endif
check_asm: dummy
@echo "/* Automatically generated. Do not edit. */" > asm_offsets.h
@echo "#ifndef __ASM_OFFSETS_H__" >> asm_offsets.h
- @echo "#define __ASM_OFFSETS_H__" >> asm_offsets.h
- @echo "" >> asm_offsets.h
- @echo "#include <linux/config.h>" >> asm_offsets.h
- @echo "" >> asm_offsets.h
- @echo "#ifndef CONFIG_SMP" >> asm_offsets.h
- @echo "" >> asm_offsets.h
+ @echo -e "#define __ASM_OFFSETS_H__\n" >> asm_offsets.h
+ @echo -e "#include <linux/config.h>\n" >> asm_offsets.h
+ @echo '#if defined(__KERNEL__) && !defined(__ASSEMBLY__)' >> asm_offsets.h
+ @if $(CC) -c -m64 -mcmodel=medlow -o /dev/null /dev/null >/dev/null 2>&1; then \
+ echo '# if !((__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))' >> asm_offsets.h; \
+ else \
+ echo '# if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)' >> asm_offsets.h; \
+ fi
+ @echo -e "# error Please issue 'make check_asm' in linux top-level directory first\n# endif\n#endif\n" >> asm_offsets.h
+ @echo -e "#ifndef CONFIG_SMP\n" >> asm_offsets.h
@echo "#include <linux/config.h>" > tmp.c
@echo "#undef CONFIG_SMP" >> tmp.c
@echo "#include <linux/sched.h>" >> tmp.c
@@ -92,11 +98,8 @@ check_asm: dummy
# </hack>
./check_asm >> asm_offsets.h
@rm -f check_asm check_asm.c
- @echo "" >> asm_offsets.h
- @echo "#else /* CONFIG_SMP */" >> asm_offsets.h
- @echo "" >> asm_offsets.h
- @echo "#ifndef SPIN_LOCK_DEBUG" >>asm_offsets.h
- @echo "" >> asm_offsets.h
+ @echo -e "\n#else /* CONFIG_SMP */\n" >> asm_offsets.h
+ @echo -e "#ifndef SPIN_LOCK_DEBUG\n" >>asm_offsets.h
@echo "#include <linux/config.h>" > tmp.c
@echo "#undef CONFIG_SMP" >> tmp.c
@echo "#define CONFIG_SMP 1" >> tmp.c
@@ -124,9 +127,7 @@ check_asm: dummy
# </hack>
./check_asm >> asm_offsets.h
@rm -f check_asm check_asm.c
- @echo "" >> asm_offsets.h
- @echo "#else /* SPIN_LOCK_DEBUG */" >> asm_offsets.h
- @echo "" >> asm_offsets.h
+ @echo -e "\n#else /* SPIN_LOCK_DEBUG */\n" >> asm_offsets.h
@echo "#include <linux/sched.h>" > tmp.c
$(CC) -D__SMP__ -DSPIN_LOCK_DEBUG -E tmp.c -o tmp.i
@echo "/* Automatically generated. Do not edit. */" > check_asm.c
@@ -151,10 +152,8 @@ check_asm: dummy
# </hack>
./check_asm >> asm_offsets.h
@rm -f check_asm check_asm.c
- @echo "#endif /* SPIN_LOCK_DEBUG */" >> asm_offsets.h
- @echo "" >> asm_offsets.h
- @echo "#endif /* CONFIG_SMP */" >> asm_offsets.h
- @echo "" >> asm_offsets.h
+ @echo -e "#endif /* SPIN_LOCK_DEBUG */\n" >> asm_offsets.h
+ @echo -e "#endif /* CONFIG_SMP */\n" >> asm_offsets.h
@echo "#endif /* __ASM_OFFSETS_H__ */" >> asm_offsets.h
@if test -r $(HPATH)/asm/asm_offsets.h; then \
if cmp -s asm_offsets.h $(HPATH)/asm/asm_offsets.h; then \
diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c
index a674399e4..c6bcb6bd7 100644
--- a/arch/sparc64/kernel/auxio.c
+++ b/arch/sparc64/kernel/auxio.c
@@ -22,7 +22,7 @@
/* Probe and map in the Auxiliary I/O register */
unsigned char *auxio_register;
-__initfunc(void auxio_probe(void))
+void __init auxio_probe(void)
{
struct linux_sbus *bus;
struct linux_sbus_device *sdev = 0;
@@ -51,17 +51,7 @@ __initfunc(void auxio_probe(void))
ebus_done:
if (edev) {
- if (check_region(edev->base_address[0],
- sizeof(unsigned int))) {
- prom_printf("%s: Can't get region %lx, %d\n",
- __FUNCTION__, edev->base_address[0],
- sizeof(unsigned int));
- prom_halt();
- }
- request_region(edev->base_address[0],
- sizeof(unsigned int), "LED auxio");
-
- led_auxio = edev->base_address[0];
+ led_auxio = edev->resource[0].start;
outl(0x01, led_auxio);
return;
}
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index bc77266f9..cbbb3557b 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -39,7 +39,8 @@ static int aout32_core_dump(long signr, struct pt_regs * regs);
extern void dump_thread(struct pt_regs *, struct user *);
static struct linux_binfmt aout32_format = {
- NULL, NULL, load_aout32_binary, load_aout32_library, aout32_core_dump
+ NULL, NULL, load_aout32_binary, load_aout32_library, aout32_core_dump,
+ PAGE_SIZE
};
static void set_brk(unsigned long start, unsigned long end)
@@ -63,12 +64,12 @@ static int dump_write(struct file *file, const void *addr, int nr)
#define DUMP_WRITE(addr, nr) \
if (!dump_write(file, (void *)(addr), (nr))) \
- goto close_coredump;
+ goto end_coredump;
#define DUMP_SEEK(offset) \
if (file->f_op->llseek) { \
if (file->f_op->llseek(file,(offset),0) != (offset)) \
- goto close_coredump; \
+ goto end_coredump; \
} else file->f_pos = (offset)
/*
@@ -82,45 +83,17 @@ if (file->f_op->llseek) { \
*/
static inline int
-do_aout32_core_dump(long signr, struct pt_regs * regs)
+do_aout32_core_dump(long signr, struct pt_regs * regs, struct file *file)
{
- struct dentry * dentry = NULL;
- struct inode * inode = NULL;
- struct file * file;
mm_segment_t fs;
int has_dumped = 0;
- char corefile[6+sizeof(current->comm)];
unsigned long dump_start, dump_size;
struct user dump;
# define START_DATA(u) (u.u_tsize)
# define START_STACK(u) ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1))
- if (!current->dumpable || atomic_read(&current->mm->count) != 1)
- return 0;
- current->dumpable = 0;
-
-/* See if we have enough room to write the upage. */
- if (current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE)
- return 0;
fs = get_fs();
set_fs(KERNEL_DS);
- memcpy(corefile,"core.",5);
-#if 0
- memcpy(corefile+5,current->comm,sizeof(current->comm));
-#else
- corefile[4] = '\0';
-#endif
- file = filp_open(corefile,O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
- if (IS_ERR(file))
- goto end_coredump;
- dentry = file->f_dentry;
- inode = dentry->d_inode;
- if (!S_ISREG(inode->i_mode))
- goto close_coredump;
- if (!inode->i_op || !inode->i_op->default_file_ops)
- goto close_coredump;
- if (!file->f_op->write)
- goto close_coredump;
has_dumped = 1;
current->flags |= PF_DUMPCORE;
strncpy(dump.u_comm, current->comm, sizeof(current->comm));
@@ -165,20 +138,18 @@ do_aout32_core_dump(long signr, struct pt_regs * regs)
/* Finally dump the task struct. Not be used by gdb, but could be useful */
set_fs(KERNEL_DS);
DUMP_WRITE(current,sizeof(*current));
-close_coredump:
- filp_close(file, NULL);
end_coredump:
set_fs(fs);
return has_dumped;
}
static int
-aout32_core_dump(long signr, struct pt_regs * regs)
+aout32_core_dump(long signr, struct pt_regs * regs, struct file * file)
{
int retval;
MOD_INC_USE_COUNT;
- retval = do_aout32_core_dump(signr, regs);
+ retval = do_aout32_core_dump(signr, regs, file);
MOD_DEC_USE_COUNT;
return retval;
}
@@ -368,6 +339,16 @@ beyond_if:
current->mm->start_stack =
(unsigned long) create_aout32_tables((char *)bprm->p, bprm);
+ if (!(current->thread.flags & SPARC_FLAG_32BIT)) {
+ unsigned long pgd_cache;
+
+ pgd_cache = ((unsigned long)current->mm->pgd[0])<<11UL;
+ __asm__ __volatile__("stxa\t%0, [%1] %2"
+ : /* no outputs */
+ : "r" (pgd_cache),
+ "r" (TSB_REG), "i" (ASI_DMMU));
+ current->thread.flags |= SPARC_FLAG_32BIT;
+ }
start_thread32(regs, ex.a_entry, current->mm->start_stack);
if (current->flags & PF_PTRACED)
send_sig(SIGTRAP, current, 0);
@@ -472,7 +453,7 @@ load_aout32_library(int fd)
}
-__initfunc(int init_aout32_binfmt(void))
+int __init init_aout32_binfmt(void)
{
return register_binfmt(&aout32_format);
}
diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c
index f0c36d1a7..252a685f4 100644
--- a/arch/sparc64/kernel/binfmt_elf32.c
+++ b/arch/sparc64/kernel/binfmt_elf32.c
@@ -142,7 +142,7 @@ struct elf_prpsinfo32
#ifdef CONFIG_BINFMT_ELF32_MODULE
#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE
#endif
-#define ELF_FLAGS_INIT current->tss.flags |= SPARC_FLAG_32BIT
+#define ELF_FLAGS_INIT current->thread.flags |= SPARC_FLAG_32BIT
MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit SparcLinux binaries on the Ultra");
MODULE_AUTHOR("Eric Youngdale, David S. Miller, Jakub Jelinek");
diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c
index 86518e50e..dbcc0d45f 100644
--- a/arch/sparc64/kernel/cpu.c
+++ b/arch/sparc64/kernel/cpu.c
@@ -33,7 +33,7 @@ struct cpu_fp_info linux_sparc_fpu[] = {
{ 0x22, 0x10, 0, "UltraSparc II integrated FPU"},
{ 0x17, 0x11, 0, "UltraSparc II integrated FPU"},
{ 0x17, 0x12, 0, "UltraSparc IIi integrated FPU"},
- { 0x17, 0x13, 0, "UltraSparc III integrated FPU"},
+ { 0x17, 0x14, 0, "UltraSparc III integrated FPU"},
};
#define NSPARCFPU (sizeof(linux_sparc_fpu)/sizeof(struct cpu_fp_info))
@@ -43,7 +43,7 @@ struct cpu_iu_info linux_sparc_chips[] = {
{ 0x22, 0x10, "TI UltraSparc II (BlackBird)"},
{ 0x17, 0x11, "TI UltraSparc II (BlackBird)"},
{ 0x17, 0x12, "TI UltraSparc IIi"},
- { 0x17, 0x13, "TI UltraSparc III (Cheetah)"}, /* A guess... */
+ { 0x17, 0x14, "TI UltraSparc III (Cheetah)"}, /* A guess... */
};
#define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info))
@@ -58,7 +58,7 @@ char *sparc_fpu_type[64] = { "fpu-oops", };
unsigned int fsr_storage;
-__initfunc(void cpu_probe(void))
+void __init cpu_probe(void)
{
int manuf, impl;
unsigned i, cpuid;
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c
index 0aef0b019..d8085bf06 100644
--- a/arch/sparc64/kernel/devices.c
+++ b/arch/sparc64/kernel/devices.c
@@ -5,8 +5,9 @@
*/
#include <linux/kernel.h>
-#include <linux/tasks.h>
+#include <linux/threads.h>
#include <linux/init.h>
+#include <linux/ioport.h>
#include <asm/page.h>
#include <asm/oplib.h>
@@ -20,14 +21,18 @@ int linux_num_cpus = 0;
extern void cpu_probe(void);
extern unsigned long central_probe(unsigned long);
-__initfunc(unsigned long
-device_scan(unsigned long mem_start))
+unsigned long __init
+device_scan(unsigned long mem_start)
{
char node_str[128];
int nd, prom_node_cpu, thismid;
int cpu_nds[64]; /* One node for each cpu */
int cpu_ctr = 0;
+ /* FIX ME FAST... -DaveM */
+ ioport_resource.end = 0xffffffffffffffffUL;
+ iomem_resource.end = 0xffffffffffffffffUL;
+
prom_getstring(prom_root_node, "device_type", node_str, sizeof(node_str));
prom_printf("Booting Linux...\n");
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
index e64e87299..0b3d16007 100644
--- a/arch/sparc64/kernel/ebus.c
+++ b/arch/sparc64/kernel/ebus.c
@@ -1,7 +1,8 @@
-/* $Id: ebus.c,v 1.36 1999/05/04 03:21:42 davem Exp $
+/* $Id: ebus.c,v 1.44 1999/09/05 09:28:09 ecd Exp $
* ebus.c: PCI to EBus bridge device.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
*/
#include <linux/config.h>
@@ -17,15 +18,7 @@
#include <asm/ebus.h>
#include <asm/oplib.h>
#include <asm/bpp.h>
-
-#undef PROM_DEBUG
-#undef DEBUG_FILL_EBUS_DEV
-
-#ifdef PROM_DEBUG
-#define dprintf prom_printf
-#else
-#define dprintf printk
-#endif
+#include <asm/irq.h>
struct linux_ebus *ebus_chain = 0;
@@ -45,20 +38,20 @@ extern int flash_init(void);
extern int envctrl_init(void);
#endif
-static inline unsigned long ebus_alloc(size_t size)
+static inline void *ebus_alloc(size_t size)
{
- unsigned long mem;
+ void *mem;
- mem = (unsigned long)kmalloc(size, GFP_ATOMIC);
+ mem = kmalloc(size, GFP_ATOMIC);
if (!mem)
panic(__FUNCTION__ ": out of memory");
memset((char *)mem, 0, size);
return mem;
}
-__initfunc(void ebus_intmap_match(struct linux_ebus *ebus,
- struct linux_prom_registers *reg,
- int *interrupt))
+void __init ebus_intmap_match(struct linux_ebus *ebus,
+ struct linux_prom_registers *reg,
+ int *interrupt)
{
unsigned int hi, lo, irq;
int i;
@@ -83,28 +76,43 @@ __initfunc(void ebus_intmap_match(struct linux_ebus *ebus,
prom_halt();
}
-__initfunc(void fill_ebus_child(int node, struct linux_prom_registers *preg,
- struct linux_ebus_child *dev))
+void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
+ struct linux_ebus_child *dev, int non_standard_regs)
{
int regs[PROMREG_MAX];
int irqs[PROMREG_MAX];
- char lbuf[128];
int i, len;
dev->prom_node = node;
- prom_getstring(node, "name", lbuf, sizeof(lbuf));
- strcpy(dev->prom_name, lbuf);
+ prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
+ printk(" (%s)", dev->prom_name);
len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
dev->num_addrs = len / sizeof(regs[0]);
- for (i = 0; i < dev->num_addrs; i++) {
- if (regs[i] >= dev->parent->num_addrs) {
- prom_printf("UGH: property for %s was %d, need < %d\n",
- dev->prom_name, len, dev->parent->num_addrs);
- panic(__FUNCTION__);
+ if (non_standard_regs) {
+ /* This is to handle reg properties which are not
+ * in the parent relative format. One example are
+ * children of the i2c device on CompactPCI systems.
+ *
+ * So, for such devices we just record the property
+ * raw in the child resources.
+ */
+ for (i = 0; i < dev->num_addrs; i++)
+ dev->resource[i].start = regs[i];
+ } else {
+ for (i = 0; i < dev->num_addrs; i++) {
+ int rnum = regs[i];
+ if (rnum >= dev->parent->num_addrs) {
+ prom_printf("UGH: property for %s was %d, need < %d\n",
+ dev->prom_name, len, dev->parent->num_addrs);
+ panic(__FUNCTION__);
+ }
+ dev->resource[i].start = dev->parent->resource[i].start;
+ dev->resource[i].end = dev->parent->resource[i].end;
+ dev->resource[i].flags = IORESOURCE_MEM;
+ dev->resource[i].name = dev->prom_name;
}
- dev->base_address[i] = dev->parent->base_address[regs[i]];
}
len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
@@ -128,52 +136,53 @@ __initfunc(void fill_ebus_child(int node, struct linux_prom_registers *preg,
} else {
dev->num_irqs = len / sizeof(irqs[0]);
for (i = 0; i < dev->num_irqs; i++) {
+ struct pci_pbm_info *pbm = dev->bus->parent;
+ struct pci_controller_info *p = pbm->parent;
+
ebus_intmap_match(dev->bus, preg, &irqs[i]);
- dev->irqs[i] = psycho_irq_build(dev->bus->parent,
- dev->bus->self, irqs[i]);
+ dev->irqs[i] = p->irq_build(p, dev->bus->self, irqs[i]);
}
}
+}
-#ifdef DEBUG_FILL_EBUS_DEV
- dprintf("child '%s': address%s\n", dev->prom_name,
- dev->num_addrs > 1 ? "es" : "");
- for (i = 0; i < dev->num_addrs; i++)
- dprintf(" %016lx\n", dev->base_address[i]);
- if (dev->num_irqs) {
- dprintf(" IRQ%s", dev->num_irqs > 1 ? "s" : "");
- for (i = 0; i < dev->num_irqs; i++)
- dprintf(" %s", __irq_itoa(dev->irqs[i]));
- dprintf("\n");
- }
-#endif
+static int __init child_regs_nonstandard(struct linux_ebus_device *dev)
+{
+ if (!strcmp(dev->prom_name, "i2c"))
+ return 1;
+ return 0;
}
-__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev))
+void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
{
struct linux_prom_registers regs[PROMREG_MAX];
struct linux_ebus_child *child;
int irqs[PROMINTR_MAX];
- char lbuf[128];
int i, n, len;
dev->prom_node = node;
- prom_getstring(node, "name", lbuf, sizeof(lbuf));
- strcpy(dev->prom_name, lbuf);
+ prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
+ printk(" [%s", dev->prom_name);
len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
if (len % sizeof(struct linux_prom_registers)) {
prom_printf("UGH: proplen for %s was %d, need multiple of %d\n",
dev->prom_name, len,
(int)sizeof(struct linux_prom_registers));
- panic(__FUNCTION__);
+ prom_halt();
}
dev->num_addrs = len / sizeof(struct linux_prom_registers);
for (i = 0; i < dev->num_addrs; i++) {
n = (regs[i].which_io - 0x10) >> 2;
- dev->base_address[i] = dev->bus->self->base_address[n];
- dev->base_address[i] += (unsigned long)regs[i].phys_addr;
+ dev->resource[i].start = dev->bus->self->resource[n].start;
+ dev->resource[i].start += (unsigned long)regs[i].phys_addr;
+ dev->resource[i].end =
+ (dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL);
+ dev->resource[i].flags = IORESOURCE_MEM;
+ dev->resource[i].name = dev->prom_name;
+ request_resource(&dev->bus->self->resource[n],
+ &dev->resource[i]);
}
len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
@@ -182,62 +191,51 @@ __initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev))
} else {
dev->num_irqs = len / sizeof(irqs[0]);
for (i = 0; i < dev->num_irqs; i++) {
+ struct pci_pbm_info *pbm = dev->bus->parent;
+ struct pci_controller_info *p = pbm->parent;
+
ebus_intmap_match(dev->bus, &regs[0], &irqs[i]);
- dev->irqs[i] = psycho_irq_build(dev->bus->parent,
- dev->bus->self, irqs[i]);
+ dev->irqs[i] = p->irq_build(p, dev->bus->self, irqs[i]);
}
}
-#ifdef DEBUG_FILL_EBUS_DEV
- dprintf("'%s': address%s\n", dev->prom_name,
- dev->num_addrs > 1 ? "es" : "");
- for (i = 0; i < dev->num_addrs; i++)
- dprintf(" %016lx\n", dev->base_address[i]);
- if (dev->num_irqs) {
- dprintf(" IRQ%s", dev->num_irqs > 1 ? "s" : "");
- for (i = 0; i < dev->num_irqs; i++)
- dprintf(" %s", __irq_itoa(dev->irqs[i]));
- dprintf("\n");
- }
-#endif
if ((node = prom_getchild(node))) {
- dev->children = (struct linux_ebus_child *)
- ebus_alloc(sizeof(struct linux_ebus_child));
+ printk(" ->");
+ dev->children = ebus_alloc(sizeof(struct linux_ebus_child));
child = dev->children;
child->next = 0;
child->parent = dev;
child->bus = dev->bus;
- fill_ebus_child(node, &regs[0], child);
+ fill_ebus_child(node, &regs[0],
+ child, child_regs_nonstandard(dev));
while ((node = prom_getsibling(node))) {
- child->next = (struct linux_ebus_child *)
- ebus_alloc(sizeof(struct linux_ebus_child));
+ child->next = ebus_alloc(sizeof(struct linux_ebus_child));
child = child->next;
child->next = 0;
child->parent = dev;
child->bus = dev->bus;
- fill_ebus_child(node, &regs[0], child);
+ fill_ebus_child(node, &regs[0],
+ child, child_regs_nonstandard(dev));
}
}
+ printk("]");
}
extern void clock_probe(void);
+extern void power_init(void);
-__initfunc(void ebus_init(void))
+void __init ebus_init(void)
{
- struct linux_prom_pci_registers regs[PROMREG_MAX];
- struct linux_pbm_info *pbm;
+ struct pci_pbm_info *pbm;
struct linux_ebus_device *dev;
struct linux_ebus *ebus;
struct pci_dev *pdev;
struct pcidev_cookie *cookie;
- char lbuf[128];
- unsigned long addr, *base;
unsigned short pci_command;
- int nd, len, ebusnd;
- int reg, rng, nreg;
+ int nd, ebusnd;
int num_ebus = 0;
if (!pci_present())
@@ -246,17 +244,13 @@ __initfunc(void ebus_init(void))
pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0);
if (!pdev) {
printk("ebus: No EBus's found.\n");
-#ifdef PROM_DEBUG
- dprintf("ebus: No EBus's found.\n");
-#endif
return;
}
cookie = pdev->sysdata;
ebusnd = cookie->prom_node;
- ebus_chain = ebus = (struct linux_ebus *)
- ebus_alloc(sizeof(struct linux_ebus));
+ ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus));
ebus->next = 0;
while (ebusnd) {
@@ -273,9 +267,6 @@ __initfunc(void ebus_init(void))
if (ebus == ebus_chain) {
ebus_chain = NULL;
printk("ebus: No EBus's found.\n");
-#ifdef PROM_DEBUG
- dprintf("ebus: No EBus's found.\n");
-#endif
return;
}
break;
@@ -286,14 +277,10 @@ __initfunc(void ebus_init(void))
continue;
}
printk("ebus%d:", num_ebus);
-#ifdef PROM_DEBUG
- dprintf("ebus%d:", num_ebus);
-#endif
- prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf));
+ prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name));
+ ebus->index = num_ebus;
ebus->prom_node = ebusnd;
- strcpy(ebus->prom_name, lbuf);
-
ebus->self = pdev;
ebus->parent = pbm = cookie->pbm;
@@ -306,49 +293,7 @@ __initfunc(void ebus_init(void))
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
/* NOTE: Cache line size is in 32-bit word units. */
- pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x10);
-
- len = prom_getproperty(ebusnd, "reg", (void *)regs,
- sizeof(regs));
- if (len == 0 || len == -1) {
- prom_printf("%s: can't find reg property\n",
- __FUNCTION__);
- prom_halt();
- }
- nreg = len / sizeof(struct linux_prom_pci_registers);
-
- base = &ebus->self->base_address[0];
- for (reg = 0; reg < nreg; reg++) {
- if (!(regs[reg].phys_hi & 0x03000000))
- continue;
-
- for (rng = 0; rng < pbm->num_pbm_ranges; rng++) {
- struct linux_prom_pci_ranges *rp =
- &pbm->pbm_ranges[rng];
-
- if ((rp->child_phys_hi ^ regs[reg].phys_hi)
- & 0x03000000)
- continue;
-
- addr = (u64)regs[reg].phys_lo;
- addr += (u64)regs[reg].phys_mid << 32UL;
- addr += (u64)rp->parent_phys_lo;
- addr += (u64)rp->parent_phys_hi << 32UL;
- *base++ = (unsigned long)__va(addr);
-
- printk(" %lx[%x]", (unsigned long)__va(addr),
- regs[reg].size_lo);
-#ifdef PROM_DEBUG
- dprintf(" %lx[%x]", (unsigned long)__va(addr),
- regs[reg].size_lo);
-#endif
- break;
- }
- }
- printk("\n");
-#ifdef PROM_DEBUG
- dprintf("\n");
-#endif
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 64/sizeof(u32));
prom_ebus_ranges_init(ebus);
prom_ebus_intmap_init(ebus);
@@ -357,8 +302,7 @@ __initfunc(void ebus_init(void))
if (!nd)
goto next_ebus;
- ebus->devices = (struct linux_ebus_device *)
- ebus_alloc(sizeof(struct linux_ebus_device));
+ ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device));
dev = ebus->devices;
dev->next = 0;
@@ -367,8 +311,7 @@ __initfunc(void ebus_init(void))
fill_ebus_device(nd, dev);
while ((nd = prom_getsibling(nd))) {
- dev->next = (struct linux_ebus_device *)
- ebus_alloc(sizeof(struct linux_ebus_device));
+ dev->next = ebus_alloc(sizeof(struct linux_ebus_device));
dev = dev->next;
dev->next = 0;
@@ -378,6 +321,8 @@ __initfunc(void ebus_init(void))
}
next_ebus:
+ printk("\n");
+
pdev = pci_find_device(PCI_VENDOR_ID_SUN,
PCI_DEVICE_ID_SUN_EBUS, pdev);
if (!pdev)
@@ -386,8 +331,7 @@ __initfunc(void ebus_init(void))
cookie = pdev->sysdata;
ebusnd = cookie->prom_node;
- ebus->next = (struct linux_ebus *)
- ebus_alloc(sizeof(struct linux_ebus));
+ ebus->next = ebus_alloc(sizeof(struct linux_ebus));
ebus = ebus->next;
ebus->next = 0;
++num_ebus;
@@ -409,4 +353,5 @@ __initfunc(void ebus_init(void))
flash_init();
#endif
clock_probe();
+ power_init();
}
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 4134dcc3a..fbd64a507 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.103 1999/05/08 03:00:21 davem Exp $
+/* $Id: entry.S,v 1.107 1999/08/31 19:25:29 davem Exp $
* arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points.
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -42,13 +42,13 @@ sparc64_vpte_patchme2:
/* This is trivial with the new code... */
.globl do_fpdis
do_fpdis:
- ldub [%g6 + AOFF_task_tss + AOFF_thread_fpsaved], %g5 ! Load Group
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_fpsaved], %g5 ! Load Group
sethi %hi(TSTATE_PEF), %g4 ! IEU0
wr %g0, FPRS_FEF, %fprs ! LSU Group+4bubbles
andcc %g5, FPRS_FEF, %g0 ! IEU1 Group
be,a,pt %icc, 1f ! CTI
clr %g7 ! IEU0
- ldub [%g6 + AOFF_task_tss + AOFF_thread_gsr], %g7 ! Load Group
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_gsr], %g7 ! Load Group
1: andcc %g5, FPRS_DL, %g0 ! IEU1
bne,pn %icc, 2f ! CTI
fzero %f0 ! FPA
@@ -157,7 +157,7 @@ fpdis_exit:
flush %g6
fpdis_exit2:
wr %g7, 0, %gsr
- ldx [%g6 + AOFF_task_tss + AOFF_thread_xfsr], %fsr
+ ldx [%g6 + AOFF_task_thread + AOFF_thread_xfsr], %fsr
rdpr %tstate, %g3
or %g3, %g4, %g3 ! anal...
wrpr %g3, %tstate
@@ -167,13 +167,13 @@ fpdis_exit2:
.globl do_fptrap
.align 32
do_fptrap:
- ldub [%g6 + AOFF_task_tss + AOFF_thread_fpsaved], %g3
- stx %fsr, [%g6 + AOFF_task_tss + AOFF_thread_xfsr]
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_fpsaved], %g3
+ stx %fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr]
rd %fprs, %g1
or %g3, %g1, %g3
- stb %g3, [%g6 + AOFF_task_tss + AOFF_thread_fpsaved]
+ stb %g3, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved]
rd %gsr, %g3
- stb %g3, [%g6 + AOFF_task_tss + AOFF_thread_gsr]
+ stb %g3, [%g6 + AOFF_task_thread + AOFF_thread_gsr]
mov SECONDARY_CONTEXT, %g3
add %g6, AOFF_task_fpregs, %g2
ldxa [%g3] ASI_DMMU, %g5
@@ -478,6 +478,97 @@ __do_instruction_access_exception:
ba,pt %xcc, rtrap
clr %l6
+ /* This is the trap handler entry point for ECC correctable
+ * errors. They are corrected, but we listen for the trap
+ * so that the event can be logged.
+ *
+ * Disrupting errors are either:
+ * 1) single-bit ECC errors during UDB reads to system
+ * memory
+ * 2) data parity errors during write-back events
+ *
+ * As far as I can make out from the manual, the CEE trap
+ * is only for correctable errors during memory read
+ * accesses by the front-end of the processor.
+ *
+ * The code below is only for trap level 1 CEE events,
+ * as it is the only situation where we can safely record
+ * and log. For trap level >1 we just clear the CE bit
+ * in the AFSR and return.
+ */
+
+ /* Our trap handling infrastructure allows us to preserve
+ * two 64-bit values during etrap for arguments to
+ * subsequent C code. Therefore we encode the information
+ * as follows:
+ *
+ * value 1) Full 64-bits of AFAR
+ * value 2) Low 33-bits of AFSR, then bits 33-->42
+ * are UDBL error status and bits 43-->52
+ * are UDBH error status
+ */
+ .align 64
+ .globl cee_trap
+cee_trap:
+ ldxa [%g0] ASI_AFSR, %g1 ! Read AFSR
+ ldxa [%g0] ASI_AFAR, %g2 ! Read AFAR
+ sllx %g1, 31, %g1 ! Clear reserved bits
+ srlx %g1, 31, %g1 ! in AFSR
+
+ /* NOTE: UltraSparc-I/II have high and low UDB error
+ * registers, corresponding to the two UDB units
+ * present on those chips. UltraSparc-IIi only
+ * has a single UDB, called "SDB" in the manual.
+ * For IIi the upper UDB register always reads
+ * as zero so for our purposes things will just
+ * work with the checks below.
+ */
+ ldxa [%g0] ASI_UDBL_ERROR_R, %g3 ! Read UDB-Low error status
+ andcc %g3, (1 << 8), %g4 ! Check CE bit
+ sllx %g3, (64 - 10), %g3 ! Clear reserved bits
+ srlx %g3, (64 - 10), %g3 ! in UDB-Low error status
+
+ sllx %g3, (33 + 0), %g3 ! Shift up to encoding area
+ or %g1, %g3, %g1 ! Or it in
+ be,pn %xcc, 1f ! Branch if CE bit was clear
+ nop
+ stxa %g4, [%g0] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBL
+ membar #Sync ! Synchronize ASI stores
+1: mov 0x18, %g5 ! Addr of UDB-High error status
+ ldxa [%g5] ASI_UDBH_ERROR_R, %g3 ! Read it
+
+ andcc %g3, (1 << 8), %g4 ! Check CE bit
+ sllx %g3, (64 - 10), %g3 ! Clear reserved bits
+ srlx %g3, (64 - 10), %g3 ! in UDB-High error status
+ sllx %g3, (33 + 10), %g3 ! Shift up to encoding area
+ or %g1, %g3, %g1 ! Or it in
+ be,pn %xcc, 1f ! Branch if CE bit was clear
+ nop
+ nop
+
+ stxa %g4, [%g5] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBH
+ membar #Sync ! Synchronize ASI stores
+1: mov 1, %g5 ! AFSR CE bit is
+ sllx %g5, 20, %g5 ! bit 20
+ stxa %g5, [%g0] ASI_AFSR ! Clear CE sticky bit in AFSR
+ membar #Sync ! Synchronize ASI stores
+ sllx %g2, (64 - 41), %g2 ! Clear reserved bits
+ srlx %g2, (64 - 41), %g2 ! in latched AFAR
+
+ andn %g2, 0x0f, %g2 ! Finish resv bit clearing
+ mov %g1, %g4 ! Move AFSR+UDB* into save reg
+ mov %g2, %g5 ! Move AFAR into save reg
+ rdpr %pil, %g2
+ wrpr %g0, 15, %pil
+ ba,pt %xcc, etrap_irq
+ rd %pc, %g7
+ mov %l4, %o0
+
+ mov %l5, %o1
+ call cee_log
+ add %sp, STACK_BIAS + REGWIN_SZ, %o2
+ ba,a,pt %xcc, rtrap_clr_l6
+
.globl __do_privact
__do_privact:
mov TLB_SFSR, %g3
@@ -633,41 +724,28 @@ execve_merge:
jmpl %g1, %g0
add %sp, STACK_BIAS + REGWIN_SZ, %o0
- .globl sys_pipe, sys_execve, sys_sigpause, sys_nis_syscall
+ .globl sys_pipe, sys_sigpause, sys_nis_syscall
.globl sys_sigsuspend, sys_rt_sigsuspend, sys32_rt_sigsuspend
- .globl sys_sigreturn, sys_rt_sigreturn
+ .globl sys_rt_sigreturn
.globl sys32_sigreturn, sys32_rt_sigreturn
.globl sys32_execve, sys_ptrace
.globl sys_sigaltstack, sys32_sigaltstack
.globl sys32_sigstack
.align 32
-sys_pipe: sethi %hi(sparc_pipe), %g1
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
- jmpl %g1 + %lo(sparc_pipe), %g0
- nop
-sys_nis_syscall:sethi %hi(c_sys_nis_syscall), %g1
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
- jmpl %g1 + %lo(c_sys_nis_syscall), %g0
- nop
-
+sys_pipe: ba,pt %xcc, sparc_pipe
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+sys_nis_syscall:ba,pt %xcc, c_sys_nis_syscall
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
sys_memory_ordering:
- sethi %hi(sparc_memory_ordering), %g1
- add %sp, STACK_BIAS + REGWIN_SZ, %o1
- jmpl %g1 + %lo(sparc_memory_ordering), %g0
- nop
-sys_sigaltstack:sethi %hi(do_sigaltstack), %g1
- add %i6, STACK_BIAS, %o2
- jmpl %g1 + %lo(do_sigaltstack), %g1
- nop
-sys32_sigstack: sethi %hi(do_sys32_sigstack), %g1
- mov %i6, %o2
- jmpl %g1 + %lo(do_sys32_sigstack), %g1
- nop
+ ba,pt %xcc, sparc_memory_ordering
+ add %sp, STACK_BIAS + REGWIN_SZ, %o1
+sys_sigaltstack:ba,pt %xcc, do_sigaltstack
+ add %i6, STACK_BIAS, %o2
+sys32_sigstack: ba,pt %xcc, do_sys32_sigstack
+ mov %i6, %o2
sys32_sigaltstack:
- sethi %hi(do_sys32_sigaltstack), %g1
- mov %i6, %o2
- jmpl %g1 + %lo(do_sys32_sigaltstack), %g1
- nop
+ ba,pt %xcc, do_sys32_sigaltstack
+ mov %i6, %o2
.align 32
sys_sigsuspend: add %sp, STACK_BIAS + REGWIN_SZ, %o0
@@ -689,10 +767,6 @@ sys_sigpause: add %sp, STACK_BIAS + REGWIN_SZ, %o1
call do_sigpause
add %o7, 1f-.-4, %o7
nop
-sys_sigreturn: add %sp, STACK_BIAS + REGWIN_SZ, %o0
- call do_sigreturn
- add %o7, 1f-.-4, %o7
- nop
sys32_sigreturn:
add %sp, STACK_BIAS + REGWIN_SZ, %o0
call do_sigreturn32
@@ -761,38 +835,30 @@ sys_clone: flushw
ba,pt %xcc, do_fork
add %sp, STACK_BIAS + REGWIN_SZ, %o2
ret_from_syscall:
- /* Clear SPARC_FLAG_NEWCHILD, switch_to leaves tss.flags in
+ /* Clear SPARC_FLAG_NEWCHILD, switch_to leaves thread.flags in
* %o7 for us. Check performance counter stuff too.
*/
-#ifdef __SMP__
- andn %o7, 0x100, %l0
+ andn %o7, SPARC_FLAG_NEWCHILD, %l0
mov %g5, %o0 /* 'prev' */
call schedule_tail
- sth %l0, [%g6 + AOFF_task_tss + AOFF_thread_flags]
-#else
- andn %o7, 0x100, %l0
- sth %l0, [%g6 + AOFF_task_tss + AOFF_thread_flags]
-#endif
- andcc %l0, 0x200, %g0
+ stb %l0, [%g6 + AOFF_task_thread + AOFF_thread_flags]
+ andcc %l0, SPARC_FLAG_PERFCTR, %g0
be,pt %icc, 1f
nop
- ldx [%g6 + AOFF_task_tss + AOFF_thread_pcr_reg], %o7
+ ldx [%g6 + AOFF_task_thread + AOFF_thread_pcr_reg], %o7
wr %g0, %o7, %pcr
wr %g0, %g0, %pic
1: b,pt %xcc, ret_sys_call
ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0
sparc_exit: rdpr %otherwin, %g1
- rdpr %pstate, %g2
- wrpr %g2, PSTATE_IE, %pstate
+ wrpr %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV), %pstate
rdpr %cansave, %g3
add %g3, %g1, %g3
wrpr %g3, 0x0, %cansave
wrpr %g0, 0x0, %otherwin
- wrpr %g2, 0x0, %pstate
- mov %o7, %l5
- sth %g0, [%g6 + AOFF_task_tss + AOFF_thread_w_saved]
- call sys_exit
- mov %l5, %o7
+ wrpr %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE), %pstate
+ ba,pt %xcc, sys_exit
+ stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_w_saved]
linux_sparc_ni_syscall:
sethi %hi(sys_ni_syscall), %l7
diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
index 6a94cf3ab..d243a43b3 100644
--- a/arch/sparc64/kernel/etrap.S
+++ b/arch/sparc64/kernel/etrap.S
@@ -1,4 +1,4 @@
-/* $Id: etrap.S,v 1.41 1999/05/25 16:53:09 jj Exp $
+/* $Id: etrap.S,v 1.42 1999/07/30 09:35:18 davem Exp $
* etrap.S: Preparing for entry into the kernel on Sparc V9.
*
* Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -56,7 +56,7 @@ etrap_irq: rdpr %tstate, %g1 ! Single Group
wrpr %g0, 0, %canrestore ! Single Group+4bubbles
sll %g2, 3, %g2 ! IEU0 Group
mov 1, %l5 ! IEU1
- stb %l5, [%l6 + AOFF_task_tss + AOFF_thread_fpdepth] ! Store
+ stb %l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth] ! Store
wrpr %g3, 0, %otherwin ! Single Group+4bubbles
wrpr %g2, 0, %wstate ! Single Group+4bubbles
stxa %g0, [%l4] ASI_DMMU ! Store Group
@@ -89,11 +89,11 @@ etrap_irq: rdpr %tstate, %g1 ! Single Group
jmpl %l2 + 0x4, %g0 ! CTI Group
mov %l6, %g6 ! IEU0
-3: ldub [%l6 + AOFF_task_tss + AOFF_thread_fpdepth], %l5 ! Load Group
- add %l6, AOFF_task_tss + AOFF_thread_fpsaved + 1, %l4 ! IEU0
+3: ldub [%l6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5 ! Load Group
+ add %l6, AOFF_task_thread + AOFF_thread_fpsaved + 1, %l4 ! IEU0
srl %l5, 1, %l3 ! IEU0 Group
add %l5, 2, %l5 ! IEU1
- stb %l5, [%l6 + AOFF_task_tss + AOFF_thread_fpdepth] ! Store
+ stb %l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth] ! Store
ba,pt %xcc, 2b ! CTI
stb %g0, [%l4 + %l3] ! Store Group
diff --git a/arch/sparc64/kernel/idprom.c b/arch/sparc64/kernel/idprom.c
index 08a4a6b6a..3b6789e09 100644
--- a/arch/sparc64/kernel/idprom.c
+++ b/arch/sparc64/kernel/idprom.c
@@ -1,4 +1,4 @@
-/* $Id: idprom.c,v 1.2 1997/04/17 02:28:10 miguel Exp $
+/* $Id: idprom.c,v 1.3 1999/08/31 06:54:53 davem Exp $
* idprom.c: Routines to load the idprom into kernel addresses and
* interpret the data contained within.
*
@@ -16,7 +16,7 @@ struct idprom *idprom;
static struct idprom idprom_buffer;
/* Calculate the IDPROM checksum (xor of the data bytes). */
-__initfunc(static unsigned char calc_idprom_cksum(struct idprom *idprom))
+static unsigned char __init calc_idprom_cksum(struct idprom *idprom)
{
unsigned char cksum, i, *ptr = (unsigned char *)idprom;
@@ -27,7 +27,7 @@ __initfunc(static unsigned char calc_idprom_cksum(struct idprom *idprom))
}
/* Create a local IDPROM copy and verify integrity. */
-__initfunc(void idprom_init(void))
+void __init idprom_init(void)
{
prom_get_idprom((char *) &idprom_buffer, sizeof(idprom_buffer));
diff --git a/arch/sparc64/kernel/init_task.c b/arch/sparc64/kernel/init_task.c
index 66869404d..d256b5761 100644
--- a/arch/sparc64/kernel/init_task.c
+++ b/arch/sparc64/kernel/init_task.c
@@ -6,7 +6,6 @@
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index 833331202..0affcf0eb 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.63 1999/06/09 04:56:14 davem Exp $
+/* $Id: ioctl32.c,v 1.68 1999/09/10 05:59:25 davem Exp $
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -38,6 +38,7 @@
#include <linux/ext2_fs.h>
#include <linux/videodev.h>
#include <linux/netdevice.h>
+#include <linux/raw.h>
#include <scsi/scsi.h>
/* Ugly hack. */
@@ -409,6 +410,7 @@ struct ifreq32 {
int ifru_mtu;
struct ifmap32 ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
+ char ifru_newname[IFNAMSIZ];
__kernel_caddr_t32 ifru_data;
} ifr_ifru;
};
@@ -420,7 +422,7 @@ struct ifconf32 {
static int dev_ifname32(unsigned int fd, unsigned long arg)
{
- struct device *dev;
+ struct net_device *dev;
struct ifreq32 ifr32;
int err;
@@ -431,6 +433,8 @@ static int dev_ifname32(unsigned int fd, unsigned long arg)
if (!dev)
return -ENODEV;
+ strcpy(ifr32.ifr_name, dev->name);
+
err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32));
return (err ? -EFAULT : 0);
}
@@ -570,7 +574,7 @@ static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long ar
if(cmd == SIOCETHTOOL)
len = sizeof(struct ethtool_cmd);
if(cmd == SIOCGPPPVER)
- len = strlen(PPP_VERSION) + 1;
+ len = strlen((char *)ifr.ifr_data) + 1;
else if(cmd == SIOCGPPPCSTATS)
len = sizeof(struct ppp_comp_stats);
else
@@ -2366,6 +2370,10 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
case AUTOFS_IOC_PROTOVER:
case AUTOFS_IOC_EXPIRE:
+ /* Raw devices */
+ case RAW_SETBIND:
+ case RAW_GETBIND:
+
error = sys_ioctl (fd, cmd, arg);
goto out;
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 6eccb883a..598cece4e 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.76 1999/04/02 14:54:30 davem Exp $
+/* $Id: irq.c,v 1.78 1999/08/31 06:54:54 davem Exp $
* irq.c: UltraSparc IRQ handling/init/registry.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -31,11 +31,6 @@
#include <asm/hardirq.h>
#include <asm/softirq.h>
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
-#include <asm/pbm.h>
-#endif
-
/* Internal flag, should not be visible elsewhere at all. */
#define SA_IMAP_MASKED 0x100
#define SA_DMA_SYNC 0x200
@@ -79,15 +74,6 @@ struct irqaction *irq_action[NR_IRQS+1] = {
NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
};
-/* Only 8-bits are available, be careful. -DaveM */
-#define IBF_DMA_SYNC 0x01 /* DMA synchronization behind PCI bridge needed. */
-#define IBF_PCI 0x02 /* Indicates PSYCHO/SCHIZO PCI interrupt. */
-#define IBF_ACTIVE 0x04 /* This interrupt is active and has a handler. */
-#define IBF_MULTI 0x08 /* On PCI, indicates shared bucket. */
-
-#define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq))
-#define __irq(bucket) ((unsigned int)(unsigned long)(bucket))
-
int get_irq_list(char *buf)
{
int i, len = 0;
@@ -183,67 +169,22 @@ offset(imap_pmgmt),
/* Convert Interrupt Mapping register pointer to assosciated
* Interrupt Clear register pointer, SYSIO specific version.
*/
-static unsigned int *sysio_imap_to_iclr(unsigned int *imap)
+static volatile unsigned int *sysio_imap_to_iclr(volatile unsigned int *imap)
{
unsigned long diff;
diff = offset(iclr_unused0) - offset(imap_slot0);
- return (unsigned int *) (((unsigned long)imap) + diff);
+ return (volatile unsigned int *) (((unsigned long)imap) + diff);
}
#undef offset
-#ifdef CONFIG_PCI
-/* PCI PSYCHO INO number to Sparc PIL level. */
-unsigned char psycho_ino_to_pil[] = {
- 7, 5, 4, 2, /* PCI A slot 0 Int A, B, C, D */
- 7, 5, 4, 2, /* PCI A slot 1 Int A, B, C, D */
- 7, 5, 4, 2, /* PCI A slot 2 Int A, B, C, D */
- 7, 5, 4, 2, /* PCI A slot 3 Int A, B, C, D */
- 6, 4, 3, 1, /* PCI B slot 0 Int A, B, C, D */
- 6, 4, 3, 1, /* PCI B slot 1 Int A, B, C, D */
- 6, 4, 3, 1, /* PCI B slot 2 Int A, B, C, D */
- 6, 4, 3, 1, /* PCI B slot 3 Int A, B, C, D */
- 3, /* SCSI */
- 5, /* Ethernet */
- 8, /* Parallel Port */
- 13, /* Audio Record */
- 14, /* Audio Playback */
- 15, /* PowerFail */
- 3, /* second SCSI */
- 11, /* Floppy */
- 2, /* Spare Hardware */
- 9, /* Keyboard */
- 4, /* Mouse */
- 12, /* Serial */
- 10, /* Timer 0 */
- 11, /* Timer 1 */
- 15, /* Uncorrectable ECC */
- 15, /* Correctable ECC */
- 15, /* PCI Bus A Error */
- 15, /* PCI Bus B Error */
- 1, /* Power Management */
-};
-
-/* INO number to IMAP register offset for PSYCHO external IRQ's. */
-#define psycho_offset(x) ((unsigned long)(&(((struct psycho_regs *)0)->x)))
-
-#define psycho_imap_offset(ino) \
- ((ino & 0x20) ? (psycho_offset(imap_scsi) + (((ino) & 0x1f) << 3)) : \
- (psycho_offset(imap_a_slot0) + (((ino) & 0x3c) << 1)))
-
-#define psycho_iclr_offset(ino) \
- ((ino & 0x20) ? (psycho_offset(iclr_scsi) + (((ino) & 0x1f) << 3)) : \
- (psycho_offset(iclr_a_slot0[0]) + (((ino) & 0x1f)<<3)))
-
-#endif
-
/* Now these are always passed a true fully specified sun4u INO. */
void enable_irq(unsigned int irq)
{
extern int this_is_starfire;
struct ino_bucket *bucket = __bucket(irq);
- unsigned int *imap;
+ volatile unsigned int *imap;
unsigned long tid;
imap = bucket->imap;
@@ -257,7 +198,7 @@ void enable_irq(unsigned int irq)
: "i" (ASI_UPA_CONFIG));
tid = ((tid & UPA_CONFIG_MID) << 9);
} else {
- extern unsigned int starfire_translate(unsigned int *imap,
+ extern unsigned int starfire_translate(volatile unsigned int *imap,
unsigned int upaid);
tid = (starfire_translate(imap, current->processor) << 26);
@@ -278,7 +219,7 @@ void enable_irq(unsigned int irq)
void disable_irq(unsigned int irq)
{
struct ino_bucket *bucket = __bucket(irq);
- unsigned int *imap;
+ volatile unsigned int *imap;
imap = bucket->imap;
if (imap != NULL) {
@@ -306,7 +247,7 @@ static struct ino_bucket pil0_dummy_bucket = {
NULL, /* imap */
};
-unsigned int build_irq(int pil, int inofixup, unsigned int *iclr, unsigned int *imap)
+unsigned int build_irq(int pil, int inofixup, volatile unsigned int *iclr, volatile unsigned int *imap)
{
struct ino_bucket *bucket;
int ino;
@@ -365,7 +306,7 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
struct sysio_regs *sregs = sbus->iommu->sysio_regs;
unsigned long offset;
int pil;
- unsigned int *imap, *iclr;
+ volatile unsigned int *imap, *iclr;
int sbus_level = 0;
pil = sysio_ino_to_pil[ino];
@@ -380,7 +321,7 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
panic("BAD SYSIO IRQ offset...");
}
offset += ((unsigned long)sregs);
- imap = ((unsigned int *)offset);
+ imap = ((volatile unsigned int *)offset);
/* SYSIO inconsistancy. For external SLOTS, we have to select
* the right ICLR register based upon the lower SBUS irq level
@@ -412,81 +353,11 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
iclraddr = (unsigned long) iclr;
iclraddr += ((sbus_level - 1) * 8);
- iclr = (unsigned int *) iclraddr;
+ iclr = (volatile unsigned int *) iclraddr;
}
return build_irq(pil, sbus_level, iclr, imap);
}
-#ifdef CONFIG_PCI
-unsigned int psycho_build_irq(void *buscookie, int imap_off, int ino, int need_dma_sync)
-{
- struct linux_psycho *psycho = (struct linux_psycho *)buscookie;
- struct psycho_regs *pregs = psycho->psycho_regs;
- unsigned long addr;
- struct ino_bucket *bucket;
- int pil;
- unsigned int *imap, *iclr;
- int inofixup = 0;
-
- pil = psycho_ino_to_pil[ino & PCI_IRQ_INO];
-
- addr = (unsigned long) &pregs->imap_a_slot0;
- addr = addr + imap_off;
- imap = ((unsigned int *)addr) + 1;
-
- addr = (unsigned long) pregs;
- addr += psycho_iclr_offset(ino & (PCI_IRQ_INO));
- iclr = ((unsigned int *)addr) + 1;
-
- if(!(ino & 0x20))
- inofixup = ino & 0x03;
-
- /* First check for sharing. */
- ino = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)) + inofixup;
- if (ino > NUM_IVECS) {
- prom_printf("PSYCHO: Invalid INO %04x (%d:%d:%016lx:%016lx)\n",
- ino, pil, inofixup, iclr, imap);
- prom_halt();
- }
- bucket = &ivector_table[ino];
- if(bucket->flags & IBF_ACTIVE) {
- void *old_handler = bucket->irq_info;
- unsigned long flags;
-
- if(old_handler == NULL) {
- prom_printf("PSYCHO: Active bucket, but no handler.\n");
- prom_halt();
- }
- save_and_cli(flags);
- if((bucket->flags & IBF_MULTI) == 0) {
- void **vector;
-
- vector = kmalloc(sizeof(void *) * 4,
- GFP_KERNEL);
-
- /* We might have slept. */
- if((bucket->flags & IBF_MULTI) != 0) {
- kfree(vector);
- } else {
- vector[0] = old_handler;
- vector[1] = vector[2] = vector[3] = NULL;
- bucket->irq_info = vector;
- bucket->flags |= IBF_MULTI;
- }
- }
- restore_flags(flags);
- } else {
- /* Just init the bucket */
- bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
- }
- if (need_dma_sync)
- bucket->flags |= IBF_DMA_SYNC;
-
- bucket->flags |= IBF_PCI;
- return __irq(bucket);
-}
-#endif
-
static void atomic_bucket_insert(struct ino_bucket *bucket)
{
unsigned long pstate;
@@ -731,7 +602,7 @@ void free_irq(unsigned int irq, void *dev_id)
*(bucket->pil + irq_action) = action->next;
if(action->flags & SA_IMAP_MASKED) {
- unsigned int *imap = bucket->imap;
+ volatile unsigned int *imap = bucket->imap;
void **vector, *orig;
int ent;
@@ -1286,7 +1157,7 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu)
{
extern int this_is_starfire;
struct ino_bucket *bucket = __bucket(p->mask);
- unsigned int *imap = bucket->imap;
+ volatile unsigned int *imap = bucket->imap;
unsigned int tid;
/* Never change this, it causes problems on Ex000 systems. */
@@ -1296,7 +1167,7 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu)
if(this_is_starfire == 0) {
tid = __cpu_logical_map[goal_cpu] << 26;
} else {
- extern unsigned int starfire_translate(unsigned int *imap,
+ extern unsigned int starfire_translate(volatile unsigned int *imap,
unsigned int upaid);
tid = (starfire_translate(imap, __cpu_logical_map[goal_cpu]) << 26);
@@ -1399,7 +1270,7 @@ void enable_prom_timer(void)
prom_timers->count0 = 0;
}
-__initfunc(void init_IRQ(void))
+void __init init_IRQ(void)
{
static int called = 0;
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
new file mode 100644
index 000000000..1776e6d7e
--- /dev/null
+++ b/arch/sparc64/kernel/pci.c
@@ -0,0 +1,339 @@
+/* $Id: pci.c,v 1.6 1999/09/08 03:40:41 davem Exp $
+ * pci.c: UltraSparc PCI controller support.
+ *
+ * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be)
+ * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/capability.h>
+#include <linux/errno.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/pbm.h>
+#include <asm/irq.h>
+#include <asm/ebus.h>
+
+unsigned long pci_dvma_v2p_hash[PCI_DVMA_HASHSZ];
+unsigned long pci_dvma_p2v_hash[PCI_DVMA_HASHSZ];
+unsigned long pci_memspace_mask = 0xffffffffUL;
+
+#ifndef CONFIG_PCI
+/* A "nop" PCI implementation. */
+int pcibios_present(void) { return 0; }
+asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn,
+ unsigned long off, unsigned long len,
+ unsigned char *buf)
+{
+ return 0;
+}
+asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn,
+ unsigned long off, unsigned long len,
+ unsigned char *buf)
+{
+ return 0;
+}
+#else
+
+/* List of all PCI controllers found in the system. */
+spinlock_t pci_controller_lock = SPIN_LOCK_UNLOCKED;
+struct pci_controller_info *pci_controller_root = NULL;
+
+/* Each PCI controller found gets a unique index. */
+int pci_num_controllers = 0;
+
+/* Given an 8-bit PCI bus number, this yields the
+ * controlling PBM module info.
+ *
+ * Some explanation is in order here. The Linux APIs for
+ * the PCI subsystem require that the configuration space
+ * types are enough to signify PCI configuration space
+ * accesses correctly. This gives us 8-bits for the bus
+ * number, however we have multiple PCI controllers on
+ * UltraSparc systems.
+ *
+ * So what we do is give the PCI busses under each controller
+ * a unique portion of the 8-bit PCI bus number space.
+ * Therefore one can obtain the controller from the bus
+ * number. For example, say PSYCHO PBM-A a subordinate bus
+ * space of 0 to 4, and PBM-B has a space of 0 to 2. PBM-A
+ * will use 0 to 4, and PBM-B will use 5 to 7.
+ */
+struct pci_pbm_info *pci_bus2pbm[256];
+unsigned char pci_highest_busnum = 0;
+
+/* At boot time the user can give the kernel a command
+ * line option which controls if and how PCI devices
+ * are reordered at PCI bus probing time.
+ */
+int pci_device_reorder = 0;
+
+spinlock_t pci_poke_lock = SPIN_LOCK_UNLOCKED;
+volatile int pci_poke_in_progress;
+volatile int pci_poke_faulted;
+
+/* Probe for all PCI controllers in the system. */
+extern void sabre_init(int);
+extern void psycho_init(int);
+
+static struct {
+ char *model_name;
+ void (*init)(int);
+} pci_controller_table[] = {
+ { "SUNW,sabre", sabre_init },
+ { "pci108e,a000", sabre_init },
+ { "SUNW,psycho", psycho_init },
+ { "pci108e,8000", psycho_init }
+};
+#define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
+ sizeof(pci_controller_table[0]))
+
+static void pci_controller_init(char *model_name, int namelen, int node)
+{
+ int i;
+
+ for (i = 0; i < PCI_NUM_CONTROLLER_TYPES; i++) {
+ if (!strncmp(model_name,
+ pci_controller_table[i].model_name,
+ namelen)) {
+ pci_controller_table[i].init(node);
+ return;
+ }
+ }
+ printk("PCI: Warning unknown controller, model name [%s]\n",
+ model_name);
+ printk("PCI: Ignoring controller...\n");
+}
+
+/* Find each controller in the system, attach and initialize
+ * software state structure for each and link into the
+ * pci_controller_root. Setup the controller enough such
+ * that bus scanning can be done.
+ */
+static void pci_controller_probe(void)
+{
+ char namebuf[16];
+ int node;
+
+ printk("PCI: Probing for controllers.\n");
+ node = prom_getchild(prom_root_node);
+ while ((node = prom_searchsiblings(node, "pci")) != 0) {
+ int len;
+
+ len = prom_getproperty(node, "model",
+ namebuf, sizeof(namebuf));
+ if (len > 0)
+ pci_controller_init(namebuf, len, node);
+ else {
+ len = prom_getproperty(node, "compatible",
+ namebuf, sizeof(namebuf));
+ if (len > 0)
+ pci_controller_init(namebuf, len, node);
+ }
+ node = prom_getsibling(node);
+ if (!node)
+ break;
+ }
+}
+
+static void pci_scan_each_controller_bus(void)
+{
+ struct pci_controller_info *p;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pci_controller_lock, flags);
+ for (p = pci_controller_root; p; p = p->next)
+ p->scan_bus(p);
+ spin_unlock_irqrestore(&pci_controller_lock, flags);
+}
+
+/* Reorder the pci_dev chain, so that onboard devices come first
+ * and then come the pluggable cards.
+ */
+static void __init pci_reorder_devs(void)
+{
+ struct pci_dev **pci_onboard = &pci_devices;
+ struct pci_dev **pci_tail = &pci_devices;
+ struct pci_dev *pdev = pci_devices, *pci_other = NULL;
+
+ while (pdev) {
+ if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) {
+ if (pci_other) {
+ *pci_onboard = pdev;
+ pci_onboard = &pdev->next;
+ pdev = pdev->next;
+ *pci_onboard = pci_other;
+ *pci_tail = pdev;
+ continue;
+ } else
+ pci_onboard = &pdev->next;
+ } else if (!pci_other)
+ pci_other = pdev;
+ pci_tail = &pdev->next;
+ pdev = pdev->next;
+ }
+}
+
+void __init pcibios_init(void)
+{
+ pci_controller_probe();
+ if (pci_controller_root == NULL)
+ return;
+
+ pci_scan_each_controller_bus();
+
+ if (pci_device_reorder)
+ pci_reorder_devs();
+
+ ebus_init();
+}
+
+struct pci_fixup pcibios_fixups[] = {
+ { 0 }
+};
+
+void pcibios_fixup_bus(struct pci_bus *pbus)
+{
+}
+
+int pcibios_assign_resource(struct pci_dev *pdev, int resource)
+{
+ return 0;
+}
+
+char * __init pcibios_setup(char *str)
+{
+ if (!strcmp(str, "onboardfirst")) {
+ pci_device_reorder = 1;
+ return NULL;
+ }
+ if (!strcmp(str, "noreorder")) {
+ pci_device_reorder = 0;
+ return NULL;
+ }
+ return str;
+}
+
+asmlinkage int sys_pciconfig_read(unsigned long bus,
+ unsigned long dfn,
+ unsigned long off,
+ unsigned long len,
+ unsigned char *buf)
+{
+ struct pci_dev *dev;
+ u8 byte;
+ u16 word;
+ u32 dword;
+ int err = 0;
+
+ if(!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ dev = pci_find_slot(bus, dfn);
+ if (!dev) {
+ /* Xfree86 is such a turd, it does not check the
+ * return value and just relies on the buffer being
+ * set to all 1's to mean "device not present".
+ */
+ switch(len) {
+ case 1:
+ put_user(0xff, (unsigned char *)buf);
+ break;
+ case 2:
+ put_user(0xffff, (unsigned short *)buf);
+ break;
+ case 4:
+ put_user(0xffffffff, (unsigned int *)buf);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ };
+ goto out;
+ }
+
+ lock_kernel();
+ switch(len) {
+ case 1:
+ pci_read_config_byte(dev, off, &byte);
+ put_user(byte, (unsigned char *)buf);
+ break;
+ case 2:
+ pci_read_config_word(dev, off, &word);
+ put_user(word, (unsigned short *)buf);
+ break;
+ case 4:
+ pci_read_config_dword(dev, off, &dword);
+ put_user(dword, (unsigned int *)buf);
+ break;
+
+ default:
+ err = -EINVAL;
+ break;
+ };
+ unlock_kernel();
+out:
+ return err;
+}
+
+asmlinkage int sys_pciconfig_write(unsigned long bus,
+ unsigned long dfn,
+ unsigned long off,
+ unsigned long len,
+ unsigned char *buf)
+{
+ struct pci_dev *dev;
+ u8 byte;
+ u16 word;
+ u32 dword;
+ int err = 0;
+
+ if(!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ dev = pci_find_slot(bus, dfn);
+ if (!dev) {
+ /* See commentary above about Xfree86 */
+ goto out;
+ }
+
+ lock_kernel();
+ switch(len) {
+ case 1:
+ err = get_user(byte, (u8 *)buf);
+ if(err)
+ break;
+ pci_write_config_byte(dev, off, byte);
+ break;
+
+ case 2:
+ err = get_user(word, (u16 *)buf);
+ if(err)
+ break;
+ pci_write_config_byte(dev, off, word);
+ break;
+
+ case 4:
+ err = get_user(dword, (u32 *)buf);
+ if(err)
+ break;
+ pci_write_config_byte(dev, off, dword);
+ break;
+
+ default:
+ err = -EINVAL;
+ break;
+
+ };
+ unlock_kernel();
+
+out:
+ return err;
+}
+
+#endif /* !(CONFIG_PCI) */
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
new file mode 100644
index 000000000..a3600df9c
--- /dev/null
+++ b/arch/sparc64/kernel/pci_common.c
@@ -0,0 +1,651 @@
+/* $Id: pci_common.c,v 1.3 1999/09/04 22:26:32 ecd Exp $
+ * pci_common.c: PCI controller common support.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+
+#include <asm/pbm.h>
+
+/* Find the OBP PROM device tree node for a PCI device.
+ * Return zero if not found.
+ */
+static int __init find_device_prom_node(struct pci_pbm_info *pbm,
+ struct pci_dev *pdev,
+ int bus_prom_node,
+ struct linux_prom_pci_registers *pregs,
+ int *nregs)
+{
+ int node;
+
+ /*
+ * Return the PBM's PROM node in case we are it's PCI device,
+ * as the PBM's reg property is different to standard PCI reg
+ * properties. We would delete this device entry otherwise,
+ * which confuses XFree86's device probing...
+ */
+ if ((pdev->bus->number == pbm->pci_bus->number) && (pdev->devfn == 0) &&
+ (pdev->vendor == PCI_VENDOR_ID_SUN) &&
+ (pdev->device == PCI_DEVICE_ID_SUN_PBM)) {
+ *nregs = 0;
+ return bus_prom_node;
+ }
+
+ node = prom_getchild(bus_prom_node);
+ while (node != 0) {
+ int err = prom_getproperty(node, "reg",
+ (char *)pregs,
+ sizeof(*pregs) * PROMREG_MAX);
+ if (err == 0 || err == -1)
+ goto do_next_sibling;
+ if (((pregs[0].phys_hi >> 8) & 0xff) == pdev->devfn) {
+ *nregs = err / sizeof(*pregs);
+ return node;
+ }
+
+ do_next_sibling:
+ node = prom_getsibling(node);
+ }
+ return 0;
+}
+
+/* Remove a PCI device from the device trees, then
+ * free it up. Note that this must run before
+ * the device's resources are registered because we
+ * do not handle unregistering them here.
+ */
+static void pci_device_delete(struct pci_dev *pdev)
+{
+ struct pci_dev **dpp;
+
+ /* First, unlink from list of all devices. */
+ dpp = &pci_devices;
+ while (*dpp != NULL) {
+ if (*dpp == pdev) {
+ *dpp = pdev->next;
+ pdev->next = NULL;
+ break;
+ }
+ dpp = &(*dpp)->next;
+ }
+
+ /* Next, unlink from bus sibling chain. */
+ dpp = &pdev->bus->devices;
+ while (*dpp != NULL) {
+ if (*dpp == pdev) {
+ *dpp = pdev->sibling;
+ pdev->sibling = NULL;
+ break;
+ }
+ dpp = &(*dpp)->sibling;
+ }
+
+ /* Ok, all references are gone, free it up. */
+ kfree(pdev);
+}
+
+/* Fill in the PCI device cookie sysdata for the given
+ * PCI device. This cookie is the means by which one
+ * can get to OBP and PCI controller specific information
+ * for a PCI device.
+ */
+static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm,
+ struct pci_dev *pdev,
+ int bus_prom_node)
+{
+ struct linux_prom_pci_registers pregs[PROMREG_MAX];
+ struct pcidev_cookie *pcp;
+ int device_prom_node, nregs, err;
+
+ device_prom_node = find_device_prom_node(pbm, pdev, bus_prom_node,
+ pregs, &nregs);
+ if (device_prom_node == 0) {
+ /* If it is not in the OBP device tree then
+ * there must be a damn good reason for it.
+ *
+ * So what we do is delete the device from the
+ * PCI device tree completely. This scenerio
+ * is seen, for example, on CP1500 for the
+ * second EBUS/HappyMeal pair if the external
+ * connector for it is not present.
+ */
+ pci_device_delete(pdev);
+ return;
+ }
+
+ pcp = kmalloc(sizeof(*pcp), GFP_ATOMIC);
+ if (pcp == NULL) {
+ prom_printf("PCI_COOKIE: Fatal malloc error, aborting...\n");
+ prom_halt();
+ }
+ pcp->pbm = pbm;
+ pcp->prom_node = device_prom_node;
+ memcpy(pcp->prom_regs, pregs, sizeof(pcp->prom_regs));
+ pcp->num_prom_regs = nregs;
+ err = prom_getproperty(device_prom_node, "name",
+ pcp->prom_name, sizeof(pcp->prom_name));
+ if (err > 0)
+ pcp->prom_name[err] = 0;
+ else
+ pcp->prom_name[0] = 0;
+ if (strcmp(pcp->prom_name, "ebus") == 0) {
+ struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX];
+ int iter;
+
+ /* EBUS is special... */
+ err = prom_getproperty(device_prom_node, "ranges",
+ (char *)&erng[0], sizeof(erng));
+ if (err == 0 || err == -1) {
+ prom_printf("EBUS: Fatal error, no range property\n");
+ prom_halt();
+ }
+ err = (err / sizeof(erng[0]));
+ for(iter = 0; iter < err; iter++) {
+ struct linux_prom_ebus_ranges *ep = &erng[iter];
+ struct linux_prom_pci_registers *ap;
+
+ ap = &pcp->prom_assignments[iter];
+
+ ap->phys_hi = ep->parent_phys_hi;
+ ap->phys_mid = ep->parent_phys_mid;
+ ap->phys_lo = ep->parent_phys_lo;
+ ap->size_hi = 0;
+ ap->size_lo = ep->size;
+ }
+ pcp->num_prom_assignments = err;
+ } else {
+ err = prom_getproperty(device_prom_node,
+ "assigned-addresses",
+ (char *)pcp->prom_assignments,
+ sizeof(pcp->prom_assignments));
+ if (err == 0 || err == -1)
+ pcp->num_prom_assignments = 0;
+ else
+ pcp->num_prom_assignments =
+ (err / sizeof(pcp->prom_assignments[0]));
+ }
+
+ pdev->sysdata = pcp;
+}
+
+void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus,
+ struct pci_pbm_info *pbm,
+ int prom_node)
+{
+ struct pci_dev *pdev;
+
+ /* This loop is coded like this because the cookie
+ * fillin routine can delete devices from the tree.
+ */
+ pdev = pbus->devices;
+ while (pdev != NULL) {
+ struct pci_dev *next = pdev->sibling;
+
+ pdev_cookie_fillin(pbm, pdev, prom_node);
+
+ pdev = next;
+ }
+
+ for (pbus = pbus->children; pbus; pbus = pbus->next) {
+ struct pcidev_cookie *pcp = pbus->self->sysdata;
+ pci_fill_in_pbm_cookies(pbus, pbm, pcp->prom_node);
+ }
+}
+
+static void __init bad_assignment(struct linux_prom_pci_registers *ap,
+ struct resource *res,
+ int do_prom_halt)
+{
+ prom_printf("PCI: Bogus PROM assignment.\n");
+ if (ap)
+ prom_printf("PCI: phys[%08x:%08x:%08x] size[%08x:%08x]\n",
+ ap->phys_hi, ap->phys_mid, ap->phys_lo,
+ ap->size_hi, ap->size_lo);
+ if (res)
+ prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n",
+ res->start, res->end, res->flags);
+ prom_printf("Please email this information to davem@redhat.com\n");
+ if (do_prom_halt)
+ prom_halt();
+}
+
+static struct resource *
+__init get_root_resource(struct linux_prom_pci_registers *ap,
+ struct pci_pbm_info *pbm)
+{
+ int space = (ap->phys_hi >> 24) & 3;
+
+ switch (space) {
+ case 0:
+ /* Configuration space, silently ignore it. */
+ return NULL;
+
+ case 1:
+ /* 16-bit IO space */
+ return &pbm->io_space;
+
+ case 2:
+ /* 32-bit MEM space */
+ return &pbm->mem_space;
+
+ case 3:
+ default:
+ /* 64-bit MEM space, unsupported. */
+ printk("PCI: 64-bit MEM assignment??? "
+ "Tell davem@redhat.com about it!\n");
+ return NULL;
+ };
+}
+
+static struct resource *
+__init get_device_resource(struct linux_prom_pci_registers *ap,
+ struct pci_dev *pdev)
+{
+ int breg = (ap->phys_hi & 0xff);
+ int space = (ap->phys_hi >> 24) & 3;
+
+ switch (breg) {
+ case PCI_ROM_ADDRESS:
+ /* It had better be MEM space. */
+ if (space != 2)
+ bad_assignment(ap, NULL, 0);
+
+ return &pdev->resource[PCI_ROM_RESOURCE];
+
+ case PCI_BASE_ADDRESS_0:
+ case PCI_BASE_ADDRESS_1:
+ case PCI_BASE_ADDRESS_2:
+ case PCI_BASE_ADDRESS_3:
+ case PCI_BASE_ADDRESS_4:
+ case PCI_BASE_ADDRESS_5:
+ return &pdev->resource[(breg - PCI_BASE_ADDRESS_0) / 4];
+
+ default:
+ bad_assignment(ap, NULL, 0);
+ return NULL;
+ };
+}
+
+static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
+ struct pci_dev *pdev)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ int i;
+
+ for (i = 0; i < pcp->num_prom_assignments; i++) {
+ struct linux_prom_pci_registers *ap;
+ struct resource *root, *res;
+
+ /* The format of this property is specified in
+ * the PCI Bus Binding to IEEE1275-1994.
+ */
+ ap = &pcp->prom_assignments[i];
+ root = get_root_resource(ap, pbm);
+ res = get_device_resource(ap, pdev);
+ if (root == NULL || res == NULL)
+ continue;
+
+ /* Ok we know which resource this PROM assignment is
+ * for, sanity check it.
+ */
+ if ((res->start & 0xffffffffUL) != ap->phys_lo)
+ bad_assignment(ap, res, 1);
+
+ /* Adjust the resource into the physical address space
+ * of this PBM.
+ */
+ pbm->parent->resource_adjust(pdev, res, root);
+
+ if (request_resource(root, res) < 0) {
+ /* OK, there is some conflict. But this is fine
+ * since we'll reassign it in the fixup pass.
+ * Nevertheless notify the user that OBP made
+ * an error.
+ */
+ printk(KERN_ERR "PCI: Address space collision on region %ld "
+ "of device %s\n",
+ (res - &pdev->resource[0]), pdev->name);
+ }
+ }
+}
+
+void __init pci_record_assignments(struct pci_pbm_info *pbm,
+ struct pci_bus *pbus)
+{
+ struct pci_dev *pdev;
+
+ for (pdev = pbus->devices; pdev; pdev = pdev->sibling)
+ pdev_record_assignments(pbm, pdev);
+
+ for (pbus = pbus->children; pbus; pbus = pbus->next)
+ pci_record_assignments(pbm, pbus);
+}
+
+static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm,
+ struct pci_dev *pdev)
+{
+ u32 reg;
+ u16 cmd;
+ int i, io_seen, mem_seen;
+
+ io_seen = mem_seen = 0;
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource *root, *res;
+ unsigned long size, min, max, align;
+
+ res = &pdev->resource[i];
+
+ if (res->flags & IORESOURCE_IO)
+ io_seen++;
+ else if (res->flags & IORESOURCE_MEM)
+ mem_seen++;
+
+ /* If it is already assigned or the resource does
+ * not exist, there is nothing to do.
+ */
+ if (res->parent != NULL || res->flags == 0UL)
+ continue;
+
+ /* Determine the root we allocate from. */
+ if (res->flags & IORESOURCE_IO) {
+ root = &pbm->io_space;
+ min = root->start + 0x400UL;
+ max = root->end;
+ } else {
+ root = &pbm->mem_space;
+ min = root->start;
+ max = min + 0x80000000UL;
+ }
+
+ size = res->end - res->start;
+ align = size + 1;
+ if (allocate_resource(root, res, size + 1, min, max, align) < 0) {
+ /* uh oh */
+ prom_printf("PCI: Failed to allocate resource %d for %s\n",
+ i, pdev->name);
+ prom_halt();
+ }
+
+ /* Update PCI config space. */
+ pbm->parent->base_address_update(pdev, i);
+ }
+
+ /* Special case, disable the ROM. Several devices
+ * act funny (ie. do not respond to memory space writes)
+ * when it is left enabled. A good example are Qlogic,ISP
+ * adapters.
+ */
+ pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &reg);
+ reg &= ~PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(pdev, PCI_ROM_ADDRESS, reg);
+
+ /* If we saw I/O or MEM resources, enable appropriate
+ * bits in PCI command register.
+ */
+ if (io_seen || mem_seen) {
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ if (io_seen)
+ cmd |= PCI_COMMAND_IO;
+ if (mem_seen)
+ cmd |= PCI_COMMAND_MEMORY;
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+ }
+
+ /* If this is a PCI bridge or an IDE controller,
+ * enable bus mastering. In the former case also
+ * set the cache line size correctly.
+ */
+ if (((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI) ||
+ (((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) &&
+ ((pdev->class & 0x80) != 0))) {
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_MASTER;
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+
+ if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
+ pci_write_config_byte(pdev,
+ PCI_CACHE_LINE_SIZE,
+ (64 / sizeof(u32)));
+ }
+}
+
+void __init pci_assign_unassigned(struct pci_pbm_info *pbm,
+ struct pci_bus *pbus)
+{
+ struct pci_dev *pdev;
+
+ for (pdev = pbus->devices; pdev; pdev = pdev->sibling)
+ pdev_assign_unassigned(pbm, pdev);
+
+ for (pbus = pbus->children; pbus; pbus = pbus->next)
+ pci_assign_unassigned(pbm, pbus);
+}
+
+static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt)
+{
+ struct pcidev_cookie *dev_pcp = pdev->sysdata;
+ struct pci_pbm_info *pbm = dev_pcp->pbm;
+ struct linux_prom_pci_registers *pregs = dev_pcp->prom_regs;
+ unsigned int hi, mid, lo, irq;
+ int i;
+
+ if (pbm->num_pbm_intmap == 0)
+ return 0;
+
+ /* If we are underneath a PCI bridge, use PROM register
+ * property of parent bridge.
+ */
+ if (pdev->bus->number != pbm->pci_first_busno) {
+ struct pcidev_cookie *bus_pcp;
+ int offset;
+
+ bus_pcp = pdev->bus->self->sysdata;
+ pregs = bus_pcp->prom_regs;
+ offset = prom_getint(bus_pcp->prom_node,
+ "fcode-rom-offset");
+
+ /* Did PROM know better and assign an interrupt other
+ * than #INTA to the device? - We test here for presence of
+ * FCODE on the card, in this case we assume PROM has set
+ * correct 'interrupts' property, unless it is quadhme.
+ */
+ if (offset == -1 ||
+ !strcmp(bus_pcp->prom_name, "SUNW,qfe") ||
+ !strcmp(bus_pcp->prom_name, "qfe")) {
+ /*
+ * No, use low slot number bits of child as IRQ line.
+ */
+ *interrupt = ((*interrupt - 1 + PCI_SLOT(pdev->devfn)) & 3) + 1;
+ }
+ }
+
+ hi = pregs->phys_hi & pbm->pbm_intmask.phys_hi;
+ mid = pregs->phys_mid & pbm->pbm_intmask.phys_mid;
+ lo = pregs->phys_lo & pbm->pbm_intmask.phys_lo;
+ irq = *interrupt & pbm->pbm_intmask.interrupt;
+
+ for (i = 0; i < pbm->num_pbm_intmap; i++) {
+ if (pbm->pbm_intmap[i].phys_hi == hi &&
+ pbm->pbm_intmap[i].phys_mid == mid &&
+ pbm->pbm_intmap[i].phys_lo == lo &&
+ pbm->pbm_intmap[i].interrupt == irq) {
+ *interrupt = pbm->pbm_intmap[i].cinterrupt;
+ return 1;
+ }
+ }
+
+ prom_printf("pbm_intmap_match: bus %02x, devfn %02x: ",
+ pdev->bus->number, pdev->devfn);
+ prom_printf("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n",
+ pregs->phys_hi, pregs->phys_mid, pregs->phys_lo, *interrupt);
+ prom_printf("Please email this information to davem@redhat.com\n");
+ prom_halt();
+}
+
+static void __init pdev_fixup_irq(struct pci_dev *pdev)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_pbm_info *pbm = pcp->pbm;
+ struct pci_controller_info *p = pbm->parent;
+ unsigned int portid = p->portid;
+ unsigned int prom_irq;
+ int prom_node = pcp->prom_node;
+ int err;
+
+ err = prom_getproperty(prom_node, "interrupts",
+ (char *)&prom_irq, sizeof(prom_irq));
+ if (err == 0 || err == -1) {
+ pdev->irq = 0;
+ return;
+ }
+
+ /* Fully specified already? */
+ if (((prom_irq & PCI_IRQ_IGN) >> 6) == portid) {
+ pdev->irq = p->irq_build(p, pdev, prom_irq);
+ goto have_irq;
+ }
+
+ /* An onboard device? (bit 5 set) */
+ if ((prom_irq & PCI_IRQ_INO) & 0x20) {
+ pdev->irq = p->irq_build(p, pdev, (portid << 6 | prom_irq));
+ goto have_irq;
+ }
+
+ /* Can we find a matching entry in the interrupt-map? */
+ if (pci_intmap_match(pdev, &prom_irq)) {
+ pdev->irq = p->irq_build(p, pdev, (portid << 6) | prom_irq);
+ goto have_irq;
+ }
+
+ /* Ok, we have to do it the hard way. */
+ {
+ unsigned int bus, slot, line;
+
+ bus = (pbm == &pbm->parent->pbm_B) ? (1 << 4) : 0;
+
+ /* If we have a legal interrupt property, use it as
+ * the IRQ line.
+ */
+ if (prom_irq > 0 && prom_irq < 5) {
+ line = ((prom_irq - 1) & 3);
+ } else {
+ u8 pci_irq_line;
+
+ /* Else just directly consult PCI config space. */
+ pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pci_irq_line);
+ line = ((pci_irq_line - 1) & 3);
+ }
+
+ /* Now figure out the slot. */
+ if (pdev->bus->number == pbm->pci_first_busno) {
+ if (pbm == &pbm->parent->pbm_A)
+ slot = (pdev->devfn >> 3) - 1;
+ else
+ slot = (pdev->devfn >> 3) - 2;
+ } else {
+ if (pbm == &pbm->parent->pbm_A)
+ slot = (pdev->bus->self->devfn >> 3) - 1;
+ else
+ slot = (pdev->bus->self->devfn >> 3) - 2;
+ }
+ slot = slot << 2;
+
+ pdev->irq = p->irq_build(p, pdev,
+ ((portid << 6) & PCI_IRQ_IGN) |
+ (bus | slot | line));
+ }
+
+have_irq:
+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE,
+ pdev->irq & PCI_IRQ_INO);
+}
+
+void __init pci_fixup_irq(struct pci_pbm_info *pbm,
+ struct pci_bus *pbus)
+{
+ struct pci_dev *pdev;
+
+ for (pdev = pbus->devices; pdev; pdev = pdev->sibling)
+ pdev_fixup_irq(pdev);
+
+ for (pbus = pbus->children; pbus; pbus = pbus->next)
+ pci_fixup_irq(pbm, pbus);
+}
+
+/* Generic helper routines for PCI error reporting. */
+void pci_scan_for_target_abort(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm,
+ struct pci_bus *pbus)
+{
+ struct pci_dev *pdev;
+
+ for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+ u16 status, error_bits;
+
+ pci_read_config_word(pdev, PCI_STATUS, &status);
+ error_bits =
+ (status & (PCI_STATUS_SIG_TARGET_ABORT |
+ PCI_STATUS_REC_TARGET_ABORT));
+ if (error_bits) {
+ pci_write_config_word(pdev, PCI_STATUS, error_bits);
+ printk("PCI%d(PBM%c): Device [%s] saw Target Abort [%016x]\n",
+ p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'),
+ pdev->name, status);
+ }
+ }
+
+ for (pbus = pbus->children; pbus; pbus = pbus->next)
+ pci_scan_for_target_abort(p, pbm, pbus);
+}
+
+void pci_scan_for_master_abort(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm,
+ struct pci_bus *pbus)
+{
+ struct pci_dev *pdev;
+
+ for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+ u16 status, error_bits;
+
+ pci_read_config_word(pdev, PCI_STATUS, &status);
+ error_bits =
+ (status & (PCI_STATUS_REC_MASTER_ABORT));
+ if (error_bits) {
+ pci_write_config_word(pdev, PCI_STATUS, error_bits);
+ printk("PCI%d(PBM%c): Device [%s] received Master Abort [%016x]\n",
+ p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'),
+ pdev->name, status);
+ }
+ }
+
+ for (pbus = pbus->children; pbus; pbus = pbus->next)
+ pci_scan_for_master_abort(p, pbm, pbus);
+}
+
+void pci_scan_for_parity_error(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm,
+ struct pci_bus *pbus)
+{
+ struct pci_dev *pdev;
+
+ for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+ u16 status, error_bits;
+
+ pci_read_config_word(pdev, PCI_STATUS, &status);
+ error_bits =
+ (status & (PCI_STATUS_PARITY |
+ PCI_STATUS_DETECTED_PARITY));
+ if (error_bits) {
+ pci_write_config_word(pdev, PCI_STATUS, error_bits);
+ printk("PCI%d(PBM%c): Device [%s] saw Parity Error [%016x]\n",
+ p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'),
+ pdev->name, status);
+ }
+ }
+
+ for (pbus = pbus->children; pbus; pbus = pbus->next)
+ pci_scan_for_parity_error(p, pbm, pbus);
+}
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h
new file mode 100644
index 000000000..24ed0319b
--- /dev/null
+++ b/arch/sparc64/kernel/pci_impl.h
@@ -0,0 +1,166 @@
+/* $Id: pci_impl.h,v 1.3 1999/09/10 10:40:44 davem Exp $
+ * pci_impl.h: Helper definitions for PCI controller support.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef PCI_IMPL_H
+#define PCI_IMPL_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+extern spinlock_t pci_controller_lock;
+extern struct pci_controller_info *pci_controller_root;
+
+extern struct pci_pbm_info *pci_bus2pbm[256];
+extern unsigned char pci_highest_busnum;
+extern int pci_num_controllers;
+
+/* PCI bus scanning and fixup support. */
+extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus,
+ struct pci_pbm_info *pbm,
+ int prom_node);
+extern void pci_record_assignments(struct pci_pbm_info *pbm,
+ struct pci_bus *pbus);
+extern void pci_assign_unassigned(struct pci_pbm_info *pbm,
+ struct pci_bus *pbus);
+extern void pci_fixup_irq(struct pci_pbm_info *pbm,
+ struct pci_bus *pbus);
+
+/* Error reporting support. */
+extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
+extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
+extern void pci_scan_for_parity_error(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
+
+/* IOMMU/DVMA initialization. */
+#define PCI_DVMA_HASH_NONE ~0UL
+static __inline__ void set_dvma_hash(unsigned long dvma_offset,
+ unsigned long paddr,
+ unsigned long daddr)
+{
+ unsigned long dvma_addr = dvma_offset + daddr;
+ unsigned long vaddr = (unsigned long)__va(paddr);
+
+ pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] = dvma_addr - vaddr;
+ pci_dvma_p2v_hash[pci_dvma_ahashfn(dvma_addr)] = vaddr - dvma_addr;
+}
+
+/* Configuration space access. */
+extern spinlock_t pci_poke_lock;
+extern volatile int pci_poke_in_progress;
+extern volatile int pci_poke_faulted;
+
+static __inline__ void pci_config_read8(u8 *addr, u8 *ret)
+{
+ unsigned long flags;
+ u8 byte;
+
+ spin_lock_irqsave(&pci_poke_lock, flags);
+ pci_poke_in_progress = 1;
+ pci_poke_faulted = 0;
+ __asm__ __volatile__("membar #Sync\n\t"
+ "lduba [%1] %2, %0\n\t"
+ "membar #Sync"
+ : "=r" (byte)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+ pci_poke_in_progress = 0;
+ if (!pci_poke_faulted)
+ *ret = byte;
+ spin_unlock_irqrestore(&pci_poke_lock, flags);
+}
+
+static __inline__ void pci_config_read16(u16 *addr, u16 *ret)
+{
+ unsigned long flags;
+ u16 word;
+
+ spin_lock_irqsave(&pci_poke_lock, flags);
+ pci_poke_in_progress = 1;
+ pci_poke_faulted = 0;
+ __asm__ __volatile__("membar #Sync\n\t"
+ "lduha [%1] %2, %0\n\t"
+ "membar #Sync"
+ : "=r" (word)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+ pci_poke_in_progress = 0;
+ if (!pci_poke_faulted)
+ *ret = word;
+ spin_unlock_irqrestore(&pci_poke_lock, flags);
+}
+
+static __inline__ void pci_config_read32(u32 *addr, u32 *ret)
+{
+ unsigned long flags;
+ u32 dword;
+
+ spin_lock_irqsave(&pci_poke_lock, flags);
+ pci_poke_in_progress = 1;
+ pci_poke_faulted = 0;
+ __asm__ __volatile__("membar #Sync\n\t"
+ "lduwa [%1] %2, %0\n\t"
+ "membar #Sync"
+ : "=r" (dword)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+ pci_poke_in_progress = 0;
+ if (!pci_poke_faulted)
+ *ret = dword;
+ spin_unlock_irqrestore(&pci_poke_lock, flags);
+}
+
+static __inline__ void pci_config_write8(u8 *addr, u8 val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pci_poke_lock, flags);
+ pci_poke_in_progress = 1;
+ pci_poke_faulted = 0;
+ __asm__ __volatile__("membar #Sync\n\t"
+ "stba %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* no outputs */
+ : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+ pci_poke_in_progress = 0;
+ spin_unlock_irqrestore(&pci_poke_lock, flags);
+}
+
+static __inline__ void pci_config_write16(u16 *addr, u16 val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pci_poke_lock, flags);
+ pci_poke_in_progress = 1;
+ pci_poke_faulted = 0;
+ __asm__ __volatile__("membar #Sync\n\t"
+ "stha %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* no outputs */
+ : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+ pci_poke_in_progress = 0;
+ spin_unlock_irqrestore(&pci_poke_lock, flags);
+}
+
+static __inline__ void pci_config_write32(u32 *addr, u32 val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pci_poke_lock, flags);
+ pci_poke_in_progress = 1;
+ pci_poke_faulted = 0;
+ __asm__ __volatile__("membar #Sync\n\t"
+ "stwa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* no outputs */
+ : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+ pci_poke_in_progress = 0;
+ spin_unlock_irqrestore(&pci_poke_lock, flags);
+}
+
+#endif /* !(PCI_IMPL_H) */
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
new file mode 100644
index 000000000..a7f469ec8
--- /dev/null
+++ b/arch/sparc64/kernel/pci_iommu.c
@@ -0,0 +1,510 @@
+/* $Id: pci_iommu.c,v 1.1 1999/08/30 10:00:47 davem Exp $
+ * pci_iommu.c: UltraSparc PCI controller IOM/STC support.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include <asm/pbm.h>
+#include <asm/iommu.h>
+#include <asm/scatterlist.h>
+
+#define PCI_STC_CTXMATCH_ADDR(STC, CTX) \
+ ((STC)->strbuf_ctxmatch_base + ((CTX) << 3))
+
+/* Accessing IOMMU and Streaming Buffer registers.
+ * REG parameter is a physical address. All registers
+ * are 64-bits in size.
+ */
+#define pci_iommu_read(__reg) \
+({ u64 __ret; \
+ __asm__ __volatile__("ldxa [%1] %2, %0" \
+ : "=r" (__ret) \
+ : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
+ : "memory"); \
+ __ret; \
+})
+#define pci_iommu_write(__reg, __val) \
+ __asm__ __volatile__("stxa %0, [%1] %2" \
+ : /* no outputs */ \
+ : "r" (__val), "r" (__reg), \
+ "i" (ASI_PHYS_BYPASS_EC_E))
+
+/* Find a range of iommu mappings of size NPAGES in page
+ * table PGT. Return pointer to first iopte.
+ */
+static iopte_t *iommu_find_range(unsigned long npages, iopte_t *pgt, int pgt_size)
+{
+ int i;
+
+ pgt_size -= npages;
+ for (i = 0; i < pgt_size; i++) {
+ if (!iopte_val(pgt[i]) & IOPTE_VALID) {
+ int scan;
+
+ for (scan = 1; scan < npages; scan++) {
+ if (iopte_val(pgt[i + scan]) & IOPTE_VALID) {
+ i += scan;
+ goto do_next;
+ }
+ }
+ return &pgt[i];
+ }
+ do_next:
+ }
+ return NULL;
+}
+
+#define IOPTE_CONSISTANT(CTX, PADDR) \
+ (IOPTE_VALID | IOPTE_CACHE | IOPTE_WRITE | \
+ (((CTX) << 47) & IOPTE_CONTEXT) | \
+ ((PADDR) & IOPTE_PAGE))
+
+#define IOPTE_STREAMING(CTX, PADDR) \
+ (IOPTE_CONSISTANT(CTX, PADDR) | IOPTE_STBUF)
+
+#define IOPTE_INVALID 0UL
+
+/* Map kernel buffer at ADDR of size SZ using consistant mode
+ * DMA for PCI device PDEV. Return 32-bit PCI DMA address.
+ */
+u32 pci_map_consistant(struct pci_dev *pdev, void *addr, int sz)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+ iopte_t *base;
+ unsigned long flags, npages, oaddr;
+ u32 ret;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ oaddr = (unsigned long)addr;
+ npages = PAGE_ALIGN(oaddr + sz) - (oaddr & PAGE_MASK);
+ npages >>= PAGE_SHIFT;
+ base = iommu_find_range(npages,
+ iommu->page_table, iommu->page_table_sz);
+ ret = 0;
+ if (base != NULL) {
+ unsigned long i, base_paddr, ctx;
+
+ ret = (iommu->page_table_map_base +
+ ((base - iommu->page_table) << PAGE_SHIFT));
+ ret |= (oaddr & ~PAGE_MASK);
+ base_paddr = __pa(oaddr & PAGE_MASK);
+ ctx = 0;
+ if (iommu->iommu_has_ctx_flush)
+ ctx = iommu->iommu_cur_ctx++;
+ for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE)
+ iopte_val(*base) = IOPTE_CONSISTANT(ctx, base_paddr);
+ }
+ spin_unlock_irqrestore(&iommu->lock, flags);
+
+ return ret;
+}
+
+/* Unmap a consistant DMA translation. */
+void pci_unmap_consistant(struct pci_dev *pdev, u32 bus_addr, int sz)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+ iopte_t *base;
+ unsigned long flags, npages, i, ctx;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK);
+ npages >>= PAGE_SHIFT;
+ base = iommu->page_table +
+ ((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT);
+
+ /* Data for consistant mappings cannot enter the streaming
+ * buffers, so we only need to update the TSB and flush
+ * those entries from the IOMMU's TLB.
+ */
+
+ /* Step 1: Clear out the TSB entries. Save away
+ * the context if necessary.
+ */
+ ctx = 0;
+ if (iommu->iommu_has_ctx_flush)
+ ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+ for (i = 0; i < npages; i++, base++)
+ iopte_val(*base) = IOPTE_INVALID;
+
+ /* Step 2: Flush from IOMMU TLB. */
+ if (iommu->iommu_has_ctx_flush) {
+ pci_iommu_write(iommu->iommu_ctxflush, ctx);
+ } else {
+ bus_addr &= PAGE_MASK;
+ for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE)
+ pci_iommu_write(iommu->iommu_flush, bus_addr);
+ }
+
+ /* Step 3: Ensure completion of previous PIO writes. */
+ (void) pci_iommu_read(iommu->write_complete_reg);
+
+ spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+/* Map a single buffer at PTR of SZ bytes for PCI DMA
+ * in streaming mode.
+ */
+u32 pci_map_single(struct pci_dev *pdev, void *ptr, int sz)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+ iopte_t *base;
+ unsigned long flags, npages, oaddr;
+ u32 ret;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ oaddr = (unsigned long)ptr;
+ npages = PAGE_ALIGN(oaddr + sz) - (oaddr & PAGE_MASK);
+ npages >>= PAGE_SHIFT;
+ base = iommu_find_range(npages,
+ iommu->page_table, iommu->page_table_sz);
+ ret = 0;
+ if (base != NULL) {
+ unsigned long i, base_paddr, ctx;
+
+ ret = (iommu->page_table_map_base +
+ ((base - iommu->page_table) << PAGE_SHIFT));
+ ret |= (oaddr & ~PAGE_MASK);
+ base_paddr = __pa(oaddr & PAGE_MASK);
+ ctx = 0;
+ if (iommu->iommu_has_ctx_flush)
+ ctx = iommu->iommu_cur_ctx++;
+ for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE)
+ iopte_val(*base) = IOPTE_STREAMING(ctx, base_paddr);
+ }
+ spin_unlock_irqrestore(&iommu->lock, flags);
+
+ return ret;
+}
+
+/* Unmap a single streaming mode DMA translation. */
+void pci_unmap_single(struct pci_dev *pdev, u32 bus_addr, int sz)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+ struct pci_strbuf *strbuf = &pcp->pbm->stc;
+ iopte_t *base;
+ unsigned long flags, npages, i, ctx;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK);
+ npages >>= PAGE_SHIFT;
+ base = iommu->page_table +
+ ((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT);
+ bus_addr &= PAGE_MASK;
+
+ /* Step 1: Record the context, if any. */
+ ctx = 0;
+ if (iommu->iommu_has_ctx_flush)
+ ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+
+ /* Step 2: Kick data out of streaming buffers if necessary. */
+ if (strbuf->strbuf_enabled) {
+ u32 vaddr = bus_addr;
+
+ PCI_STC_FLUSHFLAG_INIT(strbuf);
+ if (strbuf->strbuf_has_ctx_flush &&
+ iommu->iommu_has_ctx_flush) {
+ unsigned long matchreg, flushreg;
+
+ flushreg = strbuf->strbuf_ctxflush;
+ matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+ do {
+ pci_iommu_write(flushreg, ctx);
+ } while(((long)pci_iommu_read(matchreg)) < 0L);
+ } else {
+ for (i = 0; i < npages; i++, vaddr += PAGE_SIZE)
+ pci_iommu_write(strbuf->strbuf_pflush, vaddr);
+ }
+
+ pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+ (void) pci_iommu_read(iommu->write_complete_reg);
+ while (!PCI_STC_FLUSHFLAG_SET(strbuf))
+ membar("#LoadLoad");
+ }
+
+ /* Step 3: Clear out TSB entries. */
+ for (i = 0; i < npages; i++, base++)
+ iopte_val(*base) = IOPTE_INVALID;
+
+ /* Step 4: Flush the IOMMU TLB. */
+ if (iommu->iommu_has_ctx_flush) {
+ pci_iommu_write(iommu->iommu_ctxflush, ctx);
+ } else {
+ for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE)
+ pci_iommu_write(iommu->iommu_flush, bus_addr);
+ }
+
+ /* Step 5: Ensure completion of previous PIO writes. */
+ (void) pci_iommu_read(iommu->write_complete_reg);
+
+ spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+/* Map a set of buffers described by SGLIST with NELEMS array
+ * elements in streaming mode for PCI DMA.
+ */
+void pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+ unsigned long flags, ctx, i;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+
+ /* Step 1: Choose a context if necessary. */
+ ctx = 0;
+ if (iommu->iommu_has_ctx_flush)
+ ctx = iommu->iommu_cur_ctx++;
+
+ /* Step 2: Create the mappings. */
+ for (i = 0; i < nelems; i++) {
+ unsigned long oaddr, npages;
+ iopte_t *base;
+
+ oaddr = (unsigned long)sglist[i].address;
+ npages = PAGE_ALIGN(oaddr + sglist[i].length) - (oaddr & PAGE_MASK);
+ npages >>= PAGE_SHIFT;
+ base = iommu_find_range(npages,
+ iommu->page_table, iommu->page_table_sz);
+ if (base != NULL) {
+ unsigned long j, base_paddr;
+ u32 dvma_addr;
+
+ dvma_addr = (iommu->page_table_map_base +
+ ((base - iommu->page_table) << PAGE_SHIFT));
+ dvma_addr |= (oaddr & ~PAGE_MASK);
+ sglist[i].dvma_address = dvma_addr;
+ sglist[i].dvma_length = sglist[i].length;
+ base_paddr = __pa(oaddr & PAGE_MASK);
+ for (j = 0; j < npages; j++, base++, base_paddr += PAGE_SIZE)
+ iopte_val(*base) = IOPTE_STREAMING(ctx, base_paddr);
+ } else {
+ sglist[i].dvma_address = 0;
+ sglist[i].dvma_length = 0;
+ }
+ }
+
+ spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+/* Unmap a set of streaming mode DMA translations. */
+void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+ struct pci_strbuf *strbuf = &pcp->pbm->stc;
+ unsigned long flags, ctx, i;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+
+ /* Step 1: Record the context, if any. */
+ ctx = 0;
+ if (iommu->iommu_has_ctx_flush) {
+ iopte_t *iopte;
+
+ iopte = iommu->page_table +
+ ((sglist[0].dvma_address - iommu->page_table_map_base) >> PAGE_SHIFT);
+ ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
+ }
+
+ /* Step 2: Kick data out of streaming buffers if necessary. */
+ if (strbuf->strbuf_enabled) {
+ PCI_STC_FLUSHFLAG_INIT(strbuf);
+ if (strbuf->strbuf_has_ctx_flush &&
+ iommu->iommu_has_ctx_flush) {
+ unsigned long matchreg, flushreg;
+
+ flushreg = strbuf->strbuf_ctxflush;
+ matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+ do {
+ pci_iommu_write(flushreg, ctx);
+ } while(((long)pci_iommu_read(matchreg)) < 0L);
+ } else {
+ for (i = 0; i < nelems; i++) {
+ unsigned long j, npages;
+ u32 vaddr;
+
+ j = sglist[i].dvma_length;
+ if (!j)
+ break;
+ vaddr = sglist[i].dvma_address;
+ npages = PAGE_ALIGN(vaddr + j) - (vaddr & PAGE_MASK);
+ npages >>= PAGE_SHIFT;
+ vaddr &= PAGE_MASK;
+ for (j = 0; j < npages; j++, vaddr += PAGE_SIZE)
+ pci_iommu_write(strbuf->strbuf_pflush, vaddr);
+ }
+
+ pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+ (void) pci_iommu_read(iommu->write_complete_reg);
+ while (!PCI_STC_FLUSHFLAG_SET(strbuf))
+ membar("#LoadLoad");
+ }
+ }
+
+ /* Step 3: Clear out TSB entries. */
+ for (i = 0; i < nelems; i++) {
+ unsigned long j, npages;
+ iopte_t *base;
+ u32 vaddr;
+
+ j = sglist[i].dvma_length;
+ if (!j)
+ break;
+ vaddr = sglist[i].dvma_address;
+ npages = PAGE_ALIGN(vaddr + j) - (vaddr & PAGE_MASK);
+ npages >>= PAGE_SHIFT;
+ base = iommu->page_table +
+ ((vaddr - iommu->page_table_map_base) >> PAGE_SHIFT);
+ for (j = 0; j < npages; j++, base++)
+ iopte_val(*base) = IOPTE_INVALID;
+ }
+
+ /* Step 4: Flush the IOMMU TLB. */
+ if (iommu->iommu_has_ctx_flush) {
+ pci_iommu_write(iommu->iommu_ctxflush, ctx);
+ } else {
+ for (i = 0; i < nelems; i++) {
+ unsigned long j, npages;
+ u32 vaddr;
+
+ j = sglist[i].dvma_length;
+ if (!j)
+ break;
+ vaddr = sglist[i].dvma_address;
+ npages = PAGE_ALIGN(vaddr + j) - (vaddr & PAGE_MASK);
+ npages >>= PAGE_SHIFT;
+ for (j = 0; j < npages; j++, vaddr += PAGE_SIZE)
+ pci_iommu_write(iommu->iommu_flush, vaddr);
+ }
+ }
+
+ /* Step 5: Ensure completion of previous PIO writes. */
+ (void) pci_iommu_read(iommu->write_complete_reg);
+
+ spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+/* Make physical memory consistant for a single
+ * streaming mode DMA translation after a transfer.
+ */
+void pci_dma_sync_single(struct pci_dev *pdev, u32 bus_addr, int sz)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+ struct pci_strbuf *strbuf = &pcp->pbm->stc;
+ unsigned long flags, ctx, npages;
+
+ if (!strbuf->strbuf_enabled)
+ return;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+
+ npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK);
+ npages >>= PAGE_SHIFT;
+ bus_addr &= PAGE_MASK;
+
+ /* Step 1: Record the context, if any. */
+ ctx = 0;
+ if (iommu->iommu_has_ctx_flush &&
+ strbuf->strbuf_has_ctx_flush) {
+ iopte_t *iopte;
+
+ iopte = iommu->page_table +
+ ((bus_addr - iommu->page_table_map_base)>>PAGE_SHIFT);
+ ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
+ }
+
+ /* Step 2: Kick data out of streaming buffers. */
+ PCI_STC_FLUSHFLAG_INIT(strbuf);
+ if (iommu->iommu_has_ctx_flush &&
+ strbuf->strbuf_has_ctx_flush) {
+ unsigned long matchreg, flushreg;
+
+ flushreg = strbuf->strbuf_ctxflush;
+ matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+ do {
+ pci_iommu_write(flushreg, ctx);
+ } while(((long)pci_iommu_read(matchreg)) < 0L);
+ } else {
+ unsigned long i;
+
+ for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE)
+ pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
+ }
+
+ /* Step 3: Perform flush synchronization sequence. */
+ pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+ (void) pci_iommu_read(iommu->write_complete_reg);
+ while (!PCI_STC_FLUSHFLAG_SET(strbuf))
+ membar("#LoadLoad");
+
+ spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+/* Make physical memory consistant for a set of streaming
+ * mode DMA translations after a transfer.
+ */
+void pci_dma_sync_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+ struct pci_strbuf *strbuf = &pcp->pbm->stc;
+ unsigned long flags, ctx;
+
+ if (!strbuf->strbuf_enabled)
+ return;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+
+ /* Step 1: Record the context, if any. */
+ ctx = 0;
+ if (iommu->iommu_has_ctx_flush &&
+ strbuf->strbuf_has_ctx_flush) {
+ iopte_t *iopte;
+
+ iopte = iommu->page_table +
+ ((sglist[0].dvma_address - iommu->page_table_map_base) >> PAGE_SHIFT);
+ ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
+ }
+
+ /* Step 2: Kick data out of streaming buffers. */
+ PCI_STC_FLUSHFLAG_INIT(strbuf);
+ if (iommu->iommu_has_ctx_flush &&
+ strbuf->strbuf_has_ctx_flush) {
+ unsigned long matchreg, flushreg;
+
+ flushreg = strbuf->strbuf_ctxflush;
+ matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+ do {
+ pci_iommu_write(flushreg, ctx);
+ } while (((long)pci_iommu_read(matchreg)) < 0L);
+ } else {
+ unsigned long i;
+
+ for(i = 0; i < nelems; i++) {
+ unsigned long bus_addr, npages, j;
+
+ j = sglist[i].dvma_length;
+ if (!j)
+ break;
+ bus_addr = sglist[i].dvma_address;
+ npages = PAGE_ALIGN(bus_addr + j) - (bus_addr & PAGE_MASK);
+ npages >>= PAGE_SHIFT;
+ bus_addr &= PAGE_MASK;
+ for(j = 0; i < npages; i++, bus_addr += PAGE_SIZE)
+ pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
+ }
+ }
+
+ /* Step 3: Perform flush synchronization sequence. */
+ pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+ (void) pci_iommu_read(iommu->write_complete_reg);
+ while (!PCI_STC_FLUSHFLAG_SET(strbuf))
+ membar("#LoadLoad");
+
+ spin_unlock_irqrestore(&iommu->lock, flags);
+}
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
new file mode 100644
index 000000000..1afe5a67b
--- /dev/null
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -0,0 +1,1606 @@
+/* $Id: pci_psycho.c,v 1.4 1999/09/05 09:33:36 ecd Exp $
+ * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
+ *
+ * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
+ * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be)
+ * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+
+#include <asm/pbm.h>
+#include <asm/iommu.h>
+#include <asm/irq.h>
+
+#include "pci_impl.h"
+
+/* All PSYCHO registers are 64-bits. The following accessor
+ * routines are how they are accessed. The REG parameter
+ * is a physical address.
+ */
+#define psycho_read(__reg) \
+({ u64 __ret; \
+ __asm__ __volatile__("ldxa [%1] %2, %0" \
+ : "=r" (__ret) \
+ : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
+ : "memory"); \
+ __ret; \
+})
+#define psycho_write(__reg, __val) \
+ __asm__ __volatile__("stxa %0, [%1] %2" \
+ : /* no outputs */ \
+ : "r" (__val), "r" (__reg), \
+ "i" (ASI_PHYS_BYPASS_EC_E))
+
+/* Misc. PSYCHO PCI controller register offsets and definitions. */
+#define PSYCHO_CONTROL 0x0010UL
+#define PSYCHO_CONTROL_IMPL 0xf000000000000000 /* Implementation of this PSYCHO*/
+#define PSYCHO_CONTROL_VER 0x0f00000000000000 /* Version of this PSYCHO */
+#define PSYCHO_CONTROL_MID 0x00f8000000000000 /* UPA Module ID of PSYCHO */
+#define PSYCHO_CONTROL_IGN 0x0007c00000000000 /* Interrupt Group Number */
+#define PSYCHO_CONTROL_RESV 0x00003ffffffffff0 /* Reserved */
+#define PSYCHO_CONTROL_APCKEN 0x0000000000000008 /* Address Parity Check Enable */
+#define PSYCHO_CONTROL_APERR 0x0000000000000004 /* Incoming System Addr Parerr */
+#define PSYCHO_CONTROL_IAP 0x0000000000000002 /* Invert UPA Parity */
+#define PSYCHO_CONTROL_MODE 0x0000000000000001 /* PSYCHO clock mode */
+#define PSYCHO_PCIA_CTRL 0x2000UL
+#define PSYCHO_PCIB_CTRL 0x4000UL
+#define PSYCHO_PCICTRL_RESV1 0xfffffff000000000 /* Reserved */
+#define PSYCHO_PCICTRL_SBH_ERR 0x0000000800000000 /* Streaming byte hole error */
+#define PSYCHO_PCICTRL_SERR 0x0000000400000000 /* SERR signal asserted */
+#define PSYCHO_PCICTRL_SPEED 0x0000000200000000 /* PCI speed (1 is U2P clock) */
+#define PSYCHO_PCICTRL_RESV2 0x00000001ffc00000 /* Reserved */
+#define PSYCHO_PCICTRL_ARB_PARK 0x0000000000200000 /* PCI arbitration parking */
+#define PSYCHO_PCICTRL_RESV3 0x00000000001ff800 /* Reserved */
+#define PSYCHO_PCICTRL_SBH_INT 0x0000000000000400 /* Streaming byte hole int enab */
+#define PSYCHO_PCICTRL_WEN 0x0000000000000200 /* Power Mgmt Wake Enable */
+#define PSYCHO_PCICTRL_EEN 0x0000000000000100 /* PCI Error Interrupt Enable */
+#define PSYCHO_PCICTRL_RESV4 0x00000000000000c0 /* Reserved */
+#define PSYCHO_PCICTRL_AEN 0x000000000000003f /* PCI DVMA Arbitration Enable */
+
+/* U2P Programmer's Manual, page 13-55, configuration space
+ * address format:
+ *
+ * 32 24 23 16 15 11 10 8 7 2 1 0
+ * ---------------------------------------------------------
+ * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 |
+ * ---------------------------------------------------------
+ */
+#define PSYCHO_CONFIG_BASE(PBM) \
+ ((PBM)->parent->config_space | (1UL << 24))
+#define PSYCHO_CONFIG_ENCODE(BUS, DEVFN, REG) \
+ (((unsigned long)(BUS) << 16) | \
+ ((unsigned long)(DEVFN) << 8) | \
+ ((unsigned long)(REG)))
+
+static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm,
+ unsigned char bus,
+ unsigned int devfn,
+ int where)
+{
+ if (!pbm)
+ return NULL;
+ return (void *)
+ (PSYCHO_CONFIG_BASE(pbm) |
+ PSYCHO_CONFIG_ENCODE(bus, devfn, where));
+}
+
+static int psycho_out_of_range(struct pci_pbm_info *pbm,
+ unsigned char bus,
+ unsigned char devfn)
+{
+ return ((pbm->parent == 0) ||
+ ((pbm == &pbm->parent->pbm_B) &&
+ (bus == pbm->pci_first_busno) &&
+ PCI_SLOT(devfn) > 8) ||
+ ((pbm == &pbm->parent->pbm_A) &&
+ (bus == pbm->pci_first_busno) &&
+ PCI_SLOT(devfn) > 8));
+}
+
+/* PSYCHO PCI configuration space accessors. */
+
+static int psycho_read_byte(struct pci_dev *dev, int where, u8 *value)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+ unsigned char bus = dev->bus->number;
+ unsigned int devfn = dev->devfn;
+ u8 *addr;
+
+ *value = 0xff;
+ addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (psycho_out_of_range(pbm, bus, devfn))
+ return PCIBIOS_SUCCESSFUL;
+ pci_config_read8(addr, value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int psycho_read_word(struct pci_dev *dev, int where, u16 *value)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+ unsigned char bus = dev->bus->number;
+ unsigned int devfn = dev->devfn;
+ u16 *addr;
+
+ *value = 0xffff;
+ addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (psycho_out_of_range(pbm, bus, devfn))
+ return PCIBIOS_SUCCESSFUL;
+
+ if (where & 0x01) {
+ printk("pcibios_read_config_word: misaligned reg [%x]\n",
+ where);
+ return PCIBIOS_SUCCESSFUL;
+ }
+ pci_config_read16(addr, value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int psycho_read_dword(struct pci_dev *dev, int where, u32 *value)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+ unsigned char bus = dev->bus->number;
+ unsigned int devfn = dev->devfn;
+ u32 *addr;
+
+ *value = 0xffffffff;
+ addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (psycho_out_of_range(pbm, bus, devfn))
+ return PCIBIOS_SUCCESSFUL;
+
+ if (where & 0x03) {
+ printk("pcibios_read_config_dword: misaligned reg [%x]\n",
+ where);
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ pci_config_read32(addr, value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int psycho_write_byte(struct pci_dev *dev, int where, u8 value)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+ unsigned char bus = dev->bus->number;
+ unsigned int devfn = dev->devfn;
+ u8 *addr;
+
+ addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (psycho_out_of_range(pbm, bus, devfn))
+ return PCIBIOS_SUCCESSFUL;
+
+ pci_config_write8(addr, value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int psycho_write_word(struct pci_dev *dev, int where, u16 value)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+ unsigned char bus = dev->bus->number;
+ unsigned int devfn = dev->devfn;
+ u16 *addr;
+
+ addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (psycho_out_of_range(pbm, bus, devfn))
+ return PCIBIOS_SUCCESSFUL;
+
+ if (where & 0x01) {
+ printk("pcibios_write_config_word: misaligned reg [%x]\n",
+ where);
+ return PCIBIOS_SUCCESSFUL;
+ }
+ pci_config_write16(addr, value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int psycho_write_dword(struct pci_dev *dev, int where, u32 value)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+ unsigned char bus = dev->bus->number;
+ unsigned int devfn = dev->devfn;
+ u32 *addr;
+
+ addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (psycho_out_of_range(pbm, bus, devfn))
+ return PCIBIOS_SUCCESSFUL;
+
+ if (where & 0x03) {
+ printk("pcibios_write_config_dword: misaligned reg [%x]\n",
+ where);
+ return PCIBIOS_SUCCESSFUL;
+ }
+ pci_config_write32(addr, value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops psycho_ops = {
+ psycho_read_byte,
+ psycho_read_word,
+ psycho_read_dword,
+ psycho_write_byte,
+ psycho_write_word,
+ psycho_write_dword
+};
+
+/* PSYCHO interrupt mapping support. */
+#define PSYCHO_IMAP_A_SLOT0 0x0c00UL
+#define PSYCHO_IMAP_B_SLOT0 0x0c20UL
+static unsigned long psycho_pcislot_imap_offset(unsigned long ino)
+{
+ unsigned int bus = (ino & 0x10) >> 4;
+ unsigned int slot = (ino & 0x0c) >> 2;
+
+ if (bus == 0)
+ return PSYCHO_IMAP_A_SLOT0 + (slot * 8);
+ else
+ return PSYCHO_IMAP_B_SLOT0 + (slot * 8);
+}
+
+#define PSYCHO_IMAP_SCSI 0x1000UL
+#define PSYCHO_IMAP_ETH 0x1008UL
+#define PSYCHO_IMAP_BPP 0x1010UL
+#define PSYCHO_IMAP_AU_REC 0x1018UL
+#define PSYCHO_IMAP_AU_PLAY 0x1020UL
+#define PSYCHO_IMAP_PFAIL 0x1028UL
+#define PSYCHO_IMAP_KMS 0x1030UL
+#define PSYCHO_IMAP_FLPY 0x1038UL
+#define PSYCHO_IMAP_SHW 0x1040UL
+#define PSYCHO_IMAP_KBD 0x1048UL
+#define PSYCHO_IMAP_MS 0x1050UL
+#define PSYCHO_IMAP_SER 0x1058UL
+#define PSYCHO_IMAP_TIM0 0x1060UL
+#define PSYCHO_IMAP_TIM1 0x1068UL
+#define PSYCHO_IMAP_UE 0x1070UL
+#define PSYCHO_IMAP_CE 0x1078UL
+#define PSYCHO_IMAP_A_ERR 0x1080UL
+#define PSYCHO_IMAP_B_ERR 0x1088UL
+#define PSYCHO_IMAP_PMGMT 0x1090UL
+#define PSYCHO_IMAP_GFX 0x1098UL
+#define PSYCHO_IMAP_EUPA 0x10a0UL
+
+static unsigned long __onboard_imap_off[] = {
+/*0x20*/ PSYCHO_IMAP_SCSI,
+/*0x21*/ PSYCHO_IMAP_ETH,
+/*0x22*/ PSYCHO_IMAP_BPP,
+/*0x23*/ PSYCHO_IMAP_AU_REC,
+/*0x24*/ PSYCHO_IMAP_AU_PLAY,
+/*0x25*/ PSYCHO_IMAP_PFAIL,
+/*0x26*/ PSYCHO_IMAP_KMS,
+/*0x27*/ PSYCHO_IMAP_FLPY,
+/*0x28*/ PSYCHO_IMAP_SHW,
+/*0x29*/ PSYCHO_IMAP_KBD,
+/*0x2a*/ PSYCHO_IMAP_MS,
+/*0x2b*/ PSYCHO_IMAP_SER,
+/*0x2c*/ PSYCHO_IMAP_TIM0,
+/*0x2d*/ PSYCHO_IMAP_TIM1,
+/*0x2e*/ PSYCHO_IMAP_UE,
+/*0x2f*/ PSYCHO_IMAP_CE,
+/*0x30*/ PSYCHO_IMAP_A_ERR,
+/*0x31*/ PSYCHO_IMAP_B_ERR,
+/*0x32*/ PSYCHO_IMAP_PMGMT
+};
+#define PSYCHO_ONBOARD_IRQ_BASE 0x20
+#define PSYCHO_ONBOARD_IRQ_LAST 0x32
+#define psycho_onboard_imap_offset(__ino) \
+ __onboard_imap_off[(__ino) - PSYCHO_ONBOARD_IRQ_BASE]
+
+#define PSYCHO_ICLR_A_SLOT0 0x1400UL
+#define PSYCHO_ICLR_SCSI 0x1800UL
+
+#define psycho_iclr_offset(ino) \
+ ((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \
+ (PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
+
+/* PCI PSYCHO INO number to Sparc PIL level. */
+static unsigned char psycho_pil_table[] = {
+/*0x00*/0, 0, 0, 0, /* PCI A slot 0 Int A, B, C, D */
+/*0x04*/0, 0, 0, 0, /* PCI A slot 1 Int A, B, C, D */
+/*0x08*/0, 0, 0, 0, /* PCI A slot 2 Int A, B, C, D */
+/*0x0c*/0, 0, 0, 0, /* PCI A slot 3 Int A, B, C, D */
+/*0x10*/0, 0, 0, 0, /* PCI B slot 0 Int A, B, C, D */
+/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */
+/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */
+/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */
+/*0x20*/3, /* SCSI */
+/*0x21*/5, /* Ethernet */
+/*0x22*/8, /* Parallel Port */
+/*0x23*/13, /* Audio Record */
+/*0x24*/14, /* Audio Playback */
+/*0x25*/15, /* PowerFail */
+/*0x26*/3, /* second SCSI */
+/*0x27*/11, /* Floppy */
+/*0x28*/2, /* Spare Hardware */
+/*0x29*/9, /* Keyboard */
+/*0x2a*/4, /* Mouse */
+/*0x2b*/12, /* Serial */
+/*0x2c*/10, /* Timer 0 */
+/*0x2d*/11, /* Timer 1 */
+/*0x2e*/15, /* Uncorrectable ECC */
+/*0x2f*/15, /* Correctable ECC */
+/*0x30*/15, /* PCI Bus A Error */
+/*0x31*/15, /* PCI Bus B Error */
+/*0x32*/1, /* Power Management */
+};
+
+static int __init psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
+{
+ int ret;
+
+ ret = psycho_pil_table[ino];
+ if (ret == 0 && pdev == NULL) {
+ ret = 1;
+ } else if (ret == 0) {
+ switch ((pdev->class >> 16) & 0x0f) {
+ case PCI_BASE_CLASS_STORAGE:
+ ret = 4;
+
+ case PCI_BASE_CLASS_NETWORK:
+ ret = 6;
+
+ case PCI_BASE_CLASS_DISPLAY:
+ ret = 9;
+
+ case PCI_BASE_CLASS_MULTIMEDIA:
+ case PCI_BASE_CLASS_MEMORY:
+ case PCI_BASE_CLASS_BRIDGE:
+ ret = 10;
+
+ default:
+ ret = 1;
+ };
+ }
+
+ return ret;
+}
+
+static unsigned int __init psycho_irq_build(struct pci_controller_info *p,
+ struct pci_dev *pdev,
+ unsigned int ino)
+{
+ struct ino_bucket *bucket;
+ volatile unsigned int *imap, *iclr;
+ unsigned long imap_off, iclr_off;
+ int pil, inofixup = 0;
+
+ ino &= PCI_IRQ_INO;
+ if (ino < PSYCHO_ONBOARD_IRQ_BASE) {
+ /* PCI slot */
+ imap_off = psycho_pcislot_imap_offset(ino);
+ } else {
+ /* Onboard device */
+ if (ino > PSYCHO_ONBOARD_IRQ_LAST) {
+ prom_printf("psycho_irq_build: Wacky INO [%x]\n", ino);
+ prom_halt();
+ }
+ imap_off = psycho_onboard_imap_offset(ino);
+ }
+
+ /* Now build the IRQ bucket. */
+ pil = psycho_ino_to_pil(pdev, ino);
+ imap = (volatile unsigned int *)__va(p->controller_regs + imap_off);
+ imap += 1;
+
+ iclr_off = psycho_iclr_offset(ino);
+ iclr = (volatile unsigned int *)__va(p->controller_regs + iclr_off);
+ iclr += 1;
+
+ if ((ino & 0x20) == 0)
+ inofixup = ino & 0x03;
+
+ bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
+ bucket->flags |= IBF_PCI;
+
+ return __irq(bucket);
+}
+
+/* PSYCHO error handling support. */
+enum psycho_error_type {
+ UE_ERR, CE_ERR, PCI_ERR
+};
+
+/* Helper function of IOMMU error checking, which checks out
+ * the state of the streaming buffers. The IOMMU lock is
+ * held when this is called.
+ *
+ * For the PCI error case we know which PBM (and thus which
+ * streaming buffer) caused the error, but for the uncorrectable
+ * error case we do not. So we always check both streaming caches.
+ */
+#define PSYCHO_STRBUF_CONTROL_A 0x2800UL
+#define PSYCHO_STRBUF_CONTROL_B 0x4800UL
+#define PSYCHO_STRBUF_CTRL_LPTR 0x00000000000000f0 /* LRU Lock Pointer */
+#define PSYCHO_STRBUF_CTRL_LENAB 0x0000000000000008 /* LRU Lock Enable */
+#define PSYCHO_STRBUF_CTRL_RRDIS 0x0000000000000004 /* Rerun Disable */
+#define PSYCHO_STRBUF_CTRL_DENAB 0x0000000000000002 /* Diagnostic Mode Enable */
+#define PSYCHO_STRBUF_CTRL_ENAB 0x0000000000000001 /* Streaming Buffer Enable */
+#define PSYCHO_STRBUF_FLUSH_A 0x2808UL
+#define PSYCHO_STRBUF_FLUSH_B 0x4808UL
+#define PSYCHO_STRBUF_FSYNC_A 0x2810UL
+#define PSYCHO_STRBUF_FSYNC_B 0x4810UL
+#define PSYCHO_STC_DATA_A 0xb000UL
+#define PSYCHO_STC_DATA_B 0xc000UL
+#define PSYCHO_STC_ERR_A 0xb400UL
+#define PSYCHO_STC_ERR_B 0xc400UL
+#define PSYCHO_STCERR_WRITE 0x0000000000000002 /* Write Error */
+#define PSYCHO_STCERR_READ 0x0000000000000001 /* Read Error */
+#define PSYCHO_STC_TAG_A 0xb800UL
+#define PSYCHO_STC_TAG_B 0xc800UL
+#define PSYCHO_STCTAG_PPN 0x0fffffff00000000 /* Physical Page Number */
+#define PSYCHO_STCTAG_VPN 0x00000000ffffe000 /* Virtual Page Number */
+#define PSYCHO_STCTAG_VALID 0x0000000000000002 /* Valid */
+#define PSYCHO_STCTAG_WRITE 0x0000000000000001 /* Writable */
+#define PSYCHO_STC_LINE_A 0xb900UL
+#define PSYCHO_STC_LINE_B 0xc900UL
+#define PSYCHO_STCLINE_LINDX 0x0000000001e00000 /* LRU Index */
+#define PSYCHO_STCLINE_SPTR 0x00000000001f8000 /* Dirty Data Start Pointer */
+#define PSYCHO_STCLINE_LADDR 0x0000000000007f00 /* Line Address */
+#define PSYCHO_STCLINE_EPTR 0x00000000000000fc /* Dirty Data End Pointer */
+#define PSYCHO_STCLINE_VALID 0x0000000000000002 /* Valid */
+#define PSYCHO_STCLINE_FOFN 0x0000000000000001 /* Fetch Outstanding / Flush Necessary */
+
+static spinlock_t stc_buf_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long stc_error_buf[128];
+static unsigned long stc_tag_buf[16];
+static unsigned long stc_line_buf[16];
+
+static void __psycho_check_one_stc(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm,
+ int is_pbm_a)
+{
+ struct pci_strbuf *strbuf = &pbm->stc;
+ unsigned long regbase = p->controller_regs;
+ unsigned long err_base, tag_base, line_base;
+ u64 control;
+ int i;
+
+ if (is_pbm_a) {
+ err_base = regbase + PSYCHO_STC_ERR_A;
+ tag_base = regbase + PSYCHO_STC_TAG_A;
+ line_base = regbase + PSYCHO_STC_LINE_A;
+ } else {
+ err_base = regbase + PSYCHO_STC_ERR_A;
+ tag_base = regbase + PSYCHO_STC_TAG_A;
+ line_base = regbase + PSYCHO_STC_LINE_A;
+ }
+
+ spin_lock(&stc_buf_lock);
+
+ /* This is __REALLY__ dangerous. When we put the
+ * streaming buffer into diagnostic mode to probe
+ * it's tags and error status, we _must_ clear all
+ * of the line tag valid bits before re-enabling
+ * the streaming buffer. If any dirty data lives
+ * in the STC when we do this, we will end up
+ * invalidating it before it has a chance to reach
+ * main memory.
+ */
+ control = psycho_read(strbuf->strbuf_control);
+ psycho_write(strbuf->strbuf_control,
+ (control | PSYCHO_STRBUF_CTRL_DENAB));
+ for (i = 0; i < 128; i++) {
+ unsigned long val;
+
+ val = psycho_read(err_base + (i * 8UL));
+ psycho_write(err_base + (i * 8UL), 0UL);
+ stc_error_buf[i] = val;
+ }
+ for (i = 0; i < 16; i++) {
+ stc_tag_buf[i] = psycho_read(tag_base + (i * 8UL));
+ stc_line_buf[i] = psycho_read(line_base + (i * 8UL));
+ psycho_write(tag_base + (i * 8UL), 0UL);
+ psycho_write(line_base + (i * 8UL), 0UL);
+ }
+
+ /* OK, state is logged, exit diagnostic mode. */
+ psycho_write(strbuf->strbuf_control, control);
+
+ for (i = 0; i < 16; i++) {
+ int j, saw_error, first, last;
+
+ saw_error = 0;
+ first = i * 8;
+ last = first + 8;
+ for (j = first; j < last; j++) {
+ unsigned long errval = stc_error_buf[j];
+ if (errval != 0) {
+ saw_error++;
+ printk("PSYCHO%d(PBM%c): STC_ERR(%d)[wr(%d)rd(%d)]\n",
+ p->index,
+ (is_pbm_a ? 'A' : 'B'),
+ j,
+ (errval & PSYCHO_STCERR_WRITE) ? 1 : 0,
+ (errval & PSYCHO_STCERR_READ) ? 1 : 0);
+ }
+ }
+ if (saw_error != 0) {
+ unsigned long tagval = stc_tag_buf[i];
+ unsigned long lineval = stc_line_buf[i];
+ printk("PSYCHO%d(PBM%c): STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n",
+ p->index,
+ (is_pbm_a ? 'A' : 'B'),
+ i,
+ ((tagval & PSYCHO_STCTAG_PPN) >> 19UL),
+ (tagval & PSYCHO_STCTAG_VPN),
+ ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0),
+ ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0));
+ printk("PSYCHO%d(PBM%c): STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)"
+ "V(%d)FOFN(%d)]\n",
+ p->index,
+ (is_pbm_a ? 'A' : 'B'),
+ i,
+ ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL),
+ ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL),
+ ((lineval & PSYCHO_STCLINE_LADDR) >> 8UL),
+ ((lineval & PSYCHO_STCLINE_EPTR) >> 2UL),
+ ((lineval & PSYCHO_STCLINE_VALID) ? 1 : 0),
+ ((lineval & PSYCHO_STCLINE_FOFN) ? 1 : 0));
+ }
+ }
+
+ spin_unlock(&stc_buf_lock);
+}
+
+static void __psycho_check_stc_error(struct pci_controller_info *p,
+ unsigned long afsr,
+ unsigned long afar,
+ enum psycho_error_type type)
+{
+ struct pci_pbm_info *pbm;
+
+ pbm = &p->pbm_A;
+ if (pbm->stc.strbuf_enabled)
+ __psycho_check_one_stc(p, pbm, 1);
+
+ pbm = &p->pbm_B;
+ if (pbm->stc.strbuf_enabled)
+ __psycho_check_one_stc(p, pbm, 0);
+}
+
+/* When an Uncorrectable Error or a PCI Error happens, we
+ * interrogate the IOMMU state to see if it is the cause.
+ */
+#define PSYCHO_IOMMU_CONTROL 0x0200UL
+#define PSYCHO_IOMMU_CTRL_RESV 0xfffffffff9000000 /* Reserved */
+#define PSYCHO_IOMMU_CTRL_XLTESTAT 0x0000000006000000 /* Translation Error Status */
+#define PSYCHO_IOMMU_CTRL_XLTEERR 0x0000000001000000 /* Translation Error encountered */
+#define PSYCHO_IOMMU_CTRL_LCKEN 0x0000000000800000 /* Enable translation locking */
+#define PSYCHO_IOMMU_CTRL_LCKPTR 0x0000000000780000 /* Translation lock pointer */
+#define PSYCHO_IOMMU_CTRL_TSBSZ 0x0000000000070000 /* TSB Size */
+#define PSYCHO_IOMMU_TSBSZ_1K 0x0000000000000000 /* TSB Table 1024 8-byte entries */
+#define PSYCHO_IOMMU_TSBSZ_2K 0x0000000000010000 /* TSB Table 2048 8-byte entries */
+#define PSYCHO_IOMMU_TSBSZ_4K 0x0000000000020000 /* TSB Table 4096 8-byte entries */
+#define PSYCHO_IOMMU_TSBSZ_8K 0x0000000000030000 /* TSB Table 8192 8-byte entries */
+#define PSYCHO_IOMMU_TSBSZ_16K 0x0000000000040000 /* TSB Table 16k 8-byte entries */
+#define PSYCHO_IOMMU_TSBSZ_32K 0x0000000000050000 /* TSB Table 32k 8-byte entries */
+#define PSYCHO_IOMMU_TSBSZ_64K 0x0000000000060000 /* TSB Table 64k 8-byte entries */
+#define PSYCHO_IOMMU_TSBSZ_128K 0x0000000000070000 /* TSB Table 128k 8-byte entries */
+#define PSYCHO_IOMMU_CTRL_RESV2 0x000000000000fff8 /* Reserved */
+#define PSYCHO_IOMMU_CTRL_TBWSZ 0x0000000000000004 /* Assumed page size, 0=8k 1=64k */
+#define PSYCHO_IOMMU_CTRL_DENAB 0x0000000000000002 /* Diagnostic mode enable */
+#define PSYCHO_IOMMU_CTRL_ENAB 0x0000000000000001 /* IOMMU Enable */
+#define PSYCHO_IOMMU_TSBBASE 0x0208UL
+#define PSYCHO_IOMMU_FLUSH 0x0210UL
+#define PSYCHO_IOMMU_TAG 0xa580UL
+#define PSYCHO_IOMMU_TAG_ERRSTS (0x3UL << 23UL)
+#define PSYCHO_IOMMU_TAG_ERR (0x1UL << 22UL)
+#define PSYCHO_IOMMU_TAG_WRITE (0x1UL << 21UL)
+#define PSYCHO_IOMMU_TAG_STREAM (0x1UL << 20UL)
+#define PSYCHO_IOMMU_TAG_SIZE (0x1UL << 19UL)
+#define PSYCHO_IOMMU_TAG_VPAGE 0x7ffffUL
+#define PSYCHO_IOMMU_DATA 0xa600UL
+#define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL)
+#define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL)
+#define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL
+static void psycho_check_iommu_error(struct pci_controller_info *p,
+ unsigned long afsr,
+ unsigned long afar,
+ enum psycho_error_type type)
+{
+ unsigned long iommu_tag[16];
+ unsigned long iommu_data[16];
+ unsigned long flags;
+ u64 control;
+ int i;
+
+ spin_lock_irqsave(&p->iommu.lock, flags);
+ control = psycho_read(p->iommu.iommu_control);
+ if (control & PSYCHO_IOMMU_CTRL_XLTEERR) {
+ char *type_string;
+
+ /* Clear the error encountered bit. */
+ control &= ~PSYCHO_IOMMU_CTRL_XLTEERR;
+ psycho_write(p->iommu.iommu_control, control);
+
+ switch((control & PSYCHO_IOMMU_CTRL_XLTESTAT) >> 25UL) {
+ case 0:
+ type_string = "Protection Error";
+ break;
+ case 1:
+ type_string = "Invalid Error";
+ break;
+ case 2:
+ type_string = "TimeOut Error";
+ break;
+ case 3:
+ default:
+ type_string = "ECC Error";
+ break;
+ };
+ printk("PSYCHO%d: IOMMU Error, type[%s]\n",
+ p->index, type_string);
+
+ /* Put the IOMMU into diagnostic mode and probe
+ * it's TLB for entries with error status.
+ *
+ * It is very possible for another DVMA to occur
+ * while we do this probe, and corrupt the system
+ * further. But we are so screwed at this point
+ * that we are likely to crash hard anyways, so
+ * get as much diagnostic information to the
+ * console as we can.
+ */
+ psycho_write(p->iommu.iommu_control,
+ control | PSYCHO_IOMMU_CTRL_DENAB);
+ for (i = 0; i < 16; i++) {
+ unsigned long base = p->controller_regs;
+
+ iommu_tag[i] =
+ psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL));
+ iommu_data[i] =
+ psycho_read(base + PSYCHO_IOMMU_DATA + (i * 8UL));
+
+ /* Now clear out the entry. */
+ psycho_write(base + PSYCHO_IOMMU_TAG + (i * 8UL), 0);
+ psycho_write(base + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
+ }
+
+ /* Leave diagnostic mode. */
+ psycho_write(p->iommu.iommu_control, control);
+
+ for (i = 0; i < 16; i++) {
+ unsigned long tag, data;
+
+ tag = iommu_tag[i];
+ if (!(tag & PSYCHO_IOMMU_TAG_ERR))
+ continue;
+
+ data = iommu_data[i];
+ switch((tag & PSYCHO_IOMMU_TAG_ERRSTS) >> 23UL) {
+ case 0:
+ type_string = "Protection Error";
+ break;
+ case 1:
+ type_string = "Invalid Error";
+ break;
+ case 2:
+ type_string = "TimeOut Error";
+ break;
+ case 3:
+ default:
+ type_string = "ECC Error";
+ break;
+ };
+ printk("PSYCHO%d: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n",
+ p->index, i, type_string,
+ ((tag & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0),
+ ((tag & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0),
+ ((tag & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8),
+ (tag & PSYCHO_IOMMU_TAG_VPAGE) << PAGE_SHIFT);
+ printk("PSYCHO%d: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n",
+ p->index, i,
+ ((data & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0),
+ ((data & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0),
+ (data & PSYCHO_IOMMU_DATA_PPAGE) << PAGE_SHIFT);
+ }
+ }
+ __psycho_check_stc_error(p, afsr, afar, type);
+ spin_unlock_irqrestore(&p->iommu.lock, flags);
+}
+
+/* Uncorrectable Errors. Cause of the error and the address are
+ * recorded in the UE_AFSR and UE_AFAR of PSYCHO. They are errors
+ * relating to UPA interface transactions.
+ */
+#define PSYCHO_UE_AFSR 0x0030UL
+#define PSYCHO_UEAFSR_PPIO 0x8000000000000000 /* Primary PIO is cause */
+#define PSYCHO_UEAFSR_PDRD 0x4000000000000000 /* Primary DVMA read is cause */
+#define PSYCHO_UEAFSR_PDWR 0x2000000000000000 /* Primary DVMA write is cause */
+#define PSYCHO_UEAFSR_SPIO 0x1000000000000000 /* Secondary PIO is cause */
+#define PSYCHO_UEAFSR_SDRD 0x0800000000000000 /* Secondary DVMA read is cause */
+#define PSYCHO_UEAFSR_SDWR 0x0400000000000000 /* Secondary DVMA write is cause*/
+#define PSYCHO_UEAFSR_RESV1 0x03ff000000000000 /* Reserved */
+#define PSYCHO_UEAFSR_BMSK 0x0000ffff00000000 /* Bytemask of failed transfer */
+#define PSYCHO_UEAFSR_DOFF 0x00000000e0000000 /* Doubleword Offset */
+#define PSYCHO_UEAFSR_MID 0x000000001f000000 /* UPA MID causing the fault */
+#define PSYCHO_UEAFSR_BLK 0x0000000000800000 /* Trans was block operation */
+#define PSYCHO_UEAFSR_RESV2 0x00000000007fffff /* Reserved */
+#define PSYCHO_UE_AFAR 0x0038UL
+
+static void psycho_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct pci_controller_info *p = dev_id;
+ unsigned long afsr_reg = p->controller_regs + PSYCHO_UE_AFSR;
+ unsigned long afar_reg = p->controller_regs + PSYCHO_UE_AFAR;
+ unsigned long afsr, afar, error_bits;
+ int reported;
+
+ /* Latch uncorrectable error status. */
+ afar = psycho_read(afar_reg);
+ afsr = psycho_read(afsr_reg);
+
+ /* Clear the primary/secondary error status bits. */
+ error_bits = afsr &
+ (PSYCHO_UEAFSR_PPIO | PSYCHO_UEAFSR_PDRD | PSYCHO_UEAFSR_PDWR |
+ PSYCHO_UEAFSR_SPIO | PSYCHO_UEAFSR_SDRD | PSYCHO_UEAFSR_SDWR);
+ psycho_write(afsr_reg, error_bits);
+
+ /* Log the error. */
+ printk("PSYCHO%d: Uncorrectable Error, primary error type[%s]\n",
+ p->index,
+ (((error_bits & PSYCHO_UEAFSR_PPIO) ?
+ "PIO" :
+ ((error_bits & PSYCHO_UEAFSR_PDRD) ?
+ "DMA Read" :
+ ((error_bits & PSYCHO_UEAFSR_PDWR) ?
+ "DMA Write" : "???")))));
+ printk("PSYCHO%d: bytemask[%04lx] dword_offset[%lx] UPA_MID[%02lx] was_block(%d)\n",
+ p->index,
+ (afsr & PSYCHO_UEAFSR_BMSK) >> 32UL,
+ (afsr & PSYCHO_UEAFSR_DOFF) >> 29UL,
+ (afsr & PSYCHO_UEAFSR_MID) >> 24UL,
+ ((afsr & PSYCHO_UEAFSR_BLK) ? 1 : 0));
+ printk("PSYCHO%d: UE AFAR [%016lx]\n", p->index, afar);
+ printk("PSYCHO%d: UE Secondary errors [", p->index);
+ reported = 0;
+ if (afsr & PSYCHO_UEAFSR_SPIO) {
+ reported++;
+ printk("(PIO)");
+ }
+ if (afsr & PSYCHO_UEAFSR_SDRD) {
+ reported++;
+ printk("(DMA Read)");
+ }
+ if (afsr & PSYCHO_UEAFSR_SDWR) {
+ reported++;
+ printk("(DMA Write)");
+ }
+ if (!reported)
+ printk("(none)");
+ printk("]\n");
+
+ /* Interrogate IOMMU for error status. */
+ psycho_check_iommu_error(p, afsr, afar, UE_ERR);
+}
+
+/* Correctable Errors. */
+#define PSYCHO_CE_AFSR 0x0040UL
+#define PSYCHO_CEAFSR_PPIO 0x8000000000000000 /* Primary PIO is cause */
+#define PSYCHO_CEAFSR_PDRD 0x4000000000000000 /* Primary DVMA read is cause */
+#define PSYCHO_CEAFSR_PDWR 0x2000000000000000 /* Primary DVMA write is cause */
+#define PSYCHO_CEAFSR_SPIO 0x1000000000000000 /* Secondary PIO is cause */
+#define PSYCHO_CEAFSR_SDRD 0x0800000000000000 /* Secondary DVMA read is cause */
+#define PSYCHO_CEAFSR_SDWR 0x0400000000000000 /* Secondary DVMA write is cause*/
+#define PSYCHO_CEAFSR_RESV1 0x0300000000000000 /* Reserved */
+#define PSYCHO_CEAFSR_ESYND 0x00ff000000000000 /* Syndrome Bits */
+#define PSYCHO_CEAFSR_BMSK 0x0000ffff00000000 /* Bytemask of failed transfer */
+#define PSYCHO_CEAFSR_DOFF 0x00000000e0000000 /* Double Offset */
+#define PSYCHO_CEAFSR_MID 0x000000001f000000 /* UPA MID causing the fault */
+#define PSYCHO_CEAFSR_BLK 0x0000000000800000 /* Trans was block operation */
+#define PSYCHO_CEAFSR_RESV2 0x00000000007fffff /* Reserved */
+#define PSYCHO_CE_AFAR 0x0040UL
+
+static void psycho_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct pci_controller_info *p = dev_id;
+ unsigned long afsr_reg = p->controller_regs + PSYCHO_CE_AFSR;
+ unsigned long afar_reg = p->controller_regs + PSYCHO_CE_AFAR;
+ unsigned long afsr, afar, error_bits;
+ int reported;
+
+ /* Latch error status. */
+ afar = psycho_read(afar_reg);
+ afsr = psycho_read(afsr_reg);
+
+ /* Clear primary/secondary error status bits. */
+ error_bits = afsr &
+ (PSYCHO_CEAFSR_PPIO | PSYCHO_CEAFSR_PDRD | PSYCHO_CEAFSR_PDWR |
+ PSYCHO_CEAFSR_SPIO | PSYCHO_CEAFSR_SDRD | PSYCHO_CEAFSR_SDWR);
+ psycho_write(afsr_reg, error_bits);
+
+ /* Log the error. */
+ printk("PSYCHO%d: Correctable Error, primary error type[%s]\n",
+ p->index,
+ (((error_bits & PSYCHO_CEAFSR_PPIO) ?
+ "PIO" :
+ ((error_bits & PSYCHO_CEAFSR_PDRD) ?
+ "DMA Read" :
+ ((error_bits & PSYCHO_CEAFSR_PDWR) ?
+ "DMA Write" : "???")))));
+ printk("PSYCHO%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] "
+ "UPA_MID[%02lx] was_block(%d)\n",
+ p->index,
+ (afsr & PSYCHO_CEAFSR_ESYND) >> 48UL,
+ (afsr & PSYCHO_CEAFSR_BMSK) >> 32UL,
+ (afsr & PSYCHO_CEAFSR_DOFF) >> 29UL,
+ (afsr & PSYCHO_CEAFSR_MID) >> 24UL,
+ ((afsr & PSYCHO_CEAFSR_BLK) ? 1 : 0));
+ printk("PSYCHO%d: CE AFAR [%016lx]\n", p->index, afar);
+ printk("PSYCHO%d: CE Secondary errors [", p->index);
+ reported = 0;
+ if (afsr & PSYCHO_CEAFSR_SPIO) {
+ reported++;
+ printk("(PIO)");
+ }
+ if (afsr & PSYCHO_CEAFSR_SDRD) {
+ reported++;
+ printk("(DMA Read)");
+ }
+ if (afsr & PSYCHO_CEAFSR_SDWR) {
+ reported++;
+ printk("(DMA Write)");
+ }
+ if (!reported)
+ printk("(none)");
+ printk("]\n");
+}
+
+/* PCI Errors. They are signalled by the PCI bus module since they
+ * are assosciated with a specific bus segment.
+ */
+#define PSYCHO_PCI_AFSR_A 0x2010UL
+#define PSYCHO_PCI_AFSR_B 0x4010UL
+#define PSYCHO_PCIAFSR_PMA 0x8000000000000000 /* Primary Master Abort Error */
+#define PSYCHO_PCIAFSR_PTA 0x4000000000000000 /* Primary Target Abort Error */
+#define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000 /* Primary Excessive Retries */
+#define PSYCHO_PCIAFSR_PPERR 0x1000000000000000 /* Primary Parity Error */
+#define PSYCHO_PCIAFSR_SMA 0x0800000000000000 /* Secondary Master Abort Error */
+#define PSYCHO_PCIAFSR_STA 0x0400000000000000 /* Secondary Target Abort Error */
+#define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000 /* Secondary Excessive Retries */
+#define PSYCHO_PCIAFSR_SPERR 0x0100000000000000 /* Secondary Parity Error */
+#define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000 /* Reserved */
+#define PSYCHO_PCIAFSR_BMSK 0x0000ffff00000000 /* Bytemask of failed transfer */
+#define PSYCHO_PCIAFSR_BLK 0x0000000080000000 /* Trans was block operation */
+#define PSYCHO_PCIAFSR_RESV2 0x0000000040000000 /* Reserved */
+#define PSYCHO_PCIAFSR_MID 0x000000003e000000 /* MID causing the error */
+#define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffff /* Reserved */
+#define PSYCHO_PCI_AFAR_A 0x2018UL
+#define PSYCHO_PCI_AFAR_B 0x4018UL
+
+static void psycho_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct pci_pbm_info *pbm = dev_id;
+ struct pci_controller_info *p = pbm->parent;
+ unsigned long afsr_reg, afar_reg;
+ unsigned long afsr, afar, error_bits;
+ int is_pbm_a, reported;
+
+ is_pbm_a = (pbm == &pbm->parent->pbm_A);
+ if (is_pbm_a) {
+ afsr_reg = p->controller_regs + PSYCHO_PCI_AFSR_A;
+ afar_reg = p->controller_regs + PSYCHO_PCI_AFAR_A;
+ } else {
+ afsr_reg = p->controller_regs + PSYCHO_PCI_AFSR_B;
+ afar_reg = p->controller_regs + PSYCHO_PCI_AFAR_B;
+ }
+
+ /* Latch error status. */
+ afar = psycho_read(afar_reg);
+ afsr = psycho_read(afsr_reg);
+
+ /* Clear primary/secondary error status bits. */
+ error_bits = afsr &
+ (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_PTA |
+ PSYCHO_PCIAFSR_PRTRY | PSYCHO_PCIAFSR_PPERR |
+ PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA |
+ PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR);
+ psycho_write(afsr_reg, error_bits);
+
+ /* Log the error. */
+ printk("PSYCHO%d(PBM%c): PCI Error, primary error type[%s]\n",
+ p->index, (is_pbm_a ? 'A' : 'B'),
+ (((error_bits & PSYCHO_PCIAFSR_PMA) ?
+ "Master Abort" :
+ ((error_bits & PSYCHO_PCIAFSR_PTA) ?
+ "Target Abort" :
+ ((error_bits & PSYCHO_PCIAFSR_PRTRY) ?
+ "Excessive Retries" :
+ ((error_bits & PSYCHO_PCIAFSR_PPERR) ?
+ "Parity Error" : "???"))))));
+ printk("PSYCHO%d(PBM%c): bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n",
+ p->index, (is_pbm_a ? 'A' : 'B'),
+ (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL,
+ (afsr & PSYCHO_PCIAFSR_MID) >> 25UL,
+ (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0);
+ printk("PSYCHO%d(PBM%c): PCI AFAR [%016lx]\n",
+ p->index, (is_pbm_a ? 'A' : 'B'), afar);
+ printk("PSYCHO%d(PBM%c): PCI Secondary errors [",
+ p->index, (is_pbm_a ? 'A' : 'B'));
+ reported = 0;
+ if (afsr & PSYCHO_PCIAFSR_SMA) {
+ reported++;
+ printk("(Master Abort)");
+ }
+ if (afsr & PSYCHO_PCIAFSR_STA) {
+ reported++;
+ printk("(Target Abort)");
+ }
+ if (afsr & PSYCHO_PCIAFSR_SRTRY) {
+ reported++;
+ printk("(Excessive Retries)");
+ }
+ if (afsr & PSYCHO_PCIAFSR_SPERR) {
+ reported++;
+ printk("(Parity Error)");
+ }
+ if (!reported)
+ printk("(none)");
+ printk("]\n");
+
+ /* For the error types shown, scan PBM's PCI bus for devices
+ * which have logged that error type.
+ */
+
+ /* If we see a Target Abort, this could be the result of an
+ * IOMMU translation error of some sort. It is extremely
+ * useful to log this information as usually it indicates
+ * a bug in the IOMMU support code or a PCI device driver.
+ */
+ if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) {
+ psycho_check_iommu_error(p, afsr, afar, PCI_ERR);
+ pci_scan_for_target_abort(p, pbm, pbm->pci_bus);
+ }
+ if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA))
+ pci_scan_for_master_abort(p, pbm, pbm->pci_bus);
+
+ /* For excessive retries, PSYCHO/PBM will abort the device
+ * and there is no way to specifically check for excessive
+ * retries in the config space status registers. So what
+ * we hope is that we'll catch it via the master/target
+ * abort events.
+ */
+
+ if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR))
+ pci_scan_for_parity_error(p, pbm, pbm->pci_bus);
+}
+
+/* XXX What about PowerFail/PowerManagement??? -DaveM */
+#define PSYCHO_ECC_CTRL 0x0020
+#define PSYCHO_ECCCTRL_EE 0x8000000000000000 /* Enable ECC Checking */
+#define PSYCHO_ECCCTRL_UE 0x4000000000000000 /* Enable UE Interrupts */
+#define PSYCHO_ECCCTRL_CE 0x2000000000000000 /* Enable CE INterrupts */
+#define PSYCHO_UE_INO 0x2e
+#define PSYCHO_CE_INO 0x2f
+#define PSYCHO_PCIERR_A_INO 0x30
+#define PSYCHO_PCIERR_B_INO 0x31
+static void __init psycho_register_error_handlers(struct pci_controller_info *p)
+{
+ unsigned long base = p->controller_regs;
+ unsigned int irq, portid = p->portid;
+ u64 tmp;
+
+ /* Build IRQs and register handlers. */
+ irq = psycho_irq_build(p, NULL, (portid << 6) | PSYCHO_UE_INO);
+ if (request_irq(irq, psycho_ue_intr,
+ SA_SHIRQ, "PSYCHO UE", p) < 0) {
+ prom_printf("PSYCHO%d: Cannot register UE interrupt.\n",
+ p->index);
+ prom_halt();
+ }
+
+ irq = psycho_irq_build(p, NULL, (portid << 6) | PSYCHO_CE_INO);
+ if (request_irq(irq, psycho_ce_intr,
+ SA_SHIRQ, "PSYCHO CE", p) < 0) {
+ prom_printf("PSYCHO%d: Cannot register CE interrupt.\n",
+ p->index);
+ prom_halt();
+ }
+
+ irq = psycho_irq_build(p, NULL, (portid << 6) | PSYCHO_PCIERR_A_INO);
+ if (request_irq(irq, psycho_pcierr_intr,
+ SA_SHIRQ, "PSYCHO PCIERR", &p->pbm_A) < 0) {
+ prom_printf("PSYCHO%d(PBMA): Cannot register PciERR interrupt.\n",
+ p->index);
+ prom_halt();
+ }
+
+ irq = psycho_irq_build(p, NULL, (portid << 6) | PSYCHO_PCIERR_B_INO);
+ if (request_irq(irq, psycho_pcierr_intr,
+ SA_SHIRQ, "PSYCHO PCIERR", &p->pbm_B) < 0) {
+ prom_printf("PSYCHO%d(PBMB): Cannot register PciERR interrupt.\n",
+ p->index);
+ prom_halt();
+ }
+
+ /* Enable UE and CE interrupts for controller. */
+ psycho_write(base + PSYCHO_ECC_CTRL,
+ (PSYCHO_ECCCTRL_EE |
+ PSYCHO_ECCCTRL_UE |
+ PSYCHO_ECCCTRL_CE));
+
+ /* Enable PCI Error interrupts and clear error
+ * bits for each PBM.
+ */
+ tmp = psycho_read(base + PSYCHO_PCIA_CTRL);
+ tmp |= (PSYCHO_PCICTRL_SBH_ERR |
+ PSYCHO_PCICTRL_SERR |
+ PSYCHO_PCICTRL_SBH_INT |
+ PSYCHO_PCICTRL_EEN);
+ psycho_write(base + PSYCHO_PCIA_CTRL, tmp);
+
+ tmp = psycho_read(base + PSYCHO_PCIB_CTRL);
+ tmp |= (PSYCHO_PCICTRL_SBH_ERR |
+ PSYCHO_PCICTRL_SERR |
+ PSYCHO_PCICTRL_SBH_INT |
+ PSYCHO_PCICTRL_EEN);
+ psycho_write(base + PSYCHO_PCIB_CTRL, tmp);
+}
+
+/* PSYCHO boot time probing and initialization. */
+static void __init psycho_resource_adjust(struct pci_dev *pdev,
+ struct resource *res,
+ struct resource *root)
+{
+ res->start += root->start;
+ res->end += root->start;
+}
+
+static void __init psycho_base_address_update(struct pci_dev *pdev, int resource)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_pbm_info *pbm = pcp->pbm;
+ struct resource *res = &pdev->resource[resource];
+ struct resource *root;
+ u32 reg;
+ int where, size;
+
+ if (res->flags & IORESOURCE_IO)
+ root = &pbm->io_space;
+ else
+ root = &pbm->mem_space;
+
+ where = PCI_BASE_ADDRESS_0 + (resource * 4);
+ size = res->end - res->start;
+ pci_read_config_dword(pdev, where, &reg);
+ reg = ((reg & size) |
+ (((u32)(res->start - root->start)) & ~size));
+ pci_write_config_dword(pdev, where, reg);
+}
+
+/* We have to do the config space accesses by hand, thus... */
+#define PBM_BRIDGE_BUS 0x40
+#define PBM_BRIDGE_SUBORDINATE 0x41
+static void __init pbm_renumber(struct pci_pbm_info *pbm, u8 orig_busno)
+{
+ u8 *addr, busno;
+ int nbus;
+
+ busno = pci_highest_busnum;
+ nbus = pbm->pci_last_busno - pbm->pci_first_busno;
+
+ addr = psycho_pci_config_mkaddr(pbm, orig_busno,
+ 0, PBM_BRIDGE_BUS);
+ pci_config_write8(addr, busno);
+ addr = psycho_pci_config_mkaddr(pbm, busno,
+ 0, PBM_BRIDGE_SUBORDINATE);
+ pci_config_write8(addr, busno + nbus);
+
+ pbm->pci_first_busno = busno;
+ pbm->pci_last_busno = busno + nbus;
+ pci_highest_busnum = busno + nbus + 1;
+
+ do {
+ pci_bus2pbm[busno++] = pbm;
+ } while (nbus--);
+}
+
+/* We have to do the config space accesses by hand here since
+ * the pci_bus2pbm array is not ready yet.
+ */
+static void __init pbm_pci_bridge_renumber(struct pci_pbm_info *pbm,
+ u8 busno)
+{
+ u32 devfn, l, class;
+ u8 hdr_type;
+ int is_multi = 0;
+
+ for(devfn = 0; devfn < 0xff; ++devfn) {
+ u32 *dwaddr;
+ u8 *baddr;
+
+ if (PCI_FUNC(devfn) != 0 && is_multi == 0)
+ continue;
+
+ /* Anything there? */
+ dwaddr = psycho_pci_config_mkaddr(pbm, busno, devfn, PCI_VENDOR_ID);
+ l = 0xffffffff;
+ pci_config_read32(dwaddr, &l);
+ if (l == 0xffffffff || l == 0x00000000 ||
+ l == 0x0000ffff || l == 0xffff0000) {
+ is_multi = 0;
+ continue;
+ }
+
+ baddr = psycho_pci_config_mkaddr(pbm, busno, devfn, PCI_HEADER_TYPE);
+ pci_config_read8(baddr, &hdr_type);
+ if (PCI_FUNC(devfn) == 0)
+ is_multi = hdr_type & 0x80;
+
+ dwaddr = psycho_pci_config_mkaddr(pbm, busno, devfn, PCI_CLASS_REVISION);
+ class = 0xffffffff;
+ pci_config_read32(dwaddr, &class);
+ if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
+ u32 buses = 0xffffffff;
+
+ dwaddr = psycho_pci_config_mkaddr(pbm, busno, devfn,
+ PCI_PRIMARY_BUS);
+ pci_config_read32(dwaddr, &buses);
+ pbm_pci_bridge_renumber(pbm, (buses >> 8) & 0xff);
+ buses &= 0xff000000;
+ pci_config_write32(dwaddr, buses);
+ }
+ }
+}
+
+static void __init pbm_bridge_reconfigure(struct pci_controller_info *p)
+{
+ struct pci_pbm_info *pbm;
+ u8 *addr;
+
+ /* Clear out primary/secondary/subordinate bus numbers on
+ * all PCI-to-PCI bridges under each PBM. The generic bus
+ * probing will fix them up.
+ */
+ pbm_pci_bridge_renumber(&p->pbm_B, p->pbm_B.pci_first_busno);
+ pbm_pci_bridge_renumber(&p->pbm_A, p->pbm_A.pci_first_busno);
+
+ /* Move PBM A out of the way. */
+ pbm = &p->pbm_A;
+ addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno,
+ 0, PBM_BRIDGE_BUS);
+ pci_config_write8(addr, 0xff);
+ addr = psycho_pci_config_mkaddr(pbm, 0xff,
+ 0, PBM_BRIDGE_SUBORDINATE);
+ pci_config_write8(addr, 0xff);
+
+ /* Now we can safely renumber both PBMs. */
+ pbm_renumber(&p->pbm_B, p->pbm_B.pci_first_busno);
+ pbm_renumber(&p->pbm_A, 0xff);
+}
+
+static void __init pbm_scan_bus(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm)
+{
+ pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,
+ p->pci_ops,
+ pbm);
+ pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
+ pci_record_assignments(pbm, pbm->pci_bus);
+ pci_assign_unassigned(pbm, pbm->pci_bus);
+ pci_fixup_irq(pbm, pbm->pci_bus);
+}
+
+static void __init psycho_scan_bus(struct pci_controller_info *p)
+{
+ pbm_bridge_reconfigure(p);
+ pbm_scan_bus(p, &p->pbm_B);
+ pbm_scan_bus(p, &p->pbm_A);
+
+ /* After the PCI bus scan is complete, we can register
+ * the error interrupt handlers.
+ */
+ psycho_register_error_handlers(p);
+}
+
+static void __init psycho_iommu_init(struct pci_controller_info *p, int tsbsize)
+{
+ extern int this_is_starfire;
+ extern void *starfire_hookup(int);
+ struct linux_mlist_p1275 *mlist;
+ unsigned long tsbbase, i, n, order;
+ iopte_t *iopte;
+ u64 control;
+
+ /* Setup initial software IOMMU state. */
+ spin_lock_init(&p->iommu.lock);
+ p->iommu.iommu_cur_ctx = 0;
+
+ /* PSYCHO's IOMMU lacks ctx flushing. */
+ p->iommu.iommu_has_ctx_flush = 0;
+
+ /* Register addresses. */
+ p->iommu.iommu_control = p->controller_regs + PSYCHO_IOMMU_CONTROL;
+ p->iommu.iommu_tsbbase = p->controller_regs + PSYCHO_IOMMU_TSBBASE;
+ p->iommu.iommu_flush = p->controller_regs + PSYCHO_IOMMU_FLUSH;
+ p->iommu.iommu_ctxflush = 0;
+
+ /* We use the main control register of PSYCHO as the write
+ * completion register.
+ */
+ p->iommu.write_complete_reg = p->controller_regs + PSYCHO_CONTROL;
+
+ /*
+ * Invalidate TLB Entries.
+ */
+ control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL);
+ control |= PSYCHO_IOMMU_CTRL_DENAB;
+ psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
+ for(i = 0; i < 16; i++)
+ psycho_write(p->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
+
+ control &= ~(PSYCHO_IOMMU_CTRL_DENAB);
+ psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
+
+ for(order = 0;; order++)
+ if((PAGE_SIZE << order) >= ((tsbsize * 1024) * 8))
+ break;
+
+ tsbbase = __get_free_pages(GFP_DMA, order);
+ if (!tsbbase) {
+ prom_printf("PSYCHO_IOMMU: Error, gfp(tsb) failed.\n");
+ prom_halt();
+ }
+ p->iommu.page_table = iopte = (iopte_t *)tsbbase;
+ p->iommu.page_table_sz = (tsbsize * 1024);
+
+ /* Initialize to "none" settings. */
+ for(i = 0; i < PCI_DVMA_HASHSZ; i++) {
+ pci_dvma_v2p_hash[i] = PCI_DVMA_HASH_NONE;
+ pci_dvma_p2v_hash[i] = PCI_DVMA_HASH_NONE;
+ }
+
+ n = 0;
+ mlist = *prom_meminfo()->p1275_totphys;
+ while (mlist) {
+ unsigned long paddr = mlist->start_adr;
+ unsigned long num_bytes = mlist->num_bytes;
+
+ if(paddr >= (((unsigned long) high_memory) - PAGE_OFFSET))
+ goto next;
+
+ if((paddr + num_bytes) >= (((unsigned long) high_memory) - PAGE_OFFSET))
+ num_bytes = (((unsigned long) high_memory) - PAGE_OFFSET) - paddr;
+
+ /* Align base and length so we map whole hash table sized chunks
+ * at a time (and therefore full 64K IOMMU pages).
+ */
+ paddr &= ~((1UL << 24UL) - 1);
+ num_bytes = (num_bytes + ((1UL << 24UL) - 1)) & ~((1UL << 24) - 1);
+
+ /* Move up the base for mappings already created. */
+ while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] !=
+ PCI_DVMA_HASH_NONE) {
+ paddr += (1UL << 24UL);
+ num_bytes -= (1UL << 24UL);
+ if(num_bytes == 0UL)
+ goto next;
+ }
+
+ /* Move down the size for tail mappings already created. */
+ while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr + num_bytes - (1UL << 24UL))] !=
+ PCI_DVMA_HASH_NONE) {
+ num_bytes -= (1UL << 24UL);
+ if(num_bytes == 0UL)
+ goto next;
+ }
+
+ /* Now map the rest. */
+ for (i = 0; i < ((num_bytes + ((1 << 16) - 1)) >> 16); i++) {
+ iopte_val(*iopte) = ((IOPTE_VALID | IOPTE_64K |
+ IOPTE_CACHE | IOPTE_WRITE) |
+ (paddr & IOPTE_PAGE));
+
+ if (!(n & 0xff))
+ set_dvma_hash(0x80000000, paddr, (n << 16));
+
+ if (++n > (tsbsize * 1024))
+ goto out;
+
+ paddr += (1 << 16);
+ iopte++;
+ }
+ next:
+ mlist = mlist->theres_more;
+ }
+out:
+ if (mlist) {
+ prom_printf("WARNING: not all physical memory mapped in IOMMU\n");
+ prom_printf("Try booting with mem=xxxM or similar\n");
+ prom_halt();
+ }
+
+ psycho_write(p->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase));
+
+ control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL);
+ control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ);
+ control |= (PSYCHO_IOMMU_CTRL_TBWSZ | PSYCHO_IOMMU_CTRL_ENAB);
+ switch(tsbsize) {
+ case 8:
+ p->iommu.page_table_map_base = 0xe0000000;
+ control |= PSYCHO_IOMMU_TSBSZ_8K;
+ break;
+ case 16:
+ p->iommu.page_table_map_base = 0xc0000000;
+ control |= PSYCHO_IOMMU_TSBSZ_16K;
+ break;
+ case 32:
+ p->iommu.page_table_map_base = 0x80000000;
+ control |= PSYCHO_IOMMU_TSBSZ_32K;
+ break;
+ default:
+ prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
+ prom_halt();
+ break;
+ }
+ psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
+
+ /* If necessary, hook us up for starfire IRQ translations. */
+ if(this_is_starfire)
+ p->starfire_cookie = starfire_hookup(p->portid);
+ else
+ p->starfire_cookie = NULL;
+}
+
+#define PSYCHO_IRQ_RETRY 0x1a00UL
+#define PSYCHO_PCIA_DIAG 0x2020UL
+#define PSYCHO_PCIB_DIAG 0x4020UL
+#define PSYCHO_PCIDIAG_RESV 0xffffffffffffff80 /* Reserved */
+#define PSYCHO_PCIDIAG_DRETRY 0x0000000000000040 /* Disable retry limit */
+#define PSYCHO_PCIDIAG_DISYNC 0x0000000000000020 /* Disable DMA wr / irq sync */
+#define PSYCHO_PCIDIAG_DDWSYNC 0x0000000000000010 /* Disable DMA wr / PIO rd sync */
+#define PSYCHO_PCIDIAG_IDDPAR 0x0000000000000008 /* Invert DMA data parity */
+#define PSYCHO_PCIDIAG_IPDPAR 0x0000000000000004 /* Invert PIO data parity */
+#define PSYCHO_PCIDIAG_IPAPAR 0x0000000000000002 /* Invert PIO address parity */
+#define PSYCHO_PCIDIAG_LPBACK 0x0000000000000001 /* Enable loopback mode */
+
+static void psycho_controller_hwinit(struct pci_controller_info *p)
+{
+ u64 tmp;
+
+ /* PROM sets the IRQ retry value too low, increase it. */
+ psycho_write(p->controller_regs + PSYCHO_IRQ_RETRY, 0xff);
+
+ /* Enable arbiter for all PCI slots. */
+ tmp = psycho_read(p->controller_regs + PSYCHO_PCIA_CTRL);
+ tmp |= PSYCHO_PCICTRL_AEN;
+ psycho_write(p->controller_regs + PSYCHO_PCIA_CTRL, tmp);
+
+ tmp = psycho_read(p->controller_regs + PSYCHO_PCIB_CTRL);
+ tmp |= PSYCHO_PCICTRL_AEN;
+ psycho_write(p->controller_regs + PSYCHO_PCIB_CTRL, tmp);
+
+ /* Disable DMA write / PIO read synchronization on
+ * both PCI bus segments.
+ * [ U2P Erratum 1243770, STP2223BGA data sheet ]
+ */
+ tmp = psycho_read(p->controller_regs + PSYCHO_PCIA_DIAG);
+ tmp |= PSYCHO_PCIDIAG_DDWSYNC;
+ psycho_write(p->controller_regs + PSYCHO_PCIA_DIAG, tmp);
+
+ tmp = psycho_read(p->controller_regs + PSYCHO_PCIB_DIAG);
+ tmp |= PSYCHO_PCIDIAG_DDWSYNC;
+ psycho_write(p->controller_regs + PSYCHO_PCIB_DIAG, tmp);
+}
+
+static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm)
+{
+ char *name = pbm->name;
+
+ sprintf(name, "PSYCHO%d PBM%c",
+ p->index,
+ (pbm == &p->pbm_A ? 'A' : 'B'));
+ pbm->io_space.name = pbm->mem_space.name = name;
+
+ request_resource(&ioport_resource, &pbm->io_space);
+ request_resource(&iomem_resource, &pbm->mem_space);
+}
+
+static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm,
+ int is_pbm_a)
+{
+ unsigned long base = p->controller_regs;
+
+ /* Currently we don't even use it. */
+ pbm->stc.strbuf_enabled = 0;
+
+ /* PSYCHO's streaming buffer lacks ctx flushing. */
+ pbm->stc.strbuf_has_ctx_flush = 0;
+
+ if (is_pbm_a) {
+ pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_A;
+ pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_A;
+ pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_A;
+ } else {
+ pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_B;
+ pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_B;
+ pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_B;
+ }
+ pbm->stc.strbuf_ctxflush = 0;
+ pbm->stc.strbuf_ctxmatch_base = 0;
+
+ pbm->stc.strbuf_flushflag = (volatile unsigned long *)
+ ((((unsigned long)&pbm->stc.__flushflag_buf[0])
+ + 63UL)
+ & ~63UL);
+ pbm->stc.strbuf_flushflag_pa = (unsigned long)
+ __pa(pbm->stc.strbuf_flushflag);
+
+#if 0
+ /* And when we do enable it, these are the sorts of things
+ * we'll do.
+ */
+ control = psycho_read(pbm->stc.strbuf_control);
+ control |= PSYCHO_SBUFCTRL_SB_EN;
+ psycho_write(pbm->stc.strbuf_control, control);
+#endif
+}
+
+#define PSYCHO_IOSPACE_A 0x002000000UL
+#define PSYCHO_IOSPACE_B 0x002010000UL
+#define PSYCHO_IOSPACE_SIZE 0x00000ffffUL
+#define PSYCHO_MEMSPACE_A 0x100000000UL
+#define PSYCHO_MEMSPACE_B 0x180000000UL
+#define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL
+
+static void psycho_pbm_init(struct pci_controller_info *p,
+ int prom_node, int is_pbm_a)
+{
+ unsigned int busrange[2];
+ struct pci_pbm_info *pbm;
+ int err;
+
+ if (is_pbm_a) {
+ pbm = &p->pbm_A;
+ pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_A;
+ pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_A;
+ } else {
+ pbm = &p->pbm_B;
+ pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_B;
+ pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_B;
+ }
+ pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE;
+ pbm->io_space.flags = IORESOURCE_IO;
+ pbm->mem_space.end = pbm->mem_space.start + PSYCHO_MEMSPACE_SIZE;
+ pbm->mem_space.flags = IORESOURCE_MEM;
+ pbm_register_toplevel_resources(p, pbm);
+
+ pbm->parent = p;
+ pbm->prom_node = prom_node;
+ prom_getstring(prom_node, "name",
+ pbm->prom_name,
+ sizeof(pbm->prom_name));
+
+ err = prom_getproperty(prom_node, "ranges",
+ (char *)pbm->pbm_ranges,
+ sizeof(pbm->pbm_ranges));
+ if (err != -1)
+ pbm->num_pbm_ranges =
+ (err / sizeof(struct linux_prom_pci_ranges));
+ else
+ pbm->num_pbm_ranges = 0;
+
+ err = prom_getproperty(prom_node, "interrupt-map",
+ (char *)pbm->pbm_intmap,
+ sizeof(pbm->pbm_intmap));
+ if (err != -1) {
+ pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
+ err = prom_getproperty(prom_node, "interrupt-map-mask",
+ (char *)&pbm->pbm_intmask,
+ sizeof(pbm->pbm_intmask));
+ if (err == -1) {
+ prom_printf("PSYCHO-PBM: Fatal error, no "
+ "interrupt-map-mask.\n");
+ prom_halt();
+ }
+ } else {
+ pbm->num_pbm_intmap = 0;
+ memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
+ }
+
+ err = prom_getproperty(prom_node, "bus-range",
+ (char *)&busrange[0],
+ sizeof(busrange));
+ if (err == 0 || err == -1) {
+ prom_printf("PSYCHO-PBM: Fatal error, no bus-range.\n");
+ prom_halt();
+ }
+ pbm->pci_first_busno = busrange[0];
+ pbm->pci_last_busno = busrange[1];
+
+ psycho_pbm_strbuf_init(p, pbm, is_pbm_a);
+}
+
+#define PSYCHO_CONFIGSPACE 0x001000000UL
+
+void __init psycho_init(int node)
+{
+ struct linux_prom64_registers pr_regs[3];
+ struct pci_controller_info *p;
+ unsigned long flags;
+ u32 upa_portid;
+ int is_pbm_a, err;
+
+ upa_portid = prom_getintdefault(node, "upa-portid", 0xff);
+
+ spin_lock_irqsave(&pci_controller_lock, flags);
+ for(p = pci_controller_root; p; p = p->next) {
+ if (p->portid == upa_portid) {
+ spin_unlock_irqrestore(&pci_controller_lock, flags);
+ is_pbm_a = (p->pbm_A.prom_node == 0);
+ psycho_pbm_init(p, node, is_pbm_a);
+ return;
+ }
+ }
+ spin_unlock_irqrestore(&pci_controller_lock, flags);
+
+ p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
+ if (!p) {
+ prom_printf("PSYCHO: Fatal memory allocation error.\n");
+ prom_halt();
+ }
+ memset(p, 0, sizeof(*p));
+
+ spin_lock_irqsave(&pci_controller_lock, flags);
+ p->next = pci_controller_root;
+ pci_controller_root = p;
+ spin_unlock_irqrestore(&pci_controller_lock, flags);
+
+ p->portid = upa_portid;
+ p->index = pci_num_controllers++;
+ p->scan_bus = psycho_scan_bus;
+ p->irq_build = psycho_irq_build;
+ p->base_address_update = psycho_base_address_update;
+ p->resource_adjust = psycho_resource_adjust;
+ p->pci_ops = &psycho_ops;
+
+ err = prom_getproperty(node, "reg",
+ (char *)&pr_regs[0],
+ sizeof(pr_regs));
+ if (err == 0 || err == -1) {
+ prom_printf("PSYCHO: Fatal error, no reg property.\n");
+ prom_halt();
+ }
+
+ p->controller_regs = pr_regs[2].phys_addr;
+ printk("PCI: Found PSYCHO, control regs at %016lx\n",
+ p->controller_regs);
+
+ p->config_space = pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE;
+ printk("PSYCHO: PCI config space at %016lx\n", p->config_space);
+
+ /*
+ * Psycho's PCI MEM space is mapped to a 2GB aligned area, so
+ * we need to adjust our MEM space mask.
+ */
+ pci_memspace_mask = 0x7fffffffUL;
+
+ psycho_controller_hwinit(p);
+
+ psycho_iommu_init(p, 32);
+
+ is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
+ psycho_pbm_init(p, node, is_pbm_a);
+}
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
new file mode 100644
index 000000000..46a9b31cf
--- /dev/null
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -0,0 +1,1487 @@
+/* $Id: pci_sabre.c,v 1.2 1999/09/05 04:58:06 davem Exp $
+ * pci_sabre.c: Sabre specific PCI controller support.
+ *
+ * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
+ * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be)
+ * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+
+#include <asm/apb.h>
+#include <asm/pbm.h>
+#include <asm/iommu.h>
+#include <asm/irq.h>
+
+#include "pci_impl.h"
+
+/* All SABRE registers are 64-bits. The following accessor
+ * routines are how they are accessed. The REG parameter
+ * is a physical address.
+ */
+#define sabre_read(__reg) \
+({ u64 __ret; \
+ __asm__ __volatile__("ldxa [%1] %2, %0" \
+ : "=r" (__ret) \
+ : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
+ : "memory"); \
+ __ret; \
+})
+#define sabre_write(__reg, __val) \
+ __asm__ __volatile__("stxa %0, [%1] %2" \
+ : /* no outputs */ \
+ : "r" (__val), "r" (__reg), \
+ "i" (ASI_PHYS_BYPASS_EC_E))
+
+/* SABRE PCI controller register offsets and definitions. */
+#define SABRE_UE_AFSR 0x0030UL
+#define SABRE_UEAFSR_PDRD 0x4000000000000000UL /* Primary PCI DMA Read */
+#define SABRE_UEAFSR_PDWR 0x2000000000000000UL /* Primary PCI DMA Write */
+#define SABRE_UEAFSR_SDRD 0x0800000000000000UL /* Secondary PCI DMA Read */
+#define SABRE_UEAFSR_SDWR 0x0400000000000000UL /* Secondary PCI DMA Write */
+#define SABRE_UEAFSR_SDTE 0x0200000000000000UL /* Secondary DMA Translation Error */
+#define SABRE_UEAFSR_PDTE 0x0100000000000000UL /* Primary DMA Translation Error */
+#define SABRE_UEAFSR_BMSK 0x0000ffff00000000UL /* Bytemask */
+#define SABRE_UEAFSR_OFF 0x00000000e0000000UL /* Offset (AFAR bits [5:3] */
+#define SABRE_UEAFSR_BLK 0x0000000000800000UL /* Was block operation */
+#define SABRE_UECE_AFAR 0x0038UL
+#define SABRE_CE_AFSR 0x0040UL
+#define SABRE_CEAFSR_PDRD 0x4000000000000000UL /* Primary PCI DMA Read */
+#define SABRE_CEAFSR_PDWR 0x2000000000000000UL /* Primary PCI DMA Write */
+#define SABRE_CEAFSR_SDRD 0x0800000000000000UL /* Secondary PCI DMA Read */
+#define SABRE_CEAFSR_SDWR 0x0400000000000000UL /* Secondary PCI DMA Write */
+#define SABRE_CEAFSR_ESYND 0x00ff000000000000UL /* ECC Syndrome */
+#define SABRE_CEAFSR_BMSK 0x0000ffff00000000UL /* Bytemask */
+#define SABRE_CEAFSR_OFF 0x00000000e0000000UL /* Offset */
+#define SABRE_CEAFSR_BLK 0x0000000000800000UL /* Was block operation */
+#define SABRE_UECE_AFAR_ALIAS 0x0048UL /* Aliases to 0x0038 */
+#define SABRE_IOMMU_CONTROL 0x0200UL
+#define SABRE_IOMMUCTRL_ERRSTS 0x0000000006000000UL /* Error status bits */
+#define SABRE_IOMMUCTRL_ERR 0x0000000001000000UL /* Error present in IOTLB */
+#define SABRE_IOMMUCTRL_LCKEN 0x0000000000800000UL /* IOTLB lock enable */
+#define SABRE_IOMMUCTRL_LCKPTR 0x0000000000780000UL /* IOTLB lock pointer */
+#define SABRE_IOMMUCTRL_TSBSZ 0x0000000000070000UL /* TSB Size */
+#define SABRE_IOMMUCTRL_TBWSZ 0x0000000000000004UL /* TSB assumed page size */
+#define SABRE_IOMMUCTRL_DENAB 0x0000000000000002UL /* Diagnostic Mode Enable */
+#define SABRE_IOMMUCTRL_ENAB 0x0000000000000001UL /* IOMMU Enable */
+#define SABRE_IOMMU_TSBBASE 0x0208UL
+#define SABRE_IOMMU_FLUSH 0x0210UL
+#define SABRE_IMAP_A_SLOT0 0x0c00UL
+#define SABRE_IMAP_B_SLOT0 0x0c20UL
+#define SABRE_IMAP_SCSI 0x1000UL
+#define SABRE_IMAP_ETH 0x1008UL
+#define SABRE_IMAP_BPP 0x1010UL
+#define SABRE_IMAP_AU_REC 0x1018UL
+#define SABRE_IMAP_AU_PLAY 0x1020UL
+#define SABRE_IMAP_PFAIL 0x1028UL
+#define SABRE_IMAP_KMS 0x1030UL
+#define SABRE_IMAP_FLPY 0x1038UL
+#define SABRE_IMAP_SHW 0x1040UL
+#define SABRE_IMAP_KBD 0x1048UL
+#define SABRE_IMAP_MS 0x1050UL
+#define SABRE_IMAP_SER 0x1058UL
+#define SABRE_IMAP_UE 0x1070UL
+#define SABRE_IMAP_CE 0x1078UL
+#define SABRE_IMAP_PCIERR 0x1080UL
+#define SABRE_IMAP_GFX 0x1098UL
+#define SABRE_IMAP_EUPA 0x10a0UL
+#define SABRE_ICLR_A_SLOT0 0x1400UL
+#define SABRE_ICLR_B_SLOT0 0x1480UL
+#define SABRE_ICLR_SCSI 0x1800UL
+#define SABRE_ICLR_ETH 0x1808UL
+#define SABRE_ICLR_BPP 0x1810UL
+#define SABRE_ICLR_AU_REC 0x1818UL
+#define SABRE_ICLR_AU_PLAY 0x1820UL
+#define SABRE_ICLR_PFAIL 0x1828UL
+#define SABRE_ICLR_KMS 0x1830UL
+#define SABRE_ICLR_FLPY 0x1838UL
+#define SABRE_ICLR_SHW 0x1840UL
+#define SABRE_ICLR_KBD 0x1848UL
+#define SABRE_ICLR_MS 0x1850UL
+#define SABRE_ICLR_SER 0x1858UL
+#define SABRE_ICLR_UE 0x1870UL
+#define SABRE_ICLR_CE 0x1878UL
+#define SABRE_ICLR_PCIERR 0x1880UL
+#define SABRE_WRSYNC 0x1c20UL
+#define SABRE_PCICTRL 0x2000UL
+#define SABRE_PCICTRL_MRLEN 0x0000001000000000UL /* Use MemoryReadLine for block loads/stores */
+#define SABRE_PCICTRL_SERR 0x0000000400000000UL /* Set when SERR asserted on PCI bus */
+#define SABRE_PCICTRL_ARBPARK 0x0000000000200000UL /* Bus Parking 0=Ultra-IIi 1=prev-bus-owner */
+#define SABRE_PCICTRL_CPUPRIO 0x0000000000100000UL /* Ultra-IIi granted every other bus cycle */
+#define SABRE_PCICTRL_ARBPRIO 0x00000000000f0000UL /* Slot which is granted every other bus cycle */
+#define SABRE_PCICTRL_ERREN 0x0000000000000100UL /* PCI Error Interrupt Enable */
+#define SABRE_PCICTRL_RTRYWE 0x0000000000000080UL /* DMA Flow Control 0=wait-if-possible 1=retry */
+#define SABRE_PCICTRL_AEN 0x000000000000000fUL /* Slot PCI arbitration enables */
+#define SABRE_PIOAFSR 0x2010UL
+#define SABRE_PIOAFSR_PMA 0x8000000000000000UL /* Primary Master Abort */
+#define SABRE_PIOAFSR_PTA 0x4000000000000000UL /* Primary Target Abort */
+#define SABRE_PIOAFSR_PRTRY 0x2000000000000000UL /* Primary Excessive Retries */
+#define SABRE_PIOAFSR_PPERR 0x1000000000000000UL /* Primary Parity Error */
+#define SABRE_PIOAFSR_SMA 0x0800000000000000UL /* Secondary Master Abort */
+#define SABRE_PIOAFSR_STA 0x0400000000000000UL /* Secondary Target Abort */
+#define SABRE_PIOAFSR_SRTRY 0x0200000000000000UL /* Secondary Excessive Retries */
+#define SABRE_PIOAFSR_SPERR 0x0100000000000000UL /* Secondary Parity Error */
+#define SABRE_PIOAFSR_BMSK 0x0000ffff00000000UL /* Byte Mask */
+#define SABRE_PIOAFSR_BLK 0x0000000080000000UL /* Was Block Operation */
+#define SABRE_PIOAFAR 0x2018UL
+#define SABRE_PCIDIAG 0x2020UL
+#define SABRE_PCIDIAG_DRTRY 0x0000000000000040UL /* Disable PIO Retry Limit */
+#define SABRE_PCIDIAG_IPAPAR 0x0000000000000008UL /* Invert PIO Address Parity */
+#define SABRE_PCIDIAG_IPDPAR 0x0000000000000004UL /* Invert PIO Data Parity */
+#define SABRE_PCIDIAG_IDDPAR 0x0000000000000002UL /* Invert DMA Data Parity */
+#define SABRE_PCIDIAG_ELPBK 0x0000000000000001UL /* Loopback Enable - not supported */
+#define SABRE_PCITASR 0x2028UL
+#define SABRE_PCITASR_EF 0x0000000000000080UL /* Respond to 0xe0000000-0xffffffff */
+#define SABRE_PCITASR_CD 0x0000000000000040UL /* Respond to 0xc0000000-0xdfffffff */
+#define SABRE_PCITASR_AB 0x0000000000000020UL /* Respond to 0xa0000000-0xbfffffff */
+#define SABRE_PCITASR_89 0x0000000000000010UL /* Respond to 0x80000000-0x9fffffff */
+#define SABRE_PCITASR_67 0x0000000000000008UL /* Respond to 0x60000000-0x7fffffff */
+#define SABRE_PCITASR_45 0x0000000000000004UL /* Respond to 0x40000000-0x5fffffff */
+#define SABRE_PCITASR_23 0x0000000000000002UL /* Respond to 0x20000000-0x3fffffff */
+#define SABRE_PCITASR_01 0x0000000000000001UL /* Respond to 0x00000000-0x1fffffff */
+#define SABRE_PIOBUF_DIAG 0x5000UL
+#define SABRE_DMABUF_DIAGLO 0x5100UL
+#define SABRE_DMABUF_DIAGHI 0x51c0UL
+#define SABRE_IMAP_GFX_ALIAS 0x6000UL /* Aliases to 0x1098 */
+#define SABRE_IMAP_EUPA_ALIAS 0x8000UL /* Aliases to 0x10a0 */
+#define SABRE_IOMMU_VADIAG 0xa400UL
+#define SABRE_IOMMU_TCDIAG 0xa408UL
+#define SABRE_IOMMU_TAG 0xa580UL
+#define SABRE_IOMMUTAG_ERRSTS 0x0000000001800000UL /* Error status bits */
+#define SABRE_IOMMUTAG_ERR 0x0000000000400000UL /* Error present */
+#define SABRE_IOMMUTAG_WRITE 0x0000000000200000UL /* Page is writable */
+#define SABRE_IOMMUTAG_STREAM 0x0000000000100000UL /* Streamable bit - unused */
+#define SABRE_IOMMUTAG_SIZE 0x0000000000080000UL /* 0=8k 1=16k */
+#define SABRE_IOMMUTAG_VPN 0x000000000007ffffUL /* Virtual Page Number [31:13] */
+#define SABRE_IOMMU_DATA 0xa600UL
+#define SABRE_IOMMUDATA_VALID 0x0000000040000000UL /* Valid */
+#define SABRE_IOMMUDATA_USED 0x0000000020000000UL /* Used (for LRU algorithm) */
+#define SABRE_IOMMUDATA_CACHE 0x0000000010000000UL /* Cacheable */
+#define SABRE_IOMMUDATA_PPN 0x00000000001fffffUL /* Physical Page Number [33:13] */
+#define SABRE_PCI_IRQSTATE 0xa800UL
+#define SABRE_OBIO_IRQSTATE 0xa808UL
+#define SABRE_FFBCFG 0xf000UL
+#define SABRE_FFBCFG_SPRQS 0x000000000f000000 /* Slave P_RQST queue size */
+#define SABRE_FFBCFG_ONEREAD 0x0000000000004000 /* Slave supports one outstanding read */
+#define SABRE_MCCTRL0 0xf010UL
+#define SABRE_MCCTRL0_RENAB 0x0000000080000000 /* Refresh Enable */
+#define SABRE_MCCTRL0_EENAB 0x0000000010000000 /* Enable all ECC functions */
+#define SABRE_MCCTRL0_11BIT 0x0000000000001000 /* Enable 11-bit column addressing */
+#define SABRE_MCCTRL0_DPP 0x0000000000000f00 /* DIMM Pair Present Bits */
+#define SABRE_MCCTRL0_RINTVL 0x00000000000000ff /* Refresh Interval */
+#define SABRE_MCCTRL1 0xf018UL
+#define SABRE_MCCTRL1_AMDC 0x0000000038000000 /* Advance Memdata Clock */
+#define SABRE_MCCTRL1_ARDC 0x0000000007000000 /* Advance DRAM Read Data Clock */
+#define SABRE_MCCTRL1_CSR 0x0000000000e00000 /* CAS to RAS delay for CBR refresh */
+#define SABRE_MCCTRL1_CASRW 0x00000000001c0000 /* CAS length for read/write */
+#define SABRE_MCCTRL1_RCD 0x0000000000038000 /* RAS to CAS delay */
+#define SABRE_MCCTRL1_CP 0x0000000000007000 /* CAS Precharge */
+#define SABRE_MCCTRL1_RP 0x0000000000000e00 /* RAS Precharge */
+#define SABRE_MCCTRL1_RAS 0x00000000000001c0 /* Length of RAS for refresh */
+#define SABRE_MCCTRL1_CASRW2 0x0000000000000038 /* Must be same as CASRW */
+#define SABRE_MCCTRL1_RSC 0x0000000000000007 /* RAS after CAS hold time */
+#define SABRE_RESETCTRL 0xf020UL
+
+#define SABRE_CONFIGSPACE 0x001000000UL
+#define SABRE_IOSPACE 0x002000000UL
+#define SABRE_IOSPACE_SIZE 0x00000ffffUL
+#define SABRE_MEMSPACE 0x100000000UL
+#define SABRE_MEMSPACE_SIZE 0x07fffffffUL
+
+/* UltraSparc-IIi Programmer's Manual, page 325, PCI
+ * configuration space address format:
+ *
+ * 32 24 23 16 15 11 10 8 7 2 1 0
+ * ---------------------------------------------------------
+ * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 |
+ * ---------------------------------------------------------
+ */
+#define SABRE_CONFIG_BASE(PBM) \
+ ((PBM)->parent->config_space | (1UL << 24))
+#define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG) \
+ (((unsigned long)(BUS) << 16) | \
+ ((unsigned long)(DEVFN) << 8) | \
+ ((unsigned long)(REG)))
+
+static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm,
+ unsigned char bus,
+ unsigned int devfn,
+ int where)
+{
+ if (!pbm)
+ return NULL;
+ return (void *)
+ (SABRE_CONFIG_BASE(pbm) |
+ SABRE_CONFIG_ENCODE(bus, devfn, where));
+}
+
+static int sabre_out_of_range(unsigned char devfn)
+{
+ return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) ||
+ ((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) ||
+ (PCI_SLOT(devfn) > 1));
+}
+
+static int __sabre_out_of_range(struct pci_pbm_info *pbm,
+ unsigned char bus,
+ unsigned char devfn)
+{
+ return ((pbm->parent == 0) ||
+ ((pbm == &pbm->parent->pbm_B) &&
+ (bus == pbm->pci_first_busno) &&
+ PCI_SLOT(devfn) > 8) ||
+ ((pbm == &pbm->parent->pbm_A) &&
+ (bus == pbm->pci_first_busno) &&
+ PCI_SLOT(devfn) > 8));
+}
+
+static int __sabre_read_byte(struct pci_dev *dev, int where, u8 *value)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+ unsigned char bus = dev->bus->number;
+ unsigned int devfn = dev->devfn;
+ u8 *addr;
+
+ *value = 0xff;
+ addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (__sabre_out_of_range(pbm, bus, devfn))
+ return PCIBIOS_SUCCESSFUL;
+ pci_config_read8(addr, value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int __sabre_read_word(struct pci_dev *dev, int where, u16 *value)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+ unsigned char bus = dev->bus->number;
+ unsigned int devfn = dev->devfn;
+ u16 *addr;
+
+ *value = 0xffff;
+ addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (__sabre_out_of_range(pbm, bus, devfn))
+ return PCIBIOS_SUCCESSFUL;
+
+ if (where & 0x01) {
+ printk("pcibios_read_config_word: misaligned reg [%x]\n",
+ where);
+ return PCIBIOS_SUCCESSFUL;
+ }
+ pci_config_read16(addr, value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int __sabre_read_dword(struct pci_dev *dev, int where, u32 *value)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+ unsigned char bus = dev->bus->number;
+ unsigned int devfn = dev->devfn;
+ u32 *addr;
+
+ *value = 0xffffffff;
+ addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (__sabre_out_of_range(pbm, bus, devfn))
+ return PCIBIOS_SUCCESSFUL;
+
+ if (where & 0x03) {
+ printk("pcibios_read_config_dword: misaligned reg [%x]\n",
+ where);
+ return PCIBIOS_SUCCESSFUL;
+ }
+ pci_config_read32(addr, value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int sabre_read_byte(struct pci_dev *dev, int where, u8 *value)
+{
+ if (dev->bus->number)
+ return __sabre_read_byte(dev, where, value);
+
+ if (sabre_out_of_range(dev->devfn)) {
+ *value = 0xff;
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ if (where < 8) {
+ u16 tmp;
+
+ __sabre_read_word(dev, where & ~1, &tmp);
+ if (where & 1)
+ *value = tmp >> 8;
+ else
+ *value = tmp & 0xff;
+ return PCIBIOS_SUCCESSFUL;
+ } else
+ return __sabre_read_byte(dev, where, value);
+}
+
+static int sabre_read_word(struct pci_dev *dev, int where, u16 *value)
+{
+ if (dev->bus->number)
+ return __sabre_read_word(dev, where, value);
+
+ if (sabre_out_of_range(dev->devfn)) {
+ *value = 0xffff;
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ if (where < 8)
+ return __sabre_read_word(dev, where, value);
+ else {
+ u8 tmp;
+
+ __sabre_read_byte(dev, where, &tmp);
+ *value = tmp;
+ __sabre_read_byte(dev, where + 1, &tmp);
+ *value |= tmp << 8;
+ return PCIBIOS_SUCCESSFUL;
+ }
+}
+
+static int sabre_read_dword(struct pci_dev *dev, int where, u32 *value)
+{
+ u16 tmp;
+
+ if (dev->bus->number)
+ return __sabre_read_dword(dev, where, value);
+
+ if (sabre_out_of_range(dev->devfn)) {
+ *value = 0xffffffff;
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ sabre_read_word(dev, where, &tmp);
+ *value = tmp;
+ sabre_read_word(dev, where + 2, &tmp);
+ *value |= tmp << 16;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int __sabre_write_byte(struct pci_dev *dev, int where, u8 value)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+ unsigned char bus = dev->bus->number;
+ unsigned int devfn = dev->devfn;
+ u8 *addr;
+
+ addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (__sabre_out_of_range(pbm, bus, devfn))
+ return PCIBIOS_SUCCESSFUL;
+ pci_config_write8(addr, value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int __sabre_write_word(struct pci_dev *dev, int where, u16 value)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+ unsigned char bus = dev->bus->number;
+ unsigned int devfn = dev->devfn;
+ u16 *addr;
+
+ addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (__sabre_out_of_range(pbm, bus, devfn))
+ return PCIBIOS_SUCCESSFUL;
+
+ if (where & 0x01) {
+ printk("pcibios_write_config_word: misaligned reg [%x]\n",
+ where);
+ return PCIBIOS_SUCCESSFUL;
+ }
+ pci_config_write16(addr, value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int __sabre_write_dword(struct pci_dev *dev, int where, u32 value)
+{
+ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+ unsigned char bus = dev->bus->number;
+ unsigned int devfn = dev->devfn;
+ u32 *addr;
+
+ addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (__sabre_out_of_range(pbm, bus, devfn))
+ return PCIBIOS_SUCCESSFUL;
+
+ if (where & 0x03) {
+ printk("pcibios_write_config_dword: misaligned reg [%x]\n",
+ where);
+ return PCIBIOS_SUCCESSFUL;
+ }
+ pci_config_write32(addr, value);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int sabre_write_byte(struct pci_dev *dev, int where, u8 value)
+{
+ if (dev->bus->number)
+ return __sabre_write_byte(dev, where, value);
+
+ if (sabre_out_of_range(dev->devfn))
+ return PCIBIOS_SUCCESSFUL;
+
+ if (where < 8) {
+ u16 tmp;
+
+ __sabre_read_word(dev, where & ~1, &tmp);
+ if (where & 1) {
+ value &= 0x00ff;
+ value |= tmp << 8;
+ } else {
+ value &= 0xff00;
+ value |= tmp;
+ }
+ return __sabre_write_word(dev, where & ~1, tmp);
+ } else
+ return __sabre_write_byte(dev, where, value);
+}
+
+static int sabre_write_word(struct pci_dev *dev, int where, u16 value)
+{
+ if (dev->bus->number)
+ return __sabre_write_word(dev, where, value);
+
+ if (sabre_out_of_range(dev->devfn))
+ return PCIBIOS_SUCCESSFUL;
+
+ if (where < 8)
+ return __sabre_write_word(dev, where, value);
+ else {
+ __sabre_write_byte(dev, where, value & 0xff);
+ __sabre_write_byte(dev, where + 1, value >> 8);
+ return PCIBIOS_SUCCESSFUL;
+ }
+}
+
+static int sabre_write_dword(struct pci_dev *dev, int where, u32 value)
+{
+ if (dev->bus->number)
+ return __sabre_write_dword(dev, where, value);
+
+ if (sabre_out_of_range(dev->devfn))
+ return PCIBIOS_SUCCESSFUL;
+
+ sabre_write_word(dev, where, value & 0xffff);
+ sabre_write_word(dev, where + 2, value >> 16);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops sabre_ops = {
+ sabre_read_byte,
+ sabre_read_word,
+ sabre_read_dword,
+ sabre_write_byte,
+ sabre_write_word,
+ sabre_write_dword
+};
+
+static unsigned long sabre_pcislot_imap_offset(unsigned long ino)
+{
+ unsigned int bus = (ino & 0x10) >> 4;
+ unsigned int slot = (ino & 0x0c) >> 2;
+
+ if (bus == 0)
+ return SABRE_IMAP_A_SLOT0 + (slot * 8);
+ else
+ return SABRE_IMAP_B_SLOT0 + (slot * 8);
+}
+
+static unsigned long __onboard_imap_off[] = {
+/*0x20*/ SABRE_IMAP_SCSI,
+/*0x21*/ SABRE_IMAP_ETH,
+/*0x22*/ SABRE_IMAP_BPP,
+/*0x23*/ SABRE_IMAP_AU_REC,
+/*0x24*/ SABRE_IMAP_AU_PLAY,
+/*0x25*/ SABRE_IMAP_PFAIL,
+/*0x26*/ SABRE_IMAP_KMS,
+/*0x27*/ SABRE_IMAP_FLPY,
+/*0x28*/ SABRE_IMAP_SHW,
+/*0x29*/ SABRE_IMAP_KBD,
+/*0x2a*/ SABRE_IMAP_MS,
+/*0x2b*/ SABRE_IMAP_SER,
+/*0x2c*/ 0 /* reserved */,
+/*0x2d*/ 0 /* reserved */,
+/*0x2e*/ SABRE_IMAP_UE,
+/*0x2f*/ SABRE_IMAP_CE,
+/*0x30*/ SABRE_IMAP_PCIERR,
+};
+#define SABRE_ONBOARD_IRQ_BASE 0x20
+#define SABRE_ONBOARD_IRQ_LAST 0x30
+#define sabre_onboard_imap_offset(__ino) \
+ __onboard_imap_off[(__ino) - SABRE_ONBOARD_IRQ_BASE]
+
+#define sabre_iclr_offset(ino) \
+ ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \
+ (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
+
+/* PCI SABRE INO number to Sparc PIL level. */
+static unsigned char sabre_pil_table[] = {
+/*0x00*/0, 0, 0, 0, /* PCI A slot 0 Int A, B, C, D */
+/*0x04*/0, 0, 0, 0, /* PCI A slot 1 Int A, B, C, D */
+/*0x08*/0, 0, 0, 0, /* PCI A slot 2 Int A, B, C, D */
+/*0x0c*/0, 0, 0, 0, /* PCI A slot 3 Int A, B, C, D */
+/*0x10*/0, 0, 0, 0, /* PCI B slot 0 Int A, B, C, D */
+/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */
+/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */
+/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */
+/*0x20*/3, /* SCSI */
+/*0x21*/5, /* Ethernet */
+/*0x22*/8, /* Parallel Port */
+/*0x23*/13, /* Audio Record */
+/*0x24*/14, /* Audio Playback */
+/*0x25*/15, /* PowerFail */
+/*0x26*/3, /* second SCSI */
+/*0x27*/11, /* Floppy */
+/*0x28*/2, /* Spare Hardware */
+/*0x29*/9, /* Keyboard */
+/*0x2a*/4, /* Mouse */
+/*0x2b*/12, /* Serial */
+/*0x2c*/10, /* Timer 0 */
+/*0x2d*/11, /* Timer 1 */
+/*0x2e*/15, /* Uncorrectable ECC */
+/*0x2f*/15, /* Correctable ECC */
+/*0x30*/15, /* PCI Bus A Error */
+/*0x31*/15, /* PCI Bus B Error */
+/*0x32*/1, /* Power Management */
+};
+
+static int __init sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
+{
+ int ret;
+
+ ret = sabre_pil_table[ino];
+ if (ret == 0 && pdev == NULL) {
+ ret = 1;
+ } else if (ret == 0) {
+ switch ((pdev->class >> 16) & 0x0f) {
+ case PCI_BASE_CLASS_STORAGE:
+ ret = 4;
+
+ case PCI_BASE_CLASS_NETWORK:
+ ret = 6;
+
+ case PCI_BASE_CLASS_DISPLAY:
+ ret = 9;
+
+ case PCI_BASE_CLASS_MULTIMEDIA:
+ case PCI_BASE_CLASS_MEMORY:
+ case PCI_BASE_CLASS_BRIDGE:
+ ret = 10;
+
+ default:
+ ret = 1;
+ };
+ }
+ return ret;
+}
+
+static unsigned int __init sabre_irq_build(struct pci_controller_info *p,
+ struct pci_dev *pdev,
+ unsigned int ino)
+{
+ struct ino_bucket *bucket;
+ volatile unsigned int *imap, *iclr;
+ unsigned long imap_off, iclr_off;
+ int pil, inofixup = 0;
+
+ ino &= PCI_IRQ_INO;
+ if (ino < SABRE_ONBOARD_IRQ_BASE) {
+ /* PCI slot */
+ imap_off = sabre_pcislot_imap_offset(ino);
+ } else {
+ /* onboard device */
+ if (ino > SABRE_ONBOARD_IRQ_LAST) {
+ prom_printf("sabre_irq_build: Wacky INO [%x]\n", ino);
+ prom_halt();
+ }
+ imap_off = sabre_onboard_imap_offset(ino);
+ }
+
+ /* Now build the IRQ bucket. */
+ pil = sabre_ino_to_pil(pdev, ino);
+ imap = (volatile unsigned int *)__va(p->controller_regs + imap_off);
+ imap += 1;
+
+ iclr_off = sabre_iclr_offset(ino);
+ iclr = (volatile unsigned int *)__va(p->controller_regs + iclr_off);
+ iclr += 1;
+
+ if ((ino & 0x20) == 0)
+ inofixup = ino & 0x03;
+
+ bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
+ bucket->flags |= IBF_PCI;
+
+ /* XXX We still need to code up support for this in irq.c
+ * XXX It's easy to code up since only one SIMBA can exist
+ * XXX in a machine and this is where the sync register is. -DaveM
+ */
+ if (pdev) {
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ if (pdev->bus->number != pcp->pbm->pci_first_busno)
+ bucket->flags |= IBF_DMA_SYNC;
+ }
+ return __irq(bucket);
+}
+
+/* SABRE error handling support. */
+static void sabre_check_iommu_error(struct pci_controller_info *p,
+ unsigned long afsr,
+ unsigned long afar)
+{
+ unsigned long iommu_tag[16];
+ unsigned long iommu_data[16];
+ unsigned long flags;
+ u64 control;
+ int i;
+
+ spin_lock_irqsave(&p->iommu.lock, flags);
+ control = sabre_read(p->iommu.iommu_control);
+ if (control & SABRE_IOMMUCTRL_ERR) {
+ char *type_string;
+
+ /* Clear the error encountered bit.
+ * NOTE: On Sabre this is write 1 to clear,
+ * which is different from Psycho.
+ */
+ sabre_write(p->iommu.iommu_control, control);
+ switch((control & SABRE_IOMMUCTRL_ERRSTS) >> 25UL) {
+ case 1:
+ type_string = "Invalid Error";
+ break;
+ case 3:
+ type_string = "ECC Error";
+ break;
+ default:
+ type_string = "Unknown";
+ break;
+ };
+ printk("SABRE%d: IOMMU Error, type[%s]\n",
+ p->index, type_string);
+
+ /* Enter diagnostic mode and probe for error'd
+ * entries in the IOTLB.
+ */
+ control &= ~(SABRE_IOMMUCTRL_ERRSTS | SABRE_IOMMUCTRL_ERR);
+ sabre_write(p->iommu.iommu_control,
+ (control | SABRE_IOMMUCTRL_DENAB));
+ for (i = 0; i < 16; i++) {
+ unsigned long base = p->controller_regs;
+
+ iommu_tag[i] =
+ sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL));
+ iommu_data[i] =
+ sabre_read(base + SABRE_IOMMU_DATA + (i * 8UL));
+ sabre_write(base + SABRE_IOMMU_TAG + (i * 8UL), 0);
+ sabre_write(base + SABRE_IOMMU_DATA + (i * 8UL), 0);
+ }
+ sabre_write(p->iommu.iommu_control, control);
+
+ for (i = 0; i < 16; i++) {
+ unsigned long tag, data;
+
+ tag = iommu_tag[i];
+ if (!(tag & SABRE_IOMMUTAG_ERR))
+ continue;
+
+ data = iommu_data[i];
+ switch((tag & SABRE_IOMMUTAG_ERRSTS) >> 23UL) {
+ case 1:
+ type_string = "Invalid Error";
+ break;
+ case 3:
+ type_string = "ECC Error";
+ break;
+ default:
+ type_string = "Unknown";
+ break;
+ };
+ printk("SABRE%d: IOMMU TAG(%d)[error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n",
+ p->index, i, type_string,
+ ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0),
+ ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8),
+ ((tag & SABRE_IOMMUTAG_VPN) << PAGE_SHIFT));
+ printk("SABRE%d: IOMMU DATA(%d)[valid(%d)used(%d)cache(%d)ppg(%016lx)\n",
+ p->index, i,
+ ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0),
+ ((data & SABRE_IOMMUDATA_USED) ? 1 : 0),
+ ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0),
+ ((data & SABRE_IOMMUDATA_PPN) << PAGE_SHIFT));
+ }
+ }
+ spin_unlock_irqrestore(&p->iommu.lock, flags);
+}
+
+static void sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct pci_controller_info *p = dev_id;
+ unsigned long afsr_reg = p->controller_regs + SABRE_UE_AFSR;
+ unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR;
+ unsigned long afsr, afar, error_bits;
+ int reported;
+
+ /* Latch uncorrectable error status. */
+ afar = sabre_read(afar_reg);
+ afsr = sabre_read(afsr_reg);
+
+ /* Clear the primary/secondary error status bits. */
+ error_bits = afsr &
+ (SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR |
+ SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR |
+ SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE);
+ sabre_write(afsr_reg, error_bits);
+
+ /* Log the error. */
+ printk("SABRE%d: Uncorrectable Error, primary error type[%s%s]\n",
+ p->index,
+ ((error_bits & SABRE_UEAFSR_PDRD) ?
+ "DMA Read" :
+ ((error_bits & SABRE_UEAFSR_PDWR) ?
+ "DMA Write" : "???")),
+ ((error_bits & SABRE_UEAFSR_PDTE) ?
+ ":Translation Error" : ""));
+ printk("SABRE%d: bytemask[%04lx] dword_offset[%lx] was_block(%d)\n",
+ p->index,
+ (afsr & SABRE_UEAFSR_BMSK) >> 32UL,
+ (afsr & SABRE_UEAFSR_OFF) >> 29UL,
+ ((afsr & SABRE_UEAFSR_BLK) ? 1 : 0));
+ printk("SABRE%d: UE AFAR [%016lx]\n", p->index, afar);
+ printk("SABRE%d: UE Secondary errors [", p->index);
+ reported = 0;
+ if (afsr & SABRE_UEAFSR_SDRD) {
+ reported++;
+ printk("(DMA Read)");
+ }
+ if (afsr & SABRE_UEAFSR_SDWR) {
+ reported++;
+ printk("(DMA Write)");
+ }
+ if (afsr & SABRE_UEAFSR_SDTE) {
+ reported++;
+ printk("(Translation Error)");
+ }
+ if (!reported)
+ printk("(none)");
+ printk("]\n");
+
+ /* Interrogate IOMMU for error status. */
+ sabre_check_iommu_error(p, afsr, afar);
+}
+
+static void sabre_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct pci_controller_info *p = dev_id;
+ unsigned long afsr_reg = p->controller_regs + SABRE_CE_AFSR;
+ unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR;
+ unsigned long afsr, afar, error_bits;
+ int reported;
+
+ /* Latch error status. */
+ afar = sabre_read(afar_reg);
+ afsr = sabre_read(afsr_reg);
+
+ /* Clear primary/secondary error status bits. */
+ error_bits = afsr &
+ (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR |
+ SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR);
+ sabre_write(afsr_reg, error_bits);
+
+ /* Log the error. */
+ printk("SABRE%d: Correctable Error, primary error type[%s]\n",
+ p->index,
+ ((error_bits & SABRE_CEAFSR_PDRD) ?
+ "DMA Read" :
+ ((error_bits & SABRE_CEAFSR_PDWR) ?
+ "DMA Write" : "???")));
+ printk("SABRE%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] "
+ "was_block(%d)\n",
+ p->index,
+ (afsr & SABRE_CEAFSR_ESYND) >> 48UL,
+ (afsr & SABRE_CEAFSR_BMSK) >> 32UL,
+ (afsr & SABRE_CEAFSR_OFF) >> 29UL,
+ ((afsr & SABRE_CEAFSR_BLK) ? 1 : 0));
+ printk("SABRE%d: CE AFAR [%016lx]\n", p->index, afar);
+ printk("SABRE%d: CE Secondary errors [", p->index);
+ reported = 0;
+ if (afsr & SABRE_CEAFSR_SDRD) {
+ reported++;
+ printk("(DMA Read)");
+ }
+ if (afsr & SABRE_CEAFSR_SDWR) {
+ reported++;
+ printk("(DMA Write)");
+ }
+ if (!reported)
+ printk("(none)");
+ printk("]\n");
+}
+
+static void sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct pci_controller_info *p = dev_id;
+ unsigned long afsr_reg, afar_reg;
+ unsigned long afsr, afar, error_bits;
+ int reported;
+
+ afsr_reg = p->controller_regs + SABRE_PIOAFSR;
+ afar_reg = p->controller_regs + SABRE_PIOAFAR;
+
+ /* Latch error status. */
+ afar = sabre_read(afar_reg);
+ afsr = sabre_read(afsr_reg);
+
+ /* Clear primary/secondary error status bits. */
+ error_bits = afsr &
+ (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_PTA |
+ SABRE_PIOAFSR_PRTRY | SABRE_PIOAFSR_PPERR |
+ SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA |
+ SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR);
+ sabre_write(afsr_reg, error_bits);
+
+ /* Log the error. */
+ printk("SABRE%d: PCI Error, primary error type[%s]\n",
+ p->index,
+ (((error_bits & SABRE_PIOAFSR_PMA) ?
+ "Master Abort" :
+ ((error_bits & SABRE_PIOAFSR_PTA) ?
+ "Target Abort" :
+ ((error_bits & SABRE_PIOAFSR_PRTRY) ?
+ "Excessive Retries" :
+ ((error_bits & SABRE_PIOAFSR_PPERR) ?
+ "Parity Error" : "???"))))));
+ printk("SABRE%d: bytemask[%04lx] was_block(%d)\n",
+ p->index,
+ (afsr & SABRE_PIOAFSR_BMSK) >> 32UL,
+ (afsr & SABRE_PIOAFSR_BLK) ? 1 : 0);
+ printk("SABRE%d: PCI AFAR [%016lx]\n", p->index, afar);
+ printk("SABRE%d: PCI Secondary errors [", p->index);
+ reported = 0;
+ if (afsr & SABRE_PIOAFSR_SMA) {
+ reported++;
+ printk("(Master Abort)");
+ }
+ if (afsr & SABRE_PIOAFSR_STA) {
+ reported++;
+ printk("(Target Abort)");
+ }
+ if (afsr & SABRE_PIOAFSR_SRTRY) {
+ reported++;
+ printk("(Excessive Retries)");
+ }
+ if (afsr & SABRE_PIOAFSR_SPERR) {
+ reported++;
+ printk("(Parity Error)");
+ }
+ if (!reported)
+ printk("(none)");
+ printk("]\n");
+
+ /* For the error types shown, scan both PCI buses for devices
+ * which have logged that error type.
+ */
+
+ /* If we see a Target Abort, this could be the result of an
+ * IOMMU translation error of some sort. It is extremely
+ * useful to log this information as usually it indicates
+ * a bug in the IOMMU support code or a PCI device driver.
+ */
+ if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) {
+ sabre_check_iommu_error(p, afsr, afar);
+ pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus);
+ pci_scan_for_target_abort(p, &p->pbm_B, p->pbm_B.pci_bus);
+ }
+ if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) {
+ pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus);
+ pci_scan_for_master_abort(p, &p->pbm_B, p->pbm_B.pci_bus);
+ }
+ /* For excessive retries, SABRE/PBM will abort the device
+ * and there is no way to specifically check for excessive
+ * retries in the config space status registers. So what
+ * we hope is that we'll catch it via the master/target
+ * abort events.
+ */
+
+ if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) {
+ pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus);
+ pci_scan_for_parity_error(p, &p->pbm_B, p->pbm_B.pci_bus);
+ }
+}
+
+/* XXX What about PowerFail/PowerManagement??? -DaveM */
+#define SABRE_UE_INO 0x2e
+#define SABRE_CE_INO 0x2f
+#define SABRE_PCIERR_INO 0x30
+static void __init sabre_register_error_handlers(struct pci_controller_info *p)
+{
+ unsigned long base = p->controller_regs;
+ unsigned long irq, portid = p->portid;
+ u64 tmp;
+
+ /* We clear the error bits in the appropriate AFSR before
+ * registering the handler so that we don't get spurious
+ * interrupts.
+ */
+ sabre_write(base + SABRE_UE_AFSR,
+ (SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR |
+ SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR |
+ SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE));
+ irq = sabre_irq_build(p, NULL, (portid << 6) | SABRE_UE_INO);
+ if (request_irq(irq, sabre_ue_intr,
+ SA_SHIRQ, "SABRE UE", p) < 0) {
+ prom_printf("SABRE%d: Cannot register UE interrupt.\n",
+ p->index);
+ prom_halt();
+ }
+
+ sabre_write(base + SABRE_CE_AFSR,
+ (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR |
+ SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR));
+ irq = sabre_irq_build(p, NULL, (portid << 6) | SABRE_CE_INO);
+ if (request_irq(irq, sabre_ce_intr,
+ SA_SHIRQ, "SABRE CE", p) < 0) {
+ prom_printf("SABRE%d: Cannot register CE interrupt.\n",
+ p->index);
+ prom_halt();
+ }
+
+ irq = sabre_irq_build(p, NULL, (portid << 6) | SABRE_PCIERR_INO);
+ if (request_irq(irq, sabre_pcierr_intr,
+ SA_SHIRQ, "SABRE PCIERR", p) < 0) {
+ prom_printf("SABRE%d: Cannot register PciERR interrupt.\n",
+ p->index);
+ prom_halt();
+ }
+
+ tmp = sabre_read(base + SABRE_PCICTRL);
+ tmp |= SABRE_PCICTRL_ERREN;
+ sabre_write(base + SABRE_PCICTRL, tmp);
+}
+
+static void __init sabre_resource_adjust(struct pci_dev *pdev,
+ struct resource *res,
+ struct resource *root)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_controller_info *p = pcp->pbm->parent;
+ unsigned long base;
+
+ if (res->flags & IORESOURCE_IO)
+ base = p->controller_regs + SABRE_IOSPACE;
+ else
+ base = p->controller_regs + SABRE_MEMSPACE;
+
+ res->start += base;
+ res->end += base;
+}
+
+static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_pbm_info *pbm = pcp->pbm;
+ struct pci_controller_info *p = pbm->parent;
+ struct resource *res = &pdev->resource[resource];
+ unsigned long base;
+ u32 reg;
+ int where, size;
+
+ if (res->flags & IORESOURCE_IO)
+ base = p->controller_regs + SABRE_IOSPACE;
+ else
+ base = p->controller_regs + SABRE_MEMSPACE;
+
+ where = PCI_BASE_ADDRESS_0 + (resource * 4);
+ size = res->end - res->start;
+ pci_read_config_dword(pdev, where, &reg);
+ reg = ((reg & size) |
+ (((u32)(res->start - base)) & ~size));
+ pci_write_config_dword(pdev, where, reg);
+}
+
+static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
+{
+ struct pci_dev *pdev;
+ u32 dword;
+ u16 word;
+
+ for(pdev = pci_devices; pdev; pdev = pdev->next) {
+ if(pdev->vendor == PCI_VENDOR_ID_SUN &&
+ pdev->device == PCI_DEVICE_ID_SUN_SABRE) {
+ sabre_write_byte(pdev, PCI_LATENCY_TIMER, 64);
+ break;
+ }
+ }
+
+ for (pdev = sabre_bus->devices; pdev; pdev = pdev->sibling) {
+ if (pdev->vendor == PCI_VENDOR_ID_SUN &&
+ pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
+ sabre_read_word(pdev, PCI_COMMAND, &word);
+ word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_IO;
+ sabre_write_word(pdev, PCI_COMMAND, word);
+
+ /* Status register bits are "write 1 to clear". */
+ sabre_write_word(pdev, PCI_STATUS, 0xffff);
+ sabre_write_word(pdev, PCI_SEC_STATUS, 0xffff);
+
+ sabre_read_word(pdev, PCI_BRIDGE_CONTROL, &word);
+ word = PCI_BRIDGE_CTL_MASTER_ABORT |
+ PCI_BRIDGE_CTL_SERR |
+ PCI_BRIDGE_CTL_PARITY;
+ sabre_write_word(pdev, PCI_BRIDGE_CONTROL, word);
+
+ sabre_read_dword(pdev, APB_PCI_CONTROL_HIGH, &dword);
+ dword = APB_PCI_CTL_HIGH_SERR |
+ APB_PCI_CTL_HIGH_ARBITER_EN;
+ sabre_write_dword(pdev, APB_PCI_CONTROL_HIGH, dword);
+
+ /* Systems with SIMBA are usually workstations, so
+ * we configure to park to SIMBA not to the previous
+ * bus owner.
+ */
+ sabre_read_dword(pdev, APB_PCI_CONTROL_LOW, &dword);
+ dword = APB_PCI_CTL_LOW_ERRINT_EN | 0x0f;
+ sabre_write_dword(pdev, APB_PCI_CONTROL_LOW, dword);
+
+ /* Don't mess with the retry limit and PIO/DMA latency
+ * timer settings. But do set primary and secondary
+ * latency timers.
+ */
+ sabre_write_byte(pdev, PCI_LATENCY_TIMER, 64);
+ sabre_write_byte(pdev, PCI_SEC_LATENCY_TIMER, 64);
+ }
+ }
+}
+
+static void __init sabre_scan_bus(struct pci_controller_info *p)
+{
+ static int once = 0;
+ struct pci_bus *sabre_bus, *pbus;
+
+ /* Unlike for PSYCHO, we can only have one SABRE
+ * in a system. Having multiple SABREs is thus
+ * and error, and as a consequence we do not need
+ * to do any bus renumbering but we do have to have
+ * the pci_bus2pbm array setup properly.
+ *
+ * Also note that the SABRE host bridge is hardwired
+ * to live at bus 0.
+ */
+ if (once != 0) {
+ prom_printf("SABRE: Multiple controllers unsupported.\n");
+ prom_halt();
+ }
+ once++;
+
+ /* The pci_bus2pbm table has already been setup in sabre_init. */
+ sabre_bus = pci_scan_bus(p->pci_first_busno,
+ p->pci_ops,
+ &p->pbm_A);
+ apb_init(p, sabre_bus);
+
+ for (pbus = sabre_bus->children; pbus; pbus = pbus->next) {
+ struct pci_pbm_info *pbm;
+
+ if (pbus->number == p->pbm_A.pci_first_busno) {
+ pbm = &p->pbm_A;
+ } else if (pbus->number == p->pbm_B.pci_first_busno) {
+ pbm = &p->pbm_B;
+ } else
+ continue;
+
+ pbus->sysdata = pbm;
+ pbm->pci_bus = pbus;
+ pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node);
+ pci_record_assignments(pbm, pbus);
+ pci_assign_unassigned(pbm, pbus);
+ pci_fixup_irq(pbm, pbus);
+ }
+
+ sabre_register_error_handlers(p);
+}
+
+static void __init sabre_iommu_init(struct pci_controller_info *p,
+ int tsbsize, unsigned long dvma_offset)
+{
+ struct linux_mlist_p1275 *mlist;
+ unsigned long tsbbase, i, n, order;
+ iopte_t *iopte;
+ u64 control;
+
+ /* Invalidate TLB Entries. */
+ control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);
+ control |= IOMMU_CTRL_DENAB;
+ sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
+
+ for(i = 0; i < 16; i++)
+ sabre_write(p->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0);
+
+ control &= ~(IOMMU_CTRL_DENAB);
+ sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
+
+ for(order = 0;; order++)
+ if((PAGE_SIZE << order) >= ((tsbsize * 1024) * 8))
+ break;
+ tsbbase = __get_free_pages(GFP_DMA, order);
+ if (!tsbbase) {
+ prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n");
+ prom_halt();
+ }
+ iopte = (iopte_t *)tsbbase;
+
+ /* Initialize to "none" settings. */
+ for(i = 0; i < PCI_DVMA_HASHSZ; i++) {
+ pci_dvma_v2p_hash[i] = PCI_DVMA_HASH_NONE;
+ pci_dvma_p2v_hash[i] = PCI_DVMA_HASH_NONE;
+ }
+
+ n = 0;
+ mlist = *prom_meminfo()->p1275_totphys;
+ while (mlist) {
+ unsigned long paddr = mlist->start_adr;
+ unsigned long num_bytes = mlist->num_bytes;
+
+ if(paddr >= (((unsigned long) high_memory) - PAGE_OFFSET))
+ goto next;
+
+ if((paddr + num_bytes) >= (((unsigned long) high_memory) - PAGE_OFFSET))
+ num_bytes =
+ (((unsigned long) high_memory) -
+ PAGE_OFFSET) - paddr;
+
+ /* Align base and length so we map whole hash table sized chunks
+ * at a time (and therefore full 64K IOMMU pages).
+ */
+ paddr &= ~((1UL << 24UL) - 1);
+ num_bytes = (num_bytes + ((1UL << 24UL) - 1)) & ~((1UL << 24) - 1);
+
+ /* Move up the base for mappings already created. */
+ while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] !=
+ PCI_DVMA_HASH_NONE) {
+ paddr += (1UL << 24UL);
+ num_bytes -= (1UL << 24UL);
+ if(num_bytes == 0UL)
+ goto next;
+ }
+
+ /* Move down the size for tail mappings already created. */
+ while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr + num_bytes - (1UL << 24UL))] !=
+ PCI_DVMA_HASH_NONE) {
+ num_bytes -= (1UL << 24UL);
+ if(num_bytes == 0UL)
+ goto next;
+ }
+
+ /* Now map the rest. */
+ for (i = 0; i < ((num_bytes + ((1 << 16) - 1)) >> 16); i++) {
+ iopte_val(*iopte) = ((IOPTE_VALID | IOPTE_64K |
+ IOPTE_CACHE | IOPTE_WRITE) |
+ (paddr & IOPTE_PAGE));
+
+ if (!(n & 0xff))
+ set_dvma_hash(dvma_offset, paddr, (n << 16));
+ if (++n > (tsbsize * 1024))
+ goto out;
+
+ paddr += (1 << 16);
+ iopte++;
+ }
+ next:
+ mlist = mlist->theres_more;
+ }
+out:
+ if (mlist) {
+ prom_printf("WARNING: not all physical memory mapped in IOMMU\n");
+ prom_printf("Try booting with mem=xxxM or similar\n");
+ prom_halt();
+ }
+
+ sabre_write(p->controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
+
+ control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);
+ control &= ~(IOMMU_CTRL_TSBSZ);
+ control |= (IOMMU_CTRL_TBWSZ | IOMMU_CTRL_ENAB);
+ switch(tsbsize) {
+ case 8:
+ control |= IOMMU_TSBSZ_8K;
+ break;
+ case 16:
+ control |= IOMMU_TSBSZ_16K;
+ break;
+ case 32:
+ control |= IOMMU_TSBSZ_32K;
+ break;
+ default:
+ prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
+ prom_halt();
+ break;
+ }
+ sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
+}
+
+static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
+ struct pci_pbm_info *pbm)
+{
+ char *name = pbm->name;
+ unsigned long ibase = p->controller_regs + SABRE_IOSPACE;
+ unsigned long mbase = p->controller_regs + SABRE_MEMSPACE;
+ unsigned int devfn;
+ unsigned long first, last, i;
+ u8 *addr, map;
+
+ sprintf(name, "SABRE%d PBM%c",
+ p->index,
+ (pbm == &p->pbm_A ? 'A' : 'B'));
+ pbm->io_space.name = pbm->mem_space.name = name;
+
+ devfn = PCI_DEVFN(1, (pbm == &p->pbm_A) ? 0 : 1);
+ addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_IO_ADDRESS_MAP);
+ map = 0;
+ pci_config_read8(addr, &map);
+
+ first = 8;
+ last = 0;
+ for (i = 0; i < 8; i++) {
+ if ((map & (1 << i)) != 0) {
+ if (first > i)
+ first = i;
+ if (last < i)
+ last = i;
+ }
+ }
+ pbm->io_space.start = ibase + (first << 21UL);
+ pbm->io_space.end = ibase + (last << 21UL) + ((1 << 21UL) - 1);
+ pbm->io_space.flags = IORESOURCE_IO;
+
+ addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_MEM_ADDRESS_MAP);
+ map = 0;
+ pci_config_read8(addr, &map);
+
+ first = 8;
+ last = 0;
+ for (i = 0; i < 8; i++) {
+ if ((map & (1 << i)) != 0) {
+ if (first > i)
+ first = i;
+ if (last < i)
+ last = i;
+ }
+ }
+ pbm->mem_space.start = mbase + (first << 29UL);
+ pbm->mem_space.end = mbase + (last << 29UL) + ((1 << 29UL) - 1);
+ pbm->mem_space.flags = IORESOURCE_MEM;
+
+ if (request_resource(&ioport_resource, &pbm->io_space) < 0) {
+ prom_printf("Cannot register PBM-%c's IO space.\n",
+ (pbm == &p->pbm_A ? 'A' : 'B'));
+ prom_halt();
+ }
+ if (request_resource(&iomem_resource, &pbm->mem_space) < 0) {
+ prom_printf("Cannot register PBM-%c's MEM space.\n",
+ (pbm == &p->pbm_A ? 'A' : 'B'));
+ prom_halt();
+ }
+}
+
+static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node)
+{
+ char namebuf[128];
+ u32 busrange[2];
+ int node;
+
+ node = prom_getchild(sabre_node);
+ while ((node = prom_searchsiblings(node, "pci")) != 0) {
+ struct pci_pbm_info *pbm;
+ int err;
+
+ err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
+ if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err))
+ goto next_pci;
+
+ err = prom_getproperty(node, "bus-range",
+ (char *)&busrange[0], sizeof(busrange));
+ if (err == 0 || err == -1) {
+ prom_printf("APB: Error, cannot get PCI bus-range.\n");
+ prom_halt();
+ }
+
+ if (busrange[0] == 1)
+ pbm = &p->pbm_B;
+ else
+ pbm = &p->pbm_A;
+ pbm->parent = p;
+ pbm->prom_node = node;
+ pbm->pci_first_busno = busrange[0];
+ pbm->pci_last_busno = busrange[1];
+ for (err = pbm->pci_first_busno;
+ err <= pbm->pci_last_busno;
+ err++)
+ pci_bus2pbm[err] = pbm;
+
+
+ prom_getstring(node, "name", pbm->prom_name, sizeof(pbm->prom_name));
+ err = prom_getproperty(node, "ranges",
+ (char *)pbm->pbm_ranges,
+ sizeof(pbm->pbm_ranges));
+ if (err != -1)
+ pbm->num_pbm_ranges =
+ (err / sizeof(struct linux_prom_pci_ranges));
+ else
+ pbm->num_pbm_ranges = 0;
+
+ err = prom_getproperty(node, "interrupt-map",
+ (char *)pbm->pbm_intmap,
+ sizeof(pbm->pbm_intmap));
+ if (err != -1) {
+ pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
+ err = prom_getproperty(node, "interrupt-map-mask",
+ (char *)&pbm->pbm_intmask,
+ sizeof(pbm->pbm_intmask));
+ if (err == -1) {
+ prom_printf("APB: Fatal error, no interrupt-map-mask.\n");
+ prom_halt();
+ }
+ } else {
+ pbm->num_pbm_intmap = 0;
+ memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
+ }
+
+ pbm_register_toplevel_resources(p, pbm);
+
+ next_pci:
+ node = prom_getsibling(node);
+ if (!node)
+ break;
+ }
+}
+
+void __init sabre_init(int pnode)
+{
+ struct linux_prom64_registers pr_regs[2];
+ struct pci_controller_info *p;
+ unsigned long flags;
+ int tsbsize, err;
+ u32 busrange[2];
+ u32 vdma[2];
+ u32 upa_portid;
+ int bus;
+
+ p = kmalloc(sizeof(*p), GFP_ATOMIC);
+ if (!p) {
+ prom_printf("SABRE: Error, kmalloc(pci_controller_info) failed.\n");
+ prom_halt();
+ }
+
+ upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff);
+
+ memset(p, 0, sizeof(*p));
+
+ spin_lock_irqsave(&pci_controller_lock, flags);
+ p->next = pci_controller_root;
+ pci_controller_root = p;
+ spin_unlock_irqrestore(&pci_controller_lock, flags);
+
+ p->portid = upa_portid;
+ p->index = pci_num_controllers++;
+ p->scan_bus = sabre_scan_bus;
+ p->irq_build = sabre_irq_build;
+ p->base_address_update = sabre_base_address_update;
+ p->resource_adjust = sabre_resource_adjust;
+ p->pci_ops = &sabre_ops;
+
+ /*
+ * Map in SABRE register set and report the presence of this SABRE.
+ */
+ err = prom_getproperty(pnode, "reg",
+ (char *)&pr_regs[0], sizeof(pr_regs));
+ if(err == 0 || err == -1) {
+ prom_printf("SABRE: Error, cannot get U2P registers "
+ "from PROM.\n");
+ prom_halt();
+ }
+
+ /*
+ * First REG in property is base of entire SABRE register space.
+ */
+ p->controller_regs = pr_regs[0].phys_addr;
+ printk("PCI: Found SABRE, main regs at %016lx\n", p->controller_regs);
+
+ /* Error interrupts are enabled later after the bus scan. */
+ sabre_write(p->controller_regs + SABRE_PCICTRL,
+ (SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR |
+ SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN));
+
+ /* Now map in PCI config space for entire SABRE. */
+ p->config_space = p->controller_regs + SABRE_CONFIGSPACE;
+ printk("SABRE: PCI config space at %016lx\n", p->config_space);
+
+ err = prom_getproperty(pnode, "virtual-dma",
+ (char *)&vdma[0], sizeof(vdma));
+ if(err == 0 || err == -1) {
+ prom_printf("SABRE: Error, cannot get virtual-dma property "
+ "from PROM.\n");
+ prom_halt();
+ }
+
+ switch(vdma[1]) {
+ case 0x20000000:
+ tsbsize = 8;
+ break;
+ case 0x40000000:
+ tsbsize = 16;
+ break;
+ case 0x80000000:
+ tsbsize = 32;
+ break;
+ default:
+ prom_printf("SABRE: strange virtual-dma size.\n");
+ prom_halt();
+ }
+
+ sabre_iommu_init(p, tsbsize, vdma[0]);
+
+ printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);
+
+ err = prom_getproperty(pnode, "bus-range",
+ (char *)&busrange[0], sizeof(busrange));
+ if(err == 0 || err == -1) {
+ prom_printf("SABRE: Error, cannot get PCI bus-range "
+ " from PROM.\n");
+ prom_halt();
+ }
+
+ p->pci_first_busno = busrange[0];
+ p->pci_last_busno = busrange[1];
+
+ /*
+ * Handle config space reads through any Simba on APB.
+ */
+ for (bus = p->pci_first_busno; bus <= p->pci_last_busno; bus++)
+ pci_bus2pbm[bus] = &p->pbm_A;
+
+ /*
+ * Look for APB underneath.
+ */
+ sabre_pbm_init(p, pnode);
+}
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
new file mode 100644
index 000000000..831011128
--- /dev/null
+++ b/arch/sparc64/kernel/power.c
@@ -0,0 +1,105 @@
+/* $Id: power.c,v 1.4 1999/08/31 18:22:05 davem Exp $
+ * power.c: Power management driver.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/delay.h>
+
+#include <asm/ebus.h>
+
+#define __KERNEL_SYSCALLS__
+#include <linux/unistd.h>
+
+#ifdef CONFIG_PCI
+static unsigned long power_reg = 0UL;
+#define POWER_SYSTEM_OFF (1 << 0)
+#define POWER_COURTESY_OFF (1 << 1)
+
+static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
+static int button_pressed = 0;
+
+static void power_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (button_pressed == 0) {
+ wake_up(&powerd_wait);
+ button_pressed = 1;
+ }
+}
+#endif /* CONFIG_PCI */
+
+extern void machine_halt(void);
+
+void machine_power_off(void)
+{
+#ifdef CONFIG_PCI
+ if (power_reg != 0UL) {
+ /* Both register bits seem to have the
+ * same effect, so until I figure out
+ * what the difference is...
+ */
+ writel(POWER_COURTESY_OFF | POWER_SYSTEM_OFF, power_reg);
+ }
+#endif /* CONFIG_PCI */
+ machine_halt();
+}
+
+#ifdef CONFIG_PCI
+static int powerd(void *__unused)
+{
+ static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
+ char *argv[] = { "/usr/bin/shutdown", "-h", "now", NULL };
+
+ current->session = 1;
+ current->pgrp = 1;
+ sprintf(current->comm, "powerd");
+
+again:
+ while(button_pressed == 0) {
+ spin_lock_irq(&current->sigmask_lock);
+ flush_signals(current);
+ spin_unlock_irq(&current->sigmask_lock);
+ interruptible_sleep_on(&powerd_wait);
+ }
+
+ /* Ok, down we go... */
+ if (execve("/usr/bin/shutdown", argv, envp) < 0) {
+ printk("powerd: shutdown execution failed\n");
+ button_pressed = 0;
+ goto again;
+ }
+ return 0;
+}
+
+void __init power_init(void)
+{
+ struct linux_ebus *ebus;
+ struct linux_ebus_device *edev;
+
+ for_each_ebus(ebus) {
+ for_each_ebusdev(edev, ebus) {
+ if (!strcmp(edev->prom_name, "power"))
+ goto found;
+ }
+ }
+ return;
+
+found:
+ power_reg = edev->resource[0].start;
+ printk("power: Control reg at %016lx ... ", power_reg);
+ if (kernel_thread(powerd, 0, CLONE_FS) < 0) {
+ printk("Failed to start power daemon.\n");
+ return;
+ }
+ printk("powerd running.\n");
+ if (request_irq(edev->irqs[0],
+ power_handler, SA_SHIRQ, "power",
+ (void *) power_reg) < 0)
+ printk("power: Error, cannot register IRQ handler.\n");
+}
+#endif /* CONFIG_PCI */
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index ace0c1dc0..0e0f540b7 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.94 1999/05/27 04:49:30 davem Exp $
+/* $Id: process.c,v 1.100 1999/08/31 04:39:39 davem Exp $
* arch/sparc64/kernel/process.c
*
* Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -46,7 +46,7 @@
/*
* the idle loop on a Sparc... ;)
*/
-asmlinkage int sys_idle(void)
+int cpu_idle(void)
{
if (current->pid != 0)
return -EPERM;
@@ -77,7 +77,7 @@ asmlinkage int sys_idle(void)
*/
#define idle_me_harder() (cpu_data[current->processor].idle_volume += 1)
#define unidle_me() (cpu_data[current->processor].idle_volume = 0)
-asmlinkage int cpu_idle(void)
+int cpu_idle(void)
{
current->priority = 0;
current->counter = -100;
@@ -99,15 +99,6 @@ asmlinkage int cpu_idle(void)
}
}
-asmlinkage int sys_idle(void)
-{
- if(current->pid != 0)
- return -EPERM;
-
- cpu_idle();
- return 0;
-}
-
#endif
extern char reboot_command [];
@@ -152,11 +143,6 @@ void machine_restart(char * cmd)
panic("Reboot failed!");
}
-void machine_power_off(void)
-{
- machine_halt();
-}
-
static void show_regwindow32(struct pt_regs *regs)
{
struct reg_window32 *rw;
@@ -189,7 +175,7 @@ static void show_regwindow(struct pt_regs *regs)
struct reg_window r_w;
mm_segment_t old_fs;
- if ((regs->tstate & TSTATE_PRIV) || !(current->tss.flags & SPARC_FLAG_32BIT)) {
+ if ((regs->tstate & TSTATE_PRIV) || !(current->thread.flags & SPARC_FLAG_32BIT)) {
__asm__ __volatile__ ("flushw");
rw = (struct reg_window *)(regs->u_regs[14] + STACK_BIAS);
if (!(regs->tstate & TSTATE_PRIV)) {
@@ -369,90 +355,96 @@ void show_regs32(struct pt_regs32 *regs)
regs->u_regs[15]);
}
-void show_thread(struct thread_struct *tss)
+void show_thread(struct thread_struct *thread)
{
int i;
#if 0
- printk("kregs: 0x%016lx\n", (unsigned long)tss->kregs);
- show_regs(tss->kregs);
+ printk("kregs: 0x%016lx\n", (unsigned long)thread->kregs);
+ show_regs(thread->kregs);
#endif
- printk("sig_address: 0x%016lx\n", tss->sig_address);
- printk("sig_desc: 0x%016lx\n", tss->sig_desc);
- printk("ksp: 0x%016lx\n", tss->ksp);
+ printk("sig_address: 0x%016lx\n", thread->sig_address);
+ printk("sig_desc: 0x%016lx\n", thread->sig_desc);
+ printk("ksp: 0x%016lx\n", thread->ksp);
- if (tss->w_saved) {
+ if (thread->w_saved) {
for (i = 0; i < NSWINS; i++) {
- if (!tss->rwbuf_stkptrs[i])
+ if (!thread->rwbuf_stkptrs[i])
continue;
printk("reg_window[%d]:\n", i);
- printk("stack ptr: 0x%016lx\n", tss->rwbuf_stkptrs[i]);
+ printk("stack ptr: 0x%016lx\n", thread->rwbuf_stkptrs[i]);
}
- printk("w_saved: 0x%04x\n", tss->w_saved);
+ printk("w_saved: 0x%04x\n", thread->w_saved);
}
- printk("flags: 0x%08x\n", tss->flags);
- printk("current_ds: 0x%x\n", tss->current_ds.seg);
+ printk("flags: 0x%08x\n", thread->flags);
+ printk("current_ds: 0x%x\n", thread->current_ds.seg);
}
/* Free current thread data structures etc.. */
void exit_thread(void)
{
- if (current->tss.utraps) {
- if (current->tss.utraps[0] < 2)
- kfree (current->tss.utraps);
+ struct thread_struct *t = &current->thread;
+
+ if (t->utraps) {
+ if (t->utraps[0] < 2)
+ kfree (t->utraps);
else
- current->tss.utraps[0]--;
+ t->utraps[0]--;
}
/* Turn off performance counters if on. */
- if (current->tss.flags & SPARC_FLAG_PERFCTR) {
- current->tss.user_cntd0 =
- current->tss.user_cntd1 = NULL;
- current->tss.pcr_reg = 0;
- current->tss.flags &= ~(SPARC_FLAG_PERFCTR);
+ if (t->flags & SPARC_FLAG_PERFCTR) {
+ t->user_cntd0 = t->user_cntd1 = NULL;
+ t->pcr_reg = 0;
+ t->flags &= ~(SPARC_FLAG_PERFCTR);
write_pcr(0);
}
}
void flush_thread(void)
{
- if (!(current->tss.flags & SPARC_FLAG_KTHREAD))
- flush_user_windows();
- current->tss.w_saved = 0;
+ struct thread_struct *t = &current->thread;
+
+ if (current->mm) {
+ if (t->flags & SPARC_FLAG_32BIT) {
+ struct mm_struct *mm = current->mm;
+ pgd_t *pgd0 = &mm->pgd[0];
+ unsigned long pgd_cache;
+
+ if (pgd_none(*pgd0)) {
+ pmd_t *page = get_pmd_fast();
+ if (!page)
+ (void) get_pmd_slow(pgd0, 0);
+ else
+ pgd_set(pgd0, page);
+ }
+ pgd_cache = pgd_val(*pgd0) << 11UL;
+ __asm__ __volatile__("stxa %0, [%1] %2"
+ : /* no outputs */
+ : "r" (pgd_cache),
+ "r" (TSB_REG),
+ "i" (ASI_DMMU));
+ }
+ }
+ t->w_saved = 0;
/* Turn off performance counters if on. */
- if (current->tss.flags & SPARC_FLAG_PERFCTR) {
- current->tss.user_cntd0 =
- current->tss.user_cntd1 = NULL;
- current->tss.pcr_reg = 0;
- current->tss.flags &= ~(SPARC_FLAG_PERFCTR);
+ if (t->flags & SPARC_FLAG_PERFCTR) {
+ t->user_cntd0 = t->user_cntd1 = NULL;
+ t->pcr_reg = 0;
+ t->flags &= ~(SPARC_FLAG_PERFCTR);
write_pcr(0);
}
- /* No new signal delivery by default. */
- current->tss.new_signal = 0;
- current->tss.fpsaved[0] = 0;
+ /* Clear FPU register state. */
+ t->fpsaved[0] = 0;
- /* Now, this task is no longer a kernel thread. */
- current->tss.current_ds = USER_DS;
- if(current->tss.flags & SPARC_FLAG_KTHREAD) {
- current->tss.flags &= ~SPARC_FLAG_KTHREAD;
+ if (t->current_ds.seg != ASI_AIUS)
+ set_fs(USER_DS);
- /* exec_mmap() set context to NO_CONTEXT, here is
- * where we grab a new one.
- */
- activate_context(current);
- }
- if (current->tss.flags & SPARC_FLAG_32BIT)
- __asm__ __volatile__("stxa %%g0, [%0] %1"
- : /* no outputs */
- : "r"(TSB_REG), "i"(ASI_DMMU));
- __cli();
- current->tss.ctx = current->mm->context & 0x3ff;
- spitfire_set_secondary_context (current->tss.ctx);
- __asm__ __volatile__("flush %g6");
- __sti();
+ /* Init new signal delivery disposition. */
+ t->flags &= ~SPARC_FLAG_NEWSIGNALS;
}
/* It's a bit more tricky when 64-bit tasks are involved... */
@@ -460,12 +452,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
{
unsigned long fp, distance, rval;
- /* do_fork() grabs the parent semaphore, we must release it
- * temporarily so we can build the child clone stack frame
- * without deadlocking.
- */
- up(&current->mm->mmap_sem);
- if(!(current->tss.flags & SPARC_FLAG_32BIT)) {
+ if(!(current->thread.flags & SPARC_FLAG_32BIT)) {
csp += STACK_BIAS;
psp += STACK_BIAS;
__get_user(fp, &(((struct reg_window *)psp)->ins[6]));
@@ -482,7 +469,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
rval = (csp - distance);
if(copy_in_user(rval, psp, distance))
rval = 0;
- else if(current->tss.flags & SPARC_FLAG_32BIT) {
+ else if(current->thread.flags & SPARC_FLAG_32BIT) {
if(put_user(((u32)csp), &(((struct reg_window32 *)rval)->ins[6])))
rval = 0;
} else {
@@ -492,47 +479,46 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
else
rval = rval - STACK_BIAS;
}
- down(&current->mm->mmap_sem);
return rval;
}
/* Standard stuff. */
static inline void shift_window_buffer(int first_win, int last_win,
- struct thread_struct *tp)
+ struct thread_struct *t)
{
int i;
for(i = first_win; i < last_win; i++) {
- tp->rwbuf_stkptrs[i] = tp->rwbuf_stkptrs[i+1];
- memcpy(&tp->reg_window[i], &tp->reg_window[i+1],
+ t->rwbuf_stkptrs[i] = t->rwbuf_stkptrs[i+1];
+ memcpy(&t->reg_window[i], &t->reg_window[i+1],
sizeof(struct reg_window));
}
}
void synchronize_user_stack(void)
{
- struct thread_struct *tp = &current->tss;
+ struct thread_struct *t = &current->thread;
unsigned long window;
flush_user_windows();
- if((window = tp->w_saved) != 0) {
+ if((window = t->w_saved) != 0) {
int winsize = REGWIN_SZ;
int bias = 0;
- if(tp->flags & SPARC_FLAG_32BIT)
+ if(t->flags & SPARC_FLAG_32BIT)
winsize = REGWIN32_SZ;
else
bias = STACK_BIAS;
window -= 1;
do {
- unsigned long sp = (tp->rwbuf_stkptrs[window] + bias);
- struct reg_window *rwin = &tp->reg_window[window];
+ unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
+ struct reg_window *rwin = &t->reg_window[window];
if(!copy_to_user((char *)sp, rwin, winsize)) {
- shift_window_buffer(window, tp->w_saved - 1, tp);
- tp->w_saved--;
+ shift_window_buffer(window, t->w_saved - 1, t);
+ t->w_saved--;
}
} while(window--);
}
@@ -540,28 +526,28 @@ void synchronize_user_stack(void)
void fault_in_user_windows(struct pt_regs *regs)
{
- struct thread_struct *tp = &current->tss;
+ struct thread_struct *t = &current->thread;
unsigned long window;
int winsize = REGWIN_SZ;
int bias = 0;
- if(tp->flags & SPARC_FLAG_32BIT)
+ if(t->flags & SPARC_FLAG_32BIT)
winsize = REGWIN32_SZ;
else
bias = STACK_BIAS;
flush_user_windows();
- window = tp->w_saved;
+ window = t->w_saved;
if(window != 0) {
window -= 1;
do {
- unsigned long sp = (tp->rwbuf_stkptrs[window] + bias);
- struct reg_window *rwin = &tp->reg_window[window];
+ unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
+ struct reg_window *rwin = &t->reg_window[window];
if(copy_to_user((char *)sp, rwin, winsize))
goto barf;
} while(window--);
}
- current->tss.w_saved = 0;
+ t->w_saved = 0;
return;
barf:
do_exit(SIGILL);
@@ -582,65 +568,73 @@ barf:
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
struct task_struct *p, struct pt_regs *regs)
{
+ struct thread_struct *t = &p->thread;
char *child_trap_frame;
/* Calculate offset to stack_frame & pt_regs */
child_trap_frame = ((char *)p) + ((PAGE_SIZE << 1) - (TRACEREG_SZ+REGWIN_SZ));
memcpy(child_trap_frame, (((struct reg_window *)regs)-1), (TRACEREG_SZ+REGWIN_SZ));
- p->tss.ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
- p->tss.kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window));
- p->tss.cwp = (regs->tstate + 1) & TSTATE_CWP;
- p->tss.fpsaved[0] = 0;
- p->mm->segments = (void *) 0;
+ t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
+ t->flags |= SPARC_FLAG_NEWCHILD;
+ t->kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window));
+ t->cwp = (regs->tstate + 1) & TSTATE_CWP;
+ t->fpsaved[0] = 0;
if(regs->tstate & TSTATE_PRIV) {
/* Special case, if we are spawning a kernel thread from
* a userspace task (via KMOD, NFS, or similar) we must
* disable performance counters in the child because the
* address space and protection realm are changing.
*/
- if (current->tss.flags & SPARC_FLAG_PERFCTR) {
- p->tss.user_cntd0 =
- p->tss.user_cntd1 = NULL;
- p->tss.pcr_reg = 0;
- p->tss.flags &= ~(SPARC_FLAG_PERFCTR);
+ if (t->flags & SPARC_FLAG_PERFCTR) {
+ t->user_cntd0 = t->user_cntd1 = NULL;
+ t->pcr_reg = 0;
+ t->flags &= ~(SPARC_FLAG_PERFCTR);
}
- p->tss.kregs->u_regs[UREG_FP] = p->tss.ksp;
- p->tss.flags |= (SPARC_FLAG_KTHREAD | SPARC_FLAG_NEWCHILD);
- p->tss.current_ds = KERNEL_DS;
- p->tss.ctx = 0;
- __asm__ __volatile__("flushw");
- memcpy((void *)(p->tss.ksp + STACK_BIAS),
+ t->kregs->u_regs[UREG_FP] = p->thread.ksp;
+ t->current_ds = KERNEL_DS;
+ flush_register_windows();
+ memcpy((void *)(t->ksp + STACK_BIAS),
(void *)(regs->u_regs[UREG_FP] + STACK_BIAS),
sizeof(struct reg_window));
- p->tss.kregs->u_regs[UREG_G6] = (unsigned long) p;
+ t->kregs->u_regs[UREG_G6] = (unsigned long) p;
} else {
- if(current->tss.flags & SPARC_FLAG_32BIT) {
+ if(t->flags & SPARC_FLAG_32BIT) {
sp &= 0x00000000ffffffffUL;
regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
}
- p->tss.kregs->u_regs[UREG_FP] = sp;
- p->tss.flags = (p->tss.flags & ~SPARC_FLAG_KTHREAD) |
- SPARC_FLAG_NEWCHILD;
- p->tss.current_ds = USER_DS;
- p->tss.ctx = (p->mm->context & 0x3ff);
+ t->kregs->u_regs[UREG_FP] = sp;
+ t->current_ds = USER_DS;
if (sp != regs->u_regs[UREG_FP]) {
unsigned long csp;
csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
if(!csp)
return -EFAULT;
- p->tss.kregs->u_regs[UREG_FP] = csp;
+ t->kregs->u_regs[UREG_FP] = csp;
}
- if (p->tss.utraps)
- p->tss.utraps[0]++;
+ if (t->utraps)
+ t->utraps[0]++;
}
/* Set the return value for the child. */
- p->tss.kregs->u_regs[UREG_I0] = current->pid;
- p->tss.kregs->u_regs[UREG_I1] = 1;
+ t->kregs->u_regs[UREG_I0] = current->pid;
+ t->kregs->u_regs[UREG_I1] = 1;
/* Set the second return value for the parent. */
regs->u_regs[UREG_I1] = 0;
+#if 0
+ printk("\ncopy_thread: c(%p[mm(%p:%p)]) p(%p[mm(%p:%p)])\n",
+ current, current->mm, current->active_mm,
+ p, p->mm, p->active_mm);
+ printk("copy_thread: c MM_ctx(%016lx) MM_pgd(%016lx)\n",
+ (current->mm ? current->mm->context : 0),
+ (current->mm ? pgd_val(current->mm->pgd[0]) : 0));
+ printk("copy_thread: p MM_ctx(%016lx) MM_pgd(%08x)\n",
+ (p->mm ? p->mm->context : 0),
+ (p->mm ? pgd_val(p->mm->pgd[0]) : 0));
+ printk("copy_thread: c->flags(%x) p->flags(%x) ",
+ current->thread.flags, p->thread.flags);
+#endif
return 0;
}
@@ -703,10 +697,10 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
dump->u_dsize &= ~(PAGE_SIZE - 1);
first_stack_page = (regs->u_regs[UREG_FP] & ~(PAGE_SIZE - 1));
dump->u_ssize = (TASK_SIZE - first_stack_page) & ~(PAGE_SIZE - 1);
- memcpy(&dump->fpu.fpstatus.fregs.regs[0], &current->tss.float_regs[0], (sizeof(unsigned long) * 32));
- dump->fpu.fpstatus.fsr = current->tss.fsr;
+ memcpy(&dump->fpu.fpstatus.fregs.regs[0], &current->thread.float_regs[0], (sizeof(unsigned long) * 32));
+ dump->fpu.fpstatus.fsr = current->thread.fsr;
dump->fpu.fpstatus.flags = dump->fpu.fpstatus.extra = 0;
- dump->sigcode = current->tss.sig_desc;
+ dump->sigcode = current->thread.sig_desc;
#endif
}
@@ -729,9 +723,9 @@ typedef struct {
int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
{
unsigned long *kfpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
- unsigned long fprs = current->tss.fpsaved[0];
+ unsigned long fprs = current->thread.fpsaved[0];
- if ((current->tss.flags & SPARC_FLAG_32BIT) != 0) {
+ if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {
elf_fpregset_t32 *fpregs32 = (elf_fpregset_t32 *)fpregs;
if (fprs & FPRS_DL)
@@ -745,7 +739,7 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
memset(&fpregs32->pr_q[0], 0,
(sizeof(unsigned int) * 64));
if (fprs & FPRS_FEF) {
- fpregs32->pr_fsr = (unsigned int) current->tss.xfsr[0];
+ fpregs32->pr_fsr = (unsigned int) current->thread.xfsr[0];
fpregs32->pr_en = 1;
} else {
fpregs32->pr_fsr = 0;
@@ -765,8 +759,8 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
memset(&fpregs->pr_regs[16], 0,
sizeof(unsigned int) * 32);
if(fprs & FPRS_FEF) {
- fpregs->pr_fsr = current->tss.xfsr[0];
- fpregs->pr_gsr = current->tss.gsr[0];
+ fpregs->pr_fsr = current->thread.xfsr[0];
+ fpregs->pr_gsr = current->thread.gsr[0];
} else {
fpregs->pr_fsr = fpregs->pr_gsr = 0;
}
@@ -784,6 +778,8 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
int error, base = 0;
char *filename;
+ /* User register window flush is done by entry.S */
+
/* Check for indirect call. */
if(regs->u_regs[UREG_G1] == 0)
base = 1;
@@ -798,8 +794,8 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
putname(filename);
if(!error) {
fprs_write(0);
- current->tss.xfsr[0] = 0;
- current->tss.fpsaved[0] = 0;
+ current->thread.xfsr[0] = 0;
+ current->thread.fpsaved[0] = 0;
regs->tstate &= ~TSTATE_PEF;
}
out:
diff --git a/arch/sparc64/kernel/psycho.c b/arch/sparc64/kernel/psycho.c
deleted file mode 100644
index 392ddab55..000000000
--- a/arch/sparc64/kernel/psycho.c
+++ /dev/null
@@ -1,2619 +0,0 @@
-/* $Id: psycho.c,v 1.86 1999/07/01 10:39:43 davem Exp $
- * psycho.c: Ultra/AX U2P PCI controller support.
- *
- * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu)
- * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
- * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-
-#include <asm/ebus.h>
-#include <asm/sbus.h> /* for sanity check... */
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#undef PROM_DEBUG
-#undef FIXUP_REGS_DEBUG
-#undef FIXUP_IRQ_DEBUG
-#undef FIXUP_VMA_DEBUG
-#undef PCI_COOKIE_DEBUG
-
-#ifdef PROM_DEBUG
-#define dprintf prom_printf
-#else
-#define dprintf printk
-#endif
-
-unsigned long pci_dvma_offset = 0x00000000UL;
-unsigned long pci_dvma_mask = 0xffffffffUL;
-
-#define PCI_DVMA_HASH_NONE 0xffffffffffffffffUL
-unsigned long pci_dvma_v2p_hash[PCI_DVMA_HASHSZ];
-unsigned long pci_dvma_p2v_hash[PCI_DVMA_HASHSZ];
-
-#ifndef CONFIG_PCI
-
-int pcibios_present(void)
-{
- return 0;
-}
-
-asmlinkage int sys_pciconfig_read(unsigned long bus,
- unsigned long dfn,
- unsigned long off,
- unsigned long len,
- unsigned char *buf)
-{
- return 0;
-}
-
-asmlinkage int sys_pciconfig_write(unsigned long bus,
- unsigned long dfn,
- unsigned long off,
- unsigned long len,
- unsigned char *buf)
-{
- return 0;
-}
-
-#else
-
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/pci.h>
-
-#include <asm/oplib.h>
-#include <asm/pbm.h>
-#include <asm/apb.h>
-#include <asm/uaccess.h>
-
-#define PSYCHO_REORDER_ONBOARDFIRST 1
-
-struct linux_psycho *psycho_root = NULL;
-int linux_num_psycho = 0;
-static struct linux_pbm_info *bus2pbm[256];
-static int psycho_reorder __initdata = 0;
-
-static int pbm_read_config_byte(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned char *value);
-static int pbm_read_config_word(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned short *value);
-static int pbm_read_config_dword(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned int *value);
-static int pbm_write_config_byte(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned char value);
-static int pbm_write_config_word(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned short value);
-static int pbm_write_config_dword(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned int value);
-
-/* This is used to make the scan_bus in the generic PCI code be
- * a nop, as we need to control the actual bus probing sequence.
- * After that we leave it on of course.
- */
-static int pci_probe_enable = 0;
-
-static __inline__ void set_dvma_hash(unsigned long paddr, unsigned long daddr)
-{
- unsigned long dvma_addr = pci_dvma_offset + daddr;
- unsigned long vaddr = (unsigned long)__va(paddr);
-
- pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] = dvma_addr - vaddr;
- pci_dvma_p2v_hash[pci_dvma_ahashfn(dvma_addr)] = vaddr - dvma_addr;
-}
-
-static void __init psycho_iommu_init(struct linux_psycho *psycho, int tsbsize)
-{
- extern int this_is_starfire;
- extern void *starfire_hookup(int);
- struct linux_mlist_p1275 *mlist;
- unsigned long tsbbase;
- unsigned long control, i, n;
- unsigned long *iopte;
- unsigned long order;
-
- /*
- * Invalidate TLB Entries.
- */
- control = psycho->psycho_regs->iommu_control;
- control |= IOMMU_CTRL_DENAB;
- psycho->psycho_regs->iommu_control = control;
- for(i = 0; i < 16; i++) {
- psycho->psycho_regs->iommu_data[i] = 0;
- }
- control &= ~(IOMMU_CTRL_DENAB);
- psycho->psycho_regs->iommu_control = control;
-
- for(order = 0;; order++) {
- if((PAGE_SIZE << order) >= ((tsbsize * 1024) * 8))
- break;
- }
- tsbbase = __get_free_pages(GFP_DMA, order);
- if (!tsbbase) {
- prom_printf("IOMMU: Error, kmalloc(tsb) failed.\n");
- prom_halt();
- }
- iopte = (unsigned long *)tsbbase;
-
- /* Initialize to "none" settings. */
- for(i = 0; i < PCI_DVMA_HASHSZ; i++) {
- pci_dvma_v2p_hash[i] = PCI_DVMA_HASH_NONE;
- pci_dvma_p2v_hash[i] = PCI_DVMA_HASH_NONE;
- }
-
- n = 0;
- mlist = *prom_meminfo()->p1275_totphys;
- while (mlist) {
- unsigned long paddr = mlist->start_adr;
- unsigned long num_bytes = mlist->num_bytes;
-
- if(paddr >= (((unsigned long) high_memory) - PAGE_OFFSET))
- goto next;
-
- if((paddr + num_bytes) >= (((unsigned long) high_memory) - PAGE_OFFSET))
- num_bytes = (((unsigned long) high_memory) - PAGE_OFFSET) - paddr;
-
- /* Align base and length so we map whole hash table sized chunks
- * at a time (and therefore full 64K IOMMU pages).
- */
- paddr &= ~((1UL << 24UL) - 1);
- num_bytes = (num_bytes + ((1UL << 24UL) - 1)) & ~((1UL << 24) - 1);
-
- /* Move up the base for mappings already created. */
- while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] !=
- PCI_DVMA_HASH_NONE) {
- paddr += (1UL << 24UL);
- num_bytes -= (1UL << 24UL);
- if(num_bytes == 0UL)
- goto next;
- }
-
- /* Move down the size for tail mappings already created. */
- while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr + num_bytes - (1UL << 24UL))] !=
- PCI_DVMA_HASH_NONE) {
- num_bytes -= (1UL << 24UL);
- if(num_bytes == 0UL)
- goto next;
- }
-
- /* Now map the rest. */
- for (i = 0; i < ((num_bytes + ((1 << 16) - 1)) >> 16); i++) {
- *iopte = (IOPTE_VALID | IOPTE_64K |
- IOPTE_CACHE | IOPTE_WRITE);
- *iopte |= paddr;
-
- if (!(n & 0xff))
- set_dvma_hash(paddr, (n << 16));
-
- if (++n > (tsbsize * 1024))
- goto out;
-
- paddr += (1 << 16);
- iopte++;
- }
- next:
- mlist = mlist->theres_more;
- }
-out:
- if (mlist) {
- prom_printf("WARNING: not all physical memory mapped in IOMMU\n");
- prom_printf("Try booting with mem=xxxM or similar\n");
- prom_halt();
- }
-
- psycho->psycho_regs->iommu_tsbbase = __pa(tsbbase);
-
- control = psycho->psycho_regs->iommu_control;
- control &= ~(IOMMU_CTRL_TSBSZ);
- control |= (IOMMU_CTRL_TBWSZ | IOMMU_CTRL_ENAB);
- switch(tsbsize) {
- case 8:
- pci_dvma_mask = 0x1fffffffUL;
- control |= IOMMU_TSBSZ_8K;
- break;
- case 16:
- pci_dvma_mask = 0x3fffffffUL;
- control |= IOMMU_TSBSZ_16K;
- break;
- case 32:
- pci_dvma_mask = 0x7fffffffUL;
- control |= IOMMU_TSBSZ_32K;
- break;
- default:
- prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
- prom_halt();
- break;
- }
- psycho->psycho_regs->iommu_control = control;
-
- /* If necessary, hook us up for starfire IRQ translations. */
- if(this_is_starfire)
- psycho->starfire_cookie = starfire_hookup(psycho->upa_portid);
- else
- psycho->starfire_cookie = NULL;
-}
-
-extern void prom_pbm_ranges_init(int node, struct linux_pbm_info *pbm);
-extern void prom_pbm_intmap_init(int node, struct linux_pbm_info *pbm);
-
-/*
- * Poor man's PCI...
- */
-void __init sabre_init(int pnode)
-{
- struct linux_prom64_registers pr_regs[2];
- struct linux_psycho *sabre;
- unsigned long ctrl;
- int tsbsize, node, err;
- u32 busrange[2];
- u32 vdma[2];
- u32 portid;
- int bus;
-
- sabre = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC);
- if (!sabre) {
- prom_printf("SABRE: Error, kmalloc(sabre) failed.\n");
- prom_halt();
- }
-
- portid = prom_getintdefault(pnode, "upa-portid", 0xff);
-
- memset(sabre, 0, sizeof(*sabre));
-
- sabre->next = psycho_root;
- psycho_root = sabre;
-
- sabre->upa_portid = portid;
- sabre->index = linux_num_psycho++;
-
- /*
- * Map in SABRE register set and report the presence of this SABRE.
- */
- err = prom_getproperty(pnode, "reg",
- (char *)&pr_regs[0], sizeof(pr_regs));
- if(err == 0 || err == -1) {
- prom_printf("SABRE: Error, cannot get U2P registers "
- "from PROM.\n");
- prom_halt();
- }
-
- /*
- * First REG in property is base of entire SABRE register space.
- */
- sabre->psycho_regs =
- sparc_alloc_io((pr_regs[0].phys_addr & 0xffffffff),
- NULL, sizeof(struct psycho_regs),
- "SABRE Registers",
- (pr_regs[0].phys_addr >> 32), 0);
- if(sabre->psycho_regs == NULL) {
- prom_printf("SABRE: Error, cannot map SABRE main registers.\n");
- prom_halt();
- }
-
- printk("PCI: Found SABRE, main regs at %p CTRL[%016lx]\n",
- sabre->psycho_regs, sabre->psycho_regs->control);
-#ifdef PROM_DEBUG
- dprintf("PCI: Found SABRE, main regs at %p CTRL[%016lx]\n",
- sabre->psycho_regs, sabre->psycho_regs->control);
-#endif
-
- ctrl = sabre->psycho_regs->pci_a_control;
- ctrl = (1UL << 36) | (1UL << 34) | (1UL << 21) | (1UL << 8) | 0x0fUL;
- sabre->psycho_regs->pci_a_control = ctrl;
-
- /* Now map in PCI config space for entire SABRE. */
- sabre->pci_config_space =
- sparc_alloc_io(((pr_regs[0].phys_addr & 0xffffffff)
- + 0x01000000),
- NULL, 0x01000000,
- "PCI Config Space",
- (pr_regs[0].phys_addr >> 32), 0);
- if(sabre->pci_config_space == NULL) {
- prom_printf("SABRE: Error, cannot map PCI config space.\n");
- prom_halt();
- }
-
- /* Report some more info. */
- printk("SABRE: PCI config space at %p\n", sabre->pci_config_space);
-#ifdef PROM_DEBUG
- dprintf("SABRE: PCI config space at %p\n", sabre->pci_config_space);
-#endif
-
- err = prom_getproperty(pnode, "virtual-dma",
- (char *)&vdma[0], sizeof(vdma));
- if(err == 0 || err == -1) {
- prom_printf("SABRE: Error, cannot get virtual-dma property "
- "from PROM.\n");
- prom_halt();
- }
-
- switch(vdma[1]) {
- case 0x20000000:
- tsbsize = 8;
- break;
- case 0x40000000:
- tsbsize = 16;
- break;
- case 0x80000000:
- tsbsize = 32;
- break;
- default:
- prom_printf("SABRE: strange virtual-dma size.\n");
- prom_halt();
- }
-
- pci_dvma_offset = vdma[0];
- psycho_iommu_init(sabre, tsbsize);
-
- printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);
-#ifdef PROM_DEBUG
- dprintf("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);
-#endif
-
- err = prom_getproperty(pnode, "bus-range",
- (char *)&busrange[0], sizeof(busrange));
- if(err == 0 || err == -1) {
- prom_printf("SIMBA: Error, cannot get PCI bus-range "
- " from PROM.\n");
- prom_halt();
- }
-
- sabre->pci_first_busno = busrange[0];
- sabre->pci_last_busno = busrange[1];
- sabre->pci_bus = &pci_root;
-
- /*
- * Handle config space reads through any Simba on APB.
- */
- for (bus = sabre->pci_first_busno; bus <= sabre->pci_last_busno; bus++)
- bus2pbm[bus] = &sabre->pbm_A;
-
- /*
- * Look for APB underneath.
- */
- node = prom_getchild(pnode);
- while ((node = prom_searchsiblings(node, "pci"))) {
- struct linux_pbm_info *pbm;
- char namebuf[128];
-
- err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
- if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err))
- goto next_pci;
-
- err = prom_getproperty(node, "bus-range",
- (char *)&busrange[0], sizeof(busrange));
- if(err == 0 || err == -1) {
- prom_printf("SIMBA: Error, cannot get PCI bus-range "
- " from PROM.\n");
- prom_halt();
- }
-
- if (busrange[0] == 1)
- pbm = &sabre->pbm_B;
- else
- pbm = &sabre->pbm_A;
-
- pbm->parent = sabre;
- pbm->IO_assignments = NULL;
- pbm->MEM_assignments = NULL;
- pbm->prom_node = node;
-
- prom_getstring(node, "name", namebuf, sizeof(namebuf));
- strcpy(pbm->prom_name, namebuf);
-
- /* Now the ranges. */
- prom_pbm_ranges_init(pnode, pbm);
- prom_pbm_intmap_init(node, pbm);
-
- pbm->pci_first_busno = busrange[0];
- pbm->pci_last_busno = busrange[1];
- memset(&pbm->pci_bus, 0, sizeof(struct pci_bus));
-
- for (bus = pbm->pci_first_busno;
- bus <= pbm->pci_last_busno; bus++)
- bus2pbm[bus] = pbm;
-
- next_pci:
- node = prom_getsibling(node);
- if (!node)
- break;
- }
-}
-
-static __inline__ int
-apb_present(struct linux_psycho *psycho)
-{
- return psycho->pci_bus ? 1 : 0;
-}
-
-void __init pcibios_init(void)
-{
- struct linux_prom64_registers pr_regs[3];
- struct linux_psycho *psycho;
- char namebuf[128];
- u32 portid;
- int node;
-
- printk("PCI: Probing for controllers.\n");
-#ifdef PROM_DEBUG
- dprintf("PCI: Probing for controllers.\n");
-#endif
-
- node = prom_getchild(prom_root_node);
- while((node = prom_searchsiblings(node, "pci")) != 0) {
- struct linux_psycho *search;
- struct linux_pbm_info *pbm = NULL;
- u32 busrange[2];
- int err, is_pbm_a;
-
- err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
- if ((err > 0) && !strncmp(namebuf, "SUNW,sabre", err)) {
- sabre_init(node);
- goto next_pci;
- }
-
- portid = prom_getintdefault(node, "upa-portid", 0xff);
- for(search = psycho_root; search; search = search->next) {
- if(search->upa_portid == portid) {
- psycho = search;
-
- /* This represents _this_ instance, so it's
- * which ever one does _not_ have the prom node
- * info filled in yet.
- */
- is_pbm_a = (psycho->pbm_A.prom_node == 0);
- goto other_pbm;
- }
- }
-
- psycho = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC);
- if (!psycho) {
- prom_printf("PSYCHO: Error, kmalloc(psycho) failed.\n");
- prom_halt();
- }
- memset(psycho, 0, sizeof(*psycho));
-
- psycho->next = psycho_root;
- psycho_root = psycho;
-
- psycho->upa_portid = portid;
- psycho->index = linux_num_psycho++;
-
- /*
- * Map in PSYCHO register set and report the presence
- * of this PSYCHO.
- */
- err = prom_getproperty(node, "reg",
- (char *)&pr_regs[0], sizeof(pr_regs));
- if(err == 0 || err == -1) {
- prom_printf("PSYCHO: Error, cannot get U2P registers "
- "from PROM.\n");
- prom_halt();
- }
-
- /*
- * Third REG in property is base of entire PSYCHO
- * register space.
- */
- psycho->psycho_regs =
- sparc_alloc_io((pr_regs[2].phys_addr & 0xffffffff),
- NULL, sizeof(struct psycho_regs),
- "PSYCHO Registers",
- (pr_regs[2].phys_addr >> 32), 0);
- if(psycho->psycho_regs == NULL) {
- prom_printf("PSYCHO: Error, cannot map PSYCHO "
- "main registers.\n");
- prom_halt();
- }
-
- printk("PCI: Found PSYCHO, main regs at %p\n",
- psycho->psycho_regs);
-#ifdef PROM_DEBUG
- dprintf("PCI: Found PSYCHO, main regs at %p\n",
- psycho->psycho_regs);
-#endif
-
- psycho->psycho_regs->irq_retry = 0xff;
-
- /* Now map in PCI config space for entire PSYCHO. */
- psycho->pci_config_space =
- sparc_alloc_io(((pr_regs[2].phys_addr & 0xffffffff)
- + 0x01000000),
- NULL, 0x01000000,
- "PCI Config Space",
- (pr_regs[2].phys_addr >> 32), 0);
- if(psycho->pci_config_space == NULL) {
- prom_printf("PSYCHO: Error, cannot map PCI config space.\n");
- prom_halt();
- }
-
- /* Report some more info. */
- printk("PSYCHO: PCI config space at %p\n",
- psycho->pci_config_space);
-#ifdef PROM_DEBUG
- dprintf("PSYCHO: PCI config space at %p\n",
- psycho->pci_config_space);
-#endif
-
- pci_dvma_offset = 0x80000000UL;
- psycho_iommu_init(psycho, 32);
-
- is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
-
- /* Enable arbitration for all PCI slots. */
- psycho->psycho_regs->pci_a_control |= PSYCHO_PCICTRL_AEN;
- psycho->psycho_regs->pci_b_control |= PSYCHO_PCICTRL_AEN;
-
- /* Disable DMA write / PIO rd synchronization on both
- * PCI bus segments.
- */
- psycho->psycho_regs->pci_a_diag |= PSYCHO_PCIDIAG_DDWSYNC;
- psycho->psycho_regs->pci_b_diag |= PSYCHO_PCIDIAG_DDWSYNC;
-
- other_pbm:
- if(is_pbm_a)
- pbm = &psycho->pbm_A;
- else
- pbm = &psycho->pbm_B;
-
- pbm->parent = psycho;
- pbm->IO_assignments = NULL;
- pbm->MEM_assignments = NULL;
- pbm->prom_node = node;
-
- prom_getstring(node, "name", namebuf, sizeof(namebuf));
- strcpy(pbm->prom_name, namebuf);
-
- /* Now the ranges. */
- prom_pbm_ranges_init(node, pbm);
- prom_pbm_intmap_init(node, pbm);
-
- /* Finally grab the pci bus root array for this pbm after
- * having found the bus range existing under it.
- */
- err = prom_getproperty(node, "bus-range",
- (char *)&busrange[0], sizeof(busrange));
- if(err == 0 || err == -1) {
- prom_printf("PSYCHO: Error, cannot get PCI bus range.\n");
- prom_halt();
- }
- pbm->pci_first_busno = busrange[0];
- pbm->pci_last_busno = busrange[1];
- memset(&pbm->pci_bus, 0, sizeof(struct pci_bus));
-
- next_pci:
- node = prom_getsibling(node);
- if(!node)
- break;
- }
-}
-
-int pcibios_present(void)
-{
- return psycho_root != NULL;
-}
-
-static inline struct pci_vma *pci_find_vma(struct linux_pbm_info *pbm,
- unsigned long start,
- unsigned int offset, int io)
-{
- struct pci_vma *vp = (io ? pbm->IO_assignments : pbm->MEM_assignments);
-
- while (vp) {
- if (offset && (vp->offset != offset))
- goto next;
- if (vp->end >= start)
- break;
- next:
- vp = vp->next;
- }
- return vp;
-}
-
-static inline void pci_add_vma(struct linux_pbm_info *pbm, struct pci_vma *new, int io)
-{
- struct pci_vma *vp = (io ? pbm->IO_assignments : pbm->MEM_assignments);
-
- if(!vp) {
- new->next = NULL;
- if(io)
- pbm->IO_assignments = new;
- else
- pbm->MEM_assignments = new;
- } else {
- struct pci_vma *prev = NULL;
-
- while(vp && (vp->end < new->end)) {
- prev = vp;
- vp = vp->next;
- }
- new->next = vp;
- if(!prev) {
- if(io)
- pbm->IO_assignments = new;
- else
- pbm->MEM_assignments = new;
- } else {
- prev->next = new;
- }
-
- /* Check for programming errors. */
- if(vp &&
- ((vp->start >= new->start && vp->start < new->end) ||
- (vp->end >= new->start && vp->end < new->end))) {
- prom_printf("pci_add_vma: Wheee, overlapping %s PCI vma's\n",
- io ? "IO" : "MEM");
- prom_printf("pci_add_vma: vp[%016lx:%016lx] "
- "new[%016lx:%016lx]\n",
- vp->start, vp->end,
- new->start, new->end);
- }
- }
-}
-
-static inline struct pci_vma *pci_vma_alloc(void)
-{
- return kmalloc(sizeof(struct pci_vma), GFP_ATOMIC);
-}
-
-static inline struct pcidev_cookie *pci_devcookie_alloc(void)
-{
- return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC);
-}
-
-
-static void __init
-pbm_reconfigure_bridges(struct linux_pbm_info *pbm, unsigned char bus)
-{
- unsigned int devfn, l, class;
- unsigned char hdr_type = 0;
- int is_multi = 0;
-
- for (devfn = 0; devfn < 0xff; ++devfn) {
- if (PCI_FUNC(devfn) != 0 && is_multi == 0) {
- /* not a multi-function device */
- continue;
- }
- pbm_read_config_byte(pbm, bus, devfn,
- PCI_HEADER_TYPE, &hdr_type);
- if (PCI_FUNC(devfn) == 0)
- is_multi = hdr_type & 0x80;
-
- /* Check if there is anything here. */
- pbm_read_config_dword(pbm, bus, devfn, PCI_VENDOR_ID, &l);
- if (l == 0xffffffff || l == 0x00000000 ||
- l == 0x0000ffff || l == 0xffff0000) {
- is_multi = 0;
- continue;
- }
-
- /* See if this is a bridge device. */
- pbm_read_config_dword(pbm, bus, devfn,
- PCI_CLASS_REVISION, &class);
-
- if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
- unsigned int buses;
-
- pbm_read_config_dword(pbm, bus, devfn,
- PCI_PRIMARY_BUS, &buses);
-
- /*
- * First reconfigure everything underneath the bridge.
- */
- pbm_reconfigure_bridges(pbm, (buses >> 8) & 0xff);
-
- /*
- * Unconfigure this bridges bus numbers,
- * pci_scan_bus() will fix this up properly.
- */
- buses &= 0xff000000;
- pbm_write_config_dword(pbm, bus, devfn,
- PCI_PRIMARY_BUS, buses);
- }
- }
-}
-
-static void __init pbm_fixup_busno(struct linux_pbm_info *pbm, unsigned char bus)
-{
- unsigned int nbus;
-
- /*
- * First, reconfigure all bridge devices underneath this pbm.
- */
- pbm_reconfigure_bridges(pbm, pbm->pci_first_busno);
-
- /*
- * Now reconfigure the pbm to it's new bus number and set up
- * our bus2pbm mapping for this pbm.
- */
- nbus = pbm->pci_last_busno - pbm->pci_first_busno;
-
- pbm_write_config_byte(pbm, pbm->pci_first_busno, 0, 0x40, bus);
-
- pbm->pci_first_busno = bus;
- pbm_write_config_byte(pbm, bus, 0, 0x41, 0xff);
-
- do {
- bus2pbm[bus++] = pbm;
- } while (nbus--);
-}
-
-static void __init apb_init(struct linux_psycho *sabre)
-{
- struct pci_dev *pdev;
- unsigned short stmp;
- unsigned int itmp;
-
-#if 0
- for(pdev = pci_devices; pdev; pdev = pdev->next) {
- if(pdev->vendor == PCI_VENDOR_ID_SUN &&
- pdev->device == PCI_DEVICE_ID_SUN_SABRE) {
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
- break;
- }
- }
-#endif
- for (pdev = sabre->pci_bus->devices; pdev; pdev = pdev->sibling) {
- if (pdev->vendor == PCI_VENDOR_ID_SUN &&
- pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
- pci_read_config_word(pdev, PCI_COMMAND, &stmp);
- stmp |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
- PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY |
- PCI_COMMAND_IO;
- pci_write_config_word(pdev, PCI_COMMAND, stmp);
-
- /* Status register bits are "write 1 to clear". */
- pci_write_config_word(pdev, PCI_STATUS, 0xffff);
- pci_write_config_word(pdev, PCI_SEC_STATUS, 0xffff);
-
- pci_read_config_word(pdev, PCI_BRIDGE_CONTROL, &stmp);
- stmp = PCI_BRIDGE_CTL_MASTER_ABORT |
- PCI_BRIDGE_CTL_SERR |
- PCI_BRIDGE_CTL_PARITY;
- pci_write_config_word(pdev, PCI_BRIDGE_CONTROL, stmp);
-
- pci_read_config_dword(pdev, APB_PCI_CONTROL_HIGH, &itmp);
- itmp = APB_PCI_CTL_HIGH_SERR |
- APB_PCI_CTL_HIGH_ARBITER_EN;
- pci_write_config_dword(pdev, APB_PCI_CONTROL_HIGH, itmp);
-
- /* Systems with SIMBA are usually workstations, so
- * we configure to park to SIMBA not to the previous
- * bus owner.
- */
- pci_read_config_dword(pdev, APB_PCI_CONTROL_LOW, &itmp);
- itmp = APB_PCI_CTL_LOW_ERRINT_EN | 0x0f;
- pci_write_config_dword(pdev, APB_PCI_CONTROL_LOW, itmp);
-#if 0
- /* Don't mess with the retry limit and PIO/DMA latency
- * timer settings. But do set primary and secondary
- * latency timers.
- */
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
- pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64);
-#endif
- }
- }
-}
-
-static void __init sabre_probe(struct linux_psycho *sabre)
-{
- struct pci_bus *pbus = sabre->pci_bus;
- static unsigned char busno = 0;
-
- pbus->number = pbus->secondary = busno;
- pbus->sysdata = sabre;
-
- pbus->subordinate = pci_scan_bus(pbus);
- busno = pbus->subordinate + 1;
-
- for(pbus = pbus->children; pbus; pbus = pbus->next) {
- if (pbus->number == sabre->pbm_A.pci_first_busno)
- memcpy(&sabre->pbm_A.pci_bus, pbus, sizeof(*pbus));
- if (pbus->number == sabre->pbm_B.pci_first_busno)
- memcpy(&sabre->pbm_B.pci_bus, pbus, sizeof(*pbus));
- }
-
- apb_init(sabre);
-}
-
-
-static void __init pbm_probe(struct linux_pbm_info *pbm)
-{
- static struct pci_bus *pchain = NULL;
- struct pci_bus *pbus = &pbm->pci_bus;
- static unsigned char busno = 0;
-
- /* PSYCHO PBM's include child PCI bridges in bus-range property,
- * but we don't scan each of those ourselves, Linux generic PCI
- * probing code will find child bridges and link them into this
- * pbm's root PCI device hierarchy.
- */
-
- pbus->number = pbus->secondary = busno;
- pbus->sysdata = pbm;
-
- pbm_fixup_busno(pbm, busno);
-
- pbus->subordinate = pci_scan_bus(pbus);
-
- /*
- * Set the maximum subordinate bus of this pbm.
- */
- pbm->pci_last_busno = pbus->subordinate;
- pbm_write_config_byte(pbm, busno, 0, 0x41, pbm->pci_last_busno);
-
- busno = pbus->subordinate + 1;
-
- /*
- * Fixup the chain of primary PCI busses.
- */
- if (pchain) {
- pchain->next = &pbm->pci_bus;
- pchain = pchain->next;
- } else {
- pchain = &pci_root;
- memcpy(pchain, &pbm->pci_bus, sizeof(pci_root));
- }
-}
-
-static int __init pdev_to_pnode_sibtraverse(struct linux_pbm_info *pbm,
- struct pci_dev *pdev,
- int pnode)
-{
- struct linux_prom_pci_registers pregs[PROMREG_MAX];
- int node;
- int err;
-
- node = prom_getchild(pnode);
- while (node) {
-
- err = prom_getproperty(node, "reg", (char *)&pregs[0], sizeof(pregs));
- if(err != 0 && err != -1) {
- u32 devfn = (pregs[0].phys_hi >> 8) & 0xff;
-
- if(devfn == pdev->devfn)
- return node; /* Match */
- }
-
- node = prom_getsibling(node);
- }
- return 0;
-}
-
-static void __init pdev_cookie_fillin(struct linux_pbm_info *pbm,
- struct pci_dev *pdev, int pnode)
-{
- struct pcidev_cookie *pcp;
- int node;
-
- node = pdev_to_pnode_sibtraverse(pbm, pdev, pnode);
- if(node == 0)
- node = -1;
- pcp = pci_devcookie_alloc();
- pcp->pbm = pbm;
- pcp->prom_node = node;
- pdev->sysdata = pcp;
-#ifdef PCI_COOKIE_DEBUG
- dprintf("pdev_cookie_fillin: pdev [%02x.%02x]: pbm %p, node %x\n",
- pdev->bus->number, pdev->devfn, pbm, node);
-#endif
-}
-
-static void __init fill_in_pbm_cookies(struct pci_bus *pbus,
- struct linux_pbm_info *pbm,
- int node)
-{
- struct pci_dev *pdev;
-
- pbus->sysdata = pbm;
-
-#ifdef PCI_COOKIE_DEBUG
- dprintf("fill_in_pbm_cookies: pbus [%02x]: pbm %p\n",
- pbus->number, pbm);
-#endif
-
- for(pdev = pbus->devices; pdev; pdev = pdev->sibling)
- pdev_cookie_fillin(pbm, pdev, node);
-
- for(pbus = pbus->children; pbus; pbus = pbus->next) {
- struct pcidev_cookie *pcp = pbus->self->sysdata;
- fill_in_pbm_cookies(pbus, pbm, pcp->prom_node);
- }
-}
-
-static void __init sabre_cookie_fillin(struct linux_psycho *sabre)
-{
- struct pci_bus *pbus = sabre->pci_bus;
-
- for(pbus = pbus->children; pbus; pbus = pbus->next) {
- if (pbus->number == sabre->pbm_A.pci_first_busno)
- pdev_cookie_fillin(&sabre->pbm_A, pbus->self,
- sabre->pbm_A.prom_node);
- else if (pbus->number == sabre->pbm_B.pci_first_busno)
- pdev_cookie_fillin(&sabre->pbm_B, pbus->self,
- sabre->pbm_B.prom_node);
- }
-}
-
-/* Walk PROM device tree under PBM, looking for 'assigned-address'
- * properties, and recording them in pci_vma's linked in via
- * PBM->assignments.
- */
-static int __init gimme_ebus_assignments(int node, struct linux_prom_pci_registers *aregs)
-{
- struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX];
- int err, iter;
-
- err = prom_getproperty(node, "ranges", (char *)&erng[0], sizeof(erng));
- if(err == 0 || err == -1) {
- prom_printf("EBUS: fatal error, no range property.\n");
- prom_halt();
- }
- err = (err / sizeof(struct linux_prom_ebus_ranges));
- for(iter = 0; iter < err; iter++) {
- struct linux_prom_ebus_ranges *ep = &erng[iter];
- struct linux_prom_pci_registers *ap = &aregs[iter];
-
- ap->phys_hi = ep->parent_phys_hi;
- ap->phys_mid = ep->parent_phys_mid;
- ap->phys_lo = ep->parent_phys_lo;
-
- ap->size_hi = 0;
- ap->size_lo = ep->size;
- }
- return err;
-}
-
-static void __init assignment_process(struct linux_pbm_info *pbm, int node)
-{
- struct linux_prom_pci_registers aregs[PROMREG_MAX];
- char pname[256];
- int err, iter, numa;
-
- err = prom_getproperty(node, "name", (char *)&pname[0], sizeof(pname));
- if (err > 0)
- pname[err] = 0;
-#ifdef FIXUP_VMA_DEBUG
- dprintf("%s: %s\n", __FUNCTION__, err > 0 ? pname : "???");
-#endif
- if(strcmp(pname, "ebus") == 0) {
- numa = gimme_ebus_assignments(node, &aregs[0]);
- } else {
- err = prom_getproperty(node, "assigned-addresses",
- (char *)&aregs[0], sizeof(aregs));
-
- /* No assignments, nothing to do. */
- if(err == 0 || err == -1)
- return;
-
- numa = (err / sizeof(struct linux_prom_pci_registers));
- }
-
- for(iter = 0; iter < numa; iter++) {
- struct linux_prom_pci_registers *ap = &aregs[iter];
- struct pci_vma *vp;
- int space, breg, io;
-
- space = (ap->phys_hi >> 24) & 3;
- if(space != 1 && space != 2)
- continue;
- io = (space == 1);
-
- breg = (ap->phys_hi & 0xff);
-
- vp = pci_vma_alloc();
-
- /* XXX Means we don't support > 32-bit range of
- * XXX PCI MEM space, PSYCHO/PBM does not support it
- * XXX either due to it's layout so...
- */
- vp->start = ap->phys_lo;
- vp->end = vp->start + ap->size_lo - 1;
- vp->offset = (ap->phys_hi & 0xffffff);
-
- pci_add_vma(pbm, vp, io);
-
-#ifdef FIXUP_VMA_DEBUG
- dprintf("%s: BaseReg %02x", pname, breg);
- dprintf(" %s vma [%08x,%08x]\n",
- io ? "I/O" : breg == PCI_ROM_ADDRESS ? "ROM" : "MEM", vp->start, vp->end);
-#endif
- }
-}
-
-static void __init assignment_walk_siblings(struct linux_pbm_info *pbm, int node)
-{
- while(node) {
- int child = prom_getchild(node);
- if(child)
- assignment_walk_siblings(pbm, child);
-
- assignment_process(pbm, node);
-
- node = prom_getsibling(node);
- }
-}
-
-static inline void record_assignments(struct linux_pbm_info *pbm)
-{
- struct pci_vma *vp;
-
- if (apb_present(pbm->parent)) {
- /*
- * Disallow anything that is not in our IO/MEM map on SIMBA.
- */
- struct pci_bus *pbus = pbm->parent->pci_bus;
- struct pci_dev *pdev;
- unsigned char map;
- int bit;
-
- for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
- struct pcidev_cookie *pcp = pdev->sysdata;
- if (!pcp)
- continue;
- if (pcp->pbm == pbm)
- break;
- }
-
- if (!pdev) {
- prom_printf("record_assignments: no pdev for PBM\n");
- prom_halt();
- }
-
- pci_read_config_byte(pdev, APB_IO_ADDRESS_MAP, &map);
-#ifdef FIXUP_VMA_DEBUG
- dprintf("%s: IO %02x\n", __FUNCTION__, map);
-#endif
- for (bit = 0; bit < 8; bit++) {
- if (!(map & (1 << bit))) {
- vp = pci_vma_alloc();
- vp->start = (bit << 21);
- vp->end = vp->start + (1 << 21) - 1;
- vp->offset = 0;
- pci_add_vma(pbm, vp, 1);
-#ifdef FIXUP_VMA_DEBUG
- dprintf("%s: IO prealloc vma [%08x,%08x]\n",
- __FUNCTION__, vp->start, vp->end);
-#endif
- }
- }
- pci_read_config_byte(pdev, APB_MEM_ADDRESS_MAP, &map);
-#ifdef FIXUP_VMA_DEBUG
- dprintf("%s: MEM %02x\n", __FUNCTION__, map);
-#endif
- for (bit = 0; bit < 8; bit++) {
- if (!(map & (1 << bit))) {
- vp = pci_vma_alloc();
- vp->start = (bit << 29);
- vp->end = vp->start + (1 << 29) - 1;
- vp->offset = 0;
- pci_add_vma(pbm, vp, 0);
-#ifdef FIXUP_VMA_DEBUG
- dprintf("%s: MEM prealloc vma [%08x,%08x]\n",
- __FUNCTION__, vp->start, vp->end);
-#endif
- }
- }
- }
-
- assignment_walk_siblings(pbm, prom_getchild(pbm->prom_node));
-
- /*
- * Protect ISA IO space from being used.
- */
- vp = pci_find_vma(pbm, 0, 0, 1);
- if (!vp || 0x400 <= vp->start) {
- vp = pci_vma_alloc();
- vp->start = 0;
- vp->end = vp->start + 0x400 - 1;
- vp->offset = 0;
- pci_add_vma(pbm, vp, 1);
- }
-
-#ifdef FIXUP_VMA_DEBUG
- dprintf("PROM IO assignments for PBM %s:\n",
- pbm == &pbm->parent->pbm_A ? "A" : "B");
- vp = pbm->IO_assignments;
- while (vp) {
- dprintf(" [%08x,%08x] (%s)\n", vp->start, vp->end,
- vp->offset ? "Register" : "Unmapped");
- vp = vp->next;
- }
- dprintf("PROM MEM assignments for PBM %s:\n",
- pbm == &pbm->parent->pbm_A ? "A" : "B");
- vp = pbm->MEM_assignments;
- while (vp) {
- dprintf(" [%08x,%08x] (%s)\n", vp->start, vp->end,
- vp->offset ? "Register" : "Unmapped");
- vp = vp->next;
- }
-#endif
-}
-
-static void __init fixup_regs(struct pci_dev *pdev,
- struct linux_pbm_info *pbm,
- struct linux_prom_pci_registers *pregs,
- int nregs,
- struct linux_prom_pci_registers *assigned,
- int numaa)
-{
- int preg, rng;
- int IO_seen = 0;
- int MEM_seen = 0;
-
- for(preg = 0; preg < nregs; preg++) {
- struct linux_prom_pci_registers *ap = NULL;
- int bustype = (pregs[preg].phys_hi >> 24) & 0x3;
- int bsreg, brindex;
- unsigned int rtmp;
- u64 pci_addr;
-
- if(bustype == 0) {
- /* Config space cookie, nothing to do. */
- if(preg != 0)
- printk("%s %02x.%02x [%04x,%04x]: "
- "strange, config space not 0\n",
- __FUNCTION__,
- pdev->bus->number, pdev->devfn,
- pdev->vendor, pdev->device);
- continue;
- } else if(bustype == 3) {
- /* XXX add support for this... */
- printk("%s %02x.%02x [%04x,%04x]: "
- "Warning, ignoring 64-bit PCI memory space, "
- "tell Eddie C. Dost (ecd@skynet.be).\n",
- __FUNCTION__,
- pdev->bus->number, pdev->devfn,
- pdev->vendor, pdev->device);
- continue;
- }
-
- bsreg = (pregs[preg].phys_hi & 0xff);
-
- /* Sanity */
- if((bsreg < PCI_BASE_ADDRESS_0) ||
- ((bsreg > (PCI_BASE_ADDRESS_5 + 4)) && (bsreg != PCI_ROM_ADDRESS)) ||
- (bsreg & 3)) {
- printk("%s %02x.%02x [%04x:%04x]: "
- "Warning, ignoring bogus basereg [%x]\n",
- __FUNCTION__, pdev->bus->number, pdev->devfn,
- pdev->vendor, pdev->device, bsreg);
- printk(" PROM reg: %08x.%08x.%08x %08x.%08x\n",
- pregs[preg].phys_hi, pregs[preg].phys_mid,
- pregs[preg].phys_lo, pregs[preg].size_hi,
- pregs[preg].size_lo);
- continue;
- }
-
- brindex = (bsreg - PCI_BASE_ADDRESS_0) >> 2;
- if(numaa) {
- int r;
-
- for(r = 0; r < numaa; r++) {
- int abreg;
-
- abreg = (assigned[r].phys_hi & 0xff);
- if(abreg == bsreg) {
- ap = &assigned[r];
- break;
- }
- }
- }
-
- /* Now construct UPA physical address. */
- pci_addr = (((u64)pregs[preg].phys_mid) << 32UL);
- pci_addr |= (((u64)pregs[preg].phys_lo));
-
- if(ap) {
- pci_addr += ((u64)ap->phys_lo);
- pci_addr += (((u64)ap->phys_mid) << 32UL);
- }
-
- /* Final step, apply PBM range. */
- for(rng = 0; rng < pbm->num_pbm_ranges; rng++) {
- struct linux_prom_pci_ranges *rp = &pbm->pbm_ranges[rng];
- int space = (rp->child_phys_hi >> 24) & 3;
-
- if(space == bustype) {
- pci_addr += ((u64)rp->parent_phys_lo);
- pci_addr += (((u64)rp->parent_phys_hi) << 32UL);
- break;
- }
- }
- if(rng == pbm->num_pbm_ranges) {
- /* AIEEE */
- prom_printf("fixup_doit: YIEEE, cannot find PBM ranges\n");
- }
- if (bsreg == PCI_ROM_ADDRESS) {
- pdev->rom_address = (unsigned long)__va(pci_addr);
- pdev->rom_address &= ~1UL;
-
- /*
- * Disable access to the ROM.
- */
- pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &rtmp);
- pci_write_config_dword(pdev, PCI_ROM_ADDRESS, rtmp & ~1);
- } else
- pdev->base_address[brindex] = (unsigned long)__va(pci_addr);
-
- /* Preserve I/O space bit. */
- if(bustype == 0x1) {
- pdev->base_address[brindex] |= 1;
- IO_seen = 1;
- } else {
- MEM_seen = 1;
- }
- }
-
- /* Now handle assignments PROM did not take care of. */
- if(nregs) {
- unsigned int rtmp, ridx;
- unsigned int offset, base;
- struct pci_vma *vp;
- u64 pci_addr;
- int breg;
-
- for(breg = PCI_BASE_ADDRESS_0; breg <= PCI_BASE_ADDRESS_5; breg += 4) {
- int io;
-
- ridx = ((breg - PCI_BASE_ADDRESS_0) >> 2);
- base = (unsigned int)pdev->base_address[ridx];
-
- if(pdev->base_address[ridx] > PAGE_OFFSET)
- continue;
-
- io = (base & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO;
- base &= ~((io ?
- PCI_BASE_ADDRESS_IO_MASK :
- PCI_BASE_ADDRESS_MEM_MASK));
- offset = (pdev->bus->number << 16) | (pdev->devfn << 8) | breg;
- vp = pci_find_vma(pbm, base, offset, io);
- if(!vp || vp->start > base) {
- unsigned int size, new_base;
-
- pci_read_config_dword(pdev, breg, &rtmp);
- pci_write_config_dword(pdev, breg, 0xffffffff);
- pci_read_config_dword(pdev, breg, &size);
- if(io)
- size &= ~1;
- size = (~(size) + 1);
- if(!size)
- continue;
-
- new_base = 0;
- for(vp = pci_find_vma(pbm, new_base, 0, io); ;
- vp = vp->next) {
- if(!vp || new_base + size <= vp->start)
- break;
- new_base = (vp->end + (size - 1)) & ~(size-1);
- }
- if(vp && (new_base + size > vp->start)) {
- prom_printf("PCI: Impossible full %s space.\n",
- (io ? "IO" : "MEM"));
- prom_halt();
- }
- vp = pci_vma_alloc();
- vp->start = new_base;
- vp->end = vp->start + size - 1;
- vp->offset = offset;
-
- pci_add_vma(pbm, vp, io);
-
-#ifdef FIXUP_VMA_DEBUG
- dprintf("%02x.%02x.%x: BaseReg %02x",
- pdev->bus->number,
- PCI_SLOT(pdev->devfn),
- PCI_FUNC(pdev->devfn),
- breg);
- dprintf(" %s vma [%08x,%08x]\n",
- io ? "I/O" : breg == PCI_ROM_ADDRESS ? "ROM" : "MEM", vp->start, vp->end);
-#endif
- rtmp = new_base;
- pci_read_config_dword(pdev, breg, &base);
- if(io)
- rtmp |= (base & ~PCI_BASE_ADDRESS_IO_MASK);
- else
- rtmp |= (base & ~PCI_BASE_ADDRESS_MEM_MASK);
- pci_write_config_dword(pdev, breg, rtmp);
-
- /* Apply PBM ranges and update pci_dev. */
- pci_addr = new_base;
- for(rng = 0; rng < pbm->num_pbm_ranges; rng++) {
- struct linux_prom_pci_ranges *rp;
- int rspace;
-
- rp = &pbm->pbm_ranges[rng];
- rspace = (rp->child_phys_hi >> 24) & 3;
- if(io && rspace != 1)
- continue;
- else if(!io && rspace != 2)
- continue;
- pci_addr += ((u64)rp->parent_phys_lo);
- pci_addr += (((u64)rp->parent_phys_hi)<<32UL);
- break;
- }
- if(rng == pbm->num_pbm_ranges) {
- /* AIEEE */
- prom_printf("fixup_doit: YIEEE, cannot find "
- "PBM ranges\n");
- }
- pdev->base_address[ridx] = (unsigned long)__va(pci_addr);
-
- /* Preserve I/O space bit. */
- if(io) {
- pdev->base_address[ridx] |= 1;
- IO_seen = 1;
- } else {
- MEM_seen = 1;
- }
- }
- }
-
- /*
- * Handle PCI_ROM_ADDRESS.
- */
- breg = PCI_ROM_ADDRESS;
- base = (unsigned int)pdev->rom_address;
-
- if(pdev->rom_address > PAGE_OFFSET)
- goto rom_address_done;
-
- base &= PCI_ROM_ADDRESS_MASK;
- offset = (pdev->bus->number << 16) | (pdev->devfn << 8) | breg;
- vp = pci_find_vma(pbm, base, offset, 0);
- if(!vp || vp->start > base) {
- unsigned int size, new_base;
-
- pci_read_config_dword(pdev, breg, &rtmp);
- pci_write_config_dword(pdev, breg, 0xffffffff);
- pci_read_config_dword(pdev, breg, &size);
- size &= ~1;
- size = (~(size) + 1);
- if(!size)
- goto rom_address_done;
-
- new_base = 0;
- for(vp = pci_find_vma(pbm, new_base, 0, 0); ; vp = vp->next) {
- if(!vp || new_base + size <= vp->start)
- break;
- new_base = (vp->end + (size - 1)) & ~(size-1);
- }
- if(vp && (new_base + size > vp->start)) {
- prom_printf("PCI: Impossible full MEM space.\n");
- prom_halt();
- }
- vp = pci_vma_alloc();
- vp->start = new_base;
- vp->end = vp->start + size - 1;
- vp->offset = offset;
-
- pci_add_vma(pbm, vp, 0);
-
-#ifdef FIXUP_VMA_DEBUG
- dprintf("%02x.%02x.%x: BaseReg %02x",
- pdev->bus->number,
- PCI_SLOT(pdev->devfn),
- PCI_FUNC(pdev->devfn),
- breg);
- dprintf(" %s vma [%08x,%08x]\n",
- "ROM", vp->start, vp->end);
-#endif
-
- rtmp = new_base;
- pci_read_config_dword(pdev, breg, &base);
- rtmp &= ~(base & ~PCI_ROM_ADDRESS_MASK);
- pci_write_config_dword(pdev, breg, rtmp);
-
- /* Apply PBM ranges and update pci_dev. */
- pci_addr = new_base;
- for(rng = 0; rng < pbm->num_pbm_ranges; rng++) {
- struct linux_prom_pci_ranges *rp;
- int rspace;
-
- rp = &pbm->pbm_ranges[rng];
- rspace = (rp->child_phys_hi >> 24) & 3;
- if(rspace != 2)
- continue;
- pci_addr += ((u64)rp->parent_phys_lo);
- pci_addr += (((u64)rp->parent_phys_hi)<<32UL);
- break;
- }
- if(rng == pbm->num_pbm_ranges) {
- /* AIEEE */
- prom_printf("fixup_doit: YIEEE, cannot find "
- "PBM ranges\n");
- }
- pdev->rom_address = (unsigned long)__va(pci_addr);
- pdev->rom_address &= ~(base & ~PCI_ROM_ADDRESS_MASK);
- MEM_seen = 1;
- }
- rom_address_done:
-
- }
- if(IO_seen || MEM_seen) {
- unsigned int l;
-
- pci_read_config_dword(pdev, PCI_COMMAND, &l);
-#ifdef FIXUP_REGS_DEBUG
- dprintf("[");
-#endif
- if(IO_seen) {
-#ifdef FIXUP_REGS_DEBUG
- dprintf("IO ");
-#endif
- l |= PCI_COMMAND_IO;
- }
- if(MEM_seen) {
-#ifdef FIXUP_REGS_DEBUG
- dprintf("MEM");
-#endif
- l |= PCI_COMMAND_MEMORY;
- }
-#ifdef FIXUP_REGS_DEBUG
- dprintf("]");
-#endif
- pci_write_config_dword(pdev, PCI_COMMAND, l);
- }
-
-#ifdef FIXUP_REGS_DEBUG
- dprintf("REG_FIXUP[%04x,%04x]: ", pdev->vendor, pdev->device);
- for(preg = 0; preg < 6; preg++) {
- if(pdev->base_address[preg] != 0)
- dprintf("%d[%016lx] ", preg, pdev->base_address[preg]);
- }
- dprintf("\n");
-#endif
-}
-
-#define imap_offset(__member) \
- ((unsigned long)(&(((struct psycho_regs *)0)->__member)))
-
-static unsigned long __init psycho_pcislot_imap_offset(unsigned long ino)
-{
- unsigned int bus, slot;
-
- bus = (ino & 0x10) >> 4;
- slot = (ino & 0x0c) >> 2;
-
- if(bus == 0) {
- switch(slot) {
- case 0:
- return imap_offset(imap_a_slot0);
- case 1:
- return imap_offset(imap_a_slot1);
- case 2:
- return imap_offset(imap_a_slot2);
- case 3:
- default:
- return imap_offset(imap_a_slot3);
- }
- } else {
- switch(slot) {
- case 0:
- return imap_offset(imap_b_slot0);
- case 1:
- return imap_offset(imap_b_slot1);
- case 2:
- return imap_offset(imap_b_slot2);
- case 3:
- default:
- return imap_offset(imap_b_slot3);
- }
- }
-}
-
-/* Exported for EBUS probing layer. */
-unsigned int __init psycho_irq_build(struct linux_pbm_info *pbm,
- struct pci_dev *pdev,
- unsigned int ino)
-{
- unsigned long imap_off;
- int need_dma_sync = 0;
-
- ino &= PSYCHO_IMAP_INO;
-
- /* Compute IMAP register offset, generic IRQ layer figures out
- * the ICLR register address as this is simple given the 32-bit
- * irq number and IMAP register address.
- */
- if((ino & 0x20) == 0)
- imap_off = psycho_pcislot_imap_offset(ino);
- else {
- switch(ino) {
- case 0x20:
- /* Onboard SCSI. */
- imap_off = imap_offset(imap_scsi);
- break;
-
- case 0x21:
- /* Onboard Ethernet (ie. CheerIO/HME) */
- imap_off = imap_offset(imap_eth);
- break;
-
- case 0x22:
- /* Onboard Parallel Port */
- imap_off = imap_offset(imap_bpp);
- break;
-
- case 0x23:
- /* Audio Record */
- imap_off = imap_offset(imap_au_rec);
- break;
-
- case 0x24:
- /* Audio Play */
- imap_off = imap_offset(imap_au_play);
- break;
-
- case 0x25:
- /* Power Fail */
- imap_off = imap_offset(imap_pfail);
- break;
-
- case 0x26:
- /* Onboard KBD/MOUSE/SERIAL */
- imap_off = imap_offset(imap_kms);
- break;
-
- case 0x27:
- /* Floppy (ie. fdthree) */
- imap_off = imap_offset(imap_flpy);
- break;
-
- case 0x28:
- /* Spare HW INT */
- imap_off = imap_offset(imap_shw);
- break;
-
- case 0x29:
- /* Onboard Keyboard (only) */
- imap_off = imap_offset(imap_kbd);
- break;
-
- case 0x2a:
- /* Onboard Mouse (only) */
- imap_off = imap_offset(imap_ms);
- break;
-
- case 0x2b:
- /* Onboard Serial (only) */
- imap_off = imap_offset(imap_ser);
- break;
-
- case 0x2c:
- /* Onboard Timer 0 */
- imap_off = imap_offset(imap_tim0);
- break;
-
- case 0x2d:
- /* Onboard Timer 1 */
- imap_off = imap_offset(imap_tim1);
- break;
-
- case 0x2e:
- /* Psycho UE Interrupt */
- imap_off = imap_offset(imap_ue);
- break;
-
- case 0x2f:
- /* Psycho CE Interrupt */
- imap_off = imap_offset(imap_ce);
- break;
-
- case 0x30:
- /* Psycho PCI A Error Interrupt */
- imap_off = imap_offset(imap_a_err);
- break;
-
- case 0x31:
- /* Psycho PCI B Error Interrupt */
- imap_off = imap_offset(imap_b_err);
- break;
-
- case 0x32:
- /* Power Management */
- imap_off = imap_offset(imap_pmgmt);
- break;
-
- default:
- /* We don't expect anything else.
- */
- prom_printf("psycho_irq_build: Wacky INO [%x]\n", ino);
- prom_halt();
- };
- }
- imap_off -= imap_offset(imap_a_slot0);
-
- if (apb_present(pbm->parent) && (pdev->bus->number != pbm->pci_first_busno)) {
- need_dma_sync = 1;
- }
-
- return psycho_build_irq(pbm->parent, imap_off, ino, need_dma_sync);
-}
-
-static int __init pbm_intmap_match(struct linux_pbm_info *pbm,
- struct pci_dev *pdev,
- struct linux_prom_pci_registers *preg,
- unsigned int *interrupt)
-{
- struct linux_prom_pci_registers ppreg;
- unsigned int hi, mid, lo, irq;
- int i;
-
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("pbm_intmap_match: ");
-#endif
- if (!pbm->num_pbm_intmap) {
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("No intmap UPA[%x:%c]\n",
- pbm->parent->upa_portid,
- (pbm == &pbm->parent->pbm_A) ? 'A' : 'B');
-#endif
- return 0;
- }
- /*
- * Underneath a bridge, use register of parent bridge.
- */
- if (pdev->bus->number != pbm->pci_first_busno) {
- struct pcidev_cookie *pcp;
- int node, offset;
- char prom_name[64];
-
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("UnderBridge, ");
-#endif
- pcp = pdev->bus->self->sysdata;
- if (!pcp) {
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("No bus PCP\n");
-#endif
- goto out;
- }
- node = pcp->prom_node;
-
- i = prom_getproperty(node, "reg", (char*)&ppreg, sizeof(ppreg));
- if(i == 0 || i == -1) {
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("No reg property.\n");
-#endif
- goto out;
- }
- /*
- * Did PROM know better and assign an interrupt different
- * to #INTA to the device? - We test here for presence of
- * FCODE on the card, in this case we assume PROM has set
- * correct 'interrupts' property, unless it is quadhme.
- */
- pcp = pdev->sysdata;
- if (!pcp) {
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("No dev PCP\n");
-#endif
- goto out;
- }
- node = pcp->prom_node;
-
- offset = prom_getint(node, "fcode-rom-offset");
- prom_getstring(node, "name", prom_name, sizeof(prom_name));
- if (offset == -1 ||
- !strcmp(prom_name, "SUNW,qfe") ||
- !strcmp(prom_name, "qfe")) {
- /*
- * No, use low slot number bits of child as IRQ line.
- */
- *interrupt = ((*interrupt - 1 + PCI_SLOT(pdev->devfn)) & 3) + 1;
- }
- preg = &ppreg;
- }
-
- hi = preg->phys_hi & pbm->pbm_intmask.phys_hi;
- mid = preg->phys_mid & pbm->pbm_intmask.phys_mid;
- lo = preg->phys_lo & pbm->pbm_intmask.phys_lo;
- irq = *interrupt & pbm->pbm_intmask.interrupt;
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("intmap_match: [%02x.%02x.%x] key: [%08x.%08x.%08x.%08x] ",
- pdev->bus->number, pdev->devfn >> 3, pdev->devfn & 7,
- hi, mid, lo, irq);
-#endif
- for (i = 0; i < pbm->num_pbm_intmap; i++) {
- if ((pbm->pbm_intmap[i].phys_hi == hi) &&
- (pbm->pbm_intmap[i].phys_mid == mid) &&
- (pbm->pbm_intmap[i].phys_lo == lo) &&
- (pbm->pbm_intmap[i].interrupt == irq)) {
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("irq: [%08x]", pbm->pbm_intmap[i].cinterrupt);
-#endif
- *interrupt = pbm->pbm_intmap[i].cinterrupt;
- return 1;
- }
- }
-
-out:
- prom_printf("pbm_intmap_match: bus %02x, devfn %02x: ",
- pdev->bus->number, pdev->devfn);
- prom_printf("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n",
- preg->phys_hi, preg->phys_mid, preg->phys_lo, *interrupt);
- prom_halt();
-}
-
-static void __init fixup_irq(struct pci_dev *pdev,
- struct linux_pbm_info *pbm,
- struct linux_prom_pci_registers *preg,
- int node)
-{
- unsigned int prom_irq, portid = pbm->parent->upa_portid;
- int err;
-
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("fixup_irq[%04x:%04x]: ", pdev->vendor, pdev->device);
-#endif
- err = prom_getproperty(node, "interrupts", (void *)&prom_irq, sizeof(prom_irq));
- if(err == 0 || err == -1) {
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("No interrupts property.\n");
-#endif
- pdev->irq = 0;
- return;
- }
-
- /* See if fully specified already (ie. for onboard devices like hme) */
- if(((prom_irq & PSYCHO_IMAP_IGN) >> 6) == pbm->parent->upa_portid) {
- pdev->irq = psycho_irq_build(pbm, pdev, prom_irq);
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("fully specified prom_irq[%x] pdev->irq[%x]",
- prom_irq, pdev->irq);
-#endif
- /* See if onboard device interrupt (i.e. bit 5 set) */
- } else if((prom_irq & PSYCHO_IMAP_INO) & 0x20) {
- pdev->irq = psycho_irq_build(pbm, pdev,
- (pbm->parent->upa_portid << 6)
- | prom_irq);
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("partially specified prom_irq[%x] pdev->irq[%x]",
- prom_irq, pdev->irq);
-#endif
- /* See if we find a matching interrupt-map entry. */
- } else if (pbm_intmap_match(pbm, pdev, preg, &prom_irq)) {
- pdev->irq = psycho_irq_build(pbm, pdev,
- (pbm->parent->upa_portid << 6)
- | prom_irq);
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("interrupt-map specified: prom_irq[%x] pdev->irq[%x]",
- prom_irq, pdev->irq);
-#endif
- } else {
- unsigned int bus, slot, line;
-
- bus = (pbm == &pbm->parent->pbm_B) ? (1 << 4) : 0;
-
- /* Use the given interrupt property value as the line if it
- * is non-zero and legal. Legal encodings are INTA=1, INTB=2,
- * INTC=3, INTD=4 as per PCI OBP binding spec version 2.1 -DaveM
- */
- if(prom_irq > 0 && prom_irq < 5) {
- line = ((prom_irq - 1) & 3);
- } else {
- unsigned char pci_irq_line;
-
- /* The generic PCI probing layer will read the
- * interrupt line into pdev->irq if the interrupt
- * pin is non-zero, so we have to explicitly fetch
- * the pin here to be certain (the interrupt line is
- * typically left at zero by OBP).
- */
- pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pci_irq_line);
- line = ((pci_irq_line - 1) & 3);
- }
-
- /* Slot determination is only slightly complex. Handle
- * the easy case first.
- */
- if(pdev->bus->number == pbm->pci_first_busno) {
- if(pbm == &pbm->parent->pbm_A)
- slot = (pdev->devfn >> 3) - 1;
- else
- slot = (pdev->devfn >> 3) - 2;
- } else {
- /* Underneath a bridge, use slot number of parent
- * bridge.
- */
- if(pbm == &pbm->parent->pbm_A)
- slot = (pdev->bus->self->devfn >> 3) - 1;
- else
- slot = (pdev->bus->self->devfn >> 3) - 2;
-
- /* Use low slot number bits of child as IRQ line. */
- line = (pdev->devfn >> 3) & 0x03;
- }
- slot = (slot << 2);
-
- pdev->irq = psycho_irq_build(pbm, pdev,
- (((portid << 6) & PSYCHO_IMAP_IGN)
- | (bus | slot | line)));
-
-#ifdef FIXUP_IRQ_DEBUG
- do {
- unsigned char iline, ipin;
-
- pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &ipin);
- pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &iline);
- dprintf("FIXED portid[%x] bus[%x] slot[%x] line[%x] "
- "irq[%x] iline[%x] ipin[%x] prom_irq[%x]",
- portid, bus>>4, slot>>2, line, pdev->irq,
- iline, ipin, prom_irq);
- } while(0);
-#endif
- }
-
- /*
- * Write the INO to config space PCI_INTERRUPT_LINE.
- */
- pci_write_config_byte(pdev, PCI_INTERRUPT_LINE,
- pdev->irq & PCI_IRQ_INO);
-
-#ifdef FIXUP_IRQ_DEBUG
- dprintf("\n");
-#endif
-}
-
-static void __init fixup_doit(struct pci_dev *pdev,
- struct linux_pbm_info *pbm,
- struct linux_prom_pci_registers *pregs,
- int nregs,
- int node)
-{
- struct linux_prom_pci_registers assigned[PROMREG_MAX];
- int numaa, err;
-
- /* Get assigned addresses, if any. */
- err = prom_getproperty(node, "assigned-addresses",
- (char *)&assigned[0], sizeof(assigned));
- if(err == 0 || err == -1)
- numaa = 0;
- else
- numaa = (err / sizeof(struct linux_prom_pci_registers));
-
- /* First, scan and fixup base registers. */
- fixup_regs(pdev, pbm, pregs, nregs, &assigned[0], numaa);
-
- /* Next, fixup interrupt numbers. */
- fixup_irq(pdev, pbm, &pregs[0], node);
-}
-
-static void __init fixup_pci_dev(struct pci_dev *pdev,
- struct pci_bus *pbus,
- struct linux_pbm_info *pbm)
-{
- struct linux_prom_pci_registers pregs[PROMREG_MAX];
- struct pcidev_cookie *pcp = pdev->sysdata;
- int node, nregs, err;
-
- /* If this is a PCI bridge, we must program it. */
- if(pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI) {
- unsigned short cmd;
-
- /* First, enable bus mastering. */
- pci_read_config_word(pdev, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_MASTER;
- pci_write_config_word(pdev, PCI_COMMAND, cmd);
-
- /* Now, set cache line size to 64-bytes.
- * NOTE: Cache line size is in 32-bit word units.
- */
- pci_write_config_byte(pdev,
- PCI_CACHE_LINE_SIZE,
- (64 / sizeof(u32)));
- }
-
- /* Ignore if this is one of the PBM's, EBUS, or a
- * sub-bridge underneath the PBM. We only need to fixup
- * true devices.
- */
- if((pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI) ||
- (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) ||
- (pdev->class >> 8 == PCI_CLASS_BRIDGE_OTHER) ||
- (pcp == NULL)) {
- /*
- * Prevent access to PCI_ROM_ADDRESS, in case present
- * as we don't fixup the address.
- */
- if (pdev->rom_address) {
- pci_write_config_dword(pdev, PCI_ROM_ADDRESS, 0);
- pdev->rom_address = 0;
- }
- return;
- }
-
- node = pcp->prom_node;
-
- err = prom_getproperty(node, "reg", (char *)&pregs[0], sizeof(pregs));
- if(err == 0 || err == -1) {
- prom_printf("Cannot find REG for pci_dev\n");
- prom_halt();
- }
-
- nregs = (err / sizeof(pregs[0]));
-
- fixup_doit(pdev, pbm, &pregs[0], nregs, node);
-
- /* Enable bus mastering on IDE interfaces. */
- if ((pdev->class >> 8 == PCI_CLASS_STORAGE_IDE)
- && (pdev->class & 0x80)) {
- unsigned short cmd;
-
- pci_read_config_word(pdev, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_MASTER;
- pci_write_config_word(pdev, PCI_COMMAND, cmd);
- }
-}
-
-static void __init fixup_pci_bus(struct pci_bus *pbus, struct linux_pbm_info *pbm)
-{
- struct pci_dev *pdev;
-
- for(pdev = pbus->devices; pdev; pdev = pdev->sibling)
- fixup_pci_dev(pdev, pbus, pbm);
-
- for(pbus = pbus->children; pbus; pbus = pbus->next)
- fixup_pci_bus(pbus, pbm);
-}
-
-static void __init fixup_addr_irq(struct linux_pbm_info *pbm)
-{
- struct pci_bus *pbus = &pbm->pci_bus;
-
- /* Work through top level devices (not bridges, those and their
- * devices are handled specially in the next loop).
- */
- fixup_pci_bus(pbus, pbm);
-}
-
-/* Walk all PCI devices probes, fixing up base registers and IRQ registers.
- * We use OBP for most of this work.
- */
-static void __init psycho_final_fixup(struct linux_psycho *psycho)
-{
- /* Second, fixup base address registers and IRQ lines... */
- if (psycho->pbm_A.parent)
- fixup_addr_irq(&psycho->pbm_A);
- if (psycho->pbm_B.parent)
- fixup_addr_irq(&psycho->pbm_B);
-}
-
-/* Reorder the pci_dev chain, so that onboard devices come first
- and then come the pluggable cards. */
-void __init psycho_reorder_devs(void)
-{
- struct pci_dev **pci_onboard = &pci_devices;
- struct pci_dev **pci_tail = &pci_devices;
- struct pci_dev *pdev = pci_devices, *pci_other = NULL;
-
- while (pdev) {
- if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) {
- if (pci_other) {
- *pci_onboard = pdev;
- pci_onboard = &pdev->next;
- pdev = pdev->next;
- *pci_onboard = pci_other;
- *pci_tail = pdev;
- continue;
- } else
- pci_onboard = &pdev->next;
- } else if (!pci_other)
- pci_other = pdev;
- pci_tail = &pdev->next;
- pdev = pdev->next;
- }
-}
-
-void __init pcibios_fixup(void)
-{
- struct linux_psycho *psycho;
-
- pci_probe_enable = 1;
-
- /* XXX Really this should be per-PSYCHO, but the config space
- * XXX reads and writes give us no way to know which PSYCHO
- * XXX in which the config space reads should occur.
- * XXX
- * XXX Further thought says that we cannot change this generic
- * XXX interface, else we'd break xfree86 and other parts of the
- * XXX kernel (but whats more important is breaking userland for
- * XXX the ix86/Alpha/etc. people). So we should define our own
- * XXX internal extension initially, we can compile our own user
- * XXX apps that need to get at PCI configuration space.
- */
-
- for (psycho = psycho_root; psycho; psycho = psycho->next) {
- /* Probe bus on builtin PCI. */
- if (apb_present(psycho)) {
- sabre_probe(psycho);
- } else {
- /* Probe busses under PBM B. */
- pbm_probe(&psycho->pbm_B);
-
- /* Probe busses under PBM A. */
- pbm_probe(&psycho->pbm_A);
- }
- }
-
- /* Walk all PCI devices found. For each device, and
- * PCI bridge which is not one of the PSYCHO PBM's, fill in the
- * sysdata with a pointer to the PBM (for pci_bus's) or
- * a pci_dev cookie (PBM+PROM_NODE, for pci_dev's).
- */
- for (psycho = psycho_root; psycho; psycho = psycho->next) {
- if (apb_present(psycho))
- sabre_cookie_fillin(psycho);
-
- fill_in_pbm_cookies(&psycho->pbm_A.pci_bus,
- &psycho->pbm_A,
- psycho->pbm_A.prom_node);
- fill_in_pbm_cookies(&psycho->pbm_B.pci_bus,
- &psycho->pbm_B,
- psycho->pbm_B.prom_node);
-
- /* See what OBP has taken care of already. */
- record_assignments(&psycho->pbm_A);
- record_assignments(&psycho->pbm_B);
-
- /* Now, fix it all up. */
- psycho_final_fixup(psycho);
- }
-
- if (psycho_reorder & PSYCHO_REORDER_ONBOARDFIRST)
- psycho_reorder_devs();
-
- return ebus_init();
-}
-
-/* "PCI: The emerging standard..." 8-( */
-volatile int pci_poke_in_progress = 0;
-volatile int pci_poke_faulted = 0;
-
-/* XXX Current PCI support code is broken, it assumes one master PCI config
- * XXX space exists, on Ultra we can have many of them, especially with
- * XXX 'dual-pci' boards on Sunfire/Starfire/Wildfire.
- */
-static void *
-pci_mkaddr(struct linux_pbm_info *pbm, unsigned char bus,
- unsigned char devfn, unsigned char where)
-{
- unsigned long ret;
-
- if (!pbm)
- return NULL;
-
- ret = (unsigned long) pbm->parent->pci_config_space;
-
- ret |= (1 << 24);
- ret |= (bus << 16);
- ret |= (devfn << 8);
- ret |= where;
-
- return (void *)ret;
-}
-
-static inline int
-out_of_range(struct linux_pbm_info *pbm, unsigned char bus, unsigned char devfn)
-{
- return ((pbm->parent == 0) ||
- ((pbm == &pbm->parent->pbm_B) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 8) ||
- ((pbm == &pbm->parent->pbm_A) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 8) ||
- (pci_probe_enable == 0));
-}
-
-static inline int
-sabre_out_of_range(unsigned char devfn)
-{
- return ((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) ||
- ((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) ||
- (PCI_SLOT(devfn) > 1);
-}
-
-static int
-sabre_read_config_byte(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned char *value)
-{
- if (bus)
- return pbm_read_config_byte(pbm, bus, devfn, where, value);
-
- if (sabre_out_of_range(devfn)) {
- *value = 0xff;
- return PCIBIOS_SUCCESSFUL;
- }
-
- if (where < 8) {
- unsigned short tmp;
-
- pbm_read_config_word(pbm, bus, devfn, where & ~1, &tmp);
- if (where & 1)
- *value = tmp >> 8;
- else
- *value = tmp & 0xff;
- return PCIBIOS_SUCCESSFUL;
- } else
- return pbm_read_config_byte(pbm, bus, devfn, where, value);
-}
-
-static int
-sabre_read_config_word(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned short *value)
-{
- if (bus)
- return pbm_read_config_word(pbm, bus, devfn, where, value);
-
- if (sabre_out_of_range(devfn)) {
- *value = 0xffff;
- return PCIBIOS_SUCCESSFUL;
- }
-
- if (where < 8)
- return pbm_read_config_word(pbm, bus, devfn, where, value);
- else {
- unsigned char tmp;
-
- pbm_read_config_byte(pbm, bus, devfn, where, &tmp);
- *value = tmp;
- pbm_read_config_byte(pbm, bus, devfn, where + 1, &tmp);
- *value |= tmp << 8;
- return PCIBIOS_SUCCESSFUL;
- }
-}
-
-static int
-sabre_read_config_dword(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned int *value)
-{
- unsigned short tmp;
-
- if (bus)
- return pbm_read_config_dword(pbm, bus, devfn, where, value);
-
- if (sabre_out_of_range(devfn)) {
- *value = 0xffffffff;
- return PCIBIOS_SUCCESSFUL;
- }
-
- sabre_read_config_word(pbm, bus, devfn, where, &tmp);
- *value = tmp;
- sabre_read_config_word(pbm, bus, devfn, where + 2, &tmp);
- *value |= tmp << 16;
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-sabre_write_config_byte(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned char value)
-{
- if (bus)
- return pbm_write_config_byte(pbm, bus, devfn, where, value);
-
- if (sabre_out_of_range(devfn))
- return PCIBIOS_SUCCESSFUL;
-
- if (where < 8) {
- unsigned short tmp;
-
- pbm_read_config_word(pbm, bus, devfn, where & ~1, &tmp);
- if (where & 1) {
- value &= 0x00ff;
- value |= tmp << 8;
- } else {
- value &= 0xff00;
- value |= tmp;
- }
- return pbm_write_config_word(pbm, bus, devfn, where & ~1, tmp);
- } else
- return pbm_write_config_byte(pbm, bus, devfn, where, value);
-}
-
-static int
-sabre_write_config_word(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned short value)
-{
- if (bus)
- return pbm_write_config_word(pbm, bus, devfn, where, value);
-
- if (sabre_out_of_range(devfn))
- return PCIBIOS_SUCCESSFUL;
-
- if (where < 8)
- return pbm_write_config_word(pbm, bus, devfn, where, value);
- else {
- pbm_write_config_byte(pbm, bus, devfn, where, value & 0xff);
- pbm_write_config_byte(pbm, bus, devfn, where + 1, value >> 8);
- return PCIBIOS_SUCCESSFUL;
- }
-}
-
-static int
-sabre_write_config_dword(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned int value)
-{
- if (bus)
- return pbm_write_config_dword(pbm, bus, devfn, where, value);
-
- if (sabre_out_of_range(devfn))
- return PCIBIOS_SUCCESSFUL;
-
- sabre_write_config_word(pbm, bus, devfn, where, value & 0xffff);
- sabre_write_config_word(pbm, bus, devfn, where + 2, value >> 16);
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pbm_read_config_byte(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned char *value)
-{
- unsigned char *addr = pci_mkaddr(pbm, bus, devfn, where);
- unsigned int trapped;
- unsigned char byte;
-
- *value = 0xff;
-
- if (!addr)
- return PCIBIOS_SUCCESSFUL;
-
- if (out_of_range(pbm, bus, devfn))
- return PCIBIOS_SUCCESSFUL;
-
- pci_poke_in_progress = 1;
- pci_poke_faulted = 0;
- __asm__ __volatile__("membar #Sync\n\t"
- "lduba [%1] %2, %0\n\t"
- "membar #Sync"
- : "=r" (byte)
- : "r" (addr), "i" (ASI_PL));
- pci_poke_in_progress = 0;
- trapped = pci_poke_faulted;
- pci_poke_faulted = 0;
- if(!trapped)
- *value = byte;
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pbm_read_config_word(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned short *value)
-{
- unsigned short *addr = pci_mkaddr(pbm, bus, devfn, where);
- unsigned int trapped;
- unsigned short word;
-
- *value = 0xffff;
-
- if (!addr)
- return PCIBIOS_SUCCESSFUL;
-
- if (out_of_range(pbm, bus, devfn))
- return PCIBIOS_SUCCESSFUL;
-
- if (where & 0x01) {
- printk("pcibios_read_config_word: misaligned reg [%x]\n",
- where);
- return PCIBIOS_SUCCESSFUL;
- }
-
- pci_poke_in_progress = 1;
- pci_poke_faulted = 0;
- __asm__ __volatile__("membar #Sync\n\t"
- "lduha [%1] %2, %0\n\t"
- "membar #Sync"
- : "=r" (word)
- : "r" (addr), "i" (ASI_PL));
- pci_poke_in_progress = 0;
- trapped = pci_poke_faulted;
- pci_poke_faulted = 0;
- if(!trapped)
- *value = word;
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pbm_read_config_dword(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned int *value)
-{
- unsigned int *addr = pci_mkaddr(pbm, bus, devfn, where);
- unsigned int word, trapped;
-
- *value = 0xffffffff;
-
- if (!addr)
- return PCIBIOS_SUCCESSFUL;
-
- if (out_of_range(pbm, bus, devfn))
- return PCIBIOS_SUCCESSFUL;
-
- if (where & 0x03) {
- printk("pcibios_read_config_dword: misaligned reg [%x]\n",
- where);
- return PCIBIOS_SUCCESSFUL;
- }
-
- pci_poke_in_progress = 1;
- pci_poke_faulted = 0;
- __asm__ __volatile__("membar #Sync\n\t"
- "lduwa [%1] %2, %0\n\t"
- "membar #Sync"
- : "=r" (word)
- : "r" (addr), "i" (ASI_PL));
- pci_poke_in_progress = 0;
- trapped = pci_poke_faulted;
- pci_poke_faulted = 0;
- if(!trapped)
- *value = word;
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pbm_write_config_byte(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned char value)
-{
- unsigned char *addr = pci_mkaddr(pbm, bus, devfn, where);
-
- if (!addr)
- return PCIBIOS_SUCCESSFUL;
-
- if (out_of_range(pbm, bus, devfn))
- return PCIBIOS_SUCCESSFUL;
-
- pci_poke_in_progress = 1;
-
- /* Endianness doesn't matter but we have to get the memory
- * barriers in there so...
- */
- __asm__ __volatile__("membar #Sync\n\t"
- "stba %0, [%1] %2\n\t"
- "membar #Sync\n\t"
- : /* no outputs */
- : "r" (value), "r" (addr), "i" (ASI_PL));
- pci_poke_in_progress = 0;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pbm_write_config_word(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned short value)
-{
- unsigned short *addr = pci_mkaddr(pbm, bus, devfn, where);
-
- if (!addr)
- return PCIBIOS_SUCCESSFUL;
-
- if (out_of_range(pbm, bus, devfn))
- return PCIBIOS_SUCCESSFUL;
-
- if (where & 0x01) {
- printk("pcibios_write_config_word: misaligned reg [%x]\n",
- where);
- return PCIBIOS_SUCCESSFUL;
- }
-
- pci_poke_in_progress = 1;
- __asm__ __volatile__("membar #Sync\n\t"
- "stha %0, [%1] %2\n\t"
- "membar #Sync\n\t"
- : /* no outputs */
- : "r" (value), "r" (addr), "i" (ASI_PL));
- pci_poke_in_progress = 0;
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pbm_write_config_dword(struct linux_pbm_info *pbm,
- unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned int value)
-{
- unsigned int *addr = pci_mkaddr(pbm, bus, devfn, where);
-
- if (!addr)
- return PCIBIOS_SUCCESSFUL;
-
- if (out_of_range(pbm, bus, devfn))
- return PCIBIOS_SUCCESSFUL;
-
- if (where & 0x03) {
- printk("pcibios_write_config_dword: misaligned reg [%x]\n",
- where);
- return PCIBIOS_SUCCESSFUL;
- }
-
- pci_poke_in_progress = 1;
- __asm__ __volatile__("membar #Sync\n\t"
- "stwa %0, [%1] %2\n\t"
- "membar #Sync"
- : /* no outputs */
- : "r" (value), "r" (addr), "i" (ASI_PL));
- pci_poke_in_progress = 0;
- return PCIBIOS_SUCCESSFUL;
-}
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned char *value)
-{
- struct linux_pbm_info *pbm = bus2pbm[bus];
-
- if (pbm && pbm->parent && apb_present(pbm->parent))
- return sabre_read_config_byte(pbm, bus, devfn, where, value);
- return pbm_read_config_byte(pbm, bus, devfn, where, value);
-}
-
-int pcibios_read_config_word (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned short *value)
-{
- struct linux_pbm_info *pbm = bus2pbm[bus];
-
- if (pbm && pbm->parent && apb_present(pbm->parent))
- return sabre_read_config_word(pbm, bus, devfn, where, value);
- return pbm_read_config_word(pbm, bus, devfn, where, value);
-}
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned int *value)
-{
- struct linux_pbm_info *pbm = bus2pbm[bus];
-
- if (pbm && pbm->parent && apb_present(pbm->parent))
- return sabre_read_config_dword(pbm, bus, devfn, where, value);
- return pbm_read_config_dword(pbm, bus, devfn, where, value);
-}
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned char value)
-{
- struct linux_pbm_info *pbm = bus2pbm[bus];
-
- if (pbm && pbm->parent && apb_present(pbm->parent))
- return sabre_write_config_byte(pbm, bus, devfn, where, value);
- return pbm_write_config_byte(pbm, bus, devfn, where, value);
-}
-
-int pcibios_write_config_word (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned short value)
-{
- struct linux_pbm_info *pbm = bus2pbm[bus];
-
- if (pbm && pbm->parent && apb_present(pbm->parent))
- return sabre_write_config_word(pbm, bus, devfn, where, value);
- return pbm_write_config_word(bus2pbm[bus], bus, devfn, where, value);
-}
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned int value)
-{
- struct linux_pbm_info *pbm = bus2pbm[bus];
-
- if (pbm && pbm->parent && apb_present(pbm->parent))
- return sabre_write_config_dword(pbm, bus, devfn, where, value);
- return pbm_write_config_dword(bus2pbm[bus], bus, devfn, where, value);
-}
-
-asmlinkage int sys_pciconfig_read(unsigned long bus,
- unsigned long dfn,
- unsigned long off,
- unsigned long len,
- unsigned char *buf)
-{
- unsigned char ubyte;
- unsigned short ushort;
- unsigned int uint;
- int err = 0;
-
- if(!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- lock_kernel();
- switch(len) {
- case 1:
- pcibios_read_config_byte(bus, dfn, off, &ubyte);
- put_user(ubyte, (unsigned char *)buf);
- break;
- case 2:
- pcibios_read_config_word(bus, dfn, off, &ushort);
- put_user(ushort, (unsigned short *)buf);
- break;
- case 4:
- pcibios_read_config_dword(bus, dfn, off, &uint);
- put_user(uint, (unsigned int *)buf);
- break;
-
- default:
- err = -EINVAL;
- break;
- };
- unlock_kernel();
-
- return err;
-}
-
-asmlinkage int sys_pciconfig_write(unsigned long bus,
- unsigned long dfn,
- unsigned long off,
- unsigned long len,
- unsigned char *buf)
-{
- unsigned char ubyte;
- unsigned short ushort;
- unsigned int uint;
- int err = 0;
-
- if(!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- lock_kernel();
- switch(len) {
- case 1:
- err = get_user(ubyte, (unsigned char *)buf);
- if(err)
- break;
- pcibios_write_config_byte(bus, dfn, off, ubyte);
- break;
-
- case 2:
- err = get_user(ushort, (unsigned short *)buf);
- if(err)
- break;
- pcibios_write_config_byte(bus, dfn, off, ushort);
- break;
-
- case 4:
- err = get_user(uint, (unsigned int *)buf);
- if(err)
- break;
- pcibios_write_config_byte(bus, dfn, off, uint);
- break;
-
- default:
- err = -EINVAL;
- break;
-
- };
- unlock_kernel();
-
- return err;
-}
-
-void __init pcibios_fixup_bus(struct pci_bus *bus)
-{
-}
-
-char * __init pcibios_setup(char *str)
-{
- if (!strcmp(str, "onboardfirst")) {
- psycho_reorder |= PSYCHO_REORDER_ONBOARDFIRST;
- return NULL;
- }
- if (!strcmp(str, "noreorder")) {
- psycho_reorder = 0;
- return NULL;
- }
- return str;
-}
-
-#endif
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 61a6a6bfa..c582be060 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -52,7 +52,7 @@ static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
static inline void
pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long *addr)
{
- if (current->tss.flags & SPARC_FLAG_32BIT) {
+ if (current->thread.flags & SPARC_FLAG_32BIT) {
if(put_user(value, (unsigned int *)addr))
return pt_error_return(regs, EFAULT);
} else {
@@ -114,7 +114,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
unsigned long addr2 = regs->u_regs[UREG_I4];
struct task_struct *child;
- if (current->tss.flags & SPARC_FLAG_32BIT) {
+ if (current->thread.flags & SPARC_FLAG_32BIT) {
addr &= 0xffffffffUL;
data &= 0xffffffffUL;
addr2 &= 0xffffffffUL;
@@ -220,7 +220,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
goto out;
}
- if(!(child->tss.flags & SPARC_FLAG_32BIT) &&
+ if(!(child->thread.flags & SPARC_FLAG_32BIT) &&
((request == PTRACE_READDATA64) ||
(request == PTRACE_WRITEDATA64) ||
(request == PTRACE_READTEXT64) ||
@@ -242,7 +242,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
int res, copied;
res = -EIO;
- if (current->tss.flags & SPARC_FLAG_32BIT) {
+ if (current->thread.flags & SPARC_FLAG_32BIT) {
copied = access_process_vm(child, addr,
&tmp32, sizeof(tmp32), 0);
tmp64 = (unsigned long) tmp32;
@@ -267,7 +267,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
unsigned int tmp32;
int copied, res = -EIO;
- if (current->tss.flags & SPARC_FLAG_32BIT) {
+ if (current->thread.flags & SPARC_FLAG_32BIT) {
tmp32 = data;
copied = access_process_vm(child, addr,
&tmp32, sizeof(tmp32), 1);
@@ -289,7 +289,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_GETREGS: {
struct pt_regs32 *pregs = (struct pt_regs32 *) addr;
- struct pt_regs *cregs = child->tss.kregs;
+ struct pt_regs *cregs = child->thread.kregs;
int rval;
if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
@@ -313,7 +313,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_GETREGS64: {
struct pt_regs *pregs = (struct pt_regs *) addr;
- struct pt_regs *cregs = child->tss.kregs;
+ struct pt_regs *cregs = child->thread.kregs;
int rval;
if (__put_user(cregs->tstate, (&pregs->tstate)) ||
@@ -337,7 +337,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_SETREGS: {
struct pt_regs32 *pregs = (struct pt_regs32 *) addr;
- struct pt_regs *cregs = child->tss.kregs;
+ struct pt_regs *cregs = child->thread.kregs;
unsigned int psr, pc, npc, y;
int i;
@@ -370,7 +370,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_SETREGS64: {
struct pt_regs *pregs = (struct pt_regs *) addr;
- struct pt_regs *cregs = child->tss.kregs;
+ struct pt_regs *cregs = child->thread.kregs;
unsigned long tstate, tpc, tnpc, y;
int i;
@@ -418,7 +418,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
if (copy_to_user(&fps->regs[0], fpregs,
(32 * sizeof(unsigned int))) ||
- __put_user(child->tss.xfsr[0], (&fps->fsr)) ||
+ __put_user(child->thread.xfsr[0], (&fps->fsr)) ||
__put_user(0, (&fps->fpqd)) ||
__put_user(0, (&fps->flags)) ||
__put_user(0, (&fps->extra)) ||
@@ -439,7 +439,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
if (copy_to_user(&fps->regs[0], fpregs,
(64 * sizeof(unsigned int))) ||
- __put_user(child->tss.xfsr[0], (&fps->fsr))) {
+ __put_user(child->thread.xfsr[0], (&fps->fsr))) {
pt_error_return(regs, EFAULT);
goto out;
}
@@ -468,11 +468,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
pt_error_return(regs, EFAULT);
goto out;
}
- child->tss.xfsr[0] &= 0xffffffff00000000UL;
- child->tss.xfsr[0] |= fsr;
- if (!(child->tss.fpsaved[0] & FPRS_FEF))
- child->tss.gsr[0] = 0;
- child->tss.fpsaved[0] |= (FPRS_FEF | FPRS_DL);
+ child->thread.xfsr[0] &= 0xffffffff00000000UL;
+ child->thread.xfsr[0] |= fsr;
+ if (!(child->thread.fpsaved[0] & FPRS_FEF))
+ child->thread.gsr[0] = 0;
+ child->thread.fpsaved[0] |= (FPRS_FEF | FPRS_DL);
pt_succ_return(regs, 0);
goto out;
}
@@ -486,13 +486,13 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
if (copy_from_user(fpregs, &fps->regs[0],
(64 * sizeof(unsigned int))) ||
- __get_user(child->tss.xfsr[0], (&fps->fsr))) {
+ __get_user(child->thread.xfsr[0], (&fps->fsr))) {
pt_error_return(regs, EFAULT);
goto out;
}
- if (!(child->tss.fpsaved[0] & FPRS_FEF))
- child->tss.gsr[0] = 0;
- child->tss.fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU);
+ if (!(child->thread.fpsaved[0] & FPRS_FEF))
+ child->thread.gsr[0] = 0;
+ child->thread.fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU);
pt_succ_return(regs, 0);
goto out;
}
@@ -538,11 +538,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
goto out;
}
#ifdef DEBUG_PTRACE
- printk ("Original: %016lx %016lx\n", child->tss.kregs->tpc, child->tss.kregs->tnpc);
+ printk ("Original: %016lx %016lx\n", child->thread.kregs->tpc, child->thread.kregs->tnpc);
printk ("Continuing with %016lx %016lx\n", addr, addr+4);
#endif
- child->tss.kregs->tpc = addr;
- child->tss.kregs->tnpc = addr + 4;
+ child->thread.kregs->tpc = addr;
+ child->thread.kregs->tnpc = addr + 4;
}
if (request == PTRACE_SYSCALL)
@@ -554,8 +554,8 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
#ifdef DEBUG_PTRACE
printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm,
child->pid, child->exit_code,
- child->tss.kregs->tpc,
- child->tss.kregs->tnpc);
+ child->thread.kregs->tpc,
+ child->thread.kregs->tnpc);
#endif
wake_up_process(child);
@@ -634,7 +634,7 @@ asmlinkage void syscall_trace(void)
return;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
- current->tss.flags ^= MAGIC_CONSTANT;
+ current->thread.flags ^= MAGIC_CONSTANT;
notify_parent(current, SIGCHLD);
schedule();
/*
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index 8444bc966..bb6d7398e 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.46 1999/05/25 16:53:20 jj Exp $
+/* $Id: rtrap.S,v 1.47 1999/07/30 09:35:23 davem Exp $
* rtrap.S: Preparing for return from trap on Sparc V9.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -11,6 +11,7 @@
#include <asm/spitfire.h>
#include <asm/head.h>
#include <asm/visasm.h>
+#include <asm/processor.h>
#define PTREGS_OFF (STACK_BIAS + REGWIN_SZ)
@@ -39,13 +40,13 @@ rtrap: sethi %hi(bh_active), %l2
be,pt %icc, to_user
andn %l7, PSTATE_IE, %l7
- ldub [%g6 + AOFF_task_tss + AOFF_thread_fpdepth], %l5
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5
brz,pt %l5, rt_continue
srl %l5, 1, %o0
- add %g6, AOFF_task_tss + AOFF_thread_fpsaved, %l6
+ add %g6, AOFF_task_thread + AOFF_thread_fpsaved, %l6
ldub [%l6 + %o0], %l2
sub %l5, 2, %l5
- add %g6, AOFF_task_tss + AOFF_thread_gsr, %o1
+ add %g6, AOFF_task_thread + AOFF_thread_gsr, %o1
andcc %l2, (FPRS_FEF|FPRS_DU), %g0
be,pt %icc, 2f
and %l2, FPRS_DL, %l6
@@ -55,7 +56,7 @@ rtrap: sethi %hi(bh_active), %l2
rd %fprs, %g5
wr %g5, FPRS_FEF, %fprs
ldub [%o1 + %o0], %g5
- add %g6, AOFF_task_tss + AOFF_thread_xfsr, %o1
+ add %g6, AOFF_task_thread + AOFF_thread_xfsr, %o1
membar #StoreLoad | #LoadLoad
sll %o0, 8, %o2
add %g6, AOFF_task_fpregs, %o3
@@ -71,9 +72,8 @@ rtrap: sethi %hi(bh_active), %l2
ldda [%o4 + %o2] ASI_BLK_P, %f48
1: membar #Sync
ldx [%o1 + %o5], %fsr
-2: stb %l5, [%g6 + AOFF_task_tss + AOFF_thread_fpdepth]
-rt_continue: lduh [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0
- ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
+2: stb %l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth]
+rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
ldx [%sp + PTREGS_OFF + PT_V9_G2], %g2
ldx [%sp + PTREGS_OFF + PT_V9_G3], %g3
mov %g6, %o5
@@ -105,10 +105,11 @@ rt_continue: lduh [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0
wrpr %o2, %g0, %tnpc
brnz,pn %l3, kern_rtt
mov PRIMARY_CONTEXT, %l7
+ ldxa [%l7 + %l7] ASI_DMMU, %l0
stxa %l0, [%l7] ASI_DMMU
flush %o5
- rdpr %wstate, %l1
+ rdpr %wstate, %l1
rdpr %otherwin, %l2
srl %l1, 3, %l1
wrpr %l2, %g0, %canrestore
@@ -116,8 +117,8 @@ rt_continue: lduh [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0
wrpr %g0, %g0, %otherwin
restore
rdpr %canrestore, %g1
- wrpr %g1, 0x0, %cleanwin
+ wrpr %g1, 0x0, %cleanwin
retry
kern_rtt: restore
retry
@@ -125,8 +126,8 @@ to_user: ldx [%g6 + AOFF_task_need_resched], %l0
wrpr %l7, PSTATE_IE, %pstate
orcc %g0, %l0, %g0
be,a,pt %xcc, check_signal
- lduw [%g6 + AOFF_task_sigpending], %l0
+ lduw [%g6 + AOFF_task_sigpending], %l0
call schedule
nop
lduw [%g6 + AOFF_task_sigpending], %l0
@@ -146,7 +147,7 @@ check_signal: brz,a,pt %l0, check_user_wins
*/
check_user_wins:
wrpr %l7, 0x0, %pstate
- lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2
brz,pt %o2, 1f
sethi %hi(TSTATE_PEF), %l6
@@ -162,8 +163,8 @@ check_user_wins:
call rtrap_check
add %sp, STACK_BIAS + REGWIN_SZ, %o0
#endif
- lduh [%g6 + AOFF_task_tss + AOFF_thread_flags], %l5
- andcc %l5, 0x200, %g0
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %l5
+ andcc %l5, SPARC_FLAG_PERFCTR, %g0
be,pt %xcc, 1f
nop
@@ -172,7 +173,7 @@ check_user_wins:
call update_perfctrs
nop
wrpr %l7, 0x0, %pstate
- lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2
brz,pt %o2, 1f
sethi %hi(TSTATE_PEF), %l6
wrpr %l7, PSTATE_IE, %pstate
@@ -182,14 +183,14 @@ check_user_wins:
1:
andcc %l1, %l6, %g0
be,pt %xcc, rt_continue
- stb %g0, [%g6 + AOFF_task_tss + AOFF_thread_fpdepth] ! This is neccessary for non-syscall rtraps only
+ stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] ! This is neccessary for non-syscall rtraps only
rd %fprs, %l5
andcc %l5, FPRS_FEF, %g0
be,a,pn %icc, rt_continue
andn %l1, %l6, %l1
- ba,pt %xcc, rt_continue+4
- lduh [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0
+ ba,pt %xcc, rt_continue
+ nop
5: wr %g0, FPRS_FEF, %fprs
membar #StoreLoad | #LoadLoad
@@ -201,6 +202,6 @@ check_user_wins:
1: membar #Sync
wr %g0, FPRS_DU, %fprs
ba,pt %xcc, rt_continue
- stb %l5, [%g6 + AOFF_task_tss + AOFF_thread_fpdepth]
+ stb %l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth]
#undef PTREGS_OFF
diff --git a/arch/sparc64/kernel/semaphore.c b/arch/sparc64/kernel/semaphore.c
new file mode 100644
index 000000000..f72aeedd6
--- /dev/null
+++ b/arch/sparc64/kernel/semaphore.c
@@ -0,0 +1,129 @@
+/* $Id: semaphore.c,v 1.1 1999/08/30 10:00:50 davem Exp $
+ * Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/sched.h>
+#include <asm/semaphore-helper.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit. ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore. The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+ wake_one_more(sem);
+ wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function. Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible. This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return. If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR \
+ struct task_struct *tsk = current; \
+ wait_queue_t wait; \
+ init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state) \
+ \
+ \
+ tsk->state = (task_state); \
+ add_wait_queue(&sem->wait, &wait); \
+ \
+ /* \
+ * Ok, we're set up. sem->count is known to be less than zero \
+ * so we must wait. \
+ * \
+ * We can let go the lock for purposes of waiting. \
+ * We re-acquire it after awaking so as to protect \
+ * all semaphore operations. \
+ * \
+ * If "up()" is called before we call waking_non_zero() then \
+ * we will catch it right away. If it is called later then \
+ * we will have to go through a wakeup cycle to catch it. \
+ * \
+ * Multiple waiters contend for the semaphore lock to see \
+ * who gets to gate through and who has to wait some more. \
+ */ \
+ for (;;) {
+
+#define DOWN_TAIL(task_state) \
+ tsk->state = (task_state); \
+ } \
+ tsk->state = TASK_RUNNING; \
+ remove_wait_queue(&sem->wait, &wait);
+
+void __down(struct semaphore * sem)
+{
+ DOWN_VAR
+ DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+ if (waking_non_zero(sem))
+ break;
+ schedule();
+ DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+ int ret = 0;
+ DOWN_VAR
+ DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+ ret = waking_non_zero_interruptible(sem, tsk);
+ if (ret)
+ {
+ if (ret == 1)
+ /* ret != 0 only if we get interrupted -arca */
+ ret = 0;
+ break;
+ }
+ schedule();
+ DOWN_TAIL(TASK_INTERRUPTIBLE)
+ return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+ return waking_non_zero_trylock(sem);
+}
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index d5e980ebf..066850108 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.44 1999/05/28 02:17:29 davem Exp $
+/* $Id: setup.c,v 1.47 1999/08/31 06:54:55 davem Exp $
* linux/arch/sparc64/kernel/setup.c
*
* Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
@@ -135,17 +135,21 @@ int prom_callback(long *args)
* Find process owning ctx, lookup mapping.
*/
struct task_struct *p;
+ struct mm_struct *mm = NULL;
pgd_t *pgdp;
pmd_t *pmdp;
pte_t *ptep;
- for_each_task(p)
- if (p->tss.ctx == ctx)
+ for_each_task(p) {
+ mm = p->mm;
+ if (CTX_HWBITS(mm->context) == ctx)
break;
- if (p->tss.ctx != ctx)
+ }
+ if (!mm ||
+ CTX_HWBITS(mm->context) != ctx)
goto done;
- pgdp = pgd_offset(p->mm, va);
+ pgdp = pgd_offset(mm, va);
if (pgd_none(*pgdp))
goto done;
pmdp = pmd_offset(pgdp, va);
@@ -312,7 +316,7 @@ int obp_system_intr(void)
* Process kernel command line switches that are specific to the
* SPARC or that require special low-level processing.
*/
-__initfunc(static void process_switch(char c))
+static void __init process_switch(char c)
{
switch (c) {
case 'd':
@@ -331,7 +335,7 @@ __initfunc(static void process_switch(char c))
}
}
-__initfunc(static void boot_flags_init(char *commands))
+static void __init boot_flags_init(char *commands)
{
while (*commands) {
/* Move to the start of the next "argument". */
@@ -434,8 +438,8 @@ static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
extern struct consw sun_serial_con;
-__initfunc(void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p))
+void __init setup_arch(char **cmdline_p,
+ unsigned long * memory_start_p, unsigned long * memory_end_p)
{
extern int serial_console; /* in console.c, of course */
unsigned long lowest_paddr, end_of_phys_memory = 0;
@@ -531,11 +535,10 @@ __initfunc(void setup_arch(char **cmdline_p,
#endif
/* Due to stack alignment restrictions and assumptions... */
- init_task.mm->mmap->vm_page_prot = PAGE_SHARED;
- init_task.mm->mmap->vm_start = PAGE_OFFSET;
- init_task.mm->mmap->vm_end = *memory_end_p;
- init_task.mm->context = (unsigned long) NO_CONTEXT;
- init_task.tss.kregs = &fake_swapper_regs;
+ init_mm.mmap->vm_page_prot = PAGE_SHARED;
+ init_mm.mmap->vm_start = PAGE_OFFSET;
+ init_mm.mmap->vm_end = *memory_end_p;
+ init_task.thread.kregs = &fake_swapper_regs;
#ifdef CONFIG_IP_PNP
if (!ic_set_manually) {
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index 247afc77c..672e83493 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.41 1999/06/14 05:23:58 davem Exp $
+/* $Id: signal.c,v 1.45 1999/09/06 08:21:59 jj Exp $
* arch/sparc64/kernel/signal.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
@@ -46,7 +46,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
asmlinkage void sparc64_set_context(struct pt_regs *regs)
{
struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0];
- struct thread_struct *tp = &current->tss;
+ struct thread_struct *tp = &current->thread;
mc_gregset_t *grp;
unsigned long pc, npc, tstate;
unsigned long fp, i7;
@@ -123,9 +123,9 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
err |= copy_from_user(fpregs+16,
((unsigned long *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16,
(sizeof(unsigned int) * 32));
- err |= __get_user(current->tss.xfsr[0],
+ err |= __get_user(current->thread.xfsr[0],
&(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
- err |= __get_user(current->tss.gsr[0],
+ err |= __get_user(current->thread.gsr[0],
&(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
regs->tstate &= ~TSTATE_PEF;
}
@@ -141,7 +141,7 @@ do_sigsegv:
asmlinkage void sparc64_get_context(struct pt_regs *regs)
{
struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0];
- struct thread_struct *tp = &current->tss;
+ struct thread_struct *tp = &current->thread;
mc_gregset_t *grp;
mcontext_t *mcp;
unsigned long fp, i7;
@@ -155,7 +155,7 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs)
#if 1
fenab = 0; /* IMO get_context is like any other system call, thus modifies FPU state -jj */
#else
- fenab = (current->tss.fpsaved[0] & FPRS_FEF);
+ fenab = (current->thread.fpsaved[0] & FPRS_FEF);
#endif
mcp = &ucp->uc_mcontext;
@@ -205,7 +205,7 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs)
unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
unsigned long fprs;
- fprs = current->tss.fpsaved[0];
+ fprs = current->thread.fpsaved[0];
if (fprs & FPRS_DL)
err |= copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs,
(sizeof(unsigned int) * 32));
@@ -213,8 +213,8 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs)
err |= copy_to_user(
((unsigned long *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16,
(sizeof(unsigned int) * 32));
- err |= __put_user(current->tss.xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr));
- err |= __put_user(current->tss.gsr[0], &(mcp->mc_fpregs.mcfpu_gsr));
+ err |= __put_user(current->thread.xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr));
+ err |= __put_user(current->thread.gsr[0], &(mcp->mc_fpregs.mcfpu_gsr));
err |= __put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs));
}
if (err)
@@ -226,34 +226,17 @@ do_sigsegv:
do_exit(SIGSEGV);
}
-/*
- * The new signal frame, intended to be used for Linux applications only
- * (we have enough in there to work with clone).
- * All the interesting bits are in the info field.
- */
-
-struct new_signal_frame {
- struct sparc_stackf ss;
- __siginfo_t info;
- __siginfo_fpu_t * fpu_save;
- unsigned int insns [2];
- unsigned long extramask[_NSIG_WORDS-1];
- __siginfo_fpu_t fpu_state;
-};
-
struct rt_signal_frame {
struct sparc_stackf ss;
siginfo_t info;
struct pt_regs regs;
- sigset_t mask;
__siginfo_fpu_t * fpu_save;
- unsigned int insns [2];
stack_t stack;
+ sigset_t mask;
__siginfo_fpu_t fpu_state;
};
/* Align macros */
-#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7)))
#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
/*
@@ -265,7 +248,7 @@ asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs)
sigset_t saveset;
#ifdef CONFIG_SPARC32_COMPAT
- if (current->tss.flags & SPARC_FLAG_32BIT) {
+ if (current->thread.flags & SPARC_FLAG_32BIT) {
extern asmlinkage void _sigpause32_common(old_sigset_t32,
struct pt_regs *);
_sigpause32_common(set, regs);
@@ -372,65 +355,12 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
if (fprs & FPRS_DU)
err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],
(sizeof(unsigned int) * 32));
- err |= __get_user(current->tss.xfsr[0], &fpu->si_fsr);
- err |= __get_user(current->tss.gsr[0], &fpu->si_gsr);
- current->tss.fpsaved[0] |= fprs;
+ err |= __get_user(current->thread.xfsr[0], &fpu->si_fsr);
+ err |= __get_user(current->thread.gsr[0], &fpu->si_gsr);
+ current->thread.fpsaved[0] |= fprs;
return err;
}
-void do_sigreturn(struct pt_regs *regs)
-{
- struct new_signal_frame *sf;
- unsigned long tpc, tnpc, tstate;
- __siginfo_fpu_t *fpu_save;
- sigset_t set;
- int err;
-
- synchronize_user_stack ();
- sf = (struct new_signal_frame *)
- (regs->u_regs [UREG_FP] + STACK_BIAS);
-
- /* 1. Make sure we are not getting garbage from the user */
- if (((unsigned long) sf) & 3)
- goto segv;
-
- err = get_user(tpc, &sf->info.si_regs.tpc);
- err |= __get_user(tnpc, &sf->info.si_regs.tnpc);
- err |= ((tpc | tnpc) & 3);
-
- /* 2. Restore the state */
- err |= __get_user(regs->y, &sf->info.si_regs.y);
- err |= __get_user(tstate, &sf->info.si_regs.tstate);
- err |= copy_from_user(regs->u_regs, sf->info.si_regs.u_regs, sizeof(regs->u_regs));
-
- /* User can only change condition codes in %tstate. */
- regs->tstate &= ~(TSTATE_ICC);
- regs->tstate |= (tstate & TSTATE_ICC);
-
- err |= __get_user(fpu_save, &sf->fpu_save);
- if (fpu_save)
- err |= restore_fpu_state(regs, &sf->fpu_state);
-
- err |= __get_user(set.sig[0], &sf->info.si_mask);
- if (_NSIG_WORDS > 1)
- err |= __copy_from_user(&set.sig[1], &sf->extramask, sizeof(sf->extramask));
-
- if (err)
- goto segv;
-
- regs->tpc = tpc;
- regs->tnpc = tnpc;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sigmask_lock);
- current->blocked = set;
- recalc_sigpending(current);
- spin_unlock_irq(&current->sigmask_lock);
- return;
-segv:
- send_sig(SIGSEGV, current, 1);
-}
-
void do_rt_sigreturn(struct pt_regs *regs)
{
struct rt_signal_frame *sf;
@@ -503,15 +433,15 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
unsigned long fprs;
int err = 0;
- fprs = current->tss.fpsaved[0];
+ fprs = current->thread.fpsaved[0];
if (fprs & FPRS_DL)
err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
(sizeof(unsigned int) * 32));
if (fprs & FPRS_DU)
err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
(sizeof(unsigned int) * 32));
- err |= __put_user(current->tss.xfsr[0], &fpu->si_fsr);
- err |= __put_user(current->tss.gsr[0], &fpu->si_gsr);
+ err |= __put_user(current->thread.xfsr[0], &fpu->si_fsr);
+ err |= __put_user(current->thread.gsr[0], &fpu->si_gsr);
err |= __put_user(fprs, &fpu->si_fprs);
return err;
@@ -533,77 +463,6 @@ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, u
}
static inline void
-new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
- int signo, sigset_t *oldset)
-{
- struct new_signal_frame *sf;
- int sigframe_size, err;
-
- /* 1. Make sure everything is clean */
- synchronize_user_stack();
- save_and_clear_fpu();
-
- sigframe_size = NF_ALIGNEDSZ;
-
- if (!(current->tss.fpsaved[0] & FPRS_FEF))
- sigframe_size -= sizeof(__siginfo_fpu_t);
-
- sf = (struct new_signal_frame *)get_sigframe(ka, regs, sigframe_size);
-
- if (invalid_frame_pointer (sf, sigframe_size))
- goto sigill;
-
- if (current->tss.w_saved != 0) {
-#ifdef DEBUG_SIGNALS
- printk ("%s[%d]: Invalid user stack frame for "
- "signal delivery.\n", current->comm, current->pid);
-#endif
- goto sigill;
- }
-
- /* 2. Save the current process state */
- err = copy_to_user(&sf->info.si_regs, regs, sizeof (*regs));
-
- if (current->tss.fpsaved[0] & FPRS_FEF) {
- err |= save_fpu_state(regs, &sf->fpu_state);
- err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
- } else {
- err |= __put_user(0, &sf->fpu_save);
- }
-
- err |= __put_user(oldset->sig[0], &sf->info.si_mask);
- if (_NSIG_WORDS > 1)
- err |= __copy_to_user(sf->extramask, &oldset->sig[1],
- sizeof(sf->extramask));
-
- err |= copy_in_user((u64 *)sf,
- (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS),
- sizeof(struct reg_window));
- if (err)
- goto sigsegv;
-
- /* 3. signal handler back-trampoline and parameters */
- regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS;
- regs->u_regs[UREG_I0] = signo;
- regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
-
- /* 5. signal handler */
- regs->tpc = (unsigned long) ka->sa.sa_handler;
- regs->tnpc = (regs->tpc + 4);
-
- /* 4. return to kernel instructions */
- regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
- return;
-
-sigill:
- lock_kernel();
- do_exit(SIGILL);
-sigsegv:
- lock_kernel();
- do_exit(SIGSEGV);
-}
-
-static inline void
setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
int signo, sigset_t *oldset, siginfo_t *info)
{
@@ -615,7 +474,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
save_and_clear_fpu();
sigframe_size = RT_ALIGNEDSZ;
- if (!(current->tss.fpsaved[0] & FPRS_FEF))
+ if (!(current->thread.fpsaved[0] & FPRS_FEF))
sigframe_size -= sizeof(__siginfo_fpu_t);
sf = (struct rt_signal_frame *)get_sigframe(ka, regs, sigframe_size);
@@ -623,7 +482,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
if (invalid_frame_pointer (sf, sigframe_size))
goto sigill;
- if (current->tss.w_saved != 0) {
+ if (current->thread.w_saved != 0) {
#ifdef DEBUG_SIGNALS
printk ("%s[%d]: Invalid user stack frame for "
"signal delivery.\n", current->comm, current->pid);
@@ -634,7 +493,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
/* 2. Save the current process state */
err = copy_to_user(&sf->regs, regs, sizeof (*regs));
- if (current->tss.fpsaved[0] & FPRS_FEF) {
+ if (current->thread.fpsaved[0] & FPRS_FEF) {
err |= save_fpu_state(regs, &sf->fpu_state);
err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
} else {
@@ -652,7 +511,12 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
(u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS),
sizeof(struct reg_window));
- err |= copy_to_user(&sf->info, info, sizeof(siginfo_t));
+ if (info)
+ err |= copy_to_user(&sf->info, info, sizeof(siginfo_t));
+ else {
+ err |= __put_user(signo, &sf->info.si_signo);
+ err |= __put_user(SI_NOINFO, &sf->info.si_code);
+ }
if (err)
goto sigsegv;
@@ -681,10 +545,7 @@ static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs)
{
- if(ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(ka, regs, signr, oldset, info);
- else
- new_setup_frame(ka, regs, signr, oldset);
+ setup_rt_frame(ka, regs, signr, oldset, (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
if(ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
if(!(ka->sa.sa_flags & SA_NOMASK)) {
@@ -785,7 +646,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
oldset = &current->blocked;
#ifdef CONFIG_SPARC32_COMPAT
- if (current->tss.flags & SPARC_FLAG_32BIT) {
+ if (current->thread.flags & SPARC_FLAG_32BIT) {
extern asmlinkage int do_signal32(sigset_t *, struct pt_regs *,
unsigned long, int);
return do_signal32(oldset, regs, orig_i0, restart_syscall);
@@ -866,12 +727,8 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS:
- if(current->binfmt && current->binfmt->core_dump) {
- lock_kernel();
- if(current->binfmt->core_dump(signr, regs))
- exit_code |= 0x80;
- unlock_kernel();
- }
+ if (do_coredump(signr, regs))
+ exit_code |= 0x80;
#ifdef DEBUG_SIGNALS
/* Very useful to debug the dynamic linker */
printk ("Sig %d going...\n", (int)signr);
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index b1190d244..59388286f 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -1,4 +1,4 @@
-/* $Id: signal32.c,v 1.48 1999/06/14 05:24:01 davem Exp $
+/* $Id: signal32.c,v 1.50 1999/07/30 09:35:25 davem Exp $
* arch/sparc64/kernel/signal32.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
@@ -202,9 +202,9 @@ static inline int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu
err |= copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 32));
if (fprs & FPRS_DU)
err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], (sizeof(unsigned int) * 32));
- err |= __get_user(current->tss.xfsr[0], &fpu->si_fsr);
- err |= __get_user(current->tss.gsr[0], &fpu->si_gsr);
- current->tss.fpsaved[0] |= fprs;
+ err |= __get_user(current->thread.xfsr[0], &fpu->si_fsr);
+ err |= __get_user(current->thread.gsr[0], &fpu->si_gsr);
+ current->thread.fpsaved[0] |= fprs;
return err;
}
@@ -285,7 +285,7 @@ asmlinkage void do_sigreturn32(struct pt_regs *regs)
int err;
synchronize_user_stack();
- if (current->tss.new_signal)
+ if (current->thread.flags & SPARC_FLAG_NEWSIGNALS)
return do_new_sigreturn32(regs);
scptr = (struct sigcontext32 *)
@@ -489,20 +489,20 @@ setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
err |= __put_user(pc, &sc->sigc_pc);
err |= __put_user(npc, &sc->sigc_npc);
psr = tstate_to_psr (regs->tstate);
- if(current->tss.fpsaved[0] & FPRS_FEF)
+ if(current->thread.fpsaved[0] & FPRS_FEF)
psr |= PSR_EF;
err |= __put_user(psr, &sc->sigc_psr);
err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
- err |= __put_user(current->tss.w_saved, &sc->sigc_oswins);
+ err |= __put_user(current->thread.w_saved, &sc->sigc_oswins);
#if 0
/* w_saved is not currently used... */
- if(current->tss.w_saved)
- for(window = 0; window < current->tss.w_saved; window++) {
+ if(current->thread.w_saved)
+ for(window = 0; window < current->thread.w_saved; window++) {
sc->sigc_spbuf[window] =
- (char *)current->tss.rwbuf_stkptrs[window];
+ (char *)current->thread.rwbuf_stkptrs[window];
err |= copy_to_user(&sc->sigc_wbuf[window],
- &current->tss.reg_window[window],
+ &current->thread.reg_window[window],
sizeof(struct reg_window));
}
else
@@ -511,15 +511,15 @@ setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
(u32 *)(regs->u_regs[UREG_FP]),
sizeof(struct reg_window32));
- current->tss.w_saved = 0; /* So process is allowed to execute. */
+ current->thread.w_saved = 0; /* So process is allowed to execute. */
err |= __put_user(signr, &sframep->sig_num);
if(signr == SIGSEGV ||
signr == SIGILL ||
signr == SIGFPE ||
signr == SIGBUS ||
signr == SIGEMT) {
- err |= __put_user(current->tss.sig_desc, &sframep->sig_code);
- err |= __put_user(current->tss.sig_address, &sframep->sig_address);
+ err |= __put_user(current->thread.sig_desc, &sframep->sig_code);
+ err |= __put_user(current->thread.sig_address, &sframep->sig_address);
} else {
err |= __put_user(0, &sframep->sig_code);
err |= __put_user(0, &sframep->sig_address);
@@ -544,15 +544,15 @@ static inline int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu)
unsigned long fprs;
int err = 0;
- fprs = current->tss.fpsaved[0];
+ fprs = current->thread.fpsaved[0];
if (fprs & FPRS_DL)
err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
(sizeof(unsigned int) * 32));
if (fprs & FPRS_DU)
err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
(sizeof(unsigned int) * 32));
- err |= __put_user(current->tss.xfsr[0], &fpu->si_fsr);
- err |= __put_user(current->tss.gsr[0], &fpu->si_gsr);
+ err |= __put_user(current->thread.xfsr[0], &fpu->si_fsr);
+ err |= __put_user(current->thread.gsr[0], &fpu->si_gsr);
err |= __put_user(fprs, &fpu->si_fprs);
return err;
@@ -572,7 +572,7 @@ static inline void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *reg
save_and_clear_fpu();
sigframe_size = NF_ALIGNEDSZ;
- if (!(current->tss.fpsaved[0] & FPRS_FEF))
+ if (!(current->thread.fpsaved[0] & FPRS_FEF))
sigframe_size -= sizeof(__siginfo_fpu_t);
sf = (struct new_signal_frame32 *)get_sigframe(&ka->sa, regs, sigframe_size);
@@ -585,7 +585,7 @@ static inline void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *reg
goto sigill;
}
- if (current->tss.w_saved != 0) {
+ if (current->thread.w_saved != 0) {
#ifdef DEBUG_SIGNALS
printk ("%s[%d]: Invalid user stack frame for "
"signal delivery.\n", current->comm, current->pid);
@@ -598,7 +598,7 @@ static inline void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *reg
err |= __put_user(regs->tnpc, &sf->info.si_regs.npc);
err |= __put_user(regs->y, &sf->info.si_regs.y);
psr = tstate_to_psr (regs->tstate);
- if(current->tss.fpsaved[0] & FPRS_FEF)
+ if(current->thread.fpsaved[0] & FPRS_FEF)
psr |= PSR_EF;
err |= __put_user(psr, &sf->info.si_regs.psr);
for (i = 0; i < 16; i++)
@@ -738,7 +738,7 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
err |= __put_user(regs->tpc, &((*gr) [SVR4_PC]));
err |= __put_user(regs->tnpc, &((*gr) [SVR4_NPC]));
psr = tstate_to_psr (regs->tstate);
- if(current->tss.fpsaved[0] & FPRS_FEF)
+ if(current->thread.fpsaved[0] & FPRS_FEF)
psr |= PSR_EF;
err |= __put_user(psr, &((*gr) [SVR4_PSR]));
err |= __put_user(regs->y, &((*gr) [SVR4_Y]));
@@ -760,7 +760,7 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
err |= __put_user((u32)(long)gw, &mc->gwin);
/* 2. Number of windows to restore at setcontext (): */
- err |= __put_user(current->tss.w_saved, &gw->count);
+ err |= __put_user(current->thread.w_saved, &gw->count);
/* 3. Save each valid window
* Currently, it makes a copy of the windows from the kernel copy.
@@ -774,23 +774,23 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
* to flush the user windows.
*/
#if 0
- for(window = 0; window < current->tss.w_saved; window++) {
+ for(window = 0; window < current->thread.w_saved; window++) {
err |= __put_user((int *) &(gw->win [window]),
(int **)gw->winptr +window );
err |= copy_to_user(&gw->win [window],
- &current->tss.reg_window [window],
+ &current->thread.reg_window [window],
sizeof (svr4_rwindow_t));
err |= __put_user(0, (int *)gw->winptr + window);
}
#endif
/* 4. We just pay attention to the gw->count field on setcontext */
- current->tss.w_saved = 0; /* So process is allowed to execute. */
+ current->thread.w_saved = 0; /* So process is allowed to execute. */
/* Setup the signal information. Solaris expects a bunch of
* information to be passed to the signal handler, we don't provide
* that much currently, should use those that David already
- * is providing with tss.sig_desc
+ * is providing with thread.sig_desc
*/
err |= __put_user(signr, &si->siginfo.signo);
err |= __put_user(SVR4_SINOINFO, &si->siginfo.code);
@@ -837,8 +837,8 @@ svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs)
synchronize_user_stack();
save_and_clear_fpu();
- if (current->tss.w_saved){
- printk ("Uh oh, w_saved is not zero (%d)\n", (int) current->tss.w_saved);
+ if (current->thread.w_saved){
+ printk ("Uh oh, w_saved is not zero (%d)\n", (int) current->thread.w_saved);
do_exit (SIGSEGV);
}
err = clear_user(uc, sizeof (*uc));
@@ -863,7 +863,7 @@ svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs)
err |= __put_user(0, &uc->mcontext.greg [SVR4_PSR]);
#else
i = tstate_to_psr(regs->tstate) & ~PSR_EF;
- if (current->tss.fpsaved[0] & FPRS_FEF)
+ if (current->thread.fpsaved[0] & FPRS_FEF)
i |= PSR_EF;
err |= __put_user(i, &uc->mcontext.greg [SVR4_PSR]);
#endif
@@ -890,7 +890,7 @@ svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs)
/* Set the context for a svr4 application, this is Solaris way to sigreturn */
asmlinkage int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs)
{
- struct thread_struct *tp = &current->tss;
+ struct thread_struct *tp = &current->thread;
svr4_gregset_t *gr;
u32 pc, npc, psr;
sigset_t set;
@@ -990,7 +990,7 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs
save_and_clear_fpu();
sigframe_size = RT_ALIGNEDSZ;
- if (!(current->tss.fpsaved[0] & FPRS_FEF))
+ if (!(current->thread.fpsaved[0] & FPRS_FEF))
sigframe_size -= sizeof(__siginfo_fpu_t);
sf = (struct rt_signal_frame32 *)get_sigframe(&ka->sa, regs, sigframe_size);
@@ -1003,7 +1003,7 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs
goto sigill;
}
- if (current->tss.w_saved != 0) {
+ if (current->thread.w_saved != 0) {
#ifdef DEBUG_SIGNALS
printk ("%s[%d]: Invalid user stack frame for "
"signal delivery.\n", current->comm, current->pid);
@@ -1016,7 +1016,7 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs
err |= __put_user(regs->tnpc, &sf->regs.npc);
err |= __put_user(regs->y, &sf->regs.y);
psr = tstate_to_psr (regs->tstate);
- if(current->tss.fpsaved[0] & FPRS_FEF)
+ if(current->thread.fpsaved[0] & FPRS_FEF)
psr |= PSR_EF;
err |= __put_user(psr, &sf->regs.psr);
for (i = 0; i < 16; i++)
@@ -1032,6 +1032,42 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs
} else {
err |= __put_user(0, &sf->fpu_save);
}
+
+ err = __put_user (info->si_signo, &sf->info.si_signo);
+ err |= __put_user (info->si_errno, &sf->info.si_errno);
+ err |= __put_user (info->si_code, &sf->info.si_code);
+ if (info->si_code < 0)
+ err |= __copy_to_user (sf->info._sifields._pad, info->_sifields._pad, SI_PAD_SIZE);
+ else {
+ i = info->si_signo;
+ if (info->si_code == SI_USER)
+ i = SIGRTMIN;
+ switch (i) {
+ case SIGPOLL:
+ err |= __put_user (info->si_band, &sf->info.si_band);
+ err |= __put_user (info->si_fd, &sf->info.si_fd);
+ break;
+ case SIGCHLD:
+ err |= __put_user (info->si_pid, &sf->info.si_pid);
+ err |= __put_user (info->si_uid, &sf->info.si_uid);
+ err |= __put_user (info->si_status, &sf->info.si_status);
+ err |= __put_user (info->si_utime, &sf->info.si_utime);
+ err |= __put_user (info->si_stime, &sf->info.si_stime);
+ break;
+ case SIGSEGV:
+ case SIGILL:
+ case SIGFPE:
+ case SIGBUS:
+ case SIGEMT:
+ err |= __put_user ((long)info->si_addr, &sf->info.si_addr);
+ err |= __put_user (info->si_trapno, &sf->info.si_trapno);
+ break;
+ default:
+ err |= __put_user (info->si_pid, &sf->info.si_pid);
+ err |= __put_user (info->si_uid, &sf->info.si_uid);
+ break;
+ }
+ }
/* Setup sigaltstack */
err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
@@ -1040,13 +1076,13 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs
switch (_NSIG_WORDS) {
case 4: seta.sig[7] = (oldset->sig[3] >> 32);
- seta.sig[6] = oldset->sig[3];
+ seta.sig[6] = oldset->sig[3];
case 3: seta.sig[5] = (oldset->sig[2] >> 32);
- seta.sig[4] = oldset->sig[2];
+ seta.sig[4] = oldset->sig[2];
case 2: seta.sig[3] = (oldset->sig[1] >> 32);
- seta.sig[2] = oldset->sig[1];
+ seta.sig[2] = oldset->sig[1];
case 1: seta.sig[1] = (oldset->sig[0] >> 32);
- seta.sig[0] = oldset->sig[0];
+ seta.sig[0] = oldset->sig[0];
}
err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t));
@@ -1113,7 +1149,7 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
else {
if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame32(ka, regs, signr, oldset, info);
- else if (current->tss.new_signal)
+ else if (current->thread.flags & SPARC_FLAG_NEWSIGNALS)
new_setup_frame32(ka, regs, signr, oldset);
else
setup_frame32(&ka->sa, regs->tpc, regs->tnpc, regs, signr, oldset);
@@ -1256,13 +1292,13 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs * regs,
if(signr != SIGCHLD)
continue;
- /* sys_wait4() grabs the master kernel lock, so
- * we need not do so, that sucker should be
- * threaded and would not be that difficult to
- * do anyways.
- */
- while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
- ;
+ /* sys_wait4() grabs the master kernel lock, so
+ * we need not do so, that sucker should be
+ * threaded and would not be that difficult to
+ * do anyways.
+ */
+ while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+ ;
continue;
}
if(ka->sa.sa_handler == SIG_DFL) {
@@ -1291,14 +1327,8 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs * regs,
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS:
- if(current->binfmt && current->binfmt->core_dump) {
- lock_kernel();
- if(current->binfmt &&
- current->binfmt->core_dump &&
- current->binfmt->core_dump(signr, regs))
- exit_code |= 0x80;
- unlock_kernel();
- }
+ if (do_coredump(signr, regs))
+ exit_code |= 0x80;
#ifdef DEBUG_SIGNALS
/* Very useful to debug dynamic linker problems */
printk ("Sig %ld going for %s[%d]...\n", signr, current->comm, current->pid);
@@ -1318,10 +1348,10 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs * regs,
{
struct reg_window32 *rw = (struct reg_window32 *)(regs->u_regs[UREG_FP] & 0xffffffff);
unsigned int ins[8];
-
+
while(rw &&
!(((unsigned long) rw) & 0x3)) {
- copy_from_user(ins, &rw->ins[0], sizeof(ins));
+ copy_from_user(ins, &rw->ins[0], sizeof(ins));
printk("Caller[%08x](%08x,%08x,%08x,%08x,%08x,%08x)\n", ins[7], ins[0], ins[1], ins[2], ins[3], ins[4], ins[5]);
rw = (struct reg_window32 *)(unsigned long)ins[6];
}
@@ -1380,7 +1410,7 @@ asmlinkage int do_sys32_sigstack(u32 u_ssptr, u32 u_ossptr, unsigned long sp)
/* Now see if we want to update the new state. */
if (ssptr) {
void *ss_sp;
-
+
if (get_user((long)ss_sp, &ssptr->the_stack))
goto out;
/* If the current stack was set with sigaltstack, don't
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index a0e8f7e69..d1adeb2c7 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -7,13 +7,14 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
-#include <linux/tasks.h>
+#include <linux/threads.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/spinlock.h>
#include <asm/head.h>
#include <asm/ptrace.h>
@@ -23,7 +24,6 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/oplib.h>
-#include <asm/spinlock.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
#include <asm/uaccess.h>
@@ -53,7 +53,7 @@ unsigned long cpu_present_map = 0;
int smp_num_cpus = 1;
int smp_threads_ready = 0;
-__initfunc(void smp_setup(char *str, int *ints))
+void __init smp_setup(char *str, int *ints)
{
/* XXX implement me XXX */
}
@@ -83,7 +83,7 @@ int smp_bogo(char *buf)
return len;
}
-__initfunc(void smp_store_cpu_info(int id))
+void __init smp_store_cpu_info(int id)
{
int i;
@@ -103,7 +103,7 @@ __initfunc(void smp_store_cpu_info(int id))
cpu_data[id].irq_worklists[i] = 0;
}
-__initfunc(void smp_commence(void))
+void __init smp_commence(void)
{
}
@@ -115,7 +115,7 @@ static volatile unsigned long callin_flag = 0;
extern void inherit_locked_prom_mappings(int save_p);
extern void cpu_probe(void);
-__initfunc(void smp_callin(void))
+void __init smp_callin(void)
{
int cpuid = hard_smp_processor_id();
@@ -151,13 +151,17 @@ __initfunc(void smp_callin(void))
/* Clear this or we will die instantly when we
* schedule back to this idler...
*/
- current->tss.flags &= ~(SPARC_FLAG_NEWCHILD);
+ current->thread.flags &= ~(SPARC_FLAG_NEWCHILD);
+
+ /* Attach to the address space of init_task. */
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
while(!smp_processors_ready)
membar("#LoadLoad");
}
-extern int cpu_idle(void *unused);
+extern int cpu_idle(void);
extern void init_IRQ(void);
void initialize_secondary(void)
@@ -169,7 +173,7 @@ int start_secondary(void *unused)
trap_init();
init_IRQ();
smp_callin();
- return cpu_idle(NULL);
+ return cpu_idle();
}
void cpu_panic(void)
@@ -188,7 +192,7 @@ extern unsigned long smp_trampoline;
*/
static struct task_struct *cpu_new_task = NULL;
-__initfunc(void smp_boot_cpus(void))
+void __init smp_boot_cpus(void)
{
int cpucount = 0, i;
@@ -216,9 +220,17 @@ __initfunc(void smp_boot_cpus(void))
entry += phys_base - KERNBASE;
cookie += phys_base - KERNBASE;
kernel_thread(start_secondary, NULL, CLONE_PID);
- p = task[++cpucount];
+ cpucount++;
+
+ p = init_task.prev_task;
+ init_tasks[cpucount] = p;
+
p->processor = i;
p->has_cpu = 1; /* we schedule the first task manually */
+
+ del_from_runqueue(p);
+ unhash_process(p);
+
callin_flag = 0;
for (no = 0; no < linux_num_cpus; no++)
if (linux_cpus[no].mid == i)
@@ -384,6 +396,9 @@ void smp_flush_tlb_all(void)
* are flush_tlb_*() routines, and these run after flush_cache_*()
* which performs the flushw.
*
+ * XXX I diked out the fancy flush avoidance code for the
+ * XXX swapping cases for now until the new MM code stabilizes. -DaveM
+ *
* The SMP TLB coherency scheme we use works as follows:
*
* 1) mm->cpu_vm_mask is a bit mask of which cpus an address
@@ -395,16 +410,16 @@ void smp_flush_tlb_all(void)
* cross calls.
*
* One invariant is that when a cpu switches to a process, and
- * that processes tsk->mm->cpu_vm_mask does not have the current
- * cpu's bit set, that tlb context is flushed locally.
+ * that processes tsk->active_mm->cpu_vm_mask does not have the
+ * current cpu's bit set, that tlb context is flushed locally.
*
* If the address space is non-shared (ie. mm->count == 1) we avoid
* cross calls when we want to flush the currently running process's
* tlb state. This is done by clearing all cpu bits except the current
- * processor's in current->mm->cpu_vm_mask and performing the flush
- * locally only. This will force any subsequent cpus which run this
- * task to flush the context from the local tlb if the process migrates
- * to another cpu (again).
+ * processor's in current->active_mm->cpu_vm_mask and performing the
+ * flush locally only. This will force any subsequent cpus which run
+ * this task to flush the context from the local tlb if the process
+ * migrates to another cpu (again).
*
* 3) For shared address spaces (threads) and swapping we bite the
* bullet for most cases and perform the cross call.
@@ -422,13 +437,13 @@ void smp_flush_tlb_all(void)
*/
void smp_flush_tlb_mm(struct mm_struct *mm)
{
- u32 ctx = mm->context & 0x3ff;
+ u32 ctx = CTX_HWBITS(mm->context);
- if(mm == current->mm && atomic_read(&mm->count) == 1) {
- if(mm->cpu_vm_mask != (1UL << smp_processor_id()))
- mm->cpu_vm_mask = (1UL << smp_processor_id());
+ if (mm == current->active_mm &&
+ atomic_read(&mm->mm_users) == 1 &&
+ (mm->cpu_vm_mask == (1UL << smp_processor_id())))
goto local_flush_and_out;
- }
+
smp_cross_call(&xcall_flush_tlb_mm, ctx, 0, 0);
local_flush_and_out:
@@ -438,15 +453,15 @@ local_flush_and_out:
void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start,
unsigned long end)
{
- u32 ctx = mm->context & 0x3ff;
+ u32 ctx = CTX_HWBITS(mm->context);
start &= PAGE_MASK;
end &= PAGE_MASK;
- if(mm == current->mm && atomic_read(&mm->count) == 1) {
- if(mm->cpu_vm_mask != (1UL << smp_processor_id()))
- mm->cpu_vm_mask = (1UL << smp_processor_id());
+ if(mm == current->active_mm &&
+ atomic_read(&mm->mm_users) == 1 &&
+ (mm->cpu_vm_mask == (1UL << smp_processor_id())))
goto local_flush_and_out;
- }
+
smp_cross_call(&xcall_flush_tlb_range, ctx, start, end);
local_flush_and_out:
@@ -455,30 +470,15 @@ local_flush_and_out:
void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page)
{
- u32 ctx = mm->context & 0x3ff;
+ u32 ctx = CTX_HWBITS(mm->context);
page &= PAGE_MASK;
- if(mm == current->mm && atomic_read(&mm->count) == 1) {
- if(mm->cpu_vm_mask != (1UL << smp_processor_id()))
- mm->cpu_vm_mask = (1UL << smp_processor_id());
+ if(mm == current->active_mm &&
+ atomic_read(&mm->mm_users) == 1 &&
+ (mm->cpu_vm_mask == (1UL << smp_processor_id()))) {
goto local_flush_and_out;
- } else {
- /* Try to handle two special cases to avoid cross calls
- * in common scenerios where we are swapping process
- * pages out.
- */
- if(((mm->context ^ tlb_context_cache) & CTX_VERSION_MASK) ||
- (mm->cpu_vm_mask == 0)) {
- /* A dead context cannot ever become "alive" until
- * a task switch is done to it.
- */
- return; /* It's dead, nothing to do. */
- }
- if(mm->cpu_vm_mask == (1UL << smp_processor_id())) {
- __flush_tlb_page(ctx, page, SECONDARY_CONTEXT);
- return; /* Only local flush is necessary. */
- }
}
+
smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0);
local_flush_and_out:
@@ -547,10 +547,18 @@ void smp_penguin_jailcell(void)
atomic_dec(&smp_capture_registry);
}
-static inline void sparc64_do_profile(unsigned long pc)
+static inline void sparc64_do_profile(unsigned long pc, unsigned long g3)
{
if (prof_buffer && current->pid) {
extern int _stext;
+ extern int rwlock_impl_begin, rwlock_impl_end;
+ extern int atomic_impl_begin, atomic_impl_end;
+
+ if ((pc >= (unsigned long) &rwlock_impl_begin &&
+ pc < (unsigned long) &rwlock_impl_end) ||
+ (pc >= (unsigned long) &atomic_impl_begin &&
+ pc < (unsigned long) &atomic_impl_end))
+ pc = g3;
pc -= (unsigned long) &_stext;
pc >>= prof_shift;
@@ -589,7 +597,7 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs)
clear_softint((1UL << 0));
do {
if(!user)
- sparc64_do_profile(regs->tpc);
+ sparc64_do_profile(regs->tpc, regs->u_regs[UREG_G3]);
if(!--prof_counter(cpu))
{
if (cpu == boot_cpu_id) {
@@ -647,7 +655,7 @@ do { hardirq_enter(cpu); \
} while (tick >= compare);
}
-__initfunc(static void smp_setup_percpu_timer(void))
+static void __init smp_setup_percpu_timer(void)
{
int cpu = smp_processor_id();
@@ -661,7 +669,7 @@ __initfunc(static void smp_setup_percpu_timer(void))
: "g1");
}
-__initfunc(void smp_tick_init(void))
+void __init smp_tick_init(void)
{
int i;
@@ -707,7 +715,7 @@ static inline unsigned long find_flush_base(unsigned long size)
cycles_t cacheflush_time;
-__initfunc(static void smp_tune_scheduling (void))
+static void __init smp_tune_scheduling (void)
{
unsigned long flush_base, flags, *p;
unsigned int ecache_size;
@@ -775,7 +783,8 @@ __initfunc(static void smp_tune_scheduling (void))
(int) cacheflush_time);
}
-int __init setup_profiling_timer(unsigned int multiplier)
+/* /proc/profile writes can call this, don't __init it please. */
+int setup_profiling_timer(unsigned int multiplier)
{
unsigned long flags;
int i;
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 91277fc4a..e57b8d6f7 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.60 1999/07/03 22:11:12 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.64 1999/09/05 09:33:38 ecd Exp $
* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -190,10 +190,9 @@ EXPORT_SYMBOL(dma_chain);
#endif
#if CONFIG_PCI
EXPORT_SYMBOL(ebus_chain);
-EXPORT_SYMBOL(pci_dvma_offset);
-EXPORT_SYMBOL(pci_dvma_mask);
EXPORT_SYMBOL(pci_dvma_v2p_hash);
EXPORT_SYMBOL(pci_dvma_p2v_hash);
+EXPORT_SYMBOL(pci_memspace_mask);
EXPORT_SYMBOL(empty_zero_page);
EXPORT_SYMBOL(outsb);
EXPORT_SYMBOL(outsw);
@@ -215,7 +214,6 @@ EXPORT_SYMBOL(die_if_kernel);
/* Kernel thread creation. */
EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(init_mm);
/* prom symbols */
EXPORT_SYMBOL(idprom);
diff --git a/arch/sparc64/kernel/starfire.c b/arch/sparc64/kernel/starfire.c
index 38f33ecd6..805dce338 100644
--- a/arch/sparc64/kernel/starfire.c
+++ b/arch/sparc64/kernel/starfire.c
@@ -1,4 +1,4 @@
-/* $Id: starfire.c,v 1.2 1998/12/09 18:53:11 davem Exp $
+/* $Id: starfire.c,v 1.3 1999/08/30 10:01:13 davem Exp $
* starfire.c: Starfire/E10000 support.
*
* Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
@@ -43,7 +43,7 @@ void starfire_check(void)
int starfire_hard_smp_processor_id(void)
{
- return *((unsigned int *) __va(0x1fff40000d0));
+ return *((volatile unsigned int *) __va(0x1fff40000d0));
}
/* Each Starfire board has 32 registers which perform translation
@@ -52,8 +52,8 @@ int starfire_hard_smp_processor_id(void)
* bits than in all previous Sun5 systems.
*/
struct starfire_irqinfo {
- unsigned int *imap_slots[32];
- unsigned int *tregs[32];
+ volatile unsigned int *imap_slots[32];
+ volatile unsigned int *tregs[32];
struct starfire_irqinfo *next;
int upaid, hwmid;
};
@@ -80,7 +80,7 @@ void *starfire_hookup(int upaid)
treg_base += 0x200UL;
for(i = 0; i < 32; i++) {
p->imap_slots[i] = NULL;
- p->tregs[i] = __va(treg_base + (i * 0x10));
+ p->tregs[i] = (volatile unsigned int *)__va(treg_base + (i * 0x10));
}
p->upaid = upaid;
p->next = sflist;
@@ -89,7 +89,7 @@ void *starfire_hookup(int upaid)
return (void *) p;
}
-unsigned int starfire_translate(unsigned int *imap,
+unsigned int starfire_translate(volatile unsigned int *imap,
unsigned int upaid)
{
struct starfire_irqinfo *p;
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 4906cea93..4e87819d4 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.27 1999/06/02 12:06:34 jj Exp $
+/* $Id: sys_sparc.c,v 1.29 1999/08/04 07:04:10 jj Exp $
* linux/arch/sparc64/kernel/sys_sparc.c
*
* This file contains various random system calls that
@@ -41,7 +41,9 @@ extern asmlinkage unsigned long sys_brk(unsigned long brk);
asmlinkage unsigned long sparc_brk(unsigned long brk)
{
- if(brk >= 0x80000000000UL) /* VM hole */
+ if((brk >= 0x80000000000UL && brk < PAGE_OFFSET) ||
+ (brk - current->mm->brk > 0x80000000000UL &&
+ brk - current->mm->brk < PAGE_OFFSET)) /* VM hole */
return current->mm->brk;
return sys_brk(brk);
}
@@ -170,7 +172,7 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
}
retval = -EINVAL;
- if (current->tss.flags & SPARC_FLAG_32BIT) {
+ if (current->thread.flags & SPARC_FLAG_32BIT) {
if (len > 0xf0000000UL || addr > 0xf0000000UL - len)
goto out_putf;
} else {
@@ -178,7 +180,7 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
(addr < 0x80000000000UL &&
addr > 0x80000000000UL-len))
goto out_putf;
- if (addr >= 0x80000000000ULL && addr < 0xfffff80000000000UL) {
+ if (addr >= 0x80000000000UL && addr < PAGE_OFFSET) {
/* VM hole */
retval = current->mm->brk;
goto out_putf;
@@ -281,40 +283,40 @@ asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p,
return -EINVAL;
if (new_p == (utrap_handler_t)(long)UTH_NOCHANGE) {
if (old_p) {
- if (!current->tss.utraps)
+ if (!current->thread.utraps)
put_user_ret(NULL, old_p, -EFAULT);
else
- put_user_ret((utrap_handler_t)(current->tss.utraps[type]), old_p, -EFAULT);
+ put_user_ret((utrap_handler_t)(current->thread.utraps[type]), old_p, -EFAULT);
}
if (old_d)
put_user_ret(NULL, old_d, -EFAULT);
return 0;
}
lock_kernel();
- if (!current->tss.utraps) {
- current->tss.utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL);
- if (!current->tss.utraps) return -ENOMEM;
- current->tss.utraps[0] = 1;
- memset(current->tss.utraps+1, 0, UT_TRAP_INSTRUCTION_31*sizeof(long));
+ if (!current->thread.utraps) {
+ current->thread.utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL);
+ if (!current->thread.utraps) return -ENOMEM;
+ current->thread.utraps[0] = 1;
+ memset(current->thread.utraps+1, 0, UT_TRAP_INSTRUCTION_31*sizeof(long));
} else {
- if ((utrap_handler_t)current->tss.utraps[type] != new_p && current->tss.utraps[0] > 1) {
- long *p = current->tss.utraps;
+ if ((utrap_handler_t)current->thread.utraps[type] != new_p && current->thread.utraps[0] > 1) {
+ long *p = current->thread.utraps;
- current->tss.utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL);
- if (!current->tss.utraps) {
- current->tss.utraps = p;
+ current->thread.utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL);
+ if (!current->thread.utraps) {
+ current->thread.utraps = p;
return -ENOMEM;
}
p[0]--;
- current->tss.utraps[0] = 1;
- memcpy(current->tss.utraps+1, p+1, UT_TRAP_INSTRUCTION_31*sizeof(long));
+ current->thread.utraps[0] = 1;
+ memcpy(current->thread.utraps+1, p+1, UT_TRAP_INSTRUCTION_31*sizeof(long));
}
}
if (old_p)
- put_user_ret((utrap_handler_t)(current->tss.utraps[type]), old_p, -EFAULT);
+ put_user_ret((utrap_handler_t)(current->thread.utraps[type]), old_p, -EFAULT);
if (old_d)
put_user_ret(NULL, old_d, -EFAULT);
- current->tss.utraps[type] = (long)new_p;
+ current->thread.utraps[type] = (long)new_p;
unlock_kernel();
return 0;
}
@@ -363,10 +365,10 @@ update_perfctrs(void)
unsigned long pic, tmp;
read_pic(pic);
- tmp = (current->tss.kernel_cntd0 += (unsigned int)pic);
- __put_user(tmp, current->tss.user_cntd0);
- tmp = (current->tss.kernel_cntd1 += (pic >> 32));
- __put_user(tmp, current->tss.user_cntd1);
+ tmp = (current->thread.kernel_cntd0 += (unsigned int)pic);
+ __put_user(tmp, current->thread.user_cntd0);
+ tmp = (current->thread.kernel_cntd1 += (pic >> 32));
+ __put_user(tmp, current->thread.user_cntd1);
reset_pic();
}
@@ -377,24 +379,24 @@ sys_perfctr(int opcode, unsigned long arg0, unsigned long arg1, unsigned long ar
switch(opcode) {
case PERFCTR_ON:
- current->tss.pcr_reg = arg2;
- current->tss.user_cntd0 = (u64 *) arg0;
- current->tss.user_cntd1 = (u64 *) arg1;
- current->tss.kernel_cntd0 =
- current->tss.kernel_cntd1 = 0;
+ current->thread.pcr_reg = arg2;
+ current->thread.user_cntd0 = (u64 *) arg0;
+ current->thread.user_cntd1 = (u64 *) arg1;
+ current->thread.kernel_cntd0 =
+ current->thread.kernel_cntd1 = 0;
write_pcr(arg2);
reset_pic();
- current->tss.flags |= SPARC_FLAG_PERFCTR;
+ current->thread.flags |= SPARC_FLAG_PERFCTR;
break;
case PERFCTR_OFF:
err = -EINVAL;
- if ((current->tss.flags & SPARC_FLAG_PERFCTR) != 0) {
- current->tss.user_cntd0 =
- current->tss.user_cntd1 = NULL;
- current->tss.pcr_reg = 0;
+ if ((current->thread.flags & SPARC_FLAG_PERFCTR) != 0) {
+ current->thread.user_cntd0 =
+ current->thread.user_cntd1 = NULL;
+ current->thread.pcr_reg = 0;
write_pcr(0);
- current->tss.flags &= ~(SPARC_FLAG_PERFCTR);
+ current->thread.flags &= ~(SPARC_FLAG_PERFCTR);
err = 0;
}
break;
@@ -402,50 +404,50 @@ sys_perfctr(int opcode, unsigned long arg0, unsigned long arg1, unsigned long ar
case PERFCTR_READ: {
unsigned long pic, tmp;
- if (!(current->tss.flags & SPARC_FLAG_PERFCTR)) {
+ if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) {
err = -EINVAL;
break;
}
read_pic(pic);
- tmp = (current->tss.kernel_cntd0 += (unsigned int)pic);
- err |= __put_user(tmp, current->tss.user_cntd0);
- tmp = (current->tss.kernel_cntd1 += (pic >> 32));
- err |= __put_user(tmp, current->tss.user_cntd1);
+ tmp = (current->thread.kernel_cntd0 += (unsigned int)pic);
+ err |= __put_user(tmp, current->thread.user_cntd0);
+ tmp = (current->thread.kernel_cntd1 += (pic >> 32));
+ err |= __put_user(tmp, current->thread.user_cntd1);
reset_pic();
break;
}
case PERFCTR_CLRPIC:
- if (!(current->tss.flags & SPARC_FLAG_PERFCTR)) {
+ if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) {
err = -EINVAL;
break;
}
- current->tss.kernel_cntd0 =
- current->tss.kernel_cntd1 = 0;
+ current->thread.kernel_cntd0 =
+ current->thread.kernel_cntd1 = 0;
reset_pic();
break;
case PERFCTR_SETPCR: {
u64 *user_pcr = (u64 *)arg0;
- if (!(current->tss.flags & SPARC_FLAG_PERFCTR)) {
+ if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) {
err = -EINVAL;
break;
}
- err |= __get_user(current->tss.pcr_reg, user_pcr);
- write_pcr(current->tss.pcr_reg);
- current->tss.kernel_cntd0 =
- current->tss.kernel_cntd1 = 0;
+ err |= __get_user(current->thread.pcr_reg, user_pcr);
+ write_pcr(current->thread.pcr_reg);
+ current->thread.kernel_cntd0 =
+ current->thread.kernel_cntd1 = 0;
reset_pic();
break;
}
case PERFCTR_GETPCR: {
u64 *user_pcr = (u64 *)arg0;
- if (!(current->tss.flags & SPARC_FLAG_PERFCTR)) {
+ if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) {
err = -EINVAL;
break;
}
- err |= __put_user(current->tss.pcr_reg, user_pcr);
+ err |= __put_user(current->thread.pcr_reg, user_pcr);
break;
}
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 0e42e2c32..a1e0f26dd 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.109 1999/06/03 07:11:31 davem Exp $
+/* $Id: sys_sparc32.c,v 1.118 1999/08/30 10:01:15 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -1663,85 +1663,6 @@ asmlinkage int sys32_rt_sigpending(sigset_t32 *set, __kernel_size_t32 sigsetsize
return ret;
}
-siginfo_t32 *
-siginfo64to32(siginfo_t32 *d, siginfo_t *s)
-{
- memset (&d, 0, sizeof(siginfo_t32));
- d->si_signo = s->si_signo;
- d->si_errno = s->si_errno;
- d->si_code = s->si_code;
- if (s->si_signo >= SIGRTMIN) {
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- /* XXX: Ouch, how to find this out??? */
- d->si_int = s->si_int;
- } else switch (s->si_signo) {
- /* XXX: What about POSIX1.b timers */
- case SIGCHLD:
- d->si_pid = s->si_pid;
- d->si_status = s->si_status;
- d->si_utime = s->si_utime;
- d->si_stime = s->si_stime;
- break;
- case SIGSEGV:
- case SIGBUS:
- case SIGFPE:
- case SIGILL:
- d->si_addr = (long)(s->si_addr);
- /* XXX: Do we need to translate this from sparc64 to sparc32 traps? */
- d->si_trapno = s->si_trapno;
- break;
- case SIGPOLL:
- d->si_band = s->si_band;
- d->si_fd = s->si_fd;
- break;
- default:
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- break;
- }
- return d;
-}
-
-siginfo_t *
-siginfo32to64(siginfo_t *d, siginfo_t32 *s)
-{
- d->si_signo = s->si_signo;
- d->si_errno = s->si_errno;
- d->si_code = s->si_code;
- if (s->si_signo >= SIGRTMIN) {
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- /* XXX: Ouch, how to find this out??? */
- d->si_int = s->si_int;
- } else switch (s->si_signo) {
- /* XXX: What about POSIX1.b timers */
- case SIGCHLD:
- d->si_pid = s->si_pid;
- d->si_status = s->si_status;
- d->si_utime = s->si_utime;
- d->si_stime = s->si_stime;
- break;
- case SIGSEGV:
- case SIGBUS:
- case SIGFPE:
- case SIGILL:
- d->si_addr = (void *)A(s->si_addr);
- /* XXX: Do we need to translate this from sparc32 to sparc64 traps? */
- d->si_trapno = s->si_trapno;
- break;
- case SIGPOLL:
- d->si_band = s->si_band;
- d->si_fd = s->si_fd;
- break;
- default:
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- break;
- }
- return d;
-}
-
extern asmlinkage int
sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
const struct timespec *uts, size_t sigsetsize);
@@ -1753,10 +1674,9 @@ sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
sigset_t s;
sigset_t32 s32;
struct timespec t;
- int ret;
+ int ret, err, i;
mm_segment_t old_fs = get_fs();
siginfo_t info;
- siginfo_t32 info32;
if (copy_from_user (&s32, uthese, sizeof(sigset_t32)))
return -EFAULT;
@@ -1776,8 +1696,43 @@ sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
set_fs (old_fs);
if (ret >= 0 && uinfo) {
- if (copy_to_user (uinfo, siginfo64to32(&info32, &info), sizeof(siginfo_t32)))
- return -EFAULT;
+ err = put_user (info.si_signo, &uinfo->si_signo);
+ err |= __put_user (info.si_errno, &uinfo->si_errno);
+ err |= __put_user (info.si_code, &uinfo->si_code);
+ if (info.si_code < 0)
+ err |= __copy_to_user (uinfo->_sifields._pad, info._sifields._pad, SI_PAD_SIZE);
+ else {
+ i = info.si_signo;
+ if (info.si_code == SI_USER)
+ i = SIGRTMIN;
+ switch (i) {
+ case SIGPOLL:
+ err |= __put_user (info.si_band, &uinfo->si_band);
+ err |= __put_user (info.si_fd, &uinfo->si_fd);
+ break;
+ case SIGCHLD:
+ err |= __put_user (info.si_pid, &uinfo->si_pid);
+ err |= __put_user (info.si_uid, &uinfo->si_uid);
+ err |= __put_user (info.si_status, &uinfo->si_status);
+ err |= __put_user (info.si_utime, &uinfo->si_utime);
+ err |= __put_user (info.si_stime, &uinfo->si_stime);
+ break;
+ case SIGSEGV:
+ case SIGILL:
+ case SIGFPE:
+ case SIGBUS:
+ case SIGEMT:
+ err |= __put_user ((long)info.si_addr, &uinfo->si_addr);
+ err |= __put_user (info.si_trapno, &uinfo->si_trapno);
+ break;
+ default:
+ err |= __put_user (info.si_pid, &uinfo->si_pid);
+ err |= __put_user (info.si_uid, &uinfo->si_uid);
+ break;
+ }
+ }
+ if (err)
+ ret = -EFAULT;
}
return ret;
}
@@ -1789,14 +1744,12 @@ asmlinkage int
sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
{
siginfo_t info;
- siginfo_t32 info32;
int ret;
mm_segment_t old_fs = get_fs();
- if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32)))
+ if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
+ copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
return -EFAULT;
- /* XXX: Is this correct? */
- siginfo32to64(&info, &info32);
set_fs (KERNEL_DS);
ret = sys_rt_sigqueueinfo(pid, sig, &info);
set_fs (old_fs);
@@ -2659,7 +2612,7 @@ asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old
int ret;
if(sig < 0) {
- current->tss.new_signal = 1;
+ current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
sig = -sig;
}
@@ -2703,7 +2656,7 @@ sys32_rt_sigaction(int sig, struct sigaction32 *act, struct sigaction32 *oact,
/* All tasks which use RT signals (effectively) use
* new style signals.
*/
- current->tss.new_signal = 1;
+ current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
if (act) {
new_ka.ka_restorer = restorer;
@@ -2883,6 +2836,8 @@ asmlinkage int sparc32_execve(struct pt_regs *regs)
int error, base = 0;
char *filename;
+ /* User register window flush is done by entry.S */
+
/* Check for indirect call. */
if((u32)regs->u_regs[UREG_G1] == 0)
base = 1;
@@ -2899,8 +2854,8 @@ asmlinkage int sparc32_execve(struct pt_regs *regs)
if(!error) {
fprs_write(0);
- current->tss.xfsr[0] = 0;
- current->tss.fpsaved[0] = 0;
+ current->thread.xfsr[0] = 0;
+ current->thread.fpsaved[0] = 0;
regs->tstate &= ~TSTATE_PEF;
}
out:
@@ -3786,7 +3741,7 @@ asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
}
-extern asmlinkage int sys_personality(unsigned long);
+extern asmlinkage long sys_personality(unsigned long);
asmlinkage int sys32_personality(unsigned long personality)
{
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 156d1d8ee..0f0c2a536 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.26 1999/06/09 08:23:54 davem Exp $
+/* $Id: sys_sunos32.c,v 1.31 1999/08/30 10:01:19 davem Exp $
* sys_sunos32.c: SunOS binary compatability layer on sparc64.
*
* Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -557,9 +557,9 @@ asmlinkage int sunos_nosys(void)
struct pt_regs *regs;
lock_kernel();
- regs = current->tss.kregs;
- current->tss.sig_address = regs->tpc;
- current->tss.sig_desc = regs->u_regs[UREG_G1];
+ regs = current->thread.kregs;
+ current->thread.sig_address = regs->tpc;
+ current->thread.sig_desc = regs->u_regs[UREG_G1];
send_sig(SIGSYS, current, 1);
printk("Process makes ni_syscall number %d, register dump:\n",
(int) regs->u_regs[UREG_G1]);
@@ -981,10 +981,6 @@ extern asmlinkage s32 sunos_sysconf (int name)
return ret;
}
-extern asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg);
-extern asmlinkage int sys_semget (key_t key, int nsems, int semflg);
-extern asmlinkage int sys_semop (int semid, struct sembuf *tsops, unsigned nsops);
-
asmlinkage int sunos_semsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 ptr)
{
union semun arg4;
@@ -1119,13 +1115,6 @@ static inline int sunos_msgbuf_put(struct msgbuf32 *user, struct msgbuf *kern, i
return 0;
}
-extern asmlinkage int sys_msgget (key_t key, int msgflg);
-extern asmlinkage int sys_msgrcv (int msqid, struct msgbuf *msgp,
- size_t msgsz, long msgtyp, int msgflg);
-extern asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp,
- size_t msgsz, int msgflg);
-extern asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf);
-
asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
{
struct sparc_stackf32 *sp;
@@ -1159,7 +1148,7 @@ asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
if(!kmbuf)
break;
sp = (struct sparc_stackf32 *)
- (current->tss.kregs->u_regs[UREG_FP] & 0xffffffffUL);
+ (current->thread.kregs->u_regs[UREG_FP] & 0xffffffffUL);
if(get_user(arg5, &sp->xxargs[0])) {
rval = -EFAULT;
break;
@@ -1242,11 +1231,6 @@ static inline int sunos_shmid_put(struct shmid_ds32 *user,
return 0;
}
-extern asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr);
-extern asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
-extern asmlinkage int sys_shmdt (char *shmaddr);
-extern asmlinkage int sys_shmget (key_t key, int size, int shmflg);
-
asmlinkage int sunos_shmsys(int op, u32 arg1, u32 arg2, u32 arg3)
{
struct shmid_ds ksds;
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index e99ae0532..06a827db2 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.54 1999/06/02 12:06:31 jj Exp $
+/* $Id: systbls.S,v 1.56 1999/07/31 00:06:17 davem Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
@@ -59,7 +59,7 @@ sys_call_table32:
.word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
/*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
.word sys_nis_syscall, sys32_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
-/*210*/ .word sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys32_sysinfo
+/*210*/ .word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys32_sysinfo
.word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex
/*220*/ .word sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid
.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
@@ -112,15 +112,15 @@ sys_call_table:
.word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
.word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
+/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
.word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname
/*190*/ .word sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
.word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
-/*200*/ .word sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_nis_syscall
+/*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
.word sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
-/*210*/ .word sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
- .word sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex
-/*220*/ .word sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
+/*210*/ .word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
+ .word sys_ipc, sys_nis_syscall, sys_clone, sys_nis_syscall, sys_adjtimex
+/*220*/ .word sys_nis_syscall, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
.word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
/*230*/ .word sys_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall
.word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 0b72e6e0b..60d5e4a5f 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.20 1999/03/15 22:13:40 davem Exp $
+/* $Id: time.c,v 1.22 1999/08/30 10:01:22 davem Exp $
* time.c: UltraSparc timer and TOD clock support.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -33,9 +33,9 @@
extern rwlock_t xtime_lock;
-struct mostek48t02 *mstk48t02_regs = 0;
-static struct mostek48t08 *mstk48t08_regs = 0;
-static struct mostek48t59 *mstk48t59_regs = 0;
+unsigned long mstk48t02_regs = 0UL;
+static unsigned long mstk48t08_regs = 0UL;
+static unsigned long mstk48t59_regs = 0UL;
static int set_rtc_mmss(unsigned long);
@@ -47,7 +47,7 @@ static int set_rtc_mmss(unsigned long);
*/
unsigned long timer_tick_offset;
static unsigned long timer_tick_compare;
-static unsigned long timer_ticks_per_usec;
+static unsigned long timer_ticks_per_usec_quotient;
static __inline__ void timer_check_rtc(void)
{
@@ -146,17 +146,25 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon,
/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
static void __init kick_start_clock(void)
{
- register struct mostek48t02 *regs = mstk48t02_regs;
- unsigned char sec;
+ unsigned long regs = mstk48t02_regs;
+ u8 sec, tmp;
int i, count;
prom_printf("CLOCK: Clock was stopped. Kick start ");
/* Turn on the kick start bit to start the oscillator. */
- regs->creg |= MSTK_CREG_WRITE;
- regs->sec &= ~MSTK_STOP;
- regs->hour |= MSTK_KICK_START;
- regs->creg &= ~MSTK_CREG_WRITE;
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp |= MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
+ tmp = mostek_read(regs + MOSTEK_SEC);
+ tmp &= ~MSTK_STOP;
+ mostek_write(regs + MOSTEK_SEC, tmp);
+ tmp = mostek_read(regs + MOSTEK_HOUR);
+ tmp |= MSTK_KICK_START;
+ mostek_write(regs + MOSTEK_HOUR, tmp);
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp &= ~MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
/* Delay to allow the clock oscillator to start. */
sec = MSTK_REG_SEC(regs);
@@ -165,13 +173,17 @@ static void __init kick_start_clock(void)
for (count = 0; count < 100000; count++)
/* nothing */ ;
prom_printf(".");
- sec = regs->sec;
+ sec = MSTK_REG_SEC(regs);
}
prom_printf("\n");
/* Turn off kick start and set a "valid" time and date. */
- regs->creg |= MSTK_CREG_WRITE;
- regs->hour &= ~MSTK_KICK_START;
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp |= MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
+ tmp = mostek_read(regs + MOSTEK_HOUR);
+ tmp &= ~MSTK_KICK_START;
+ mostek_write(regs + MOSTEK_HOUR, tmp);
MSTK_SET_REG_SEC(regs,0);
MSTK_SET_REG_MIN(regs,0);
MSTK_SET_REG_HOUR(regs,0);
@@ -179,14 +191,24 @@ static void __init kick_start_clock(void)
MSTK_SET_REG_DOM(regs,1);
MSTK_SET_REG_MONTH(regs,8);
MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO);
- regs->creg &= ~MSTK_CREG_WRITE;
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp &= ~MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
/* Ensure the kick start bit is off. If it isn't, turn it off. */
- while (regs->hour & MSTK_KICK_START) {
+ while (mostek_read(regs + MOSTEK_HOUR) & MSTK_KICK_START) {
prom_printf("CLOCK: Kick start still on!\n");
- regs->creg |= MSTK_CREG_WRITE;
- regs->hour &= ~MSTK_KICK_START;
- regs->creg &= ~MSTK_CREG_WRITE;
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp |= MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
+
+ tmp = mostek_read(regs + MOSTEK_HOUR);
+ tmp &= ~MSTK_KICK_START;
+ mostek_write(regs + MOSTEK_HOUR, tmp);
+
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp &= ~MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
}
prom_printf("CLOCK: Kick start procedure successful.\n");
@@ -195,13 +217,13 @@ static void __init kick_start_clock(void)
/* Return nonzero if the clock chip battery is low. */
static int __init has_low_battery(void)
{
- register struct mostek48t02 *regs = mstk48t02_regs;
- unsigned char data1, data2;
+ unsigned long regs = mstk48t02_regs;
+ u8 data1, data2;
- data1 = regs->eeprom[0]; /* Read some data. */
- regs->eeprom[0] = ~data1; /* Write back the complement. */
- data2 = regs->eeprom[0]; /* Read back the complement. */
- regs->eeprom[0] = data1; /* Restore the original value. */
+ data1 = mostek_read(regs + MOSTEK_EEPROM); /* Read some data. */
+ mostek_write(regs + MOSTEK_EEPROM, ~data1); /* Write back the complement. */
+ data2 = mostek_read(regs + MOSTEK_EEPROM); /* Read back the complement. */
+ mostek_write(regs + MOSTEK_EEPROM, data1); /* Restore original value. */
return (data1 == data2); /* Was the write blocked? */
}
@@ -211,17 +233,20 @@ static int __init has_low_battery(void)
static void __init set_system_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- struct mostek48t02 *mregs;
+ unsigned long mregs = mstk48t02_regs;
+ u8 tmp;
do_get_fast_time = do_gettimeofday;
- mregs = mstk48t02_regs;
if(!mregs) {
prom_printf("Something wrong, clock regs not mapped yet.\n");
prom_halt();
}
- mregs->creg |= MSTK_CREG_READ;
+ tmp = mostek_read(mregs + MOSTEK_CREG);
+ tmp |= MSTK_CREG_READ;
+ mostek_write(mregs + MOSTEK_CREG, tmp);
+
sec = MSTK_REG_SEC(mregs);
min = MSTK_REG_MIN(mregs);
hour = MSTK_REG_HOUR(mregs);
@@ -230,7 +255,10 @@ static void __init set_system_time(void)
year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
xtime.tv_usec = 0;
- mregs->creg &= ~MSTK_CREG_READ;
+
+ tmp = mostek_read(mregs + MOSTEK_CREG);
+ tmp &= ~MSTK_CREG_READ;
+ mostek_write(mregs + MOSTEK_CREG, tmp);
}
void __init clock_probe(void)
@@ -315,19 +343,8 @@ void __init clock_probe(void)
prom_halt();
}
- if (check_region(edev->base_address[0],
- sizeof(struct mostek48t59))) {
- prom_printf("%s: Can't get region %lx, %d\n",
- __FUNCTION__, edev->base_address[0],
- sizeof(struct mostek48t59));
- prom_halt();
- }
- request_region(edev->base_address[0],
- sizeof(struct mostek48t59), "clock");
-
- mstk48t59_regs = (struct mostek48t59 *)
- edev->base_address[0];
- mstk48t02_regs = &mstk48t59_regs->regs;
+ mstk48t59_regs = edev->resource[0].start;
+ mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
break;
}
#endif
@@ -338,22 +355,16 @@ void __init clock_probe(void)
}
if(model[5] == '0' && model[6] == '2') {
- mstk48t02_regs = (struct mostek48t02 *)
- sparc_alloc_io(clk_reg[0].phys_addr,
- (void *) 0, sizeof(*mstk48t02_regs),
- "clock", clk_reg[0].which_io, 0x0);
+ mstk48t02_regs = (((u64)clk_reg[0].phys_addr) |
+ (((u64)clk_reg[0].which_io)<<32UL));
} else if(model[5] == '0' && model[6] == '8') {
- mstk48t08_regs = (struct mostek48t08 *)
- sparc_alloc_io(clk_reg[0].phys_addr,
- (void *) 0, sizeof(*mstk48t08_regs),
- "clock", clk_reg[0].which_io, 0x0);
- mstk48t02_regs = &mstk48t08_regs->regs;
+ mstk48t08_regs = (((u64)clk_reg[0].phys_addr) |
+ (((u64)clk_reg[0].which_io)<<32UL));
+ mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
} else {
- mstk48t59_regs = (struct mostek48t59 *)
- sparc_alloc_io(clk_reg[0].phys_addr,
- (void *) 0, sizeof(*mstk48t59_regs),
- "clock", clk_reg[0].which_io, 0x0);
- mstk48t02_regs = &mstk48t59_regs->regs;
+ mstk48t59_regs = (((u64)clk_reg[0].phys_addr) |
+ (((u64)clk_reg[0].which_io)<<32UL));
+ mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
}
break;
}
@@ -363,7 +374,7 @@ void __init clock_probe(void)
prom_printf("NVRAM: Low battery voltage!\n");
/* Kick start the clock if it is completely stopped. */
- if (mstk48t02_regs->sec & MSTK_STOP)
+ if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)
kick_start_clock();
set_system_time();
@@ -392,7 +403,7 @@ void __init time_init(void)
init_timers(timer_interrupt, &clock);
timer_tick_offset = clock / HZ;
- timer_ticks_per_usec = clock / 1000000;
+ timer_ticks_per_usec_quotient = ((1UL<<32) / (clock / 1000020));
}
static __inline__ unsigned long do_gettimeoffset(void)
@@ -408,7 +419,7 @@ static __inline__ unsigned long do_gettimeoffset(void)
: "r" (timer_tick_offset), "r" (timer_tick_compare)
: "g1", "g2");
- return ticks / timer_ticks_per_usec;
+ return (ticks * timer_ticks_per_usec_quotient) >> 32UL;
}
/* This need not obtain the xtime_lock as it is coded in
@@ -431,24 +442,22 @@ void do_gettimeofday(struct timeval *tv)
or %g2, %lo(xtime), %g2
or %g1, %lo(timer_tick_compare), %g1
1: ldda [%g2] 0x24, %o4
- membar #LoadLoad | #MemIssue
rd %tick, %o1
ldx [%g1], %g7
- membar #LoadLoad | #MemIssue
ldda [%g2] 0x24, %o2
- membar #LoadLoad
xor %o4, %o2, %o2
xor %o5, %o3, %o3
orcc %o2, %o3, %g0
bne,pn %xcc, 1b
sethi %hi(lost_ticks), %o2
- sethi %hi(timer_ticks_per_usec), %o3
+ sethi %hi(timer_ticks_per_usec_quotient), %o3
ldx [%o2 + %lo(lost_ticks)], %o2
add %g3, %o1, %o1
- ldx [%o3 + %lo(timer_ticks_per_usec)], %o3
+ ldx [%o3 + %lo(timer_ticks_per_usec_quotient)], %o3
sub %o1, %g7, %o1
+ mulx %o3, %o1, %o1
brz,pt %o2, 1f
- udivx %o1, %o3, %o1
+ srlx %o1, 32, %o1
sethi %hi(10000), %g2
or %g2, %lo(10000), %g2
add %o1, %g2, %o1
@@ -487,16 +496,23 @@ void do_settimeofday(struct timeval *tv)
static int set_rtc_mmss(unsigned long nowtime)
{
int real_seconds, real_minutes, mostek_minutes;
- struct mostek48t02 *regs = mstk48t02_regs;
+ unsigned long regs = mstk48t02_regs;
+ u8 tmp;
/* Not having a register set can lead to trouble. */
if (!regs)
return -1;
/* Read the current RTC minutes. */
- regs->creg |= MSTK_CREG_READ;
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp |= MSTK_CREG_READ;
+ mostek_write(regs + MOSTEK_CREG, tmp);
+
mostek_minutes = MSTK_REG_MIN(regs);
- regs->creg &= ~MSTK_CREG_READ;
+
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp &= ~MSTK_CREG_READ;
+ mostek_write(regs + MOSTEK_CREG, tmp);
/*
* since we're only adjusting minutes and seconds,
@@ -511,10 +527,16 @@ static int set_rtc_mmss(unsigned long nowtime)
real_minutes %= 60;
if (abs(real_minutes - mostek_minutes) < 30) {
- regs->creg |= MSTK_CREG_WRITE;
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp |= MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
+
MSTK_SET_REG_SEC(regs,real_seconds);
MSTK_SET_REG_MIN(regs,real_minutes);
- regs->creg &= ~MSTK_CREG_WRITE;
+
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp &= ~MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
} else
return -1;
diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S
index 0dd40b538..fba910a55 100644
--- a/arch/sparc64/kernel/trampoline.S
+++ b/arch/sparc64/kernel/trampoline.S
@@ -1,9 +1,11 @@
-/* $Id: trampoline.S,v 1.9 1999/05/25 16:53:12 jj Exp $
+/* $Id: trampoline.S,v 1.10 1999/09/10 10:40:48 davem Exp $
* trampoline.S: Jump start slave processors on sparc64.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/config.h>
+
#include <asm/head.h>
#include <asm/asi.h>
#include <asm/lsu.h>
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 86ee5b661..f4f2287df 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.60 1999/06/02 19:19:55 jj Exp $
+/* $Id: traps.c,v 1.62 1999/08/31 19:25:35 davem Exp $
* arch/sparc64/kernel/traps.c
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -147,12 +147,12 @@ void syscall_trace_entry(unsigned long g1, struct pt_regs *regs)
if(i)
printk(",");
if(!sdp->arg_is_string[i]) {
- if (current->tss.flags & SPARC_FLAG_32BIT)
+ if (current->thread.flags & SPARC_FLAG_32BIT)
printk("%08x", (unsigned int)regs->u_regs[UREG_I0 + i]);
else
printk("%016lx", regs->u_regs[UREG_I0 + i]);
} else {
- if (current->tss.flags & SPARC_FLAG_32BIT)
+ if (current->thread.flags & SPARC_FLAG_32BIT)
strncpy_from_user(scall_strbuf,
(char *)(regs->u_regs[UREG_I0 + i] & 0xffffffff),
512);
@@ -178,7 +178,7 @@ unsigned long syscall_trace_exit(unsigned long retval, struct pt_regs *regs)
}
#endif /* SYSCALL_TRACING */
-#if 0
+#if 1
void rtrap_check(struct pt_regs *regs)
{
register unsigned long pgd_phys asm("o1");
@@ -219,7 +219,7 @@ void rtrap_check(struct pt_regs *regs)
if((pgd_phys != __pa(current->mm->pgd)) ||
((pgd_cache != 0) &&
- (pgd_cache != pgd_val(current->mm->pgd[0]))) ||
+ (pgd_cache != pgd_val(current->mm->pgd[0])<<11UL)) ||
(g1_or_g3 != (0xfffffffe00000000UL | 0x0000000000000018UL)) ||
#define KERN_HIGHBITS ((_PAGE_VALID | _PAGE_SZ4MB) ^ 0xfffff80000000000)
#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
@@ -228,18 +228,17 @@ void rtrap_check(struct pt_regs *regs)
#undef KERN_LOWBITS
((ctx != (current->mm->context & 0x3ff)) ||
(ctx == 0) ||
- (current->tss.ctx != ctx))) {
+ (CTX_HWBITS(current->mm->context) != ctx))) {
printk("SHIT[%s:%d]: "
- "(PP[%016lx] CACH[%016lx] CTX[%x] g1g3[%016lx] g2[%016lx]) ",
+ "(PP[%016lx] CACH[%016lx] CTX[%lx] g1g3[%016lx] g2[%016lx]) ",
current->comm, current->pid,
pgd_phys, pgd_cache, ctx, g1_or_g3, g2);
printk("SHIT[%s:%d]: "
- "[PP[%016lx] CACH[%016lx] CTX[%x:%x]] PC[%016lx:%016lx]\n",
+ "[PP[%016lx] CACH[%016lx] CTX[%lx]] PC[%016lx:%016lx]\n",
current->comm, current->pid,
__pa(current->mm->pgd),
pgd_val(current->mm->pgd[0]),
current->mm->context & 0x3ff,
- current->tss.ctx,
regs->tpc, regs->tnpc);
show_regs(regs);
#if 1
@@ -262,8 +261,8 @@ void bad_trap (struct pt_regs *regs, long lvl)
}
if (regs->tstate & TSTATE_PRIV)
die_if_kernel ("Kernel bad trap", regs);
- current->tss.sig_desc = SUBSIG_BADTRAP(lvl - 0x100);
- current->tss.sig_address = regs->tpc;
+ current->thread.sig_desc = SUBSIG_BADTRAP(lvl - 0x100);
+ current->thread.sig_address = regs->tpc;
force_sig(SIGILL, current);
unlock_kernel ();
}
@@ -289,8 +288,8 @@ void instruction_access_exception (struct pt_regs *regs,
#endif
die_if_kernel("Iax", regs);
}
- current->tss.sig_desc = SUBSIG_ILLINST;
- current->tss.sig_address = regs->tpc;
+ current->thread.sig_desc = SUBSIG_ILLINST;
+ current->thread.sig_address = regs->tpc;
force_sig(SIGILL, current);
unlock_kernel();
}
@@ -396,14 +395,132 @@ void do_iae(struct pt_regs *regs)
unlock_kernel();
}
+static char ecc_syndrome_table[] = {
+ 0x4c, 0x40, 0x41, 0x48, 0x42, 0x48, 0x48, 0x49,
+ 0x43, 0x48, 0x48, 0x49, 0x48, 0x49, 0x49, 0x4a,
+ 0x44, 0x48, 0x48, 0x20, 0x48, 0x39, 0x4b, 0x48,
+ 0x48, 0x25, 0x31, 0x48, 0x28, 0x48, 0x48, 0x2c,
+ 0x45, 0x48, 0x48, 0x21, 0x48, 0x3d, 0x04, 0x48,
+ 0x48, 0x4b, 0x35, 0x48, 0x2d, 0x48, 0x48, 0x29,
+ 0x48, 0x00, 0x01, 0x48, 0x0a, 0x48, 0x48, 0x4b,
+ 0x0f, 0x48, 0x48, 0x4b, 0x48, 0x49, 0x49, 0x48,
+ 0x46, 0x48, 0x48, 0x2a, 0x48, 0x3b, 0x27, 0x48,
+ 0x48, 0x4b, 0x33, 0x48, 0x22, 0x48, 0x48, 0x2e,
+ 0x48, 0x19, 0x1d, 0x48, 0x1b, 0x4a, 0x48, 0x4b,
+ 0x1f, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48,
+ 0x48, 0x4b, 0x24, 0x48, 0x07, 0x48, 0x48, 0x36,
+ 0x4b, 0x48, 0x48, 0x3e, 0x48, 0x30, 0x38, 0x48,
+ 0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x16, 0x48,
+ 0x48, 0x12, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b,
+ 0x47, 0x48, 0x48, 0x2f, 0x48, 0x3f, 0x4b, 0x48,
+ 0x48, 0x06, 0x37, 0x48, 0x23, 0x48, 0x48, 0x2b,
+ 0x48, 0x05, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x32,
+ 0x26, 0x48, 0x48, 0x3a, 0x48, 0x34, 0x3c, 0x48,
+ 0x48, 0x11, 0x15, 0x48, 0x13, 0x4a, 0x48, 0x4b,
+ 0x17, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48,
+ 0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x1e, 0x48,
+ 0x48, 0x1a, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b,
+ 0x48, 0x08, 0x0d, 0x48, 0x02, 0x48, 0x48, 0x49,
+ 0x03, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x4b, 0x48,
+ 0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x10, 0x48,
+ 0x48, 0x14, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b,
+ 0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x18, 0x48,
+ 0x48, 0x1c, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b,
+ 0x4a, 0x0c, 0x09, 0x48, 0x0e, 0x48, 0x48, 0x4b,
+ 0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a
+};
+
+/* cee_trap in entry.S encodes AFSR/UDBH/UDBL error status
+ * in the following format. The AFAR is left as is, with
+ * reserved bits cleared, and is a raw 40-bit physical
+ * address.
+ */
+#define CE_STATUS_UDBH_UE (1UL << (43 + 9))
+#define CE_STATUS_UDBH_CE (1UL << (43 + 8))
+#define CE_STATUS_UDBH_ESYNDR (0xffUL << 43)
+#define CE_STATUS_UDBH_SHIFT 43
+#define CE_STATUS_UDBL_UE (1UL << (33 + 9))
+#define CE_STATUS_UDBL_CE (1UL << (33 + 8))
+#define CE_STATUS_UDBL_ESYNDR (0xffUL << 33)
+#define CE_STATUS_UDBL_SHIFT 33
+#define CE_STATUS_AFSR_MASK (0x1ffffffffUL)
+#define CE_STATUS_AFSR_ME (1UL << 32)
+#define CE_STATUS_AFSR_PRIV (1UL << 31)
+#define CE_STATUS_AFSR_ISAP (1UL << 30)
+#define CE_STATUS_AFSR_ETP (1UL << 29)
+#define CE_STATUS_AFSR_IVUE (1UL << 28)
+#define CE_STATUS_AFSR_TO (1UL << 27)
+#define CE_STATUS_AFSR_BERR (1UL << 26)
+#define CE_STATUS_AFSR_LDP (1UL << 25)
+#define CE_STATUS_AFSR_CP (1UL << 24)
+#define CE_STATUS_AFSR_WP (1UL << 23)
+#define CE_STATUS_AFSR_EDP (1UL << 22)
+#define CE_STATUS_AFSR_UE (1UL << 21)
+#define CE_STATUS_AFSR_CE (1UL << 20)
+#define CE_STATUS_AFSR_ETS (0xfUL << 16)
+#define CE_STATUS_AFSR_ETS_SHIFT 16
+#define CE_STATUS_AFSR_PSYND (0xffffUL << 0)
+#define CE_STATUS_AFSR_PSYND_SHIFT 0
+
+/* Layout of Ecache TAG Parity Syndrome of AFSR */
+#define AFSR_ETSYNDROME_7_0 0x1UL /* E$-tag bus bits <7:0> */
+#define AFSR_ETSYNDROME_15_8 0x2UL /* E$-tag bus bits <15:8> */
+#define AFSR_ETSYNDROME_21_16 0x4UL /* E$-tag bus bits <21:16> */
+#define AFSR_ETSYNDROME_24_22 0x8UL /* E$-tag bus bits <24:22> */
+
+static char *syndrome_unknown = "<Unknown>";
+
+asmlinkage void cee_log(unsigned long ce_status,
+ unsigned long afar,
+ struct pt_regs *regs)
+{
+ char memmod_str[64];
+ char *p;
+ unsigned short scode, udb_reg;
+
+ printk(KERN_WARNING "CPU[%d]: Correctable ECC Error "
+ "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx]\n",
+ smp_processor_id(),
+ (ce_status & CE_STATUS_AFSR_MASK),
+ afar,
+ ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL),
+ ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL));
+
+ udb_reg = ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL);
+ if (udb_reg & (1 << 8)) {
+ scode = ecc_syndrome_table[udb_reg & 0xff];
+ if (prom_getunumber(scode, afar,
+ memmod_str, sizeof(memmod_str)) == -1)
+ p = syndrome_unknown;
+ else
+ p = memmod_str;
+ printk(KERN_WARNING "CPU[%d]: UDBL Syndrome[%x] "
+ "Memory Module \"%s\"\n",
+ smp_processor_id(), scode, p);
+ }
+
+ udb_reg = ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL);
+ if (udb_reg & (1 << 8)) {
+ scode = ecc_syndrome_table[udb_reg & 0xff];
+ if (prom_getunumber(scode, afar,
+ memmod_str, sizeof(memmod_str)) == -1)
+ p = syndrome_unknown;
+ else
+ p = memmod_str;
+ printk(KERN_WARNING "CPU[%d]: UDBH Syndrome[%x] "
+ "Memory Module \"%s\"\n",
+ smp_processor_id(), scode, p);
+ }
+}
+
void do_fpe_common(struct pt_regs *regs)
{
if(regs->tstate & TSTATE_PRIV) {
regs->tpc = regs->tnpc;
regs->tnpc += 4;
} else {
- current->tss.sig_address = regs->tpc;
- current->tss.sig_desc = SUBSIG_FPERROR;
+ current->thread.sig_address = regs->tpc;
+ current->thread.sig_desc = SUBSIG_FPERROR;
send_sig(SIGFPE, current, 1);
}
}
@@ -411,7 +528,7 @@ void do_fpe_common(struct pt_regs *regs)
void do_fpieee(struct pt_regs *regs)
{
#ifdef DEBUG_FPU
- printk("fpieee %016lx\n", current->tss.xfsr[0]);
+ printk("fpieee %016lx\n", current->thread.xfsr[0]);
#endif
do_fpe_common(regs);
}
@@ -423,7 +540,7 @@ void do_fpother(struct pt_regs *regs)
struct fpustate *f = FPUSTATE;
int ret = 0;
- switch ((current->tss.xfsr[0] & 0x1c000)) {
+ switch ((current->thread.xfsr[0] & 0x1c000)) {
case (2 << 14): /* unfinished_FPop */
case (3 << 14): /* unimplemented_FPop */
ret = do_mathemu(regs, f);
@@ -431,7 +548,7 @@ void do_fpother(struct pt_regs *regs)
}
if (ret) return;
#ifdef DEBUG_FPU
- printk("fpother %016lx\n", current->tss.xfsr[0]);
+ printk("fpother %016lx\n", current->thread.xfsr[0]);
#endif
do_fpe_common(regs);
}
@@ -440,8 +557,8 @@ void do_tof(struct pt_regs *regs)
{
if(regs->tstate & TSTATE_PRIV)
die_if_kernel("Penguin overflow trap from kernel mode", regs);
- current->tss.sig_address = regs->tpc;
- current->tss.sig_desc = SUBSIG_TAG; /* as good as any */
+ current->thread.sig_address = regs->tpc;
+ current->thread.sig_desc = SUBSIG_TAG; /* as good as any */
send_sig(SIGEMT, current, 1);
}
@@ -540,7 +657,7 @@ void do_illegal_instruction(struct pt_regs *regs)
if(tstate & TSTATE_PRIV)
die_if_kernel("Kernel illegal instruction", regs);
- if(current->tss.flags & SPARC_FLAG_32BIT)
+ if(current->thread.flags & SPARC_FLAG_32BIT)
pc = (u32)pc;
if (get_user(insn, (u32 *)pc) != -EFAULT) {
if ((insn & 0xc1ffc000) == 0x81700000) /* POPC */ {
@@ -551,8 +668,8 @@ void do_illegal_instruction(struct pt_regs *regs)
return;
}
}
- current->tss.sig_address = pc;
- current->tss.sig_desc = SUBSIG_ILLINST;
+ current->thread.sig_address = pc;
+ current->thread.sig_desc = SUBSIG_ILLINST;
send_sig(SIGILL, current, 1);
}
@@ -565,23 +682,23 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo
return kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc), sfar, sfsr);
} else {
- current->tss.sig_address = regs->tpc;
- current->tss.sig_desc = SUBSIG_PRIVINST;
+ current->thread.sig_address = regs->tpc;
+ current->thread.sig_desc = SUBSIG_PRIVINST;
send_sig(SIGBUS, current, 1);
}
}
void do_privop(struct pt_regs *regs)
{
- current->tss.sig_address = regs->tpc;
- current->tss.sig_desc = SUBSIG_PRIVINST;
+ current->thread.sig_address = regs->tpc;
+ current->thread.sig_desc = SUBSIG_PRIVINST;
send_sig(SIGILL, current, 1);
}
void do_privact(struct pt_regs *regs)
{
- current->tss.sig_address = regs->tpc;
- current->tss.sig_desc = SUBSIG_PRIVINST;
+ current->thread.sig_address = regs->tpc;
+ current->thread.sig_desc = SUBSIG_PRIVINST;
send_sig(SIGILL, current, 1);
}
@@ -590,8 +707,8 @@ void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long n
{
if(tstate & TSTATE_PRIV)
die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
- current->tss.sig_address = pc;
- current->tss.sig_desc = SUBSIG_PRIVINST;
+ current->thread.sig_address = pc;
+ current->thread.sig_desc = SUBSIG_PRIVINST;
send_sig(SIGILL, current, 1);
}
@@ -727,4 +844,11 @@ void cache_flush_trap(struct pt_regs *regs)
void trap_init(void)
{
+ /* Attach to the address space of init_task. */
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+
+ /* NOTE: Other cpus have this done as they are started
+ * up on SMP.
+ */
}
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index 3a9fdf4d2..b378756c0 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -1,4 +1,4 @@
-/* $Id: ttable.S,v 1.28 1999/03/29 12:38:10 jj Exp $
+/* $Id: ttable.S,v 1.29 1999/08/31 19:25:37 davem Exp $
* ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -57,7 +57,7 @@ tl0_resv05c: BTRAP(0x5c) BTRAP(0x5d) BTRAP(0x5e) BTRAP(0x5f)
tl0_ivec: TRAP_IVEC
tl0_paw: TRAP(do_paw)
tl0_vaw: TRAP(do_vaw)
-tl0_cee: TRAP(do_cee)
+tl0_cee: TRAP_NOSAVE(cee_trap)
tl0_iamiss:
#include "itlb_base.S"
tl0_damiss:
@@ -202,7 +202,7 @@ tl1_resv05c: BTRAPTL1(0x5c) BTRAPTL1(0x5d) BTRAPTL1(0x5e) BTRAPTL1(0x5f)
tl1_ivec: TRAP_IVEC
tl1_paw: TRAPTL1(do_paw_tl1)
tl1_vaw: TRAPTL1(do_vaw_tl1)
-tl1_cee: TRAPTL1(do_cee_tl1)
+tl1_cee: TRAPTL1_CEE
tl1_iamiss: BTRAPTL1(0x64) BTRAPTL1(0x65) BTRAPTL1(0x66) BTRAPTL1(0x67)
tl1_damiss:
#include "dtlb_backend.S"
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 3b813f415..792334336 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -1,4 +1,4 @@
-/* $Id: unaligned.c,v 1.16 1999/05/25 16:53:15 jj Exp $
+/* $Id: unaligned.c,v 1.18 1999/08/02 08:39:44 davem Exp $
* unaligned.c: Unaligned load/store trap handling with special
* cases for the kernel to do them more quickly.
*
@@ -70,7 +70,7 @@ static inline int decode_access_size(unsigned int insn)
return 2;
else {
printk("Impossible unaligned trap. insn=%08x\n", insn);
- die_if_kernel("Byte sized unaligned access?!?!", current->tss.kregs);
+ die_if_kernel("Byte sized unaligned access?!?!", current->thread.kregs);
}
}
@@ -117,7 +117,7 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
struct reg_window *win;
win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
value = win->locals[reg - 16];
- } else if (current->tss.flags & SPARC_FLAG_32BIT) {
+ } else if (current->thread.flags & SPARC_FLAG_32BIT) {
struct reg_window32 *win32;
win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
get_user(value, &win32->locals[reg - 16]);
@@ -137,7 +137,7 @@ static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
struct reg_window *win;
win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
return &win->locals[reg - 16];
- } else if (current->tss.flags & SPARC_FLAG_32BIT) {
+ } else if (current->thread.flags & SPARC_FLAG_32BIT) {
struct reg_window32 *win32;
win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
return (unsigned long *)&win32->locals[reg - 16];
@@ -164,10 +164,10 @@ static inline unsigned long compute_effective_address(struct pt_regs *regs,
}
}
-/* This is just to make gcc think panic does return... */
-static void unaligned_panic(char *str)
+/* This is just to make gcc think die_if_kernel does return... */
+static void unaligned_panic(char *str, struct pt_regs *regs)
{
- panic(str);
+ die_if_kernel(str, regs);
}
#define do_integer_load(dest_reg, size, saddr, is_signed, asi, errh) ({ \
@@ -380,7 +380,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
if(!ok_for_kernel(insn) || dir == both) {
printk("Unsupported unaligned load/store trap for kernel at <%016lx>.\n",
regs->tpc);
- unaligned_panic("Wheee. Kernel does fpu/atomic unaligned load/store.");
+ unaligned_panic("Kernel does fpu/atomic unaligned load/store.", regs);
__asm__ __volatile__ ("\n"
"kernel_unaligned_trap_fault:\n\t"
@@ -453,7 +453,7 @@ int handle_popc(u32 insn, struct pt_regs *regs)
if (rd)
regs->u_regs[rd] = ret;
} else {
- if (current->tss.flags & SPARC_FLAG_32BIT) {
+ if (current->thread.flags & SPARC_FLAG_32BIT) {
struct reg_window32 *win32;
win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
put_user(ret, &win32->locals[rd - 16]);
@@ -480,9 +480,9 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
int flag = (freg < 32) ? FPRS_DL : FPRS_DU;
save_and_clear_fpu();
- current->tss.xfsr[0] &= ~0x1c000;
+ current->thread.xfsr[0] &= ~0x1c000;
if (freg & 3) {
- current->tss.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
+ current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
do_fpother(regs);
return 0;
}
@@ -490,7 +490,7 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
/* STQ */
u64 first = 0, second = 0;
- if (current->tss.fpsaved[0] & flag) {
+ if (current->thread.fpsaved[0] & flag) {
first = *(u64 *)&f->regs[freg];
second = *(u64 *)&f->regs[freg+2];
}
@@ -565,18 +565,18 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
break;
}
}
- if (!(current->tss.fpsaved[0] & FPRS_FEF)) {
- current->tss.fpsaved[0] = FPRS_FEF;
- current->tss.gsr[0] = 0;
+ if (!(current->thread.fpsaved[0] & FPRS_FEF)) {
+ current->thread.fpsaved[0] = FPRS_FEF;
+ current->thread.gsr[0] = 0;
}
- if (!(current->tss.fpsaved[0] & flag)) {
+ if (!(current->thread.fpsaved[0] & flag)) {
if (freg < 32)
memset(f->regs, 0, 32*sizeof(u32));
else
memset(f->regs+32, 0, 32*sizeof(u32));
}
memcpy(f->regs + freg, data, size * 4);
- current->tss.fpsaved[0] |= flag;
+ current->thread.fpsaved[0] |= flag;
}
advance(regs);
return 1;
@@ -609,7 +609,7 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
if(tstate & TSTATE_PRIV)
die_if_kernel("lddfmna from kernel", regs);
- if(current->tss.flags & SPARC_FLAG_32BIT)
+ if(current->thread.flags & SPARC_FLAG_32BIT)
pc = (u32)pc;
if (get_user(insn, (u32 *)pc) != -EFAULT) {
asi = sfsr >> 16;
@@ -629,18 +629,18 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
if (asi & 0x8) /* Little */
value = __swab64p(&value);
flag = (freg < 32) ? FPRS_DL : FPRS_DU;
- if (!(current->tss.fpsaved[0] & FPRS_FEF)) {
- current->tss.fpsaved[0] = FPRS_FEF;
- current->tss.gsr[0] = 0;
+ if (!(current->thread.fpsaved[0] & FPRS_FEF)) {
+ current->thread.fpsaved[0] = FPRS_FEF;
+ current->thread.gsr[0] = 0;
}
- if (!(current->tss.fpsaved[0] & flag)) {
+ if (!(current->thread.fpsaved[0] & flag)) {
if (freg < 32)
memset(f->regs, 0, 32*sizeof(u32));
else
memset(f->regs+32, 0, 32*sizeof(u32));
}
*(u64 *)(f->regs + freg) = value;
- current->tss.fpsaved[0] |= flag;
+ current->thread.fpsaved[0] |= flag;
} else {
daex: data_access_exception(regs);
return;
@@ -661,7 +661,7 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
if(tstate & TSTATE_PRIV)
die_if_kernel("stdfmna from kernel", regs);
- if(current->tss.flags & SPARC_FLAG_32BIT)
+ if(current->thread.flags & SPARC_FLAG_32BIT)
pc = (u32)pc;
if (get_user(insn, (u32 *)pc) != -EFAULT) {
freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20);
@@ -672,7 +672,7 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
(asi < ASI_P))
goto daex;
save_and_clear_fpu();
- if (current->tss.fpsaved[0] & flag)
+ if (current->thread.fpsaved[0] & flag)
value = *(u64 *)&f->regs[freg];
switch (asi) {
case ASI_P:
diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
index 5bf82db59..67653fef1 100644
--- a/arch/sparc64/kernel/winfixup.S
+++ b/arch/sparc64/kernel/winfixup.S
@@ -1,4 +1,4 @@
-/* $Id: winfixup.S,v 1.27 1998/09/25 01:09:14 davem Exp $
+/* $Id: winfixup.S,v 1.28 1999/07/30 09:35:34 davem Exp $
*
* winfixup.S: Handle cases where user stack pointer is found to be bogus.
*
@@ -95,56 +95,56 @@ fill_fixup:
* do not touch %g7 or %g2 so we handle the two cases fine.
*/
spill_fixup:
- lduh [%g6 + AOFF_task_tss + AOFF_thread_flags], %g1
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %g1
andcc %g1, SPARC_FLAG_32BIT, %g0
- lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %g1
sll %g1, 3, %g3
add %g6, %g3, %g3
- stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]
+ stx %sp, [%g3 + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs]
sll %g1, 7, %g3
bne,pt %xcc, 1f
add %g6, %g3, %g3
- stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
- stx %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
-
- stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
- stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
- stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
- stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
- stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
- stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
- stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40]
- stx %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48]
-
- stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50]
- stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58]
- stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60]
- stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68]
- stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70]
+ stx %l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00]
+ stx %l1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08]
+
+ stx %l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10]
+ stx %l3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18]
+ stx %l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20]
+ stx %l5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28]
+ stx %l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30]
+ stx %l7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38]
+ stx %i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x40]
+ stx %i1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x48]
+
+ stx %i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x50]
+ stx %i3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x58]
+ stx %i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x60]
+ stx %i5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x68]
+ stx %i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x70]
b,pt %xcc, 2f
- stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78]
-1: stw %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
-
- stw %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x04]
- stw %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
- stw %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x0c]
- stw %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
- stw %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x14]
- stw %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
- stw %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x1c]
- stw %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
-
- stw %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x24]
- stw %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
- stw %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x2c]
- stw %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
- stw %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x34]
- stw %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
- stw %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x3c]
+ stx %i7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x78]
+1: stw %l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00]
+
+ stw %l1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x04]
+ stw %l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08]
+ stw %l3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x0c]
+ stw %l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10]
+ stw %l5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x14]
+ stw %l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18]
+ stw %l7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x1c]
+ stw %i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20]
+
+ stw %i1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x24]
+ stw %i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28]
+ stw %i3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x2c]
+ stw %i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30]
+ stw %i5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x34]
+ stw %i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38]
+ stw %i7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x3c]
2: add %g1, 1, %g1
- sth %g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved]
+ stb %g1, [%g6 + AOFF_task_thread + AOFF_thread_w_saved]
rdpr %tstate, %g1
andcc %g1, TSTATE_PRIV, %g0
saved
@@ -208,47 +208,47 @@ fill_fixup_mna:
b,pt %xcc, rtrap
nop ! yes, the nop is correct
spill_fixup_mna:
- lduh [%g6 + AOFF_task_tss + AOFF_thread_flags], %g1
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %g1
andcc %g1, SPARC_FLAG_32BIT, %g0
- lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %g1
sll %g1, 3, %g3
add %g6, %g3, %g3
- stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]
+ stx %sp, [%g3 + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs]
sll %g1, 7, %g3
bne,pt %xcc, 1f
add %g6, %g3, %g3
- stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
- stx %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
- stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
- stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
- stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
-
- stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
- stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
- stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
- stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40]
- stx %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48]
- stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50]
- stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58]
- stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60]
-
- stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68]
- stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70]
- stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78]
+ stx %l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00]
+ stx %l1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08]
+ stx %l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10]
+ stx %l3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18]
+ stx %l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20]
+
+ stx %l5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28]
+ stx %l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30]
+ stx %l7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38]
+ stx %i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x40]
+ stx %i1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x48]
+ stx %i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x50]
+ stx %i3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x58]
+ stx %i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x60]
+
+ stx %i5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x68]
+ stx %i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x70]
+ stx %i7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x78]
b,pt %xcc, 2f
add %g1, 1, %g1
-1: std %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
- std %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
- std %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
-
- std %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
- std %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
- std %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
- std %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
- std %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
+1: std %l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00]
+ std %l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08]
+ std %l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10]
+
+ std %l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18]
+ std %i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20]
+ std %i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28]
+ std %i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30]
+ std %i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38]
add %g1, 1, %g1
-2: sth %g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved]
+2: stb %g1, [%g6 + AOFF_task_thread + AOFF_thread_w_saved]
rdpr %tstate, %g1
andcc %g1, TSTATE_PRIV, %g0
@@ -315,47 +315,47 @@ fill_fixup_dax:
b,pt %xcc, rtrap
nop ! yes, the nop is correct
spill_fixup_dax:
- lduh [%g6 + AOFF_task_tss + AOFF_thread_flags], %g1
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %g1
andcc %g1, SPARC_FLAG_32BIT, %g0
- lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %g1
sll %g1, 3, %g3
add %g6, %g3, %g3
- stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]
+ stx %sp, [%g3 + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs]
sll %g1, 7, %g3
bne,pt %xcc, 1f
add %g6, %g3, %g3
- stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
- stx %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
- stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
- stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
- stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
-
- stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
- stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
- stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
- stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40]
- stx %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48]
- stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50]
- stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58]
- stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60]
-
- stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68]
- stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70]
- stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78]
+ stx %l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00]
+ stx %l1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08]
+ stx %l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10]
+ stx %l3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18]
+ stx %l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20]
+
+ stx %l5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28]
+ stx %l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30]
+ stx %l7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38]
+ stx %i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x40]
+ stx %i1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x48]
+ stx %i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x50]
+ stx %i3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x58]
+ stx %i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x60]
+
+ stx %i5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x68]
+ stx %i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x70]
+ stx %i7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x78]
b,pt %xcc, 2f
add %g1, 1, %g1
-1: std %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
- std %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
- std %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
-
- std %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
- std %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
- std %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
- std %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
- std %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
+1: std %l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00]
+ std %l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08]
+ std %l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10]
+
+ std %l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18]
+ std %i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20]
+ std %i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28]
+ std %i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30]
+ std %i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38]
add %g1, 1, %g1
-2: sth %g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved]
+2: stb %g1, [%g6 + AOFF_task_thread + AOFF_thread_w_saved]
rdpr %tstate, %g1
andcc %g1, TSTATE_PRIV, %g0
diff --git a/arch/sparc64/lib/PeeCeeI.c b/arch/sparc64/lib/PeeCeeI.c
index 6677f581a..56c005dfe 100644
--- a/arch/sparc64/lib/PeeCeeI.c
+++ b/arch/sparc64/lib/PeeCeeI.c
@@ -1,4 +1,4 @@
-/* $Id: PeeCeeI.c,v 1.3 1997/08/28 23:59:52 davem Exp $
+/* $Id: PeeCeeI.c,v 1.4 1999/09/06 01:17:35 davem Exp $
* PeeCeeI.c: The emerging standard...
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -9,6 +9,7 @@
#ifdef CONFIG_PCI
#include <asm/io.h>
+#include <asm/byteorder.h>
void outsb(unsigned long addr, const void *src, unsigned long count)
{
@@ -21,25 +22,29 @@ void outsb(unsigned long addr, const void *src, unsigned long count)
void outsw(unsigned long addr, const void *src, unsigned long count)
{
if(count) {
- const u16 *ps = src;
- const u32 *pi;
+ u16 *ps = (u16 *)src;
+ u32 *pi;
if(((u64)src) & 0x2) {
- outw(*ps++, addr);
+ u16 val = le16_to_cpup(ps);
+ outw(val, addr);
+ ps++;
count--;
}
- pi = (const u32 *)ps;
+ pi = (u32 *)ps;
while(count >= 2) {
- u32 w;
+ u32 w = le32_to_cpup(pi);
- w = *pi++;
+ pi++;
+ outw(w >> 0, addr);
outw(w >> 16, addr);
- outw(w, addr);
count -= 2;
}
- ps = (const u16 *)pi;
- if(count)
- outw(*ps, addr);
+ ps = (u16 *)pi;
+ if(count) {
+ u16 val = le16_to_cpup(ps);
+ outw(val, addr);
+ }
}
}
@@ -47,60 +52,71 @@ void outsl(unsigned long addr, const void *src, unsigned long count)
{
if(count) {
if((((u64)src) & 0x3) == 0) {
- const u32 *p = src;
- while(count--)
- outl(*p++, addr);
+ u32 *p = (u32 *)src;
+ while(count--) {
+ u32 val = cpu_to_le32p(p);
+ outl(val, addr);
+ p++;
+ }
} else {
- const u8 *pb;
- const u16 *ps = src;
+ u8 *pb;
+ u16 *ps = (u16 *)src;
u32 l = 0, l2;
- const u32 *pi;
+ u32 *pi;
switch(((u64)src) & 0x3) {
case 0x2:
count -= 1;
- l = *ps++;
- pi = (const u32 *)ps;
+ l = cpu_to_le16p(ps) << 16;
+ ps++;
+ pi = (u32 *)ps;
while(count--) {
- l2 = *pi++;
- outl(((l <<16) | (l2 >> 16)), addr);
+ l2 = cpu_to_le32p(pi);
+ pi++;
+ outl(((l >> 16) | (l2 << 16)), addr);
l = l2;
}
- ps = (const u16 *)pi;
- outl(((l << 16) | (*ps >> 16)), addr);
+ ps = (u16 *)pi;
+ l2 = cpu_to_le16p(ps);
+ outl(((l >> 16) | (l2 << 16)), addr);
break;
case 0x1:
count -= 1;
- pb = src;
- l = (*pb++ << 16);
- ps = (const u16 *)pb;
- l |= *ps++;
- pi = (const u32 *)ps;
+ pb = (u8 *)src;
+ l = (*pb++ << 8);
+ ps = (u16 *)pb;
+ l2 = cpu_to_le16p(ps);
+ ps++;
+ l |= (l2 << 16);
+ pi = (u32 *)ps;
while(count--) {
- l2 = *pi++;
- outl(((l << 8) | (l2 >> 24)), addr);
+ l2 = cpu_to_le32p(pi);
+ pi++;
+ outl(((l >> 8) | (l2 << 24)), addr);
l = l2;
}
- pb = (const u8 *)pi;
- outl(((l << 8) | (*pb >> 24)), addr);
+ pb = (u8 *)pi;
+ outl(((l >> 8) | (*pb << 24)), addr);
break;
case 0x3:
count -= 1;
- pb = src;
- l = (*pb++ >> 24);
- pi = (const u32 *)pb;
+ pb = (u8 *)src;
+ l = (*pb++ << 24);
+ pi = (u32 *)pb;
while(count--) {
- l2 = *pi++;
- outl(((l << 24) | (l2 >> 8)), addr);
+ l2 = cpu_to_le32p(pi);
+ pi++;
+ outl(((l >> 24) | (l2 << 8)), addr);
l = l2;
}
- ps = (const u16 *)pi;
- l2 = (*ps++ << 16);
- pb = (const u8 *)ps;
- l2 |= (*pb << 8);
- outl(((l << 24) | (l2 >> 8)), addr);
+ ps = (u16 *)pi;
+ l2 = cpu_to_le16p(ps);
+ ps++;
+ pb = (u8 *)ps;
+ l2 |= (*pb << 16);
+ outl(((l >> 24) | (l2 << 8)), addr);
break;
}
}
@@ -122,7 +138,7 @@ void insb(unsigned long addr, void *dst, unsigned long count)
w = (inb(addr) << 24);
w |= (inb(addr) << 16);
w |= (inb(addr) << 8);
- w |= inb(addr);
+ w |= (inb(addr) << 0);
*pi++ = w;
count -= 4;
}
@@ -139,21 +155,21 @@ void insw(unsigned long addr, void *dst, unsigned long count)
u32 *pi;
if(((unsigned long)ps) & 0x2) {
- *ps++ = inw(addr);
+ *ps++ = le16_to_cpu(inw(addr));
count--;
}
pi = (u32 *)ps;
while(count >= 2) {
u32 w;
- w = (inw(addr) << 16);
- w |= inw(addr);
+ w = (le16_to_cpu(inw(addr)) << 16);
+ w |= (le16_to_cpu(inw(addr)) << 0);
*pi++ = w;
count -= 2;
}
ps = (u16 *)pi;
if(count)
- *ps = inw(addr);
+ *ps = le16_to_cpu(inw(addr));
}
}
@@ -163,7 +179,7 @@ void insl(unsigned long addr, void *dst, unsigned long count)
if((((unsigned long)dst) & 0x3) == 0) {
u32 *pi = dst;
while(count--)
- *pi++ = inl(addr);
+ *pi++ = le32_to_cpu(inl(addr));
} else {
u32 l = 0, l2, *pi;
u16 *ps;
@@ -173,47 +189,48 @@ void insl(unsigned long addr, void *dst, unsigned long count)
case 0x2:
ps = dst;
count -= 1;
- l = inl(addr);
- *ps++ = (l >> 16);
+ l = le32_to_cpu(inl(addr));
+ *ps++ = l;
pi = (u32 *)ps;
while(count--) {
- l2 = inl(addr);
+ l2 = le32_to_cpu(inl(addr));
*pi++ = (l << 16) | (l2 >> 16);
l = l2;
}
ps = (u16 *)pi;
- *ps = (l << 16);
+ *ps = l;
break;
case 0x1:
pb = dst;
count -= 1;
- *pb++ = (l >> 24);
+ l = le32_to_cpu(inl(addr));
+ *pb++ = l >> 24;
ps = (u16 *)pb;
- *ps++ = (l >> 8);
+ *ps++ = ((l >> 8) & 0xffff);
pi = (u32 *)ps;
while(count--) {
- l2 = inl(addr);
- *pi++ = ((l << 24) | (l2 >> 8));
+ l2 = le32_to_cpu(inl(addr));
+ *pi++ = (l << 24) | (l2 >> 8);
l = l2;
}
pb = (u8 *)pi;
- *pb = (l >> 8);
+ *pb = l;
break;
case 0x3:
pb = (u8 *)dst;
count -= 1;
- l = inl(addr);
+ l = le32_to_cpu(inl(addr));
*pb++ = l >> 24;
pi = (u32 *)pb;
while(count--) {
- l2 = inl(addr);
- *pi++ = ((l >> 24) | (l2 << 8));
+ l2 = le32_to_cpu(inl(addr));
+ *pi++ = (l << 8) | (l2 >> 24);
l = l2;
}
ps = (u16 *)pi;
- *ps++ = l >> 8;
+ *ps++ = ((l >> 8) & 0xffff);
pb = (u8 *)ps;
*pb = l;
break;
diff --git a/arch/sparc64/lib/VIScopy.S b/arch/sparc64/lib/VIScopy.S
index bb1d81acd..57cf6b0f1 100644
--- a/arch/sparc64/lib/VIScopy.S
+++ b/arch/sparc64/lib/VIScopy.S
@@ -1,4 +1,4 @@
-/* $Id: VIScopy.S,v 1.20 1999/05/25 16:52:57 jj Exp $
+/* $Id: VIScopy.S,v 1.21 1999/07/30 09:35:35 davem Exp $
* VIScopy.S: High speed copy operations utilizing the UltraSparc
* Visual Instruction Set.
*
@@ -29,19 +29,19 @@
#include <asm/asm_offsets.h>
#define FPU_CLEAN_RETL \
- ldub [%g6 + AOFF_task_tss + AOFF_thread_current_ds], %o1; \
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1; \
VISExit \
clr %o0; \
retl; \
wr %o1, %g0, %asi;
#define FPU_RETL \
- ldub [%g6 + AOFF_task_tss + AOFF_thread_current_ds], %o1; \
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1; \
VISExit \
clr %o0; \
retl; \
wr %o1, %g0, %asi;
#define NORMAL_RETL \
- ldub [%g6 + AOFF_task_tss + AOFF_thread_current_ds], %o1; \
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1; \
clr %o0; \
retl; \
wr %o1, %g0, %asi;
@@ -1009,7 +1009,7 @@ VIScopyfixup_ret:
/* If this is copy_from_user(), zero out the rest of the
* kernel buffer.
*/
- ldub [%g6 + AOFF_task_tss + AOFF_thread_current_ds], %o4
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o4
andcc asi_src, 0x1, %g0
be,pt %icc, 1f
VISExit
diff --git a/arch/sparc64/lib/VIScsum.S b/arch/sparc64/lib/VIScsum.S
index 0326ff057..aad5d941a 100644
--- a/arch/sparc64/lib/VIScsum.S
+++ b/arch/sparc64/lib/VIScsum.S
@@ -1,4 +1,4 @@
-/* $Id: VIScsum.S,v 1.4 1999/05/25 16:53:00 jj Exp $
+/* $Id: VIScsum.S,v 1.5 1999/07/30 09:35:36 davem Exp $
* VIScsum.S: High bandwidth IP checksumming utilizing the UltraSparc
* Visual Instruction Set.
*
@@ -341,7 +341,7 @@ csum_partial:
DO_THE_TRICK(f44,f46,f48,f50,f52,f54,f56,f58,f60,f62,f0,f2,f4,f6,f8,f10,f12,f14)
END_THE_TRICK(f60,f62,f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30)
#ifdef __KERNEL__
- ldub [%g6 + AOFF_task_tss + AOFF_thread_current_ds], %g7
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %g7
#endif
and %o1, 0x3f, %o1 /* IEU0 Group */
#ifdef __KERNEL__
diff --git a/arch/sparc64/lib/VISsave.S b/arch/sparc64/lib/VISsave.S
index a189d0db6..2254ba5c5 100644
--- a/arch/sparc64/lib/VISsave.S
+++ b/arch/sparc64/lib/VISsave.S
@@ -1,4 +1,4 @@
-/* $Id: VISsave.S,v 1.3 1998/10/21 10:36:39 jj Exp $
+/* $Id: VISsave.S,v 1.4 1999/07/30 09:35:37 davem Exp $
* VISsave.S: Code for saving FPU register state for
* VIS routines. One should not call this directly,
* but use macros provided in <asm/visasm.h>.
@@ -19,35 +19,35 @@
.align 32
VISenter:
- ldub [%g6 + AOFF_task_tss + AOFF_thread_fpdepth], %g1
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %g1
brnz,a,pn %g1, 1f
cmp %g1, 1
- stb %g0, [%g6 + AOFF_task_tss + AOFF_thread_fpsaved]
- stx %fsr, [%g6 + AOFF_task_tss + AOFF_thread_xfsr]
+ stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved]
+ stx %fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr]
9: jmpl %g7 + %g0, %g0
nop
1: bne,pn %icc, 2f
srl %g1, 1, %g1
-vis1: ldub [%g6 + AOFF_task_tss + AOFF_thread_fpsaved], %g3
- stx %fsr, [%g6 + AOFF_task_tss + AOFF_thread_xfsr]
+vis1: ldub [%g6 + AOFF_task_thread + AOFF_thread_fpsaved], %g3
+ stx %fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr]
or %g3, %o5, %g3
- stb %g3, [%g6 + AOFF_task_tss + AOFF_thread_fpsaved]
+ stb %g3, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved]
rd %gsr, %g3
clr %g1
ba,pt %xcc, 3f
- stb %g3, [%g6 + AOFF_task_tss + AOFF_thread_gsr]
+ stb %g3, [%g6 + AOFF_task_thread + AOFF_thread_gsr]
2: add %g6, %g1, %g3
cmp %o5, FPRS_DU
be,pn %icc, 6f
sll %g1, 3, %g1
- stb %o5, [%g3 + AOFF_task_tss + AOFF_thread_fpsaved]
+ stb %o5, [%g3 + AOFF_task_thread + AOFF_thread_fpsaved]
rd %gsr, %g2
- stb %g2, [%g3 + AOFF_task_tss + AOFF_thread_gsr]
+ stb %g2, [%g3 + AOFF_task_thread + AOFF_thread_gsr]
add %g6, %g1, %g2
- stx %fsr, [%g2 + AOFF_task_tss + AOFF_thread_xfsr]
+ stx %fsr, [%g2 + AOFF_task_thread + AOFF_thread_xfsr]
sll %g1, 5, %g1
3: andcc %o5, FPRS_DL|FPRS_DU, %g0
be,pn %icc, 9b
@@ -69,10 +69,10 @@ vis1: ldub [%g6 + AOFF_task_tss + AOFF_thread_fpsaved], %g3
jmpl %g7 + %g0, %g0
nop
-6: ldub [%g3 + AOFF_task_tss + AOFF_thread_fpsaved], %o5
+6: ldub [%g3 + AOFF_task_thread + AOFF_thread_fpsaved], %o5
or %o5, FPRS_DU, %o5
add %g6, AOFF_task_fpregs+0x80, %g2
- stb %o5, [%g3 + AOFF_task_tss + AOFF_thread_fpsaved]
+ stb %o5, [%g3 + AOFF_task_thread + AOFF_thread_fpsaved]
sll %g1, 5, %g1
add %g6, AOFF_task_fpregs+0xc0, %g3
@@ -87,11 +87,11 @@ vis1: ldub [%g6 + AOFF_task_tss + AOFF_thread_fpsaved], %g3
.align 32
VISenterhalf:
- ldub [%g6 + AOFF_task_tss + AOFF_thread_fpdepth], %g1
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %g1
brnz,a,pn %g1, 1f
cmp %g1, 1
- stb %g0, [%g6 + AOFF_task_tss + AOFF_thread_fpsaved]
- stx %fsr, [%g6 + AOFF_task_tss + AOFF_thread_xfsr]
+ stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved]
+ stx %fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr]
clr %o5
jmpl %g7 + %g0, %g0
wr %g0, FPRS_FEF, %fprs
@@ -103,12 +103,12 @@ VISenterhalf:
2: addcc %g6, %g1, %g3
sll %g1, 3, %g1
andn %o5, FPRS_DU, %g2
- stb %g2, [%g3 + AOFF_task_tss + AOFF_thread_fpsaved]
+ stb %g2, [%g3 + AOFF_task_thread + AOFF_thread_fpsaved]
rd %gsr, %g2
- stb %g2, [%g3 + AOFF_task_tss + AOFF_thread_gsr]
+ stb %g2, [%g3 + AOFF_task_thread + AOFF_thread_gsr]
add %g6, %g1, %g2
- stx %fsr, [%g2 + AOFF_task_tss + AOFF_thread_xfsr]
+ stx %fsr, [%g2 + AOFF_task_thread + AOFF_thread_xfsr]
sll %g1, 5, %g1
3: andcc %o5, FPRS_DL, %g0
be,pn %icc, 4f
diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S
index 3c0dce16a..cac9d15dd 100644
--- a/arch/sparc64/lib/atomic.S
+++ b/arch/sparc64/lib/atomic.S
@@ -1,4 +1,4 @@
-/* $Id: atomic.S,v 1.1 1999/07/03 22:11:04 davem Exp $
+/* $Id: atomic.S,v 1.2 1999/08/23 05:15:58 davem Exp $
* atomic.S: These things are too big to do inline.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -9,7 +9,10 @@
.text
.align 64
+ .globl atomic_impl_begin, atomic_impl_end
+
.globl __atomic_add
+atomic_impl_begin:
__atomic_add:
lduw [%g1], %g5
add %g5, %g2, %g7
@@ -30,3 +33,4 @@ __atomic_sub:
nop
jmpl %g3 + 8, %g0
sub %g7, %g2, %g2
+atomic_impl_end:
diff --git a/arch/sparc64/lib/blockops.S b/arch/sparc64/lib/blockops.S
index 840839c95..202b57270 100644
--- a/arch/sparc64/lib/blockops.S
+++ b/arch/sparc64/lib/blockops.S
@@ -1,4 +1,4 @@
-/* $Id: blockops.S,v 1.17 1999/05/25 16:52:52 jj Exp $
+/* $Id: blockops.S,v 1.18 1999/07/30 09:35:37 davem Exp $
* blockops.S: UltraSparc block zero optimized routines.
*
* Copyright (C) 1996,1998 David S. Miller (davem@caip.rutgers.edu)
@@ -29,7 +29,7 @@
.type copy_page,@function
copy_page: /* %o0=dest, %o1=src */
VISEntry
- ldx [%g6 + AOFF_task_mm], %o2
+ ldx [%g6 + AOFF_task_active_mm], %o2
sub %o0, %g4, %g1
sethi %uhi(_PAGE_VALID), %g3
sub %o1, %g4, %g2
@@ -107,7 +107,7 @@ copy_page: /* %o0=dest, %o1=src */
.type clear_page,@function
clear_page: /* %o0=dest */
VISEntryHalf
- ldx [%g6 + AOFF_task_mm], %o2
+ ldx [%g6 + AOFF_task_active_mm], %o2
sub %o0, %g4, %g1
sethi %uhi(_PAGE_VALID), %g3
sllx %g3, 32, %g3
diff --git a/arch/sparc64/lib/checksum.S b/arch/sparc64/lib/checksum.S
index d720bb55e..07d10ba42 100644
--- a/arch/sparc64/lib/checksum.S
+++ b/arch/sparc64/lib/checksum.S
@@ -266,7 +266,7 @@ cpc_end:
.globl cpc_handler
cpc_handler:
ldx [%sp + 0x7ff + 128], %g1
- ldub [%g6 + AOFF_task_tss + AOFF_thread_current_ds], %g3
+ ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %g3
sub %g0, EFAULT, %g2
brnz,a,pt %g1, 1f
st %g2, [%g1]
diff --git a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c
index 69286c4b7..315724ec3 100644
--- a/arch/sparc64/lib/debuglocks.c
+++ b/arch/sparc64/lib/debuglocks.c
@@ -1,4 +1,4 @@
-/* $Id: debuglocks.c,v 1.2 1998/10/13 09:07:27 davem Exp $
+/* $Id: debuglocks.c,v 1.3 1999/09/10 10:40:50 davem Exp $
* debuglocks.c: Debugging versions of SMP locking primitives.
*
* Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
@@ -6,8 +6,8 @@
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/spinlock.h>
#include <asm/system.h>
-#include <asm/spinlock.h>
#ifdef __SMP__
diff --git a/arch/sparc64/lib/rwlock.S b/arch/sparc64/lib/rwlock.S
index cee94eef0..74360bf68 100644
--- a/arch/sparc64/lib/rwlock.S
+++ b/arch/sparc64/lib/rwlock.S
@@ -1,4 +1,4 @@
-/* $Id: rwlock.S,v 1.1 1999/07/03 22:11:06 davem Exp $
+/* $Id: rwlock.S,v 1.2 1999/08/23 05:15:58 davem Exp $
* rwlocks.S: These things are too big to do inline.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -7,10 +7,13 @@
.text
.align 64
+ .globl rwlock_impl_begin, rwlock_impl_end
+
/* The non-contention read lock usage is 2 cache lines. */
.globl __read_lock, __read_unlock
/* g1=lock, g3=retpc, g5/g7=scratch */
+rwlock_impl_begin:
__read_lock:
ldsw [%g1], %g5
brlz,pn %g5, __read_wait_for_writer
@@ -78,4 +81,5 @@ __write_lock:
be,pn %icc, 99b
membar #LoadLoad
b,a,pt %xcc, 99b
+rwlock_impl_end:
diff --git a/arch/sparc64/math-emu/.cvsignore b/arch/sparc64/math-emu/.cvsignore
deleted file mode 100644
index 857dd22e9..000000000
--- a/arch/sparc64/math-emu/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.depend
-.*.flags
diff --git a/arch/sparc64/math-emu/Makefile b/arch/sparc64/math-emu/Makefile
index 4437032b5..382366da5 100644
--- a/arch/sparc64/math-emu/Makefile
+++ b/arch/sparc64/math-emu/Makefile
@@ -8,12 +8,7 @@
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := math-emu.o
-O_OBJS := math.o fabsq.o faddq.o fdivq.o fdmulq.o fitoq.o \
- fmovq.o fmulq.o fnegq.o fqtoi.o fqtox.o fsubq.o \
- fxtoq.o fdtoq.o fstoq.o fqtos.o fqtod.o fsqrtq.o \
- fcmpq.o fcmpeq.o \
- fsqrts.o fsqrtd.o fadds.o faddd.o fsubs.o fsubd.o \
- fmuls.o fmuld.o fdivs.o fdivd.o fsmuld.o \
- fstoi.o fdtoi.o fstox.o fdtox.o fstod.o fdtos.o
+O_OBJS := math.o
+CFLAGS += -I. -I$(TOPDIR)/include/math-emu -w
include $(TOPDIR)/Rules.make
diff --git a/arch/sparc64/math-emu/double.h b/arch/sparc64/math-emu/double.h
deleted file mode 100644
index ee581c2da..000000000
--- a/arch/sparc64/math-emu/double.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/* Software floating-point emulation.
- Definitions for IEEE Double Precision
- Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson (rth@cygnus.com),
- Jakub Jelinek (jj@ultra.linux.cz),
- David S. Miller (davem@redhat.com) and
- Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel kid. Go buy yourself a real computer."
-#endif
-
-#if _FP_W_TYPE_SIZE < 64
-#define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE)
-#else
-#define _FP_FRACTBITS_D _FP_W_TYPE_SIZE
-#endif
-
-#define _FP_FRACBITS_D 53
-#define _FP_FRACXBITS_D (_FP_FRACTBITS_D - _FP_FRACBITS_D)
-#define _FP_WFRACBITS_D (_FP_WORKBITS + _FP_FRACBITS_D)
-#define _FP_WFRACXBITS_D (_FP_FRACTBITS_D - _FP_WFRACBITS_D)
-#define _FP_EXPBITS_D 11
-#define _FP_EXPBIAS_D 1023
-#define _FP_EXPMAX_D 2047
-
-#define _FP_QNANBIT_D \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE)
-#define _FP_IMPLBIT_D \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE)
-#define _FP_OVERFLOW_D \
- ((_FP_W_TYPE)1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE)
-
-#if _FP_W_TYPE_SIZE < 64
-
-union _FP_UNION_D
-{
- double flt;
- struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
- unsigned sign : 1;
- unsigned exp : _FP_EXPBITS_D;
- unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
- unsigned frac0 : _FP_W_TYPE_SIZE;
-#else
- unsigned frac0 : _FP_W_TYPE_SIZE;
- unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
- unsigned exp : _FP_EXPBITS_D;
- unsigned sign : 1;
-#endif
- } bits __attribute__((packed));
-};
-
-#define FP_DECL_D(X) _FP_DECL(2,X)
-#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_2(D,X,val)
-#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_2_P(D,X,val)
-#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_2(D,val,X)
-#define FP_PACK_RAW_DP(val,X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_2_P(D,val,X); \
- } while (0)
-
-#define FP_UNPACK_D(X,val) \
- do { \
- _FP_UNPACK_RAW_2(D,X,val); \
- _FP_UNPACK_CANONICAL(D,2,X); \
- } while (0)
-
-#define FP_UNPACK_DP(X,val) \
- do { \
- _FP_UNPACK_RAW_2_P(D,X,val); \
- _FP_UNPACK_CANONICAL(D,2,X); \
- } while (0)
-
-#define FP_PACK_D(val,X) \
- do { \
- _FP_PACK_CANONICAL(D,2,X); \
- _FP_PACK_RAW_2(D,val,X); \
- } while (0)
-
-#define FP_PACK_DP(val,X) \
- do { \
- _FP_PACK_CANONICAL(D,2,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_2_P(D,val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,2,X)
-#define FP_NEG_D(R,X) _FP_NEG(D,2,R,X)
-#define FP_ADD_D(R,X,Y) _FP_ADD(D,2,R,X,Y)
-#define FP_SUB_D(R,X,Y) _FP_SUB(D,2,R,X,Y)
-#define FP_MUL_D(R,X,Y) _FP_MUL(D,2,R,X,Y)
-#define FP_DIV_D(R,X,Y) _FP_DIV(D,2,R,X,Y)
-#define FP_SQRT_D(R,X) _FP_SQRT(D,2,R,X)
-#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q)
-
-#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,2,r,X,Y,un)
-#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,2,r,X,Y)
-
-#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,2,r,X,rsz,rsg)
-#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,2,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_2(X)
-#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_2(X)
-
-#else
-
-union _FP_UNION_D
-{
- double flt;
- struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
- unsigned sign : 1;
- unsigned exp : _FP_EXPBITS_D;
- unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
-#else
- unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
- unsigned exp : _FP_EXPBITS_D;
- unsigned sign : 1;
-#endif
- } bits __attribute__((packed));
-};
-
-#define FP_DECL_D(X) _FP_DECL(1,X)
-#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_1(D,X,val)
-#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_1_P(D,X,val)
-#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_1(D,val,X)
-#define FP_PACK_RAW_DP(val,X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_1_P(D,val,X); \
- } while (0)
-
-#define FP_UNPACK_D(X,val) \
- do { \
- _FP_UNPACK_RAW_1(D,X,val); \
- _FP_UNPACK_CANONICAL(D,1,X); \
- } while (0)
-
-#define FP_UNPACK_DP(X,val) \
- do { \
- _FP_UNPACK_RAW_1_P(D,X,val); \
- _FP_UNPACK_CANONICAL(D,1,X); \
- } while (0)
-
-#define FP_PACK_D(val,X) \
- do { \
- _FP_PACK_CANONICAL(D,1,X); \
- _FP_PACK_RAW_1(D,val,X); \
- } while (0)
-
-#define FP_PACK_DP(val,X) \
- do { \
- _FP_PACK_CANONICAL(D,1,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_1_P(D,val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,1,X)
-#define FP_NEG_D(R,X) _FP_NEG(D,1,R,X)
-#define FP_ADD_D(R,X,Y) _FP_ADD(D,1,R,X,Y)
-#define FP_SUB_D(R,X,Y) _FP_SUB(D,1,R,X,Y)
-#define FP_MUL_D(R,X,Y) _FP_MUL(D,1,R,X,Y)
-#define FP_DIV_D(R,X,Y) _FP_DIV(D,1,R,X,Y)
-#define FP_SQRT_D(R,X) _FP_SQRT(D,1,R,X)
-#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q)
-
-/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
- the target machine. */
-
-#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,1,r,X,Y,un)
-#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,1,r,X,Y)
-
-#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,1,r,X,rsz,rsg)
-#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,1,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_1(X)
-#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_1(X)
-
-#endif /* W_TYPE_SIZE < 64 */
diff --git a/arch/sparc64/math-emu/extended.h b/arch/sparc64/math-emu/extended.h
deleted file mode 100644
index 4a1d7e711..000000000
--- a/arch/sparc64/math-emu/extended.h
+++ /dev/null
@@ -1,388 +0,0 @@
-/* Software floating-point emulation.
- Definitions for IEEE Extended Precision.
- Copyright (C) 1999 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Jakub Jelinek (jj@ultra.linux.cz).
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel, kid. Go buy yourself a real computer."
-#endif
-
-#if _FP_W_TYPE_SIZE < 64
-#define _FP_FRACTBITS_E (4*_FP_W_TYPE_SIZE)
-#else
-#define _FP_FRACTBITS_E (2*_FP_W_TYPE_SIZE)
-#endif
-
-#define _FP_FRACBITS_E 64
-#define _FP_FRACXBITS_E (_FP_FRACTBITS_E - _FP_FRACBITS_E)
-#define _FP_WFRACBITS_E (_FP_WORKBITS + _FP_FRACBITS_E)
-#define _FP_WFRACXBITS_E (_FP_FRACTBITS_E - _FP_WFRACBITS_E)
-#define _FP_EXPBITS_E 15
-#define _FP_EXPBIAS_E 16383
-#define _FP_EXPMAX_E 32767
-
-#define _FP_QNANBIT_E \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2) % _FP_W_TYPE_SIZE)
-#define _FP_IMPLBIT_E \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1) % _FP_W_TYPE_SIZE)
-#define _FP_OVERFLOW_E \
- ((_FP_W_TYPE)1 << (_FP_WFRACBITS_E % _FP_W_TYPE_SIZE))
-
-#if _FP_W_TYPE_SIZE < 64
-
-union _FP_UNION_E
-{
- long double flt;
- struct
- {
-#if __BYTE_ORDER == __BIG_ENDIAN
- unsigned long pad1 : _FP_W_TYPE_SIZE;
- unsigned long pad2 : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
- unsigned long sign : 1;
- unsigned long exp : _FP_EXPBITS_E;
- unsigned long frac1 : _FP_W_TYPE_SIZE;
- unsigned long frac0 : _FP_W_TYPE_SIZE;
-#else
- unsigned long frac0 : _FP_W_TYPE_SIZE;
- unsigned long frac1 : _FP_W_TYPE_SIZE;
- unsigned exp : _FP_EXPBITS_E;
- unsigned sign : 1;
-#endif /* not bigendian */
- } bits __attribute__((packed));
-};
-
-
-#define FP_DECL_E(X) _FP_DECL(4,X)
-
-#define FP_UNPACK_RAW_E(X, val) \
- do { \
- union _FP_UNION_E _flo; _flo.flt = (val); \
- \
- X##_f[2] = 0; X##_f[3] = 0; \
- X##_f[0] = _flo.bits.frac0; \
- X##_f[1] = _flo.bits.frac1; \
- X##_e = _flo.bits.exp; \
- X##_s = _flo.bits.sign; \
- if (!X##_e && (X##_f[1] || X##_f[0]) \
- && !(X##_f[1] & _FP_IMPLBIT_E)) \
- { \
- X##_e++; \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- } \
- } while (0)
-
-#define FP_UNPACK_RAW_EP(X, val) \
- do { \
- union _FP_UNION_E *_flo = \
- (union _FP_UNION_E *)(val); \
- \
- X##_f[2] = 0; X##_f[3] = 0; \
- X##_f[0] = _flo->bits.frac0; \
- X##_f[1] = _flo->bits.frac1; \
- X##_e = _flo->bits.exp; \
- X##_s = _flo->bits.sign; \
- if (!X##_e && (X##_f[1] || X##_f[0]) \
- && !(X##_f[1] & _FP_IMPLBIT_E)) \
- { \
- X##_e++; \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- } \
- } while (0)
-
-#define FP_PACK_RAW_E(val, X) \
- do { \
- union _FP_UNION_E _flo; \
- \
- if (X##_e) X##_f[1] |= _FP_IMPLBIT_E; \
- else X##_f[1] &= ~(_FP_IMPLBIT_E); \
- _flo.bits.frac0 = X##_f[0]; \
- _flo.bits.frac1 = X##_f[1]; \
- _flo.bits.exp = X##_e; \
- _flo.bits.sign = X##_s; \
- \
- (val) = _flo.flt; \
- } while (0)
-
-#define FP_PACK_RAW_EP(val, X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- { \
- union _FP_UNION_E *_flo = \
- (union _FP_UNION_E *)(val); \
- \
- if (X##_e) X##_f[1] |= _FP_IMPLBIT_E; \
- else X##_f[1] &= ~(_FP_IMPLBIT_E); \
- _flo->bits.frac0 = X##_f[0]; \
- _flo->bits.frac1 = X##_f[1]; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } \
- } while (0)
-
-#define FP_UNPACK_E(X,val) \
- do { \
- FP_UNPACK_RAW_E(X,val); \
- _FP_UNPACK_CANONICAL(E,4,X); \
- } while (0)
-
-#define FP_UNPACK_EP(X,val) \
- do { \
- FP_UNPACK_RAW_2_P(X,val); \
- _FP_UNPACK_CANONICAL(E,4,X); \
- } while (0)
-
-#define FP_PACK_E(val,X) \
- do { \
- _FP_PACK_CANONICAL(E,4,X); \
- FP_PACK_RAW_E(val,X); \
- } while (0)
-
-#define FP_PACK_EP(val,X) \
- do { \
- _FP_PACK_CANONICAL(E,4,X); \
- FP_PACK_RAW_EP(val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,4,X)
-#define FP_NEG_E(R,X) _FP_NEG(E,4,R,X)
-#define FP_ADD_E(R,X,Y) _FP_ADD(E,4,R,X,Y)
-#define FP_SUB_E(R,X,Y) _FP_SUB(E,4,R,X,Y)
-#define FP_MUL_E(R,X,Y) _FP_MUL(E,4,R,X,Y)
-#define FP_DIV_E(R,X,Y) _FP_DIV(E,4,R,X,Y)
-#define FP_SQRT_E(R,X) _FP_SQRT(E,4,R,X)
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- * This has special _E version because standard _4 square
- * root would not work (it has to start normally with the
- * second word and not the first), but as we have to do it
- * anyway, we optimize it by doing most of the calculations
- * in two UWtype registers instead of four.
- */
-
-#define _FP_SQRT_MEAT_E(R, S, T, X, q) \
- do { \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- _FP_FRAC_SRL_4(X, (_FP_WORKBITS)); \
- while (q) \
- { \
- T##_f[1] = S##_f[1] + q; \
- if (T##_f[1] <= X##_f[1]) \
- { \
- S##_f[1] = T##_f[1] + q; \
- X##_f[1] -= T##_f[1]; \
- R##_f[1] += q; \
- } \
- _FP_FRAC_SLL_2(X, 1); \
- q >>= 1; \
- } \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- while (q) \
- { \
- T##_f[0] = S##_f[0] + q; \
- T##_f[1] = S##_f[1]; \
- if (T##_f[1] < X##_f[1] || \
- (T##_f[1] == X##_f[1] && \
- T##_f[0] <= X##_f[0])) \
- { \
- S##_f[0] = T##_f[0] + q; \
- S##_f[1] += (T##_f[0] > S##_f[0]); \
- _FP_FRAC_DEC_2(X, T); \
- R##_f[0] += q; \
- } \
- _FP_FRAC_SLL_2(X, 1); \
- q >>= 1; \
- } \
- _FP_FRAC_SLL_4(R, (_FP_WORKBITS)); \
- if (X##_f[0] | X##_f[1]) \
- { \
- if (S##_f[1] < X##_f[1] || \
- (S##_f[1] == X##_f[1] && \
- S##_f[0] < X##_f[0])) \
- R##_f[0] |= _FP_WORK_ROUND; \
- R##_f[0] |= _FP_WORK_STICKY; \
- } \
- } while (0)
-
-#define FP_CMP_E(r,X,Y,un) _FP_CMP(E,4,r,X,Y,un)
-#define FP_CMP_EQ_E(r,X,Y) _FP_CMP_EQ(E,4,r,X,Y)
-
-#define FP_TO_INT_E(r,X,rsz,rsg) _FP_TO_INT(E,4,r,X,rsz,rsg)
-#define FP_FROM_INT_E(X,r,rs,rt) _FP_FROM_INT(E,4,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_E(X) (X##_f[2])
-#define _FP_FRAC_HIGH_RAW_E(X) (X##_f[1])
-
-#else /* not _FP_W_TYPE_SIZE < 64 */
-union _FP_UNION_E
-{
- long double flt /* __attribute__((mode(TF))) */ ;
- struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
- unsigned long pad : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
- unsigned sign : 1;
- unsigned exp : _FP_EXPBITS_E;
- unsigned long frac : _FP_W_TYPE_SIZE;
-#else
- unsigned long frac : _FP_W_TYPE_SIZE;
- unsigned exp : _FP_EXPBITS_E;
- unsigned sign : 1;
-#endif
- } bits;
-};
-
-#define FP_DECL_E(X) _FP_DECL(2,X)
-
-#define FP_UNPACK_RAW_E(X, val) \
- do { \
- union _FP_UNION_E _flo; _flo.flt = (val); \
- \
- X##_f0 = _flo.bits.frac; \
- X##_f1 = 0; \
- X##_e = _flo.bits.exp; \
- X##_s = _flo.bits.sign; \
- if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E)) \
- { \
- X##_e++; \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- } \
- } while (0)
-
-#define FP_UNPACK_RAW_EP(X, val) \
- do { \
- union _FP_UNION_E *_flo = \
- (union _FP_UNION_E *)(val); \
- \
- X##_f0 = _flo->bits.frac; \
- X##_f1 = 0; \
- X##_e = _flo->bits.exp; \
- X##_s = _flo->bits.sign; \
- if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E)) \
- { \
- X##_e++; \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- } \
- } while (0)
-
-#define FP_PACK_RAW_E(val, X) \
- do { \
- union _FP_UNION_E _flo; \
- \
- if (X##_e) X##_f0 |= _FP_IMPLBIT_E; \
- else X##_f0 &= ~(_FP_IMPLBIT_E); \
- _flo.bits.frac = X##_f0; \
- _flo.bits.exp = X##_e; \
- _flo.bits.sign = X##_s; \
- \
- (val) = _flo.flt; \
- } while (0)
-
-#define FP_PACK_RAW_EP(fs, val, X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- { \
- union _FP_UNION_E *_flo = \
- (union _FP_UNION_E *)(val); \
- \
- if (X##_e) X##_f0 |= _FP_IMPLBIT_E; \
- else X##_f0 &= ~(_FP_IMPLBIT_E); \
- _flo->bits.frac = X##_f0; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } \
- } while (0)
-
-
-#define FP_UNPACK_E(X,val) \
- do { \
- FP_UNPACK_RAW_E(X,val); \
- _FP_UNPACK_CANONICAL(E,2,X); \
- } while (0)
-
-#define FP_UNPACK_EP(X,val) \
- do { \
- FP_UNPACK_RAW_EP(X,val); \
- _FP_UNPACK_CANONICAL(E,2,X); \
- } while (0)
-
-#define FP_PACK_E(val,X) \
- do { \
- _FP_PACK_CANONICAL(E,2,X); \
- FP_PACK_RAW_E(val,X); \
- } while (0)
-
-#define FP_PACK_EP(val,X) \
- do { \
- _FP_PACK_CANONICAL(E,2,X); \
- FP_PACK_RAW_EP(val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,2,X)
-#define FP_NEG_E(R,X) _FP_NEG(E,2,R,X)
-#define FP_ADD_E(R,X,Y) _FP_ADD(E,2,R,X,Y)
-#define FP_SUB_E(R,X,Y) _FP_SUB(E,2,R,X,Y)
-#define FP_MUL_E(R,X,Y) _FP_MUL(E,2,R,X,Y)
-#define FP_DIV_E(R,X,Y) _FP_DIV(E,2,R,X,Y)
-#define FP_SQRT_E(R,X) _FP_SQRT(E,2,R,X)
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- * We optimize it by doing most of the calculations
- * in one UWtype registers instead of two, although we don't
- * have to.
- */
-#define _FP_SQRT_MEAT_E(R, S, T, X, q) \
- do { \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- _FP_FRAC_SRL_2(X, (_FP_WORKBITS)); \
- while (q) \
- { \
- T##_f0 = S##_f0 + q; \
- if (T##_f0 <= X##_f0) \
- { \
- S##_f0 = T##_f0 + q; \
- X##_f0 -= T##_f0; \
- R##_f0 += q; \
- } \
- _FP_FRAC_SLL_1(X, 1); \
- q >>= 1; \
- } \
- _FP_FRAC_SLL_2(R, (_FP_WORKBITS)); \
- if (X##_f0) \
- { \
- if (S##_f0 < X##_f0) \
- R##_f0 |= _FP_WORK_ROUND; \
- R##_f0 |= _FP_WORK_STICKY; \
- } \
- } while (0)
-
-#define FP_CMP_E(r,X,Y,un) _FP_CMP(E,2,r,X,Y,un)
-#define FP_CMP_EQ_E(r,X,Y) _FP_CMP_EQ(E,2,r,X,Y)
-
-#define FP_TO_INT_E(r,X,rsz,rsg) _FP_TO_INT(E,2,r,X,rsz,rsg)
-#define FP_FROM_INT_E(X,r,rs,rt) _FP_FROM_INT(E,2,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_E(X) (X##_f1)
-#define _FP_FRAC_HIGH_RAW_E(X) (X##_f0)
-
-#endif /* not _FP_W_TYPE_SIZE < 64 */
diff --git a/arch/sparc64/math-emu/fabsq.c b/arch/sparc64/math-emu/fabsq.c
deleted file mode 100644
index 22da43d71..000000000
--- a/arch/sparc64/math-emu/fabsq.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $Id: fabsq.c,v 1.5 1999/05/28 13:42:27 jj Exp $
- * arch/sparc64/math-emu/fabsq.c
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@ultra.linux.cz)
- *
- */
-
-int FABSQ(unsigned long *rd, unsigned long *rs2)
-{
- rd[0] = rs2[0] & 0x7fffffffffffffffUL;
- rd[1] = rs2[1];
- return 0;
-}
diff --git a/arch/sparc64/math-emu/faddd.c b/arch/sparc64/math-emu/faddd.c
deleted file mode 100644
index 7ce9de721..000000000
--- a/arch/sparc64/math-emu/faddd.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: faddd.c,v 1.4 1999/05/28 13:43:17 jj Exp $
- * arch/sparc64/math-emu/faddd.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FADDD(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
-
- FP_UNPACK_DP(A, rs1);
- FP_UNPACK_DP(B, rs2);
- FP_ADD_D(R, A, B);
- FP_PACK_DP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/faddq.c b/arch/sparc64/math-emu/faddq.c
deleted file mode 100644
index c555585af..000000000
--- a/arch/sparc64/math-emu/faddq.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: faddq.c,v 1.4 1999/05/28 13:43:19 jj Exp $
- * arch/sparc64/math-emu/faddq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FADDQ(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
-
- FP_UNPACK_QP(A, rs1);
- FP_UNPACK_QP(B, rs2);
- FP_ADD_Q(R, A, B);
- FP_PACK_QP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fadds.c b/arch/sparc64/math-emu/fadds.c
deleted file mode 100644
index 73e865b4a..000000000
--- a/arch/sparc64/math-emu/fadds.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: fadds.c,v 1.4 1999/05/28 13:43:25 jj Exp $
- * arch/sparc64/math-emu/fadds.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FADDS(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
-
- FP_UNPACK_SP(A, rs1);
- FP_UNPACK_SP(B, rs2);
- FP_ADD_S(R, A, B);
- FP_PACK_SP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fcmpeq.c b/arch/sparc64/math-emu/fcmpeq.c
deleted file mode 100644
index 3e418b9e5..000000000
--- a/arch/sparc64/math-emu/fcmpeq.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* $Id: fcmpeq.c,v 1.5 1999/05/28 13:43:29 jj Exp $
- * arch/sparc64/math-emu/fcmpeq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FCMPEQ(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B);
- long ret;
- long fccno = (long)rd;
- unsigned long fsr;
-
- FP_UNPACK_RAW_QP(A, rs1);
- FP_UNPACK_RAW_QP(B, rs2);
- FP_CMP_Q(ret, B, A, 3);
- if (ret == 3)
- FP_SET_EXCEPTION(FP_EX_INVALID);
- if (!FP_INHIBIT_RESULTS) {
- rd = (void *)(((long)rd)&~3);
- if (ret == -1) ret = 2;
- fsr = current->tss.xfsr[0];
- switch (fccno) {
- case 0: fsr &= ~0xc00; fsr |= (ret << 10); break;
- case 1: fsr &= ~0x300000000UL; fsr |= (ret << 32); break;
- case 2: fsr &= ~0xc00000000UL; fsr |= (ret << 34); break;
- case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break;
- }
- current->tss.xfsr[0] = fsr;
- }
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fcmpq.c b/arch/sparc64/math-emu/fcmpq.c
deleted file mode 100644
index b95e62d20..000000000
--- a/arch/sparc64/math-emu/fcmpq.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* $Id: fcmpq.c,v 1.5 1999/05/28 13:43:33 jj Exp $
- * arch/sparc64/math-emu/fcmpq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FCMPQ(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B);
- long ret;
- long fccno = (long)rd;
- unsigned long fsr;
-
- FP_UNPACK_RAW_QP(A, rs1);
- FP_UNPACK_RAW_QP(B, rs2);
- FP_CMP_Q(ret, B, A, 3);
- if (ret == 3 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
- FP_SET_EXCEPTION(FP_EX_INVALID);
- if (!FP_INHIBIT_RESULTS) {
- rd = (void *)(((long)rd)&~3);
- if (ret == -1) ret = 2;
- fsr = current->tss.xfsr[0];
- switch (fccno) {
- case 0: fsr &= ~0xc00; fsr |= (ret << 10); break;
- case 1: fsr &= ~0x300000000UL; fsr |= (ret << 32); break;
- case 2: fsr &= ~0xc00000000UL; fsr |= (ret << 34); break;
- case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break;
- }
- current->tss.xfsr[0] = fsr;
- }
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fdivd.c b/arch/sparc64/math-emu/fdivd.c
deleted file mode 100644
index c6f4e9810..000000000
--- a/arch/sparc64/math-emu/fdivd.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: fdivd.c,v 1.4 1999/05/28 13:43:36 jj Exp $
- * arch/sparc64/math-emu/fdivd.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FDIVD(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
-
- FP_UNPACK_DP(A, rs1);
- FP_UNPACK_DP(B, rs2);
- FP_DIV_D(R, A, B);
- FP_PACK_DP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fdivq.c b/arch/sparc64/math-emu/fdivq.c
deleted file mode 100644
index f154bcdb8..000000000
--- a/arch/sparc64/math-emu/fdivq.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: fdivq.c,v 1.4 1999/05/28 13:43:41 jj Exp $
- * arch/sparc64/math-emu/fdivq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FDIVQ(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
-
- FP_UNPACK_QP(A, rs1);
- FP_UNPACK_QP(B, rs2);
- FP_DIV_Q(R, A, B);
- FP_PACK_QP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fdivs.c b/arch/sparc64/math-emu/fdivs.c
deleted file mode 100644
index dd317751f..000000000
--- a/arch/sparc64/math-emu/fdivs.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/* $Id: fdivs.c,v 1.4 1999/05/28 13:43:45 jj Exp $
- * arch/sparc64/math-emu/fdivs.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FDIVS(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
-
- FP_UNPACK_SP(A, rs1);
- FP_UNPACK_SP(B, rs2);
- FP_DIV_S(R, A, B);
- FP_PACK_SP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
-
diff --git a/arch/sparc64/math-emu/fdmulq.c b/arch/sparc64/math-emu/fdmulq.c
deleted file mode 100644
index d8b99ecc0..000000000
--- a/arch/sparc64/math-emu/fdmulq.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/* $Id: fdmulq.c,v 1.4 1999/05/28 13:43:48 jj Exp $
- * arch/sparc64/math-emu/fdmulq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "double.h"
-
-int FDMULQ(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_D(IN); FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
-
- FP_UNPACK_DP(IN, rs1);
- FP_CONV(Q,D,2,1,A,IN);
- FP_UNPACK_DP(IN, rs2);
- FP_CONV(Q,D,2,1,B,IN);
- FP_MUL_Q(R, A, B);
- FP_PACK_QP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fdtoi.c b/arch/sparc64/math-emu/fdtoi.c
deleted file mode 100644
index 8c616c07a..000000000
--- a/arch/sparc64/math-emu/fdtoi.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* $Id: fdtoi.c,v 1.3 1999/05/28 13:43:52 jj Exp $
- * arch/sparc64/math-emu/fdtoi.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#define FP_ROUNDMODE FP_RND_ZERO
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FDTOI(int *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_D(A);
- int r;
-
- FP_UNPACK_DP(A, rs2);
- FP_TO_INT_D(r, A, 32, 1);
- if (!FP_INHIBIT_RESULTS)
- *rd = r;
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fdtoq.c b/arch/sparc64/math-emu/fdtoq.c
deleted file mode 100644
index 0607525d6..000000000
--- a/arch/sparc64/math-emu/fdtoq.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: fdtoq.c,v 1.4 1999/05/28 13:43:56 jj Exp $
- * arch/sparc64/math-emu/fdtoq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "double.h"
-
-int FDTOQ(void *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_Q(R);
-
- FP_UNPACK_DP(A, rs2);
- FP_CONV(Q,D,2,1,R,A);
- FP_PACK_QP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fdtos.c b/arch/sparc64/math-emu/fdtos.c
deleted file mode 100644
index 1a86a96c7..000000000
--- a/arch/sparc64/math-emu/fdtos.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: fdtos.c,v 1.4 1999/05/28 13:43:58 jj Exp $
- * arch/sparc64/math-emu/fdtos.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
-
-int FDTOS(void *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_S(R);
-
- FP_UNPACK_DP(A, rs2);
- FP_CONV(S,D,1,1,R,A);
- FP_PACK_SP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fdtox.c b/arch/sparc64/math-emu/fdtox.c
deleted file mode 100644
index 465d9962b..000000000
--- a/arch/sparc64/math-emu/fdtox.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* $Id: fdtox.c,v 1.3 1999/05/28 13:44:02 jj Exp $
- * arch/sparc64/math-emu/fdtox.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#define FP_ROUNDMODE FP_RND_ZERO
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FDTOX(long *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_D(A);
- long r;
-
- FP_UNPACK_DP(A, rs2);
- FP_TO_INT_D(r, A, 64, 1);
- if (!FP_INHIBIT_RESULTS)
- *rd = r;
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fitoq.c b/arch/sparc64/math-emu/fitoq.c
deleted file mode 100644
index 3a9af3073..000000000
--- a/arch/sparc64/math-emu/fitoq.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* $Id: fitoq.c,v 1.5 1999/05/28 13:44:06 jj Exp $
- * arch/sparc64/math-emu/fitoq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FITOQ(void *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_Q(R);
- int a = *(int *)rs2;
-
- FP_FROM_INT_Q(R, a, 32, int);
- FP_PACK_QP(rd, R);
- return 0;
-}
diff --git a/arch/sparc64/math-emu/fmovq.c b/arch/sparc64/math-emu/fmovq.c
deleted file mode 100644
index ee5a7e4f5..000000000
--- a/arch/sparc64/math-emu/fmovq.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $Id: fmovq.c,v 1.2 1999/05/28 13:44:09 jj Exp $
- * arch/sparc64/math-emu/fmovq.c
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@ultra.linux.cz)
- *
- */
-
-int FMOVQ(unsigned long *rd, unsigned long *rs2)
-{
- rd[0] = rs2[0];
- rd[1] = rs2[1];
- return 0;
-}
diff --git a/arch/sparc64/math-emu/fmuld.c b/arch/sparc64/math-emu/fmuld.c
deleted file mode 100644
index 2dde7c271..000000000
--- a/arch/sparc64/math-emu/fmuld.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: fmuld.c,v 1.4 1999/05/28 13:44:11 jj Exp $
- * arch/sparc64/math-emu/fmuld.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FMULD(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
-
- FP_UNPACK_DP(A, rs1);
- FP_UNPACK_DP(B, rs2);
- FP_MUL_D(R, A, B);
- FP_PACK_DP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fmulq.c b/arch/sparc64/math-emu/fmulq.c
deleted file mode 100644
index 227d1f928..000000000
--- a/arch/sparc64/math-emu/fmulq.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: fmulq.c,v 1.4 1999/05/28 13:44:14 jj Exp $
- * arch/sparc64/math-emu/fmulq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FMULQ(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
-
- FP_UNPACK_QP(A, rs1);
- FP_UNPACK_QP(B, rs2);
- FP_MUL_Q(R, A, B);
- FP_PACK_QP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fmuls.c b/arch/sparc64/math-emu/fmuls.c
deleted file mode 100644
index 623c4aa4c..000000000
--- a/arch/sparc64/math-emu/fmuls.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: fmuls.c,v 1.4 1999/05/28 13:44:18 jj Exp $
- * arch/sparc64/math-emu/fmuls.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FMULS(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
-
- FP_UNPACK_SP(A, rs1);
- FP_UNPACK_SP(B, rs2);
- FP_MUL_S(R, A, B);
- FP_PACK_SP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fnegq.c b/arch/sparc64/math-emu/fnegq.c
deleted file mode 100644
index 4e4a68795..000000000
--- a/arch/sparc64/math-emu/fnegq.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $Id: fnegq.c,v 1.6 1999/05/28 13:44:21 jj Exp $
- * arch/sparc64/math-emu/fnegq.c
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@ultra.linux.cz)
- *
- */
-
-int FNEGQ(unsigned long *rd, unsigned long *rs2)
-{
- rd[0] = rs2[0] ^ 0x8000000000000000UL;
- rd[1] = rs2[1];
- return 0;
-}
diff --git a/arch/sparc64/math-emu/fqtod.c b/arch/sparc64/math-emu/fqtod.c
deleted file mode 100644
index 55b6d4443..000000000
--- a/arch/sparc64/math-emu/fqtod.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: fqtod.c,v 1.4 1999/05/28 13:44:24 jj Exp $
- * arch/sparc64/math-emu/fqtod.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "double.h"
-
-int FQTOD(void *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_D(R);
-
- FP_UNPACK_QP(A, rs2);
- FP_CONV(D,Q,1,2,R,A);
- FP_PACK_DP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fqtoi.c b/arch/sparc64/math-emu/fqtoi.c
deleted file mode 100644
index a1b8ea741..000000000
--- a/arch/sparc64/math-emu/fqtoi.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* $Id: fqtoi.c,v 1.4 1999/05/28 13:44:26 jj Exp $
- * arch/sparc64/math-emu/fqtoi.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#define FP_ROUNDMODE FP_RND_ZERO
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FQTOI(int *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_Q(A);
- int r;
-
- FP_UNPACK_QP(A, rs2);
- FP_TO_INT_Q(r, A, 32, 1);
- if (!FP_INHIBIT_RESULTS)
- *rd = r;
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fqtos.c b/arch/sparc64/math-emu/fqtos.c
deleted file mode 100644
index 6edb6aaca..000000000
--- a/arch/sparc64/math-emu/fqtos.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: fqtos.c,v 1.4 1999/05/28 13:44:30 jj Exp $
- * arch/sparc64/math-emu/fqtos.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "single.h"
-
-int FQTOS(void *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_S(R);
-
- FP_UNPACK_QP(A, rs2);
- FP_CONV(S,Q,1,2,R,A);
- FP_PACK_SP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fqtox.c b/arch/sparc64/math-emu/fqtox.c
deleted file mode 100644
index 458061fb0..000000000
--- a/arch/sparc64/math-emu/fqtox.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* $Id: fqtox.c,v 1.4 1999/05/28 13:44:34 jj Exp $
- * arch/sparc64/math-emu/fqtox.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#define FP_ROUNDMODE FP_RND_ZERO
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FQTOX(long *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_Q(A);
- long r;
-
- FP_UNPACK_QP(A, rs2);
- FP_TO_INT_Q(r, A, 64, 1);
- if (!FP_INHIBIT_RESULTS)
- *rd = r;
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fsmuld.c b/arch/sparc64/math-emu/fsmuld.c
deleted file mode 100644
index 92b86288f..000000000
--- a/arch/sparc64/math-emu/fsmuld.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/* $Id: fsmuld.c,v 1.4 1999/05/28 13:44:37 jj Exp $
- * arch/sparc64/math-emu/fsmuld.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
-
-int FSMULD(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_S(IN); FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
-
- FP_UNPACK_SP(IN, rs1);
- FP_CONV(D,S,1,1,A,IN);
- FP_UNPACK_SP(IN, rs2);
- FP_CONV(D,S,1,1,B,IN);
- FP_MUL_D(R, A, B);
- FP_PACK_DP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fsqrtd.c b/arch/sparc64/math-emu/fsqrtd.c
deleted file mode 100644
index 5d02ed5c0..000000000
--- a/arch/sparc64/math-emu/fsqrtd.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* $Id: fsqrtd.c,v 1.4 1999/05/28 13:44:39 jj Exp $
- * arch/sparc64/math-emu/fsqrtd.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FSQRTD(void *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(R);
-
- FP_UNPACK_DP(A, rs2);
- FP_SQRT_D(R, A);
- FP_PACK_DP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fsqrtq.c b/arch/sparc64/math-emu/fsqrtq.c
deleted file mode 100644
index bb2e6c51e..000000000
--- a/arch/sparc64/math-emu/fsqrtq.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* $Id: fsqrtq.c,v 1.5 1999/05/28 13:44:44 jj Exp $
- * arch/sparc64/math-emu/fsqrtq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FSQRTQ(void *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(R);
-
- FP_UNPACK_QP(A, rs2);
- FP_SQRT_Q(R, A);
- FP_PACK_QP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fsqrts.c b/arch/sparc64/math-emu/fsqrts.c
deleted file mode 100644
index ee32737ed..000000000
--- a/arch/sparc64/math-emu/fsqrts.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* $Id: fsqrts.c,v 1.4 1999/05/28 13:44:48 jj Exp $
- * arch/sparc64/math-emu/fsqrts.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FSQRTS(void *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(R);
-
- FP_UNPACK_SP(A, rs2);
- FP_SQRT_S(R, A);
- FP_PACK_SP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fstod.c b/arch/sparc64/math-emu/fstod.c
deleted file mode 100644
index 3c7a974ca..000000000
--- a/arch/sparc64/math-emu/fstod.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: fstod.c,v 1.4 1999/05/28 13:44:51 jj Exp $
- * arch/sparc64/math-emu/fstod.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
-
-int FSTOD(void *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_D(R);
-
- FP_UNPACK_SP(A, rs2);
- FP_CONV(D,S,1,1,R,A);
- FP_PACK_DP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fstoi.c b/arch/sparc64/math-emu/fstoi.c
deleted file mode 100644
index 40ef2badd..000000000
--- a/arch/sparc64/math-emu/fstoi.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* $Id: fstoi.c,v 1.3 1999/05/28 13:44:54 jj Exp $
- * arch/sparc64/math-emu/fstoi.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#define FP_ROUNDMODE FP_RND_ZERO
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FSTOI(int *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_S(A);
- int r;
-
- FP_UNPACK_SP(A, rs2);
- FP_TO_INT_S(r, A, 32, 1);
- if (!FP_INHIBIT_RESULTS)
- *rd = r;
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fstoq.c b/arch/sparc64/math-emu/fstoq.c
deleted file mode 100644
index d23e187c6..000000000
--- a/arch/sparc64/math-emu/fstoq.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* $Id: fstoq.c,v 1.4 1999/05/28 13:44:58 jj Exp $
- * arch/sparc64/math-emu/fstoq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "single.h"
-
-int FSTOQ(void *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_Q(R);
-
- FP_UNPACK_SP(A, rs2);
- FP_CONV(Q,S,2,1,R,A);
- FP_PACK_QP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fstox.c b/arch/sparc64/math-emu/fstox.c
deleted file mode 100644
index fecca41d3..000000000
--- a/arch/sparc64/math-emu/fstox.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* $Id: fstox.c,v 1.3 1999/05/28 13:45:01 jj Exp $
- * arch/sparc64/math-emu/fstox.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#define FP_ROUNDMODE FP_RND_ZERO
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FSTOX(long *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_S(A);
- long r;
-
- FP_UNPACK_SP(A, rs2);
- FP_TO_INT_S(r, A, 64, 1);
- if (!FP_INHIBIT_RESULTS)
- *rd = r;
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fsubd.c b/arch/sparc64/math-emu/fsubd.c
deleted file mode 100644
index 66a7c5664..000000000
--- a/arch/sparc64/math-emu/fsubd.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* $Id: fsubd.c,v 1.4 1999/05/28 13:45:04 jj Exp $
- * arch/sparc64/math-emu/fsubd.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FSUBD(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
-
- FP_UNPACK_DP(A, rs1);
- FP_UNPACK_DP(B, rs2);
- if (B_c != FP_CLS_NAN)
- B_s ^= 1;
- FP_ADD_D(R, A, B);
- FP_PACK_DP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fsubq.c b/arch/sparc64/math-emu/fsubq.c
deleted file mode 100644
index 96b2e08dd..000000000
--- a/arch/sparc64/math-emu/fsubq.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* $Id: fsubq.c,v 1.4 1999/05/28 13:45:09 jj Exp $
- * arch/sparc64/math-emu/fsubq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FSUBQ(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
-
- FP_UNPACK_QP(A, rs1);
- FP_UNPACK_QP(B, rs2);
- if (B_c != FP_CLS_NAN)
- B_s ^= 1;
- FP_ADD_Q(R, A, B);
- FP_PACK_QP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fsubs.c b/arch/sparc64/math-emu/fsubs.c
deleted file mode 100644
index 3eef72572..000000000
--- a/arch/sparc64/math-emu/fsubs.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* $Id: fsubs.c,v 1.4 1999/05/28 13:45:12 jj Exp $
- * arch/sparc64/math-emu/fsubs.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FSUBS(void *rd, void *rs2, void *rs1)
-{
- FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
-
- FP_UNPACK_SP(A, rs1);
- FP_UNPACK_SP(B, rs2);
- if (B_c != FP_CLS_NAN)
- B_s ^= 1;
- FP_ADD_S(R, A, B);
- FP_PACK_SP(rd, R);
- FP_HANDLE_EXCEPTIONS;
-}
diff --git a/arch/sparc64/math-emu/fxtoq.c b/arch/sparc64/math-emu/fxtoq.c
deleted file mode 100644
index 205567cd9..000000000
--- a/arch/sparc64/math-emu/fxtoq.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* $Id: fxtoq.c,v 1.5 1999/05/28 13:45:15 jj Exp $
- * arch/sparc64/math-emu/fxtoq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FXTOQ(void *rd, void *rs2)
-{
- FP_DECL_EX;
- FP_DECL_Q(R);
- long a = *(long *)rs2;
-
- FP_FROM_INT_Q(R, a, 64, long);
- FP_PACK_QP(rd, R);
- return 0;
-}
diff --git a/arch/sparc64/math-emu/math.c b/arch/sparc64/math-emu/math.c
index 9f2a21f9f..38a846c9f 100644
--- a/arch/sparc64/math-emu/math.c
+++ b/arch/sparc64/math-emu/math.c
@@ -1,4 +1,4 @@
-/* $Id: math.c,v 1.8 1999/05/28 13:43:11 jj Exp $
+/* $Id: math.c,v 1.10 1999/08/13 16:02:06 jj Exp $
* arch/sparc64/math-emu/math.c
*
* Copyright (C) 1997,1999 Jakub Jelinek (jj@ultra.linux.cz)
@@ -17,46 +17,61 @@
#include "sfp-util.h"
#include "soft-fp.h"
+#include "single.h"
+#include "double.h"
+#include "quad.h"
-#define FLOATFUNC(x) extern int x(void *,void *,void *);
-
-FLOATFUNC(FMOVQ)
-FLOATFUNC(FNEGQ)
-FLOATFUNC(FABSQ)
-FLOATFUNC(FSQRTQ)
-FLOATFUNC(FADDQ)
-FLOATFUNC(FSUBQ)
-FLOATFUNC(FMULQ)
-FLOATFUNC(FDIVQ)
-FLOATFUNC(FDMULQ)
-FLOATFUNC(FQTOX)
-FLOATFUNC(FXTOQ)
-FLOATFUNC(FQTOS)
-FLOATFUNC(FQTOD)
-FLOATFUNC(FITOQ)
-FLOATFUNC(FSTOQ)
-FLOATFUNC(FDTOQ)
-FLOATFUNC(FQTOI)
-FLOATFUNC(FCMPQ)
-FLOATFUNC(FCMPEQ)
-
-FLOATFUNC(FSQRTS)
-FLOATFUNC(FSQRTD)
-FLOATFUNC(FADDS)
-FLOATFUNC(FADDD)
-FLOATFUNC(FSUBS)
-FLOATFUNC(FSUBD)
-FLOATFUNC(FMULS)
-FLOATFUNC(FMULD)
-FLOATFUNC(FDIVS)
-FLOATFUNC(FDIVD)
-FLOATFUNC(FSMULD)
-FLOATFUNC(FSTOX)
-FLOATFUNC(FDTOX)
-FLOATFUNC(FDTOS)
-FLOATFUNC(FSTOD)
-FLOATFUNC(FSTOI)
-FLOATFUNC(FDTOI)
+/* QUAD - ftt == 3 */
+#define FMOVQ 0x003
+#define FNEGQ 0x007
+#define FABSQ 0x00b
+#define FSQRTQ 0x02b
+#define FADDQ 0x043
+#define FSUBQ 0x047
+#define FMULQ 0x04b
+#define FDIVQ 0x04f
+#define FDMULQ 0x06e
+#define FQTOX 0x083
+#define FXTOQ 0x08c
+#define FQTOS 0x0c7
+#define FQTOD 0x0cb
+#define FITOQ 0x0cc
+#define FSTOQ 0x0cd
+#define FDTOQ 0x0ce
+#define FQTOI 0x0d3
+/* SUBNORMAL - ftt == 2 */
+#define FSQRTS 0x029
+#define FSQRTD 0x02a
+#define FADDS 0x041
+#define FADDD 0x042
+#define FSUBS 0x045
+#define FSUBD 0x046
+#define FMULS 0x049
+#define FMULD 0x04a
+#define FDIVS 0x04d
+#define FDIVD 0x04e
+#define FSMULD 0x069
+#define FSTOX 0x081
+#define FDTOX 0x082
+#define FDTOS 0x0c6
+#define FSTOD 0x0c9
+#define FSTOI 0x0d1
+#define FDTOI 0x0d2
+/* FPOP2 */
+#define FCMPQ 0x053
+#define FCMPEQ 0x057
+#define FMOVQ0 0x003
+#define FMOVQ1 0x043
+#define FMOVQ2 0x083
+#define FMOVQ3 0x0c3
+#define FMOVQI 0x103
+#define FMOVQX 0x183
+#define FMOVQZ 0x027
+#define FMOVQLE 0x047
+#define FMOVQLZ 0x067
+#define FMOVQNZ 0x0a7
+#define FMOVQGZ 0x0c7
+#define FMOVQGE 0x0e7
#define FSR_TEM_SHIFT 23UL
#define FSR_TEM_MASK (0x1fUL << FSR_TEM_SHIFT)
@@ -73,9 +88,9 @@ FLOATFUNC(FDTOI)
*
* We return 0 if a SIGFPE should be sent, 1 otherwise.
*/
-static int record_exception(struct pt_regs *regs, int eflag)
+static inline int record_exception(struct pt_regs *regs, int eflag)
{
- u64 fsr = current->tss.xfsr[0];
+ u64 fsr = current->thread.xfsr[0];
int would_trap;
/* Determine if this exception would have generated a trap. */
@@ -120,7 +135,7 @@ static int record_exception(struct pt_regs *regs, int eflag)
if(would_trap != 0)
fsr |= (1UL << 14);
- current->tss.xfsr[0] = fsr;
+ current->thread.xfsr[0] = fsr;
/* If we will not trap, advance the program counter over
* the instruction being handled.
@@ -133,133 +148,321 @@ static int record_exception(struct pt_regs *regs, int eflag)
return (would_trap ? 0 : 1);
}
+typedef union {
+ u32 s;
+ u64 d;
+ u64 q[2];
+} *argp;
+
int do_mathemu(struct pt_regs *regs, struct fpustate *f)
{
unsigned long pc = regs->tpc;
unsigned long tstate = regs->tstate;
u32 insn = 0;
- int type = 0; /* 01 is single, 10 is double, 11 is quad,
- 000011 is rs1, 001100 is rs2, 110000 is rd (00 in rd is fcc)
- 111100000000 tells which ftt may that happen in */
+ int type = 0;
+ /* ftt tells which ftt it may happen in, r is rd, b is rs2 and a is rs1. The *u arg tells
+ whether the argument should be packed/unpacked (0 - do not unpack/pack, 1 - unpack/pack)
+ non-u args tells the size of the argument (0 - no argument, 1 - single, 2 - double, 3 - quad */
+#define TYPE(ftt, r, ru, b, bu, a, au) type = (au << 2) | (a << 0) | (bu << 5) | (b << 3) | (ru << 8) | (r << 6) | (ftt << 9)
int freg;
static u64 zero[2] = { 0L, 0L };
int flags;
- int (*func)(void *,void *,void *) = NULL;
+ FP_DECL_EX;
+ FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
+ FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
+ FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR);
+ int IR;
+ long XR, xfsr;
if(tstate & TSTATE_PRIV)
die_if_kernel("FPQuad from kernel", regs);
- if(current->tss.flags & SPARC_FLAG_32BIT)
+ if(current->thread.flags & SPARC_FLAG_32BIT)
pc = (u32)pc;
if (get_user(insn, (u32 *)pc) != -EFAULT) {
if ((insn & 0xc1f80000) == 0x81a00000) /* FPOP1 */ {
switch ((insn >> 5) & 0x1ff) {
/* QUAD - ftt == 3 */
- case 0x003: type = 0x33c; func = FMOVQ; break;
- case 0x007: type = 0x33c; func = FNEGQ; break;
- case 0x00b: type = 0x33c; func = FABSQ; break;
- case 0x02b: type = 0x33c; func = FSQRTQ; break;
- case 0x043: type = 0x33f; func = FADDQ; break;
- case 0x047: type = 0x33f; func = FSUBQ; break;
- case 0x04b: type = 0x33f; func = FMULQ; break;
- case 0x04f: type = 0x33f; func = FDIVQ; break;
- case 0x06e: type = 0x33a; func = FDMULQ; break;
- case 0x083: type = 0x32c; func = FQTOX; break;
- case 0x08c: type = 0x338; func = FXTOQ; break;
- case 0x0c7: type = 0x31c; func = FQTOS; break;
- case 0x0cb: type = 0x32c; func = FQTOD; break;
- case 0x0cc: type = 0x334; func = FITOQ; break;
- case 0x0cd: type = 0x334; func = FSTOQ; break;
- case 0x0ce: type = 0x338; func = FDTOQ; break;
- case 0x0d3: type = 0x31c; func = FQTOI; break;
+ case FMOVQ:
+ case FNEGQ:
+ case FABSQ: TYPE(3,3,0,3,0,0,0); break;
+ case FSQRTQ: TYPE(3,3,1,3,1,0,0); break;
+ case FADDQ:
+ case FSUBQ:
+ case FMULQ:
+ case FDIVQ: TYPE(3,3,1,3,1,3,1); break;
+ case FDMULQ: TYPE(3,3,1,2,1,2,1); break;
+ case FQTOX: TYPE(3,2,0,3,1,0,0); break;
+ case FXTOQ: TYPE(3,3,1,2,0,0,0); break;
+ case FQTOS: TYPE(3,1,1,3,1,0,0); break;
+ case FQTOD: TYPE(3,2,1,3,1,0,0); break;
+ case FITOQ: TYPE(3,3,1,1,0,0,0); break;
+ case FSTOQ: TYPE(3,3,1,1,1,0,0); break;
+ case FDTOQ: TYPE(3,3,1,2,1,0,0); break;
+ case FQTOI: TYPE(3,1,0,3,1,0,0); break;
/* SUBNORMAL - ftt == 2 */
- case 0x029: type = 0x214; func = FSQRTS; break;
- case 0x02a: type = 0x228; func = FSQRTD; break;
- case 0x041: type = 0x215; func = FADDS; break;
- case 0x042: type = 0x22a; func = FADDD; break;
- case 0x045: type = 0x215; func = FSUBS; break;
- case 0x046: type = 0x22a; func = FSUBD; break;
- case 0x049: type = 0x215; func = FMULS; break;
- case 0x04a: type = 0x22a; func = FMULD; break;
- case 0x04d: type = 0x215; func = FDIVS; break;
- case 0x04e: type = 0x22a; func = FDIVD; break;
- case 0x069: type = 0x225; func = FSMULD; break;
- case 0x081: type = 0x224; func = FSTOX; break;
- case 0x082: type = 0x228; func = FDTOX; break;
- case 0x0c6: type = 0x218; func = FDTOS; break;
- case 0x0c9: type = 0x224; func = FSTOD; break;
- case 0x0d1: type = 0x214; func = FSTOI; break;
- case 0x0d2: type = 0x218; func = FDTOI; break;
+ case FSQRTS: TYPE(2,1,1,1,1,0,0); break;
+ case FSQRTD: TYPE(2,2,1,2,1,0,0); break;
+ case FADDD:
+ case FSUBD:
+ case FMULD:
+ case FDIVD: TYPE(2,2,1,2,1,2,1); break;
+ case FADDS:
+ case FSUBS:
+ case FMULS:
+ case FDIVS: TYPE(2,1,1,1,1,1,1); break;
+ case FSMULD: TYPE(2,2,1,1,1,1,1); break;
+ case FSTOX: TYPE(2,2,0,1,1,0,0); break;
+ case FDTOX: TYPE(2,2,0,2,1,0,0); break;
+ case FDTOS: TYPE(2,1,1,2,1,0,0); break;
+ case FSTOD: TYPE(2,2,1,1,1,0,0); break;
+ case FSTOI: TYPE(2,1,0,1,1,0,0); break;
+ case FDTOI: TYPE(2,1,0,2,1,0,0); break;
}
}
else if ((insn & 0xc1f80000) == 0x81a80000) /* FPOP2 */ {
+ IR = 2;
switch ((insn >> 5) & 0x1ff) {
- case 0x053: type = 0x30f; func = FCMPQ; break;
- case 0x057: type = 0x30f; func = FCMPEQ; break;
+ case FCMPQ: TYPE(3,0,0,3,1,3,1); break;
+ case FCMPEQ: TYPE(3,0,0,3,1,3,1); break;
+ /* Now the conditional fmovq support */
+ case FMOVQ0:
+ case FMOVQ1:
+ case FMOVQ2:
+ case FMOVQ3:
+ /* fmovq %fccX, %fY, %fZ */
+ if (!((insn >> 11) & 3))
+ XR = current->thread.xfsr[0] >> 10;
+ else
+ XR = current->thread.xfsr[0] >> (30 + ((insn >> 10) & 0x6));
+ XR &= 3;
+ IR = 0;
+ switch ((insn >> 14) & 0x7) {
+ /* case 0: IR = 0; break; */ /* Never */
+ case 1: if (XR) IR = 1; break; /* Not Equal */
+ case 2: if (XR == 1 || XR == 2) IR = 1; break; /* Less or Greater */
+ case 3: if (XR & 1) IR = 1; break; /* Unordered or Less */
+ case 4: if (XR == 1) IR = 1; break; /* Less */
+ case 5: if (XR & 2) IR = 1; break; /* Unordered or Greater */
+ case 6: if (XR == 2) IR = 1; break; /* Greater */
+ case 7: if (XR == 3) IR = 1; break; /* Unordered */
+ }
+ if ((insn >> 14) & 8)
+ IR ^= 1;
+ break;
+ case FMOVQI:
+ case FMOVQX:
+ /* fmovq %[ix]cc, %fY, %fZ */
+ XR = regs->tstate >> 32;
+ if ((insn >> 5) & 0x80)
+ XR >>= 4;
+ XR &= 0xf;
+ IR = 0;
+ freg = ((XR >> 2) ^ XR) & 2;
+ switch ((insn >> 14) & 0x7) {
+ /* case 0: IR = 0; break; */ /* Never */
+ case 1: if (XR & 4) IR = 1; break; /* Equal */
+ case 2: if ((XR & 4) || freg) IR = 1; break; /* Less or Equal */
+ case 3: if (freg) IR = 1; break; /* Less */
+ case 4: if (XR & 5) IR = 1; break; /* Less or Equal Unsigned */
+ case 5: if (XR & 1) IR = 1; break; /* Carry Set */
+ case 6: if (XR & 8) IR = 1; break; /* Negative */
+ case 7: if (XR & 2) IR = 1; break; /* Overflow Set */
+ }
+ if ((insn >> 14) & 8)
+ IR ^= 1;
+ break;
+ case FMOVQZ:
+ case FMOVQLE:
+ case FMOVQLZ:
+ case FMOVQNZ:
+ case FMOVQGZ:
+ case FMOVQGE:
+ freg = (insn >> 14) & 0x1f;
+ if (!freg)
+ XR = 0;
+ else if (freg < 16)
+ XR = regs->u_regs[freg];
+ else if (current->thread.flags & SPARC_FLAG_32BIT) {
+ struct reg_window32 *win32;
+ flushw_user ();
+ win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+ get_user(XR, &win32->locals[freg - 16]);
+ } else {
+ struct reg_window *win;
+ flushw_user ();
+ win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+ get_user(XR, &win->locals[freg - 16]);
+ }
+ IR = 0;
+ switch ((insn >> 10) & 3) {
+ case 1: if (!XR) IR = 1; break; /* Register Zero */
+ case 2: if (XR <= 0) IR = 1; break; /* Register Less Than or Equal to Zero */
+ case 3: if (XR < 0) IR = 1; break; /* Register Less Than Zero */
+ }
+ if ((insn >> 10) & 4)
+ IR ^= 1;
+ break;
+ }
+ if (IR == 0) {
+ /* The fmov test was false. Do a nop instead */
+ current->thread.xfsr[0] &= ~(FSR_CEXC_MASK);
+ regs->tpc = regs->tnpc;
+ regs->tnpc += 4;
+ return 1;
+ } else if (IR == 1) {
+ /* Change the instruction into plain fmovq */
+ insn = (insn & 0x3e00001f) | 0x81a00060;
+ TYPE(3,3,0,3,0,0,0);
}
}
}
if (type) {
- void *rs1 = NULL, *rs2 = NULL, *rd = NULL;
+ argp rs1 = NULL, rs2 = NULL, rd = NULL;
- freg = (current->tss.xfsr[0] >> 14) & 0xf;
- if (freg != (type >> 8))
+ freg = (current->thread.xfsr[0] >> 14) & 0xf;
+ if (freg != (type >> 9))
goto err;
- current->tss.xfsr[0] &= ~0x1c000;
+ current->thread.xfsr[0] &= ~0x1c000;
freg = ((insn >> 14) & 0x1f);
switch (type & 0x3) {
case 3: if (freg & 2) {
- current->tss.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
+ current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
goto err;
}
case 2: freg = ((freg & 1) << 5) | (freg & 0x1e);
- case 1: rs1 = (void *)&f->regs[freg];
+ case 1: rs1 = (argp)&f->regs[freg];
flags = (freg < 32) ? FPRS_DL : FPRS_DU;
- if (!(current->tss.fpsaved[0] & flags))
- rs1 = (void *)&zero;
+ if (!(current->thread.fpsaved[0] & flags))
+ rs1 = (argp)&zero;
break;
}
+ switch (type & 0x7) {
+ case 7: FP_UNPACK_QP (QA, rs1); break;
+ case 6: FP_UNPACK_DP (DA, rs1); break;
+ case 5: FP_UNPACK_SP (SA, rs1); break;
+ }
freg = (insn & 0x1f);
- switch ((type >> 2) & 0x3) {
+ switch ((type >> 3) & 0x3) {
case 3: if (freg & 2) {
- current->tss.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
+ current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
goto err;
}
case 2: freg = ((freg & 1) << 5) | (freg & 0x1e);
- case 1: rs2 = (void *)&f->regs[freg];
+ case 1: rs2 = (argp)&f->regs[freg];
flags = (freg < 32) ? FPRS_DL : FPRS_DU;
- if (!(current->tss.fpsaved[0] & flags))
- rs2 = (void *)&zero;
+ if (!(current->thread.fpsaved[0] & flags))
+ rs2 = (argp)&zero;
break;
}
+ switch ((type >> 3) & 0x7) {
+ case 7: FP_UNPACK_QP (QB, rs2); break;
+ case 6: FP_UNPACK_DP (DB, rs2); break;
+ case 5: FP_UNPACK_SP (SB, rs2); break;
+ }
freg = ((insn >> 25) & 0x1f);
- switch ((type >> 4) & 0x3) {
- case 0: rd = (void *)(long)(freg & 3); break;
+ switch ((type >> 6) & 0x3) {
case 3: if (freg & 2) {
- current->tss.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
+ current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
goto err;
}
case 2: freg = ((freg & 1) << 5) | (freg & 0x1e);
- case 1: rd = (void *)&f->regs[freg];
+ case 1: rd = (argp)&f->regs[freg];
flags = (freg < 32) ? FPRS_DL : FPRS_DU;
- if (!(current->tss.fpsaved[0] & FPRS_FEF)) {
- current->tss.fpsaved[0] = FPRS_FEF;
- current->tss.gsr[0] = 0;
+ if (!(current->thread.fpsaved[0] & FPRS_FEF)) {
+ current->thread.fpsaved[0] = FPRS_FEF;
+ current->thread.gsr[0] = 0;
}
- if (!(current->tss.fpsaved[0] & flags)) {
+ if (!(current->thread.fpsaved[0] & flags)) {
if (freg < 32)
memset(f->regs, 0, 32*sizeof(u32));
else
memset(f->regs+32, 0, 32*sizeof(u32));
}
- current->tss.fpsaved[0] |= flags;
+ current->thread.fpsaved[0] |= flags;
break;
}
- flags = func(rd, rs2, rs1);
- if(flags != 0)
- return record_exception(regs, flags);
+ switch ((insn >> 5) & 0x1ff) {
+ /* + */
+ case FADDS: FP_ADD_S (SR, SA, SB); break;
+ case FADDD: FP_ADD_D (DR, DA, DB); break;
+ case FADDQ: FP_ADD_Q (QR, QA, QB); break;
+ /* - */
+ case FSUBS: FP_SUB_S (SR, SA, SB); break;
+ case FSUBD: FP_SUB_D (DR, DA, DB); break;
+ case FSUBQ: FP_SUB_Q (QR, QA, QB); break;
+ /* * */
+ case FMULS: FP_MUL_S (SR, SA, SB); break;
+ case FSMULD: FP_CONV (D, S, 1, 1, DA, SA);
+ FP_CONV (D, S, 1, 1, DB, SB);
+ case FMULD: FP_MUL_D (DR, DA, DB); break;
+ case FDMULQ: FP_CONV (Q, D, 2, 1, QA, DA);
+ FP_CONV (Q, D, 2, 1, QB, DB);
+ case FMULQ: FP_MUL_Q (QR, QA, QB); break;
+ /* / */
+ case FDIVS: FP_DIV_S (SR, SA, SB); break;
+ case FDIVD: FP_DIV_D (DR, DA, DB); break;
+ case FDIVQ: FP_DIV_Q (QR, QA, QB); break;
+ /* sqrt */
+ case FSQRTS: FP_SQRT_S (SR, SB); break;
+ case FSQRTD: FP_SQRT_D (DR, DB); break;
+ case FSQRTQ: FP_SQRT_Q (QR, QB); break;
+ /* mov */
+ case FMOVQ: rd->q[0] = rs2->q[0]; rd->q[1] = rs2->q[1]; break;
+ case FABSQ: rd->q[0] = rs2->q[0] & 0x7fffffffffffffffUL; rd->q[1] = rs2->q[1]; break;
+ case FNEGQ: rd->q[0] = rs2->q[0] ^ 0x8000000000000000UL; rd->q[1] = rs2->q[1]; break;
+ /* float to int */
+ case FSTOI: FP_TO_INT_S (IR, SB, 32, 1); break;
+ case FDTOI: FP_TO_INT_D (IR, DB, 32, 1); break;
+ case FQTOI: FP_TO_INT_Q (IR, QB, 32, 1); break;
+ case FSTOX: FP_TO_INT_S (XR, SB, 64, 1); break;
+ case FDTOX: FP_TO_INT_D (XR, DB, 64, 1); break;
+ case FQTOX: FP_TO_INT_Q (XR, QB, 64, 1); break;
+ /* int to float */
+ case FITOQ: IR = rs2->s; FP_FROM_INT_Q (QR, IR, 32, int); break;
+ case FXTOQ: XR = rs2->d; FP_FROM_INT_Q (QR, XR, 64, long); break;
+ /* float to float */
+ case FSTOD: FP_CONV (D, S, 1, 1, DR, SB); break;
+ case FSTOQ: FP_CONV (Q, S, 2, 1, QR, SB); break;
+ case FDTOQ: FP_CONV (Q, D, 2, 1, QR, DB); break;
+ case FDTOS: FP_CONV (S, D, 1, 1, SR, DB); break;
+ case FQTOS: FP_CONV (S, Q, 1, 2, SR, QB); break;
+ case FQTOD: FP_CONV (D, Q, 1, 2, DR, QB); break;
+ /* comparison */
+ case FCMPQ:
+ case FCMPEQ:
+ FP_CMP_Q(XR, QB, QA, 3);
+ if (XR == 3 &&
+ (((insn >> 5) & 0x1ff) == FCMPEQ ||
+ FP_ISSIGNAN_Q(QA) ||
+ FP_ISSIGNAN_Q(QB)))
+ FP_SET_EXCEPTION (FP_EX_INVALID);
+ }
+ if (!FP_INHIBIT_RESULTS) {
+ switch ((type >> 6) & 0x7) {
+ case 0: xfsr = current->thread.xfsr[0];
+ if (XR == -1) XR = 2;
+ switch (freg & 3) {
+ /* fcc0, 1, 2, 3 */
+ case 0: xfsr &= ~0xc00; xfsr |= (XR << 10); break;
+ case 1: xfsr &= ~0x300000000UL; xfsr |= (XR << 32); break;
+ case 2: xfsr &= ~0xc00000000UL; xfsr |= (XR << 34); break;
+ case 3: xfsr &= ~0x3000000000UL; xfsr |= (XR << 36); break;
+ }
+ current->thread.xfsr[0] = xfsr;
+ break;
+ case 1: rd->s = IR; break;
+ case 2: rd->d = XR; break;
+ case 5: FP_PACK_SP (rd, SR); break;
+ case 6: FP_PACK_DP (rd, DR); break;
+ case 7: FP_PACK_QP (rd, QR); break;
+ }
+ }
+
+ if(_fex != 0)
+ return record_exception(regs, _fex);
/* Success and no exceptions detected. */
- current->tss.xfsr[0] &= ~(FSR_CEXC_MASK);
+ current->thread.xfsr[0] &= ~(FSR_CEXC_MASK);
regs->tpc = regs->tnpc;
regs->tnpc += 4;
return 1;
diff --git a/arch/sparc64/math-emu/op-1.h b/arch/sparc64/math-emu/op-1.h
deleted file mode 100644
index fe83d376a..000000000
--- a/arch/sparc64/math-emu/op-1.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/* Software floating-point emulation.
- Basic one-word fraction declaration and manipulation.
- Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson (rth@cygnus.com),
- Jakub Jelinek (jj@ultra.linux.cz),
- David S. Miller (davem@redhat.com) and
- Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f
-#define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f)
-#define _FP_FRAC_SET_1(X,I) (X##_f = I)
-#define _FP_FRAC_HIGH_1(X) (X##_f)
-#define _FP_FRAC_LOW_1(X) (X##_f)
-#define _FP_FRAC_WORD_1(X,w) (X##_f)
-
-#define _FP_FRAC_ADDI_1(X,I) (X##_f += I)
-#define _FP_FRAC_SLL_1(X,N) \
- do { \
- if (__builtin_constant_p(N) && (N) == 1) \
- X##_f += X##_f; \
- else \
- X##_f <<= (N); \
- } while (0)
-#define _FP_FRAC_SRL_1(X,N) (X##_f >>= N)
-
-/* Right shift with sticky-lsb. */
-#define _FP_FRAC_SRS_1(X,N,sz) __FP_FRAC_SRS_1(X##_f, N, sz)
-
-#define __FP_FRAC_SRS_1(X,N,sz) \
- (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1 \
- ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
-
-#define _FP_FRAC_ADD_1(R,X,Y) (R##_f = X##_f + Y##_f)
-#define _FP_FRAC_SUB_1(R,X,Y) (R##_f = X##_f - Y##_f)
-#define _FP_FRAC_DEC_1(X,Y) (X##_f -= Y##_f)
-#define _FP_FRAC_CLZ_1(z, X) __FP_CLZ(z, X##_f)
-
-/* Predicates */
-#define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE)X##_f < 0)
-#define _FP_FRAC_ZEROP_1(X) (X##_f == 0)
-#define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs)
-#define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f)
-#define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f)
-#define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f)
-
-#define _FP_ZEROFRAC_1 0
-#define _FP_MINFRAC_1 1
-#define _FP_MAXFRAC_1 (~(_FP_WS_TYPE)0)
-
-/*
- * Unpack the raw bits of a native fp value. Do not classify or
- * normalize the data.
- */
-
-#define _FP_UNPACK_RAW_1(fs, X, val) \
- do { \
- union _FP_UNION_##fs _flo; _flo.flt = (val); \
- \
- X##_f = _flo.bits.frac; \
- X##_e = _flo.bits.exp; \
- X##_s = _flo.bits.sign; \
- } while (0)
-
-#define _FP_UNPACK_RAW_1_P(fs, X, val) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)(val); \
- \
- X##_f = _flo->bits.frac; \
- X##_e = _flo->bits.exp; \
- X##_s = _flo->bits.sign; \
- } while (0)
-
-/*
- * Repack the raw bits of a native fp value.
- */
-
-#define _FP_PACK_RAW_1(fs, val, X) \
- do { \
- union _FP_UNION_##fs _flo; \
- \
- _flo.bits.frac = X##_f; \
- _flo.bits.exp = X##_e; \
- _flo.bits.sign = X##_s; \
- \
- (val) = _flo.flt; \
- } while (0)
-
-#define _FP_PACK_RAW_1_P(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)(val); \
- \
- _flo->bits.frac = X##_f; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
-
-
-/*
- * Multiplication algorithms:
- */
-
-/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
- multiplication immediately. */
-
-#define _FP_MUL_MEAT_1_imm(fs, R, X, Y) \
- do { \
- R##_f = X##_f * Y##_f; \
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_1(R, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \
- } while (0)
-
-/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
-
-#define _FP_MUL_MEAT_1_wide(fs, R, X, Y, doit) \
- do { \
- _FP_W_TYPE _Z_f0, _Z_f1; \
- doit(_Z_f1, _Z_f0, X##_f, Y##_f); \
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_2(_Z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \
- R##_f = _Z_f0; \
- } while (0)
-
-/* Finally, a simple widening multiply algorithm. What fun! */
-
-#define _FP_MUL_MEAT_1_hard(fs, R, X, Y) \
- do { \
- _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1; \
- \
- /* split the words in half */ \
- _xh = X##_f >> (_FP_W_TYPE_SIZE/2); \
- _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
- _yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \
- _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
- \
- /* multiply the pieces */ \
- _z_f0 = _xl * _yl; \
- _a_f0 = _xh * _yl; \
- _a_f1 = _xl * _yh; \
- _z_f1 = _xh * _yh; \
- \
- /* reassemble into two full words */ \
- if ((_a_f0 += _a_f1) < _a_f1) \
- _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2); \
- _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2); \
- _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2); \
- _FP_FRAC_ADD_2(_z, _z, _a); \
- \
- /* normalize */ \
- _FP_FRAC_SRS_2(_z, _FP_WFRACBITS_##fs - 1, 2*_FP_WFRACBITS_##fs); \
- R##_f = _z_f0; \
- } while (0)
-
-
-/*
- * Division algorithms:
- */
-
-/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
- division immediately. Give this macro either _FP_DIV_HELP_imm for
- C primitives or _FP_DIV_HELP_ldiv for the ISO function. Which you
- choose will depend on what the compiler does with divrem4. */
-
-#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \
- do { \
- _FP_W_TYPE _q, _r; \
- X##_f <<= (X##_f < Y##_f \
- ? R##_e--, _FP_WFRACBITS_##fs \
- : _FP_WFRACBITS_##fs - 1); \
- doit(_q, _r, X##_f, Y##_f); \
- R##_f = _q | (_r != 0); \
- } while (0)
-
-/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
- that may be useful in this situation. This first is for a primitive
- that requires normalization, the second for one that does not. Look
- for UDIV_NEEDS_NORMALIZATION to tell which your machine needs. */
-
-#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y) \
- do { \
- _FP_W_TYPE _nh, _nl, _q, _r; \
- \
- /* Normalize Y -- i.e. make the most significant bit set. */ \
- Y##_f <<= _FP_WFRACXBITS_##fs - 1; \
- \
- /* Shift X op correspondingly high, that is, up one full word. */ \
- if (X##_f <= Y##_f) \
- { \
- _nl = 0; \
- _nh = X##_f; \
- } \
- else \
- { \
- R##_e++; \
- _nl = X##_f << (_FP_W_TYPE_SIZE-1); \
- _nh = X##_f >> 1; \
- } \
- \
- udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \
- R##_f = _q | (_r != 0); \
- } while (0)
-
-#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y) \
- do { \
- _FP_W_TYPE _nh, _nl, _q, _r; \
- if (X##_f < Y##_f) \
- { \
- R##_e--; \
- _nl = X##_f << _FP_WFRACBITS_##fs; \
- _nh = X##_f >> _FP_WFRACXBITS_##fs; \
- } \
- else \
- { \
- _nl = X##_f << (_FP_WFRACBITS_##fs - 1); \
- _nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \
- } \
- udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \
- R##_f = _q | (_r != 0); \
- } while (0)
-
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- */
-
-#define _FP_SQRT_MEAT_1(R, S, T, X, q) \
- do { \
- while (q != _FP_WORK_ROUND) \
- { \
- T##_f = S##_f + q; \
- if (T##_f <= X##_f) \
- { \
- S##_f = T##_f + q; \
- X##_f -= T##_f; \
- R##_f += q; \
- } \
- _FP_FRAC_SLL_1(X, 1); \
- q >>= 1; \
- } \
- if (X##_f) \
- { \
- if (S##_f < X##_f) \
- R##_f |= _FP_WORK_ROUND; \
- R##_f |= _FP_WORK_STICKY; \
- } \
- } while (0)
-
-/*
- * Assembly/disassembly for converting to/from integral types.
- * No shifting or overflow handled here.
- */
-
-#define _FP_FRAC_ASSEMBLE_1(r, X, rsize) (r = X##_f)
-#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize) (X##_f = r)
-
-
-/*
- * Convert FP values between word sizes
- */
-
-#define _FP_FRAC_CONV_1_1(dfs, sfs, D, S) \
- do { \
- D##_f = S##_f; \
- if (_FP_WFRACBITS_##sfs > _FP_WFRACBITS_##dfs) \
- { \
- if (S##_c != FP_CLS_NAN) \
- _FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs), \
- _FP_WFRACBITS_##sfs); \
- else \
- _FP_FRAC_SRL_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs)); \
- } \
- else \
- D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs; \
- } while (0)
diff --git a/arch/sparc64/math-emu/op-2.h b/arch/sparc64/math-emu/op-2.h
deleted file mode 100644
index 9735244a5..000000000
--- a/arch/sparc64/math-emu/op-2.h
+++ /dev/null
@@ -1,513 +0,0 @@
-/* Software floating-point emulation.
- Basic two-word fraction declaration and manipulation.
- Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson (rth@cygnus.com),
- Jakub Jelinek (jj@ultra.linux.cz),
- David S. Miller (davem@redhat.com) and
- Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1
-#define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1)
-#define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I)
-#define _FP_FRAC_HIGH_2(X) (X##_f1)
-#define _FP_FRAC_LOW_2(X) (X##_f0)
-#define _FP_FRAC_WORD_2(X,w) (X##_f##w)
-
-#define _FP_FRAC_SLL_2(X,N) \
- do { \
- if ((N) < _FP_W_TYPE_SIZE) \
- { \
- if (__builtin_constant_p(N) && (N) == 1) \
- { \
- X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0); \
- X##_f0 += X##_f0; \
- } \
- else \
- { \
- X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \
- X##_f0 <<= (N); \
- } \
- } \
- else \
- { \
- X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE); \
- X##_f0 = 0; \
- } \
- } while (0)
-
-#define _FP_FRAC_SRL_2(X,N) \
- do { \
- if ((N) < _FP_W_TYPE_SIZE) \
- { \
- X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N)); \
- X##_f1 >>= (N); \
- } \
- else \
- { \
- X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE); \
- X##_f1 = 0; \
- } \
- } while (0)
-
-/* Right shift with sticky-lsb. */
-#define _FP_FRAC_SRS_2(X,N,sz) \
- do { \
- if ((N) < _FP_W_TYPE_SIZE) \
- { \
- X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) | \
- (__builtin_constant_p(N) && (N) == 1 \
- ? X##_f0 & 1 \
- : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \
- X##_f1 >>= (N); \
- } \
- else \
- { \
- X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) | \
- (((X##_f1 << (sz - (N))) | X##_f0) != 0)); \
- X##_f1 = 0; \
- } \
- } while (0)
-
-#define _FP_FRAC_ADDI_2(X,I) \
- __FP_FRAC_ADDI_2(X##_f1, X##_f0, I)
-
-#define _FP_FRAC_ADD_2(R,X,Y) \
- __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
-
-#define _FP_FRAC_SUB_2(R,X,Y) \
- __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
-
-#define _FP_FRAC_DEC_2(X,Y) \
- __FP_FRAC_DEC_2(X##_f1, X##_f0, Y##_f1, Y##_f0)
-
-#define _FP_FRAC_CLZ_2(R,X) \
- do { \
- if (X##_f1) \
- __FP_CLZ(R,X##_f1); \
- else \
- { \
- __FP_CLZ(R,X##_f0); \
- R += _FP_W_TYPE_SIZE; \
- } \
- } while(0)
-
-/* Predicates */
-#define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE)X##_f1 < 0)
-#define _FP_FRAC_ZEROP_2(X) ((X##_f1 | X##_f0) == 0)
-#define _FP_FRAC_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
-#define _FP_FRAC_EQ_2(X, Y) (X##_f1 == Y##_f1 && X##_f0 == Y##_f0)
-#define _FP_FRAC_GT_2(X, Y) \
- (X##_f1 > Y##_f1 || X##_f1 == Y##_f1 && X##_f0 > Y##_f0)
-#define _FP_FRAC_GE_2(X, Y) \
- (X##_f1 > Y##_f1 || X##_f1 == Y##_f1 && X##_f0 >= Y##_f0)
-
-#define _FP_ZEROFRAC_2 0, 0
-#define _FP_MINFRAC_2 0, 1
-#define _FP_MAXFRAC_2 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
-
-/*
- * Internals
- */
-
-#define __FP_FRAC_SET_2(X,I1,I0) (X##_f0 = I0, X##_f1 = I1)
-
-#define __FP_CLZ_2(R, xh, xl) \
- do { \
- if (xh) \
- __FP_CLZ(R,xh); \
- else \
- { \
- __FP_CLZ(R,xl); \
- R += _FP_W_TYPE_SIZE; \
- } \
- } while(0)
-
-#if 0
-
-#ifndef __FP_FRAC_ADDI_2
-#define __FP_FRAC_ADDI_2(xh, xl, i) \
- (xh += ((xl += i) < i))
-#endif
-#ifndef __FP_FRAC_ADD_2
-#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \
- (rh = xh + yh + ((rl = xl + yl) < xl))
-#endif
-#ifndef __FP_FRAC_SUB_2
-#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \
- (rh = xh - yh - ((rl = xl - yl) > xl))
-#endif
-#ifndef __FP_FRAC_DEC_2
-#define __FP_FRAC_DEC_2(xh, xl, yh, yl) \
- do { \
- UWtype _t = xl; \
- xh -= yh + ((xl -= yl) > _t); \
- } while (0)
-#endif
-
-#else
-
-#undef __FP_FRAC_ADDI_2
-#define __FP_FRAC_ADDI_2(xh, xl, i) add_ssaaaa(xh, xl, xh, xl, 0, i)
-#undef __FP_FRAC_ADD_2
-#define __FP_FRAC_ADD_2 add_ssaaaa
-#undef __FP_FRAC_SUB_2
-#define __FP_FRAC_SUB_2 sub_ddmmss
-#undef __FP_FRAC_DEC_2
-#define __FP_FRAC_DEC_2(xh, xl, yh, yl) sub_ddmmss(xh, xl, xh, xl, yh, yl)
-
-#endif
-
-/*
- * Unpack the raw bits of a native fp value. Do not classify or
- * normalize the data.
- */
-
-#define _FP_UNPACK_RAW_2(fs, X, val) \
- do { \
- union _FP_UNION_##fs _flo; _flo.flt = (val); \
- \
- X##_f0 = _flo.bits.frac0; \
- X##_f1 = _flo.bits.frac1; \
- X##_e = _flo.bits.exp; \
- X##_s = _flo.bits.sign; \
- } while (0)
-
-#define _FP_UNPACK_RAW_2_P(fs, X, val) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)(val); \
- \
- X##_f0 = _flo->bits.frac0; \
- X##_f1 = _flo->bits.frac1; \
- X##_e = _flo->bits.exp; \
- X##_s = _flo->bits.sign; \
- } while (0)
-
-
-/*
- * Repack the raw bits of a native fp value.
- */
-
-#define _FP_PACK_RAW_2(fs, val, X) \
- do { \
- union _FP_UNION_##fs _flo; \
- \
- _flo.bits.frac0 = X##_f0; \
- _flo.bits.frac1 = X##_f1; \
- _flo.bits.exp = X##_e; \
- _flo.bits.sign = X##_s; \
- \
- (val) = _flo.flt; \
- } while (0)
-
-#define _FP_PACK_RAW_2_P(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)(val); \
- \
- _flo->bits.frac0 = X##_f0; \
- _flo->bits.frac1 = X##_f1; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
-
-
-/*
- * Multiplication algorithms:
- */
-
-/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
-
-#define _FP_MUL_MEAT_2_wide(fs, R, X, Y, doit) \
- do { \
- _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
- \
- doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
- doit(_b_f1, _b_f0, X##_f0, Y##_f1); \
- doit(_c_f1, _c_f0, X##_f1, Y##_f0); \
- doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \
- \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1), 0, _b_f1, _b_f0, \
- _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0, \
- _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1)); \
- \
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_4(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \
- R##_f0 = _FP_FRAC_WORD_4(_z,0); \
- R##_f1 = _FP_FRAC_WORD_4(_z,1); \
- } while (0)
-
-/* Given a 1W * 1W => 2W primitive, do the extended multiplication.
- Do only 3 multiplications instead of four. This one is for machines
- where multiplication is much more expensive than subtraction. */
-
-#define _FP_MUL_MEAT_2_wide_3mul(fs, R, X, Y, doit) \
- do { \
- _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
- _FP_W_TYPE _d; \
- int _c1, _c2; \
- \
- _b_f0 = X##_f0 + X##_f1; \
- _c1 = _b_f0 < X##_f0; \
- _b_f1 = Y##_f0 + Y##_f1; \
- _c2 = _b_f1 < Y##_f0; \
- doit(_d, _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
- doit(_FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1), _b_f0, _b_f1); \
- doit(_c_f1, _c_f0, X##_f1, Y##_f1); \
- \
- _b_f0 &= -_c2; \
- _b_f1 &= -_c1; \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1), (_c1 & _c2), 0, _d, \
- 0, _FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1)); \
- __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _b_f0); \
- __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _b_f1); \
- __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1), \
- 0, _d, _FP_FRAC_WORD_4(_z,0)); \
- __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0); \
- __FP_FRAC_ADD_2(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), \
- _c_f1, _c_f0, \
- _FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2)); \
- \
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_4(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \
- R##_f0 = _FP_FRAC_WORD_4(_z,0); \
- R##_f1 = _FP_FRAC_WORD_4(_z,1); \
- } while (0)
-
-#define _FP_MUL_MEAT_2_gmp(fs, R, X, Y) \
- do { \
- _FP_FRAC_DECL_4(_z); \
- _FP_W_TYPE _x[2], _y[2]; \
- _x[0] = X##_f0; _x[1] = X##_f1; \
- _y[0] = Y##_f0; _y[1] = Y##_f1; \
- \
- mpn_mul_n(_z_f, _x, _y, 2); \
- \
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_4(_z, _FP_WFRACBITS##_fs-1, 2*_FP_WFRACBITS_##fs); \
- R##_f0 = _z_f[0]; \
- R##_f1 = _z_f[1]; \
- } while (0)
-
-
-/*
- * Division algorithms:
- */
-
-#define _FP_DIV_MEAT_2_udiv(fs, R, X, Y) \
- do { \
- _FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0; \
- if (_FP_FRAC_GT_2(X, Y)) \
- { \
- _n_f2 = X##_f1 >> 1; \
- _n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1; \
- _n_f0 = X##_f0 << (_FP_W_TYPE_SIZE - 1); \
- } \
- else \
- { \
- R##_e--; \
- _n_f2 = X##_f1; \
- _n_f1 = X##_f0; \
- _n_f0 = 0; \
- } \
- \
- /* Normalize, i.e. make the most significant bit of the \
- denominator set. */ \
- _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs); \
- \
- udiv_qrnnd(R##_f1, _r_f1, _n_f2, _n_f1, Y##_f1); \
- umul_ppmm(_m_f1, _m_f0, R##_f1, Y##_f0); \
- _r_f0 = _n_f0; \
- if (_FP_FRAC_GT_2(_m, _r)) \
- { \
- R##_f1--; \
- _FP_FRAC_ADD_2(_r, Y, _r); \
- if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \
- { \
- R##_f1--; \
- _FP_FRAC_ADD_2(_r, Y, _r); \
- } \
- } \
- _FP_FRAC_DEC_2(_r, _m); \
- \
- if (_r_f1 == Y##_f1) \
- { \
- /* This is a special case, not an optimization \
- (_r/Y##_f1 would not fit into UWtype). \
- As _r is guaranteed to be < Y, R##_f0 can be either \
- (UWtype)-1 or (UWtype)-2. But as we know what kind \
- of bits it is (sticky, guard, round), we don't care. \
- We also don't care what the reminder is, because the \
- guard bit will be set anyway. -jj */ \
- R##_f0 = -1; \
- } \
- else \
- { \
- udiv_qrnnd(R##_f0, _r_f1, _r_f1, _r_f0, Y##_f1); \
- umul_ppmm(_m_f1, _m_f0, R##_f0, Y##_f0); \
- _r_f0 = 0; \
- if (_FP_FRAC_GT_2(_m, _r)) \
- { \
- R##_f0--; \
- _FP_FRAC_ADD_2(_r, Y, _r); \
- if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \
- { \
- R##_f0--; \
- _FP_FRAC_ADD_2(_r, Y, _r); \
- } \
- } \
- if (!_FP_FRAC_EQ_2(_r, _m)) \
- R##_f0 |= _FP_WORK_STICKY; \
- } \
- } while (0)
-
-
-#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y) \
- do { \
- _FP_W_TYPE _x[4], _y[2], _z[4]; \
- _y[0] = Y##_f0; _y[1] = Y##_f1; \
- _x[0] = _x[3] = 0; \
- if (_FP_FRAC_GT_2(X, Y)) \
- { \
- R##_e++; \
- _x[1] = (X##_f0 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE) | \
- X##_f1 >> (_FP_W_TYPE_SIZE - \
- (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE))); \
- _x[2] = X##_f1 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE); \
- } \
- else \
- { \
- _x[1] = (X##_f0 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE) | \
- X##_f1 >> (_FP_W_TYPE_SIZE - \
- (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE))); \
- _x[2] = X##_f1 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE); \
- } \
- \
- (void) mpn_divrem (_z, 0, _x, 4, _y, 2); \
- R##_f1 = _z[1]; \
- R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0); \
- } while (0)
-
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- */
-
-#define _FP_SQRT_MEAT_2(R, S, T, X, q) \
- do { \
- while (q) \
- { \
- T##_f1 = S##_f1 + q; \
- if (T##_f1 <= X##_f1) \
- { \
- S##_f1 = T##_f1 + q; \
- X##_f1 -= T##_f1; \
- R##_f1 += q; \
- } \
- _FP_FRAC_SLL_2(X, 1); \
- q >>= 1; \
- } \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- while (q != _FP_WORK_ROUND) \
- { \
- T##_f0 = S##_f0 + q; \
- T##_f1 = S##_f1; \
- if (T##_f1 < X##_f1 || \
- (T##_f1 == X##_f1 && T##_f0 <= X##_f0)) \
- { \
- S##_f0 = T##_f0 + q; \
- S##_f1 += (T##_f0 > S##_f0); \
- _FP_FRAC_DEC_2(X, T); \
- R##_f0 += q; \
- } \
- _FP_FRAC_SLL_2(X, 1); \
- q >>= 1; \
- } \
- if (X##_f0 | X##_f1) \
- { \
- if (S##_f1 < X##_f1 || \
- (S##_f1 == X##_f1 && S##_f0 < X##_f0)) \
- R##_f0 |= _FP_WORK_ROUND; \
- R##_f0 |= _FP_WORK_STICKY; \
- } \
- } while (0)
-
-
-/*
- * Assembly/disassembly for converting to/from integral types.
- * No shifting or overflow handled here.
- */
-
-#define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \
- do { \
- if (rsize <= _FP_W_TYPE_SIZE) \
- r = X##_f0; \
- else \
- { \
- r = X##_f1; \
- r <<= _FP_W_TYPE_SIZE; \
- r += X##_f0; \
- } \
- } while (0)
-
-#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \
- do { \
- X##_f0 = r; \
- X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
- } while (0)
-
-/*
- * Convert FP values between word sizes
- */
-
-#define _FP_FRAC_CONV_1_2(dfs, sfs, D, S) \
- do { \
- if (S##_c != FP_CLS_NAN) \
- _FP_FRAC_SRS_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \
- _FP_WFRACBITS_##sfs); \
- else \
- _FP_FRAC_SRL_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs)); \
- D##_f = S##_f0; \
- } while (0)
-
-#define _FP_FRAC_CONV_2_1(dfs, sfs, D, S) \
- do { \
- D##_f0 = S##_f; \
- D##_f1 = 0; \
- _FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \
- } while (0)
-
diff --git a/arch/sparc64/math-emu/op-4.h b/arch/sparc64/math-emu/op-4.h
deleted file mode 100644
index 7f027d580..000000000
--- a/arch/sparc64/math-emu/op-4.h
+++ /dev/null
@@ -1,661 +0,0 @@
-/* Software floating-point emulation.
- Basic four-word fraction declaration and manipulation.
- Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson (rth@cygnus.com),
- Jakub Jelinek (jj@ultra.linux.cz),
- David S. Miller (davem@redhat.com) and
- Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4]
-#define _FP_FRAC_COPY_4(D,S) \
- (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \
- D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
-#define _FP_FRAC_SET_4(X,I) __FP_FRAC_SET_4(X, I)
-#define _FP_FRAC_HIGH_4(X) (X##_f[3])
-#define _FP_FRAC_LOW_4(X) (X##_f[0])
-#define _FP_FRAC_WORD_4(X,w) (X##_f[w])
-
-#define _FP_FRAC_SLL_4(X,N) \
- do { \
- _FP_I_TYPE _up, _down, _skip, _i; \
- _skip = (N) / _FP_W_TYPE_SIZE; \
- _up = (N) % _FP_W_TYPE_SIZE; \
- _down = _FP_W_TYPE_SIZE - _up; \
- if (!_up) \
- for (_i = 3; _i >= _skip; --_i) \
- X##_f[_i] = X##_f[_i-_skip]; \
- else \
- { \
- for (_i = 3; _i > _skip; --_i) \
- X##_f[_i] = X##_f[_i-_skip] << _up \
- | X##_f[_i-_skip-1] >> _down; \
- X##_f[_i--] = X##_f[0] << _up; \
- } \
- for (; _i >= 0; --_i) \
- X##_f[_i] = 0; \
- } while (0)
-
-/* This one was broken too */
-#define _FP_FRAC_SRL_4(X,N) \
- do { \
- _FP_I_TYPE _up, _down, _skip, _i; \
- _skip = (N) / _FP_W_TYPE_SIZE; \
- _down = (N) % _FP_W_TYPE_SIZE; \
- _up = _FP_W_TYPE_SIZE - _down; \
- if (!_down) \
- for (_i = 0; _i <= 3-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip]; \
- else \
- { \
- for (_i = 0; _i < 3-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip] >> _down \
- | X##_f[_i+_skip+1] << _up; \
- X##_f[_i++] = X##_f[3] >> _down; \
- } \
- for (; _i < 4; ++_i) \
- X##_f[_i] = 0; \
- } while (0)
-
-
-/* Right shift with sticky-lsb.
- * What this actually means is that we do a standard right-shift,
- * but that if any of the bits that fall off the right hand side
- * were one then we always set the LSbit.
- */
-#define _FP_FRAC_SRS_4(X,N,size) \
- do { \
- _FP_I_TYPE _up, _down, _skip, _i; \
- _FP_W_TYPE _s; \
- _skip = (N) / _FP_W_TYPE_SIZE; \
- _down = (N) % _FP_W_TYPE_SIZE; \
- _up = _FP_W_TYPE_SIZE - _down; \
- for (_s = _i = 0; _i < _skip; ++_i) \
- _s |= X##_f[_i]; \
- _s |= X##_f[_i] << _up; \
-/* s is now != 0 if we want to set the LSbit */ \
- if (!_down) \
- for (_i = 0; _i <= 3-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip]; \
- else \
- { \
- for (_i = 0; _i < 3-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip] >> _down \
- | X##_f[_i+_skip+1] << _up; \
- X##_f[_i++] = X##_f[3] >> _down; \
- } \
- for (; _i < 4; ++_i) \
- X##_f[_i] = 0; \
- /* don't fix the LSB until the very end when we're sure f[0] is stable */ \
- X##_f[0] |= (_s != 0); \
- } while (0)
-
-#define _FP_FRAC_ADD_4(R,X,Y) \
- __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
- X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
- Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
-
-#define _FP_FRAC_SUB_4(R,X,Y) \
- __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
- X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
- Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
-
-#define _FP_FRAC_DEC_4(X,Y) \
- __FP_FRAC_DEC_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
- Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
-
-#define _FP_FRAC_ADDI_4(X,I) \
- __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
-
-#define _FP_ZEROFRAC_4 0,0,0,0
-#define _FP_MINFRAC_4 0,0,0,1
-#define _FP_MAXFRAC_4 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
-
-#define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
-#define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE)X##_f[3] < 0)
-#define _FP_FRAC_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
-
-#define _FP_FRAC_EQ_4(X,Y) \
- (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \
- && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
-
-#define _FP_FRAC_GT_4(X,Y) \
- (X##_f[3] > Y##_f[3] || \
- (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \
- (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \
- (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0]) \
- )) \
- )) \
- )
-
-#define _FP_FRAC_GE_4(X,Y) \
- (X##_f[3] > Y##_f[3] || \
- (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \
- (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \
- (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0]) \
- )) \
- )) \
- )
-
-
-#define _FP_FRAC_CLZ_4(R,X) \
- do { \
- if (X##_f[3]) \
- { \
- __FP_CLZ(R,X##_f[3]); \
- } \
- else if (X##_f[2]) \
- { \
- __FP_CLZ(R,X##_f[2]); \
- R += _FP_W_TYPE_SIZE; \
- } \
- else if (X##_f[1]) \
- { \
- __FP_CLZ(R,X##_f[2]); \
- R += _FP_W_TYPE_SIZE*2; \
- } \
- else \
- { \
- __FP_CLZ(R,X##_f[0]); \
- R += _FP_W_TYPE_SIZE*3; \
- } \
- } while(0)
-
-
-#define _FP_UNPACK_RAW_4(fs, X, val) \
- do { \
- union _FP_UNION_##fs _flo; _flo.flt = (val); \
- X##_f[0] = _flo.bits.frac0; \
- X##_f[1] = _flo.bits.frac1; \
- X##_f[2] = _flo.bits.frac2; \
- X##_f[3] = _flo.bits.frac3; \
- X##_e = _flo.bits.exp; \
- X##_s = _flo.bits.sign; \
- } while (0)
-
-#define _FP_UNPACK_RAW_4_P(fs, X, val) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)(val); \
- \
- X##_f[0] = _flo->bits.frac0; \
- X##_f[1] = _flo->bits.frac1; \
- X##_f[2] = _flo->bits.frac2; \
- X##_f[3] = _flo->bits.frac3; \
- X##_e = _flo->bits.exp; \
- X##_s = _flo->bits.sign; \
- } while (0)
-
-#define _FP_PACK_RAW_4(fs, val, X) \
- do { \
- union _FP_UNION_##fs _flo; \
- _flo.bits.frac0 = X##_f[0]; \
- _flo.bits.frac1 = X##_f[1]; \
- _flo.bits.frac2 = X##_f[2]; \
- _flo.bits.frac3 = X##_f[3]; \
- _flo.bits.exp = X##_e; \
- _flo.bits.sign = X##_s; \
- (val) = _flo.flt; \
- } while (0)
-
-#define _FP_PACK_RAW_4_P(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)(val); \
- \
- _flo->bits.frac0 = X##_f[0]; \
- _flo->bits.frac1 = X##_f[1]; \
- _flo->bits.frac2 = X##_f[2]; \
- _flo->bits.frac3 = X##_f[3]; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
-
-/*
- * Multiplication algorithms:
- */
-
-/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
-
-#define _FP_MUL_MEAT_4_wide(fs, R, X, Y, doit) \
- do { \
- _FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
- _FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f); \
- \
- doit(_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0), X##_f[0], Y##_f[0]); \
- doit(_b_f1, _b_f0, X##_f[0], Y##_f[1]); \
- doit(_c_f1, _c_f0, X##_f[1], Y##_f[0]); \
- doit(_d_f1, _d_f0, X##_f[1], Y##_f[1]); \
- doit(_e_f1, _e_f0, X##_f[0], Y##_f[2]); \
- doit(_f_f1, _f_f0, X##_f[2], Y##_f[0]); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
- _FP_FRAC_WORD_8(_z,1), 0,_b_f1,_b_f0, \
- 0,0,_FP_FRAC_WORD_8(_z,1)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
- _FP_FRAC_WORD_8(_z,1), 0,_c_f1,_c_f0, \
- _FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
- _FP_FRAC_WORD_8(_z,1)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
- _FP_FRAC_WORD_8(_z,2), 0,_d_f1,_d_f0, \
- 0,_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
- _FP_FRAC_WORD_8(_z,2), 0,_e_f1,_e_f0, \
- _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
- _FP_FRAC_WORD_8(_z,2)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
- _FP_FRAC_WORD_8(_z,2), 0,_f_f1,_f_f0, \
- _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
- _FP_FRAC_WORD_8(_z,2)); \
- doit(_b_f1, _b_f0, X##_f[0], Y##_f[3]); \
- doit(_c_f1, _c_f0, X##_f[3], Y##_f[0]); \
- doit(_d_f1, _d_f0, X##_f[1], Y##_f[2]); \
- doit(_e_f1, _e_f0, X##_f[2], Y##_f[1]); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3), 0,_b_f1,_b_f0, \
- 0,_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3), 0,_c_f1,_c_f0, \
- _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3), 0,_d_f1,_d_f0, \
- _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3), 0,_e_f1,_e_f0, \
- _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3)); \
- doit(_b_f1, _b_f0, X##_f[2], Y##_f[2]); \
- doit(_c_f1, _c_f0, X##_f[1], Y##_f[3]); \
- doit(_d_f1, _d_f0, X##_f[3], Y##_f[1]); \
- doit(_e_f1, _e_f0, X##_f[2], Y##_f[3]); \
- doit(_f_f1, _f_f0, X##_f[3], Y##_f[2]); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
- _FP_FRAC_WORD_8(_z,4), 0,_b_f1,_b_f0, \
- 0,_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
- _FP_FRAC_WORD_8(_z,4), 0,_c_f1,_c_f0, \
- _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
- _FP_FRAC_WORD_8(_z,4)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
- _FP_FRAC_WORD_8(_z,4), 0,_d_f1,_d_f0, \
- _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
- _FP_FRAC_WORD_8(_z,4)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
- _FP_FRAC_WORD_8(_z,5), 0,_e_f1,_e_f0, \
- 0,_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
- _FP_FRAC_WORD_8(_z,5), 0,_f_f1,_f_f0, \
- _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
- _FP_FRAC_WORD_8(_z,5)); \
- doit(_b_f1, _b_f0, X##_f[3], Y##_f[3]); \
- __FP_FRAC_ADD_2(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
- _b_f1,_b_f0, \
- _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6)); \
- \
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_8(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \
- __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \
- _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \
- } while (0)
-
-#define _FP_MUL_MEAT_4_gmp(fs, R, X, Y) \
- do { \
- _FP_FRAC_DECL_8(_z); \
- \
- mpn_mul_n(_z_f, _x_f, _y_f, 4); \
- \
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_8(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \
- __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \
- _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \
- } while (0)
-
-/*
- * Helper utility for _FP_DIV_MEAT_4_udiv:
- * pppp = m * nnn
- */
-#define umul_ppppmnnn(p3,p2,p1,p0,m,n2,n1,n0) \
- do { \
- UWtype _t; \
- umul_ppmm(p1,p0,m,n0); \
- umul_ppmm(p2,_t,m,n1); \
- __FP_FRAC_ADDI_2(p2,p1,_t); \
- umul_ppmm(p3,_t,m,n2); \
- __FP_FRAC_ADDI_2(p3,p2,_t); \
- } while (0)
-
-/*
- * Division algorithms:
- */
-
-#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y) \
- do { \
- int _i; \
- _FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m); \
- _FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4); \
- if (_FP_FRAC_GT_4(X, Y)) \
- { \
- _n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1); \
- _FP_FRAC_SRL_4(X, 1); \
- } \
- else \
- R##_e--; \
- \
- /* Normalize, i.e. make the most significant bit of the \
- denominator set. */ \
- _FP_FRAC_SLL_4(Y, _FP_WFRACXBITS_##fs); \
- \
- for (_i = 3; ; _i--) \
- { \
- if (X##_f[3] == Y##_f[3]) \
- { \
- /* This is a special case, not an optimization \
- (X##_f[3]/Y##_f[3] would not fit into UWtype). \
- As X## is guaranteed to be < Y, R##_f[_i] can be either \
- (UWtype)-1 or (UWtype)-2. */ \
- R##_f[_i] = -1; \
- if (!_i) \
- break; \
- __FP_FRAC_SUB_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
- Y##_f[2], Y##_f[1], Y##_f[0], 0, \
- X##_f[2], X##_f[1], X##_f[0], _n_f[_i]); \
- _FP_FRAC_SUB_4(X, Y, X); \
- if (X##_f[3] > Y##_f[3]) \
- { \
- R##_f[_i] = -2; \
- _FP_FRAC_ADD_4(X, Y, X); \
- } \
- } \
- else \
- { \
- udiv_qrnnd(R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]); \
- umul_ppppmnnn(_m_f[3], _m_f[2], _m_f[1], _m_f[0], \
- R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]); \
- X##_f[2] = X##_f[1]; \
- X##_f[1] = X##_f[0]; \
- X##_f[0] = _n_f[_i]; \
- if (_FP_FRAC_GT_4(_m, X)) \
- { \
- R##_f[_i]--; \
- _FP_FRAC_ADD_4(X, Y, X); \
- if (_FP_FRAC_GE_4(X, Y) && _FP_FRAC_GT_4(_m, X)) \
- { \
- R##_f[_i]--; \
- _FP_FRAC_ADD_4(X, Y, X); \
- } \
- } \
- _FP_FRAC_DEC_4(X, _m); \
- if (!_i) \
- { \
- if (!_FP_FRAC_EQ_4(X, _m)) \
- R##_f[0] |= _FP_WORK_STICKY; \
- break; \
- } \
- } \
- } \
- } while (0)
-
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- */
-
-#define _FP_SQRT_MEAT_4(R, S, T, X, q) \
- do { \
- while (q) \
- { \
- T##_f[3] = S##_f[3] + q; \
- if (T##_f[3] <= X##_f[3]) \
- { \
- S##_f[3] = T##_f[3] + q; \
- X##_f[3] -= T##_f[3]; \
- R##_f[3] += q; \
- } \
- _FP_FRAC_SLL_4(X, 1); \
- q >>= 1; \
- } \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- while (q) \
- { \
- T##_f[2] = S##_f[2] + q; \
- T##_f[3] = S##_f[3]; \
- if (T##_f[3] < X##_f[3] || \
- (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2])) \
- { \
- S##_f[2] = T##_f[2] + q; \
- S##_f[3] += (T##_f[2] > S##_f[2]); \
- __FP_FRAC_DEC_2(X##_f[3], X##_f[2], \
- T##_f[3], T##_f[2]); \
- R##_f[2] += q; \
- } \
- _FP_FRAC_SLL_4(X, 1); \
- q >>= 1; \
- } \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- while (q) \
- { \
- T##_f[1] = S##_f[1] + q; \
- T##_f[2] = S##_f[2]; \
- T##_f[3] = S##_f[3]; \
- if (T##_f[3] < X##_f[3] || \
- (T##_f[3] == X##_f[3] && (T##_f[2] < X##_f[2] || \
- (T##_f[2] == X##_f[2] && T##_f[1] <= X##_f[1])))) \
- { \
- S##_f[1] = T##_f[1] + q; \
- S##_f[2] += (T##_f[1] > S##_f[1]); \
- S##_f[3] += (T##_f[2] > S##_f[2]); \
- __FP_FRAC_DEC_3(X##_f[3], X##_f[2], X##_f[1], \
- T##_f[3], T##_f[2], T##_f[1]); \
- R##_f[1] += q; \
- } \
- _FP_FRAC_SLL_4(X, 1); \
- q >>= 1; \
- } \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- while (q != _FP_WORK_ROUND) \
- { \
- T##_f[0] = S##_f[0] + q; \
- T##_f[1] = S##_f[1]; \
- T##_f[2] = S##_f[2]; \
- T##_f[3] = S##_f[3]; \
- if (_FP_FRAC_GE_4(X,T)) \
- { \
- S##_f[0] = T##_f[0] + q; \
- S##_f[1] += (T##_f[0] > S##_f[0]); \
- S##_f[2] += (T##_f[1] > S##_f[1]); \
- S##_f[3] += (T##_f[2] > S##_f[2]); \
- _FP_FRAC_DEC_4(X, T); \
- R##_f[0] += q; \
- } \
- _FP_FRAC_SLL_4(X, 1); \
- q >>= 1; \
- } \
- if (!_FP_FRAC_ZEROP_4(X)) \
- { \
- if (_FP_FRAC_GT_4(X,S)) \
- R##_f[0] |= _FP_WORK_ROUND; \
- R##_f[0] |= _FP_WORK_STICKY; \
- } \
- } while (0)
-
-
-/*
- * Internals
- */
-
-#define __FP_FRAC_SET_4(X,I3,I2,I1,I0) \
- (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)
-
-#ifndef __FP_FRAC_ADD_3
-#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \
- (r0 = x0 + y0, \
- r1 = x1 + y1 + (r0 < x0), \
- r2 = x2 + y2 + (r1 < x1))
-#endif
-
-#ifndef __FP_FRAC_ADD_4
-#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
- (r0 = x0 + y0, \
- r1 = x1 + y1 + (r0 < x0), \
- r2 = x2 + y2 + (r1 < x1), \
- r3 = x3 + y3 + (r2 < x2))
-#endif
-
-#ifndef __FP_FRAC_SUB_3
-#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \
- (r0 = x0 - y0, \
- r1 = x1 - y1 - (r0 > x0), \
- r2 = x2 - y2 - (r1 > x1))
-#endif
-
-#ifndef __FP_FRAC_SUB_4
-#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
- (r0 = x0 - y0, \
- r1 = x1 - y1 - (r0 > x0), \
- r2 = x2 - y2 - (r1 > x1), \
- r3 = x3 - y3 - (r2 > x2))
-#endif
-
-#ifndef __FP_FRAC_DEC_3
-#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) \
- do { \
- UWtype _t0, _t1; \
- _t0 = x0; \
- x0 -= y0; \
- _t1 = x1; \
- x1 -= y1 + (x0 > _t0); \
- x2 -= y2 + (x1 > _t1); \
- } while (0)
-#endif
-
-#ifndef __FP_FRAC_DEC_4
-#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) \
- do { \
- UWtype _t0, _t1; \
- _t0 = x0; \
- x0 -= y0; \
- _t1 = x1; \
- x1 -= y1 + (x0 > _t0); \
- _t0 = x2; \
- x2 -= y2 + (x1 > _t1); \
- x3 -= y3 + (x2 > _t0); \
- } while (0)
-#endif
-
-#ifndef __FP_FRAC_ADDI_4
-#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \
- do { \
- UWtype _t; \
- _t = ((x0 += i) < i); \
- x1 += _t; _t = (x1 < _t); \
- x2 += _t; _t = (x2 < _t); \
- x3 += _t; \
- } while (0)
-#endif
-
-/* Convert FP values between word sizes. This appears to be more
- * complicated than I'd have expected it to be, so these might be
- * wrong... These macros are in any case somewhat bogus because they
- * use information about what various FRAC_n variables look like
- * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do
- * the ones in op-2.h and op-1.h.
- */
-#define _FP_FRAC_CONV_1_4(dfs, sfs, D, S) \
- do { \
- if (S##_c != FP_CLS_NAN) \
- _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \
- _FP_WFRACBITS_##sfs); \
- else \
- _FP_FRAC_SRL_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs)); \
- D##_f = S##_f[0]; \
- } while (0)
-
-#define _FP_FRAC_CONV_2_4(dfs, sfs, D, S) \
- do { \
- if (S##_c != FP_CLS_NAN) \
- _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \
- _FP_WFRACBITS_##sfs); \
- else \
- _FP_FRAC_SRL_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs)); \
- D##_f0 = S##_f[0]; \
- D##_f1 = S##_f[1]; \
- } while (0)
-
-/* Assembly/disassembly for converting to/from integral types.
- * No shifting or overflow handled here.
- */
-/* Put the FP value X into r, which is an integer of size rsize. */
-#define _FP_FRAC_ASSEMBLE_4(r, X, rsize) \
- do { \
- if (rsize <= _FP_W_TYPE_SIZE) \
- r = X##_f[0]; \
- else if (rsize <= 2*_FP_W_TYPE_SIZE) \
- { \
- r = X##_f[1]; \
- r <<= _FP_W_TYPE_SIZE; \
- r += X##_f[0]; \
- } \
- else \
- { \
- /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \
- /* and int == 4words as a single case. */ \
- r = X##_f[3]; \
- r <<= _FP_W_TYPE_SIZE; \
- r += X##_f[2]; \
- r <<= _FP_W_TYPE_SIZE; \
- r += X##_f[1]; \
- r <<= _FP_W_TYPE_SIZE; \
- r += X##_f[0]; \
- } \
- } while (0)
-
-/* "No disassemble Number Five!" */
-/* move an integer of size rsize into X's fractional part. We rely on
- * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid
- * having to mask the values we store into it.
- */
-#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize) \
- do { \
- X##_f[0] = r; \
- X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
- X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
- X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
- } while (0);
-
-#define _FP_FRAC_CONV_4_1(dfs, sfs, D, S) \
- do { \
- D##_f[0] = S##_f; \
- D##_f[1] = D##_f[2] = D##_f[3] = 0; \
- _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \
- } while (0)
-
-#define _FP_FRAC_CONV_4_2(dfs, sfs, D, S) \
- do { \
- D##_f[0] = S##_f0; \
- D##_f[1] = S##_f1; \
- D##_f[2] = D##_f[3] = 0; \
- _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \
- } while (0)
-
diff --git a/arch/sparc64/math-emu/op-8.h b/arch/sparc64/math-emu/op-8.h
deleted file mode 100644
index a9d7dbf59..000000000
--- a/arch/sparc64/math-emu/op-8.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* Software floating-point emulation.
- Basic eight-word fraction declaration and manipulation.
- Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson (rth@cygnus.com),
- Jakub Jelinek (jj@ultra.linux.cz) and
- Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/* We need just a few things from here for op-4, if we ever need some
- other macros, they can be added. */
-#define _FP_FRAC_DECL_8(X) _FP_W_TYPE X##_f[8]
-#define _FP_FRAC_HIGH_8(X) (X##_f[7])
-#define _FP_FRAC_LOW_8(X) (X##_f[0])
-#define _FP_FRAC_WORD_8(X,w) (X##_f[w])
-
-#define _FP_FRAC_SLL_8(X,N) \
- do { \
- _FP_I_TYPE _up, _down, _skip, _i; \
- _skip = (N) / _FP_W_TYPE_SIZE; \
- _up = (N) % _FP_W_TYPE_SIZE; \
- _down = _FP_W_TYPE_SIZE - _up; \
- if (!_up) \
- for (_i = 7; _i >= _skip; --_i) \
- X##_f[_i] = X##_f[_i-_skip]; \
- else \
- { \
- for (_i = 7; _i > _skip; --_i) \
- X##_f[_i] = X##_f[_i-_skip] << _up \
- | X##_f[_i-_skip-1] >> _down; \
- X##_f[_i--] = X##_f[0] << _up; \
- } \
- for (; _i >= 0; --_i) \
- X##_f[_i] = 0; \
- } while (0)
-
-#define _FP_FRAC_SRL_8(X,N) \
- do { \
- _FP_I_TYPE _up, _down, _skip, _i; \
- _skip = (N) / _FP_W_TYPE_SIZE; \
- _down = (N) % _FP_W_TYPE_SIZE; \
- _up = _FP_W_TYPE_SIZE - _down; \
- if (!_down) \
- for (_i = 0; _i <= 7-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip]; \
- else \
- { \
- for (_i = 0; _i < 7-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip] >> _down \
- | X##_f[_i+_skip+1] << _up; \
- X##_f[_i++] = X##_f[7] >> _down; \
- } \
- for (; _i < 8; ++_i) \
- X##_f[_i] = 0; \
- } while (0)
-
-
-/* Right shift with sticky-lsb.
- * What this actually means is that we do a standard right-shift,
- * but that if any of the bits that fall off the right hand side
- * were one then we always set the LSbit.
- */
-#define _FP_FRAC_SRS_8(X,N,size) \
- do { \
- _FP_I_TYPE _up, _down, _skip, _i; \
- _FP_W_TYPE _s; \
- _skip = (N) / _FP_W_TYPE_SIZE; \
- _down = (N) % _FP_W_TYPE_SIZE; \
- _up = _FP_W_TYPE_SIZE - _down; \
- for (_s = _i = 0; _i < _skip; ++_i) \
- _s |= X##_f[_i]; \
- _s |= X##_f[_i] << _up; \
-/* s is now != 0 if we want to set the LSbit */ \
- if (!_down) \
- for (_i = 0; _i <= 7-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip]; \
- else \
- { \
- for (_i = 0; _i < 7-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip] >> _down \
- | X##_f[_i+_skip+1] << _up; \
- X##_f[_i++] = X##_f[7] >> _down; \
- } \
- for (; _i < 8; ++_i) \
- X##_f[_i] = 0; \
- /* don't fix the LSB until the very end when we're sure f[0] is stable */ \
- X##_f[0] |= (_s != 0); \
- } while (0)
-
diff --git a/arch/sparc64/math-emu/op-common.h b/arch/sparc64/math-emu/op-common.h
deleted file mode 100644
index 529f0e4b2..000000000
--- a/arch/sparc64/math-emu/op-common.h
+++ /dev/null
@@ -1,760 +0,0 @@
-/* Software floating-point emulation. Common operations.
- Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson (rth@cygnus.com),
- Jakub Jelinek (jj@ultra.linux.cz),
- David S. Miller (davem@redhat.com) and
- Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#define _FP_DECL(wc, X) \
- _FP_I_TYPE X##_c, X##_s, X##_e; \
- _FP_FRAC_DECL_##wc(X)
-
-/*
- * Finish truely unpacking a native fp value by classifying the kind
- * of fp value and normalizing both the exponent and the fraction.
- */
-
-#define _FP_UNPACK_CANONICAL(fs, wc, X) \
-do { \
- switch (X##_e) \
- { \
- default: \
- _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \
- _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \
- X##_e -= _FP_EXPBIAS_##fs; \
- X##_c = FP_CLS_NORMAL; \
- break; \
- \
- case 0: \
- if (_FP_FRAC_ZEROP_##wc(X)) \
- X##_c = FP_CLS_ZERO; \
- else \
- { \
- /* a denormalized number */ \
- _FP_I_TYPE _shift; \
- _FP_FRAC_CLZ_##wc(_shift, X); \
- _shift -= _FP_FRACXBITS_##fs; \
- _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \
- X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \
- X##_c = FP_CLS_NORMAL; \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- } \
- break; \
- \
- case _FP_EXPMAX_##fs: \
- if (_FP_FRAC_ZEROP_##wc(X)) \
- X##_c = FP_CLS_INF; \
- else \
- { \
- X##_c = FP_CLS_NAN; \
- /* Check for signaling NaN */ \
- if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- } \
- break; \
- } \
-} while (0)
-
-/*
- * Before packing the bits back into the native fp result, take care
- * of such mundane things as rounding and overflow. Also, for some
- * kinds of fp values, the original parts may not have been fully
- * extracted -- but that is ok, we can regenerate them now.
- */
-
-#define _FP_PACK_CANONICAL(fs, wc, X) \
-do { \
- switch (X##_c) \
- { \
- case FP_CLS_NORMAL: \
- X##_e += _FP_EXPBIAS_##fs; \
- if (X##_e > 0) \
- { \
- _FP_ROUND(wc, X); \
- if (_FP_FRAC_OVERP_##wc(fs, X)) \
- { \
- _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1)); \
- X##_e++; \
- } \
- else \
- _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
- if (X##_e >= _FP_EXPMAX_##fs) \
- { \
- /* overflow */ \
- switch (FP_ROUNDMODE) \
- { \
- case FP_RND_NEAREST: \
- X##_c = FP_CLS_INF; \
- break; \
- case FP_RND_PINF: \
- if (!X##_s) X##_c = FP_CLS_INF; \
- break; \
- case FP_RND_MINF: \
- if (X##_s) X##_c = FP_CLS_INF; \
- break; \
- } \
- if (X##_c == FP_CLS_INF) \
- { \
- /* Overflow to infinity */ \
- X##_e = _FP_EXPMAX_##fs; \
- _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
- } \
- else \
- { \
- /* Overflow to maximum normal */ \
- X##_e = _FP_EXPMAX_##fs - 1; \
- _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \
- } \
- FP_SET_EXCEPTION(FP_EX_OVERFLOW); \
- FP_SET_EXCEPTION(FP_EX_INEXACT); \
- } \
- } \
- else \
- { \
- /* we've got a denormalized number */ \
- X##_e = -X##_e + 1; \
- if (X##_e <= _FP_WFRACBITS_##fs) \
- { \
- _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \
- _FP_ROUND(wc, X); \
- if (_FP_FRAC_HIGH_##fs(X) \
- & (_FP_OVERFLOW_##fs >> 1)) \
- { \
- X##_e = 1; \
- _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
- } \
- else \
- { \
- X##_e = 0; \
- _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
- FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
- } \
- } \
- else \
- { \
- /* underflow to zero */ \
- X##_e = 0; \
- if (!_FP_FRAC_ZEROP_##wc(X)) \
- { \
- _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
- _FP_ROUND(wc, X); \
- _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS); \
- } \
- FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
- } \
- } \
- break; \
- \
- case FP_CLS_ZERO: \
- X##_e = 0; \
- _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
- break; \
- \
- case FP_CLS_INF: \
- X##_e = _FP_EXPMAX_##fs; \
- _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
- break; \
- \
- case FP_CLS_NAN: \
- X##_e = _FP_EXPMAX_##fs; \
- if (!_FP_KEEPNANFRACP) \
- { \
- _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
- X##_s = _FP_NANSIGN_##fs; \
- } \
- else \
- _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \
- break; \
- } \
-} while (0)
-
-/* This one accepts raw argument and not cooked, returns
- * 1 if X is a signaling NaN.
- */
-#define _FP_ISSIGNAN(fs, wc, X) \
-({ \
- int __ret = 0; \
- if (X##_e == _FP_EXPMAX_##fs) \
- { \
- if (!_FP_FRAC_ZEROP_##wc(X) \
- && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
- __ret = 1; \
- } \
- __ret; \
-})
-
-
-
-
-
-/*
- * Main addition routine. The input values should be cooked.
- */
-
-#define _FP_ADD(fs, wc, R, X, Y) \
-do { \
- switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
- { \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
- { \
- /* shift the smaller number so that its exponent matches the larger */ \
- _FP_I_TYPE diff = X##_e - Y##_e; \
- \
- if (diff < 0) \
- { \
- diff = -diff; \
- if (diff <= _FP_WFRACBITS_##fs) \
- _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs); \
- else if (!_FP_FRAC_ZEROP_##wc(X)) \
- _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
- R##_e = Y##_e; \
- } \
- else \
- { \
- if (diff > 0) \
- { \
- if (diff <= _FP_WFRACBITS_##fs) \
- _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs); \
- else if (!_FP_FRAC_ZEROP_##wc(Y)) \
- _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \
- } \
- R##_e = X##_e; \
- } \
- \
- R##_c = FP_CLS_NORMAL; \
- \
- if (X##_s == Y##_s) \
- { \
- R##_s = X##_s; \
- _FP_FRAC_ADD_##wc(R, X, Y); \
- if (_FP_FRAC_OVERP_##wc(fs, R)) \
- { \
- _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
- R##_e++; \
- } \
- } \
- else \
- { \
- R##_s = X##_s; \
- _FP_FRAC_SUB_##wc(R, X, Y); \
- if (_FP_FRAC_ZEROP_##wc(R)) \
- { \
- /* return an exact zero */ \
- if (FP_ROUNDMODE == FP_RND_MINF) \
- R##_s |= Y##_s; \
- else \
- R##_s &= Y##_s; \
- R##_c = FP_CLS_ZERO; \
- } \
- else \
- { \
- if (_FP_FRAC_NEGP_##wc(R)) \
- { \
- _FP_FRAC_SUB_##wc(R, Y, X); \
- R##_s = Y##_s; \
- } \
- \
- /* renormalize after subtraction */ \
- _FP_FRAC_CLZ_##wc(diff, R); \
- diff -= _FP_WFRACXBITS_##fs; \
- if (diff) \
- { \
- R##_e -= diff; \
- _FP_FRAC_SLL_##wc(R, diff); \
- } \
- } \
- } \
- break; \
- } \
- \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
- _FP_CHOOSENAN(fs, wc, R, X, Y); \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
- R##_e = X##_e; \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
- _FP_FRAC_COPY_##wc(R, X); \
- R##_s = X##_s; \
- R##_c = X##_c; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
- R##_e = Y##_e; \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
- _FP_FRAC_COPY_##wc(R, Y); \
- R##_s = Y##_s; \
- R##_c = Y##_c; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
- if (X##_s != Y##_s) \
- { \
- /* +INF + -INF => NAN */ \
- _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
- R##_s = _FP_NANSIGN_##fs; \
- R##_c = FP_CLS_NAN; \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- break; \
- } \
- /* FALLTHRU */ \
- \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
- R##_s = X##_s; \
- R##_c = FP_CLS_INF; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
- R##_s = Y##_s; \
- R##_c = FP_CLS_INF; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
- /* make sure the sign is correct */ \
- if (FP_ROUNDMODE == FP_RND_MINF) \
- R##_s = X##_s | Y##_s; \
- else \
- R##_s = X##_s & Y##_s; \
- R##_c = FP_CLS_ZERO; \
- break; \
- \
- default: \
- abort(); \
- } \
-} while (0)
-
-
-/*
- * Main negation routine. FIXME -- when we care about setting exception
- * bits reliably, this will not do. We should examine all of the fp classes.
- */
-
-#define _FP_NEG(fs, wc, R, X) \
- do { \
- _FP_FRAC_COPY_##wc(R, X); \
- R##_c = X##_c; \
- R##_e = X##_e; \
- R##_s = 1 ^ X##_s; \
- } while (0)
-
-
-/*
- * Main multiplication routine. The input values should be cooked.
- */
-
-#define _FP_MUL(fs, wc, R, X, Y) \
-do { \
- R##_s = X##_s ^ Y##_s; \
- switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
- { \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
- R##_c = FP_CLS_NORMAL; \
- R##_e = X##_e + Y##_e + 1; \
- \
- _FP_MUL_MEAT_##fs(R,X,Y); \
- \
- if (_FP_FRAC_OVERP_##wc(fs, R)) \
- _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
- else \
- R##_e--; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
- _FP_CHOOSENAN(fs, wc, R, X, Y); \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
- R##_s = X##_s; \
- \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
- _FP_FRAC_COPY_##wc(R, X); \
- R##_c = X##_c; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
- R##_s = Y##_s; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
- _FP_FRAC_COPY_##wc(R, Y); \
- R##_c = Y##_c; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
- R##_s = _FP_NANSIGN_##fs; \
- R##_c = FP_CLS_NAN; \
- _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- break; \
- \
- default: \
- abort(); \
- } \
-} while (0)
-
-
-/*
- * Main division routine. The input values should be cooked.
- */
-
-#define _FP_DIV(fs, wc, R, X, Y) \
-do { \
- R##_s = X##_s ^ Y##_s; \
- switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
- { \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
- R##_c = FP_CLS_NORMAL; \
- R##_e = X##_e - Y##_e; \
- \
- _FP_DIV_MEAT_##fs(R,X,Y); \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
- _FP_CHOOSENAN(fs, wc, R, X, Y); \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
- R##_s = X##_s; \
- _FP_FRAC_COPY_##wc(R, X); \
- R##_c = X##_c; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
- R##_s = Y##_s; \
- _FP_FRAC_COPY_##wc(R, Y); \
- R##_c = Y##_c; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
- R##_c = FP_CLS_ZERO; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
- FP_SET_EXCEPTION(FP_EX_DIVZERO); \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
- R##_c = FP_CLS_INF; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
- R##_s = _FP_NANSIGN_##fs; \
- R##_c = FP_CLS_NAN; \
- _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- break; \
- \
- default: \
- abort(); \
- } \
-} while (0)
-
-
-/*
- * Main differential comparison routine. The inputs should be raw not
- * cooked. The return is -1,0,1 for normal values, 2 otherwise.
- */
-
-#define _FP_CMP(fs, wc, ret, X, Y, un) \
- do { \
- /* NANs are unordered */ \
- if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
- || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
- { \
- ret = un; \
- } \
- else \
- { \
- int __is_zero_x; \
- int __is_zero_y; \
- \
- __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
- __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
- \
- if (__is_zero_x && __is_zero_y) \
- ret = 0; \
- else if (__is_zero_x) \
- ret = Y##_s ? 1 : -1; \
- else if (__is_zero_y) \
- ret = X##_s ? -1 : 1; \
- else if (X##_s != Y##_s) \
- ret = X##_s ? -1 : 1; \
- else if (X##_e > Y##_e) \
- ret = X##_s ? -1 : 1; \
- else if (X##_e < Y##_e) \
- ret = X##_s ? 1 : -1; \
- else if (_FP_FRAC_GT_##wc(X, Y)) \
- ret = X##_s ? -1 : 1; \
- else if (_FP_FRAC_GT_##wc(Y, X)) \
- ret = X##_s ? 1 : -1; \
- else \
- ret = 0; \
- } \
- } while (0)
-
-
-/* Simplification for strict equality. */
-
-#define _FP_CMP_EQ(fs, wc, ret, X, Y) \
- do { \
- /* NANs are unordered */ \
- if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
- || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
- { \
- ret = 1; \
- } \
- else \
- { \
- ret = !(X##_e == Y##_e \
- && _FP_FRAC_EQ_##wc(X, Y) \
- && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
- } \
- } while (0)
-
-/*
- * Main square root routine. The input value should be cooked.
- */
-
-#define _FP_SQRT(fs, wc, R, X) \
-do { \
- _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \
- _FP_W_TYPE q; \
- switch (X##_c) \
- { \
- case FP_CLS_NAN: \
- _FP_FRAC_COPY_##wc(R, X); \
- R##_s = X##_s; \
- R##_c = FP_CLS_NAN; \
- break; \
- case FP_CLS_INF: \
- if (X##_s) \
- { \
- R##_s = _FP_NANSIGN_##fs; \
- R##_c = FP_CLS_NAN; /* NAN */ \
- _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- } \
- else \
- { \
- R##_s = 0; \
- R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
- } \
- break; \
- case FP_CLS_ZERO: \
- R##_s = X##_s; \
- R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
- break; \
- case FP_CLS_NORMAL: \
- R##_s = 0; \
- if (X##_s) \
- { \
- R##_c = FP_CLS_NAN; /* sNAN */ \
- R##_s = _FP_NANSIGN_##fs; \
- _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- break; \
- } \
- R##_c = FP_CLS_NORMAL; \
- if (X##_e & 1) \
- _FP_FRAC_SLL_##wc(X, 1); \
- R##_e = X##_e >> 1; \
- _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \
- _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \
- q = _FP_OVERFLOW_##fs >> 1; \
- _FP_SQRT_MEAT_##wc(R, S, T, X, q); \
- } \
- } while (0)
-
-/*
- * Convert from FP to integer
- */
-
-/* RSIGNED can have following values:
- * 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus
- * the result is either 0 or (2^rsize)-1 depending on the sign in such case.
- * 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
- * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
- * on the sign in such case.
- * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
- * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
- * on the sign in such case.
- */
-#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
- do { \
- switch (X##_c) \
- { \
- case FP_CLS_NORMAL: \
- if (X##_e < 0) \
- { \
- FP_SET_EXCEPTION(FP_EX_INEXACT); \
- case FP_CLS_ZERO: \
- r = 0; \
- } \
- else if (X##_e >= rsize - (rsigned > 0 || X##_s) \
- || (!rsigned && X##_s)) \
- { /* overflow */ \
- case FP_CLS_NAN: \
- case FP_CLS_INF: \
- if (rsigned) \
- { \
- r = 1; \
- r <<= rsize - 1; \
- r -= 1 - X##_s; \
- } else { \
- r = 0; \
- if (X##_s) \
- r = ~r; \
- } \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- } \
- else \
- { \
- if (_FP_W_TYPE_SIZE*wc < rsize) \
- { \
- _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
- r <<= X##_e - _FP_WFRACBITS_##fs; \
- } \
- else \
- { \
- if (X##_e >= _FP_WFRACBITS_##fs) \
- _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
- else if (X##_e < _FP_WFRACBITS_##fs - 1) \
- { \
- _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2), \
- _FP_WFRACBITS_##fs); \
- if (_FP_FRAC_LOW_##wc(X) & 1) \
- FP_SET_EXCEPTION(FP_EX_INEXACT); \
- _FP_FRAC_SRL_##wc(X, 1); \
- } \
- _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
- } \
- if (rsigned && X##_s) \
- r = -r; \
- } \
- break; \
- } \
- } while (0)
-
-#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
- do { \
- if (r) \
- { \
- X##_c = FP_CLS_NORMAL; \
- \
- if ((X##_s = (r < 0))) \
- r = -r; \
- \
- if (rsize <= _FP_W_TYPE_SIZE) \
- __FP_CLZ(X##_e, r); \
- else \
- __FP_CLZ_2(X##_e, (_FP_W_TYPE)(r >> _FP_W_TYPE_SIZE), \
- (_FP_W_TYPE)r); \
- if (rsize < _FP_W_TYPE_SIZE) \
- X##_e -= (_FP_W_TYPE_SIZE - rsize); \
- X##_e = rsize - X##_e - 1; \
- \
- if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e) \
- __FP_FRAC_SRS_1(r, (X##_e - _FP_WFRACBITS_##fs), rsize); \
- r &= ~((rtype)1 << X##_e); \
- _FP_FRAC_DISASSEMBLE_##wc(X, ((unsigned rtype)r), rsize); \
- _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \
- } \
- else \
- { \
- X##_c = FP_CLS_ZERO, X##_s = 0; \
- } \
- } while (0)
-
-
-#define FP_CONV(dfs,sfs,dwc,swc,D,S) \
- do { \
- _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \
- D##_e = S##_e; \
- D##_c = S##_c; \
- D##_s = S##_s; \
- } while (0)
-
-/*
- * Helper primitives.
- */
-
-/* Count leading zeros in a word. */
-
-#ifndef __FP_CLZ
-#if _FP_W_TYPE_SIZE < 64
-/* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
-#define __FP_CLZ(r, x) \
- do { \
- _FP_W_TYPE _t = (x); \
- r = _FP_W_TYPE_SIZE - 1; \
- if (_t > 0xffff) r -= 16; \
- if (_t > 0xffff) _t >>= 16; \
- if (_t > 0xff) r -= 8; \
- if (_t > 0xff) _t >>= 8; \
- if (_t & 0xf0) r -= 4; \
- if (_t & 0xf0) _t >>= 4; \
- if (_t & 0xc) r -= 2; \
- if (_t & 0xc) _t >>= 2; \
- if (_t & 0x2) r -= 1; \
- } while (0)
-#else /* not _FP_W_TYPE_SIZE < 64 */
-#define __FP_CLZ(r, x) \
- do { \
- _FP_W_TYPE _t = (x); \
- r = _FP_W_TYPE_SIZE - 1; \
- if (_t > 0xffffffff) r -= 32; \
- if (_t > 0xffffffff) _t >>= 32; \
- if (_t > 0xffff) r -= 16; \
- if (_t > 0xffff) _t >>= 16; \
- if (_t > 0xff) r -= 8; \
- if (_t > 0xff) _t >>= 8; \
- if (_t & 0xf0) r -= 4; \
- if (_t & 0xf0) _t >>= 4; \
- if (_t & 0xc) r -= 2; \
- if (_t & 0xc) _t >>= 2; \
- if (_t & 0x2) r -= 1; \
- } while (0)
-#endif /* not _FP_W_TYPE_SIZE < 64 */
-#endif /* ndef __FP_CLZ */
-
-#define _FP_DIV_HELP_imm(q, r, n, d) \
- do { \
- q = n / d, r = n % d; \
- } while (0)
-
diff --git a/arch/sparc64/math-emu/quad.h b/arch/sparc64/math-emu/quad.h
deleted file mode 100644
index 4392a38c1..000000000
--- a/arch/sparc64/math-emu/quad.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/* Software floating-point emulation.
- Definitions for IEEE Quad Precision.
- Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson (rth@cygnus.com),
- Jakub Jelinek (jj@ultra.linux.cz),
- David S. Miller (davem@redhat.com) and
- Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel, kid. Go buy yourself a real computer."
-#endif
-
-#if _FP_W_TYPE_SIZE < 64
-#define _FP_FRACTBITS_Q (4*_FP_W_TYPE_SIZE)
-#else
-#define _FP_FRACTBITS_Q (2*_FP_W_TYPE_SIZE)
-#endif
-
-#define _FP_FRACBITS_Q 113
-#define _FP_FRACXBITS_Q (_FP_FRACTBITS_Q - _FP_FRACBITS_Q)
-#define _FP_WFRACBITS_Q (_FP_WORKBITS + _FP_FRACBITS_Q)
-#define _FP_WFRACXBITS_Q (_FP_FRACTBITS_Q - _FP_WFRACBITS_Q)
-#define _FP_EXPBITS_Q 15
-#define _FP_EXPBIAS_Q 16383
-#define _FP_EXPMAX_Q 32767
-
-#define _FP_QNANBIT_Q \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2) % _FP_W_TYPE_SIZE)
-#define _FP_IMPLBIT_Q \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1) % _FP_W_TYPE_SIZE)
-#define _FP_OVERFLOW_Q \
- ((_FP_W_TYPE)1 << (_FP_WFRACBITS_Q % _FP_W_TYPE_SIZE))
-
-#if _FP_W_TYPE_SIZE < 64
-
-union _FP_UNION_Q
-{
- long double flt;
- struct
- {
-#if __BYTE_ORDER == __BIG_ENDIAN
- unsigned sign : 1;
- unsigned exp : _FP_EXPBITS_Q;
- unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
- unsigned long frac2 : _FP_W_TYPE_SIZE;
- unsigned long frac1 : _FP_W_TYPE_SIZE;
- unsigned long frac0 : _FP_W_TYPE_SIZE;
-#else
- unsigned long frac0 : _FP_W_TYPE_SIZE;
- unsigned long frac1 : _FP_W_TYPE_SIZE;
- unsigned long frac2 : _FP_W_TYPE_SIZE;
- unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
- unsigned exp : _FP_EXPBITS_Q;
- unsigned sign : 1;
-#endif /* not bigendian */
- } bits __attribute__((packed));
-};
-
-
-#define FP_DECL_Q(X) _FP_DECL(4,X)
-#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_4(Q,X,val)
-#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_4_P(Q,X,val)
-#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_4(Q,val,X)
-#define FP_PACK_RAW_QP(val,X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_4_P(Q,val,X); \
- } while (0)
-
-#define FP_UNPACK_Q(X,val) \
- do { \
- _FP_UNPACK_RAW_4(Q,X,val); \
- _FP_UNPACK_CANONICAL(Q,4,X); \
- } while (0)
-
-#define FP_UNPACK_QP(X,val) \
- do { \
- _FP_UNPACK_RAW_4_P(Q,X,val); \
- _FP_UNPACK_CANONICAL(Q,4,X); \
- } while (0)
-
-#define FP_PACK_Q(val,X) \
- do { \
- _FP_PACK_CANONICAL(Q,4,X); \
- _FP_PACK_RAW_4(Q,val,X); \
- } while (0)
-
-#define FP_PACK_QP(val,X) \
- do { \
- _FP_PACK_CANONICAL(Q,4,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_4_P(Q,val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,4,X)
-#define FP_NEG_Q(R,X) _FP_NEG(Q,4,R,X)
-#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,4,R,X,Y)
-/* single.h and double.h define FP_SUB_t this way too. However, _FP_SUB is
- * never defined in op-common.h! Fortunately nobody seems to use the FP_SUB_t
- * macros: I suggest a combination of FP_NEG and FP_ADD :-> -- PMM 02/1998
- */
-#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,4,R,X,Y)
-#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,4,R,X,Y)
-#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,4,R,X,Y)
-#define FP_SQRT_Q(R,X) _FP_SQRT(Q,4,R,X)
-#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_4(R,S,T,X,Q)
-
-#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,4,r,X,Y,un)
-#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,4,r,X,Y)
-
-#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,4,r,X,rsz,rsg)
-#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,4,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_4(X)
-#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_4(X)
-
-#else /* not _FP_W_TYPE_SIZE < 64 */
-union _FP_UNION_Q
-{
- long double flt /* __attribute__((mode(TF))) */ ;
- struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
- unsigned sign : 1;
- unsigned exp : _FP_EXPBITS_Q;
- unsigned long frac1 : _FP_FRACBITS_Q-(_FP_IMPLBIT_Q != 0)-_FP_W_TYPE_SIZE;
- unsigned long frac0 : _FP_W_TYPE_SIZE;
-#else
- unsigned long frac0 : _FP_W_TYPE_SIZE;
- unsigned long frac1 : _FP_FRACBITS_Q-(_FP_IMPLBIT_Q != 0)-_FP_W_TYPE_SIZE;
- unsigned exp : _FP_EXPBITS_Q;
- unsigned sign : 1;
-#endif
- } bits;
-};
-
-#define FP_DECL_Q(X) _FP_DECL(2,X)
-#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_2(Q,X,val)
-#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_2_P(Q,X,val)
-#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_2(Q,val,X)
-#define FP_PACK_RAW_QP(val,X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_2_P(Q,val,X); \
- } while (0)
-
-#define FP_UNPACK_Q(X,val) \
- do { \
- _FP_UNPACK_RAW_2(Q,X,val); \
- _FP_UNPACK_CANONICAL(Q,2,X); \
- } while (0)
-
-#define FP_UNPACK_QP(X,val) \
- do { \
- _FP_UNPACK_RAW_2_P(Q,X,val); \
- _FP_UNPACK_CANONICAL(Q,2,X); \
- } while (0)
-
-#define FP_PACK_Q(val,X) \
- do { \
- _FP_PACK_CANONICAL(Q,2,X); \
- _FP_PACK_RAW_2(Q,val,X); \
- } while (0)
-
-#define FP_PACK_QP(val,X) \
- do { \
- _FP_PACK_CANONICAL(Q,2,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_2_P(Q,val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,2,X)
-#define FP_NEG_Q(R,X) _FP_NEG(Q,2,R,X)
-#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,2,R,X,Y)
-#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,2,R,X,Y)
-#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,2,R,X,Y)
-#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,2,R,X,Y)
-#define FP_SQRT_Q(R,X) _FP_SQRT(Q,2,R,X)
-#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q)
-
-#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,2,r,X,Y,un)
-#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,2,r,X,Y)
-
-#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,2,r,X,rsz,rsg)
-#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,2,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_2(X)
-#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_2(X)
-
-#endif /* not _FP_W_TYPE_SIZE < 64 */
diff --git a/arch/sparc64/math-emu/sfp-machine.h b/arch/sparc64/math-emu/sfp-machine.h
index 958d57786..edb309873 100644
--- a/arch/sparc64/math-emu/sfp-machine.h
+++ b/arch/sparc64/math-emu/sfp-machine.h
@@ -29,9 +29,12 @@
#define _FP_WS_TYPE signed long
#define _FP_I_TYPE long
-#define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_imm(S,R,X,Y)
-#define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_1_wide(D,R,X,Y,umul_ppmm)
-#define _FP_MUL_MEAT_Q(R,X,Y) _FP_MUL_MEAT_2_wide_3mul(Q,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv(D,R,X,Y)
@@ -53,7 +56,7 @@
* CPU instruction emulation this should prefer Y.
* (see SPAMv9 B.2.2 section).
*/
-#define _FP_CHOOSENAN(fs, wc, R, X, Y) \
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
do { \
if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs) \
&& !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
@@ -71,7 +74,7 @@
/* Obtain the current rounding mode. */
#ifndef FP_ROUNDMODE
-#define FP_ROUNDMODE ((current->tss.xfsr[0] >> 30) & 0x3)
+#define FP_ROUNDMODE ((current->thread.xfsr[0] >> 30) & 0x3)
#endif
/* Exception flags. */
@@ -83,6 +86,6 @@
#define FP_HANDLE_EXCEPTIONS return _fex
-#define FP_INHIBIT_RESULTS ((current->tss.xfsr[0] >> 23) & _fex)
+#define FP_INHIBIT_RESULTS ((current->thread.xfsr[0] >> 23) & _fex)
#endif
diff --git a/arch/sparc64/math-emu/single.h b/arch/sparc64/math-emu/single.h
deleted file mode 100644
index 6504e5283..000000000
--- a/arch/sparc64/math-emu/single.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* Software floating-point emulation.
- Definitions for IEEE Single Precision.
- Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson (rth@cygnus.com),
- Jakub Jelinek (jj@ultra.linux.cz),
- David S. Miller (davem@redhat.com) and
- Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel kid. Go buy yourself a real computer."
-#endif
-
-#define _FP_FRACBITS_S 24
-#define _FP_FRACXBITS_S (_FP_W_TYPE_SIZE - _FP_FRACBITS_S)
-#define _FP_WFRACBITS_S (_FP_WORKBITS + _FP_FRACBITS_S)
-#define _FP_WFRACXBITS_S (_FP_W_TYPE_SIZE - _FP_WFRACBITS_S)
-#define _FP_EXPBITS_S 8
-#define _FP_EXPBIAS_S 127
-#define _FP_EXPMAX_S 255
-#define _FP_QNANBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2))
-#define _FP_IMPLBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1))
-#define _FP_OVERFLOW_S ((_FP_W_TYPE)1 << (_FP_WFRACBITS_S))
-
-/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be
- chosen by the target machine. */
-
-union _FP_UNION_S
-{
- float flt;
- struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
- unsigned sign : 1;
- unsigned exp : _FP_EXPBITS_S;
- unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
-#else
- unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
- unsigned exp : _FP_EXPBITS_S;
- unsigned sign : 1;
-#endif
- } bits __attribute__((packed));
-};
-
-#define FP_DECL_S(X) _FP_DECL(1,X)
-#define FP_UNPACK_RAW_S(X,val) _FP_UNPACK_RAW_1(S,X,val)
-#define FP_UNPACK_RAW_SP(X,val) _FP_UNPACK_RAW_1_P(S,X,val)
-#define FP_PACK_RAW_S(val,X) _FP_PACK_RAW_1(S,val,X)
-#define FP_PACK_RAW_SP(val,X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_1_P(S,val,X); \
- } while (0)
-
-#define FP_UNPACK_S(X,val) \
- do { \
- _FP_UNPACK_RAW_1(S,X,val); \
- _FP_UNPACK_CANONICAL(S,1,X); \
- } while (0)
-
-#define FP_UNPACK_SP(X,val) \
- do { \
- _FP_UNPACK_RAW_1_P(S,X,val); \
- _FP_UNPACK_CANONICAL(S,1,X); \
- } while (0)
-
-#define FP_PACK_S(val,X) \
- do { \
- _FP_PACK_CANONICAL(S,1,X); \
- _FP_PACK_RAW_1(S,val,X); \
- } while (0)
-
-#define FP_PACK_SP(val,X) \
- do { \
- _FP_PACK_CANONICAL(S,1,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_1_P(S,val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_S(X) _FP_ISSIGNAN(S,1,X)
-#define FP_NEG_S(R,X) _FP_NEG(S,1,R,X)
-#define FP_ADD_S(R,X,Y) _FP_ADD(S,1,R,X,Y)
-#define FP_SUB_S(R,X,Y) _FP_SUB(S,1,R,X,Y)
-#define FP_MUL_S(R,X,Y) _FP_MUL(S,1,R,X,Y)
-#define FP_DIV_S(R,X,Y) _FP_DIV(S,1,R,X,Y)
-#define FP_SQRT_S(R,X) _FP_SQRT(S,1,R,X)
-#define _FP_SQRT_MEAT_S(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q)
-
-#define FP_CMP_S(r,X,Y,un) _FP_CMP(S,1,r,X,Y,un)
-#define FP_CMP_EQ_S(r,X,Y) _FP_CMP_EQ(S,1,r,X,Y)
-
-#define FP_TO_INT_S(r,X,rsz,rsg) _FP_TO_INT(S,1,r,X,rsz,rsg)
-#define FP_FROM_INT_S(X,r,rs,rt) _FP_FROM_INT(S,1,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_S(X) _FP_FRAC_HIGH_1(X)
-#define _FP_FRAC_HIGH_RAW_S(X) _FP_FRAC_HIGH_1(X)
diff --git a/arch/sparc64/math-emu/soft-fp.h b/arch/sparc64/math-emu/soft-fp.h
deleted file mode 100644
index 3c5072e51..000000000
--- a/arch/sparc64/math-emu/soft-fp.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/* Software floating-point emulation.
- Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Richard Henderson (rth@cygnus.com),
- Jakub Jelinek (jj@ultra.linux.cz),
- David S. Miller (davem@redhat.com) and
- Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#ifndef SOFT_FP_H
-#define SOFT_FP_H
-
-#include "sfp-machine.h"
-
-/* Allow sfp-machine to have its own byte order definitions. */
-#ifndef __BYTE_ORDER
-#include <endian.h>
-#endif
-
-#define _FP_WORKBITS 3
-#define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3)
-#define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2)
-#define _FP_WORK_GUARD ((_FP_W_TYPE)1 << 1)
-#define _FP_WORK_STICKY ((_FP_W_TYPE)1 << 0)
-
-#ifndef FP_RND_NEAREST
-# define FP_RND_NEAREST 0
-# define FP_RND_ZERO 1
-# define FP_RND_PINF 2
-# define FP_RND_MINF 3
-#ifndef FP_ROUNDMODE
-# define FP_ROUNDMODE FP_RND_NEAREST
-#endif
-#endif
-
-/* By default don't care about exceptions. */
-#ifndef FP_EX_INVALID
-#define FP_EX_INVALID 0
-#endif
-#ifndef FP_EX_OVERFLOW
-#define FP_EX_OVERFLOW 0
-#endif
-#ifndef FP_EX_UNDERFLOW
-#define FP_EX_UNDERFLOW
-#endif
-#ifndef FP_EX_DIVZERO
-#define FP_EX_DIVZERO 0
-#endif
-#ifndef FP_EX_INEXACT
-#define FP_EX_INEXACT 0
-#endif
-#ifndef FP_EX_DENORM
-#define FP_EX_DENORM 0
-#endif
-
-#ifdef _FP_DECL_EX
-#define FP_DECL_EX \
- int _fex = 0; \
- _FP_DECL_EX
-#else
-#define FP_DECL_EX int _fex = 0
-#endif
-
-#ifndef FP_INIT_ROUNDMODE
-#define FP_INIT_ROUNDMODE do {} while (0)
-#endif
-
-#ifndef FP_HANDLE_EXCEPTIONS
-#define FP_HANDLE_EXCEPTIONS do {} while (0)
-#endif
-
-#ifndef FP_INHIBIT_RESULTS
-/* By default we write the results always.
- * sfp-machine may override this and e.g.
- * check if some exceptions are unmasked
- * and inhibit it in such a case.
- */
-#define FP_INHIBIT_RESULTS 0
-#endif
-
-#define FP_SET_EXCEPTION(ex) \
- _fex |= (ex)
-
-#define FP_UNSET_EXCEPTION(ex) \
- _fex &= ~(ex)
-
-#define FP_CLEAR_EXCEPTIONS \
- _fex = 0
-
-#define _FP_ROUND_NEAREST(wc, X) \
-do { \
- if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND) \
- _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \
-} while (0)
-
-#define _FP_ROUND_ZERO(wc, X) 0
-
-#define _FP_ROUND_PINF(wc, X) \
-do { \
- if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
- _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
-} while (0)
-
-#define _FP_ROUND_MINF(wc, X) \
-do { \
- if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
- _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
-} while (0)
-
-#define _FP_ROUND(wc, X) \
-do { \
- if (_FP_FRAC_LOW_##wc(X) & 7) \
- FP_SET_EXCEPTION(FP_EX_INEXACT); \
- switch (FP_ROUNDMODE) \
- { \
- case FP_RND_NEAREST: \
- _FP_ROUND_NEAREST(wc,X); \
- break; \
- case FP_RND_ZERO: \
- _FP_ROUND_ZERO(wc,X); \
- break; \
- case FP_RND_PINF: \
- _FP_ROUND_PINF(wc,X); \
- break; \
- case FP_RND_MINF: \
- _FP_ROUND_MINF(wc,X); \
- break; \
- } \
-} while (0)
-
-#define FP_CLS_NORMAL 0
-#define FP_CLS_ZERO 1
-#define FP_CLS_INF 2
-#define FP_CLS_NAN 3
-
-#define _FP_CLS_COMBINE(x,y) (((x) << 2) | (y))
-
-#include "op-1.h"
-#include "op-2.h"
-#include "op-4.h"
-#include "op-8.h"
-#include "op-common.h"
-
-/* Sigh. Silly things longlong.h needs. */
-#define UWtype _FP_W_TYPE
-#define W_TYPE_SIZE _FP_W_TYPE_SIZE
-
-typedef int SItype __attribute__((mode(SI)));
-typedef int DItype __attribute__((mode(DI)));
-typedef unsigned int USItype __attribute__((mode(SI)));
-typedef unsigned int UDItype __attribute__((mode(DI)));
-#if _FP_W_TYPE_SIZE == 32
-typedef unsigned int UHWtype __attribute__((mode(HI)));
-#elif _FP_W_TYPE_SIZE == 64
-typedef USItype UHWtype;
-#endif
-
-#ifndef umul_ppmm
-#include <stdlib/longlong.h>
-#endif
-
-#endif
diff --git a/arch/sparc64/mm/asyncd.c b/arch/sparc64/mm/asyncd.c
index e9607cb8f..30272e9b5 100644
--- a/arch/sparc64/mm/asyncd.c
+++ b/arch/sparc64/mm/asyncd.c
@@ -1,4 +1,4 @@
-/* $Id: asyncd.c,v 1.8 1999/07/04 04:35:55 davem Exp $
+/* $Id: asyncd.c,v 1.9 1999/07/30 09:35:43 davem Exp $
* The asyncd kernel daemon. This handles paging on behalf of
* processes that receive page faults due to remote (async) memory
* accesses.
@@ -91,7 +91,8 @@ static void add_to_async_queue(int taskid,
void async_fault(unsigned long address, int write, int taskid,
void (*callback)(int,unsigned long,int,int))
{
- struct task_struct *tsk = task[taskid];
+#warning Need some fixing here... -DaveM
+ struct task_struct *tsk = current /* XXX task[taskid] */;
struct mm_struct *mm = tsk->mm;
stats.faults++;
@@ -111,7 +112,8 @@ static int fault_in_page(int taskid,
{
static unsigned last_address;
static int last_task, loop_counter;
- struct task_struct *tsk = task[taskid];
+#warning Need some fixing here... -DaveM
+ struct task_struct *tsk = current /* XXX task[taskid] */;
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
@@ -178,8 +180,8 @@ no_memory:
bad_area:
stats.failure++;
- tsk->tss.sig_address = address;
- tsk->tss.sig_desc = SUBSIG_NOMAPPING;
+ tsk->thread.sig_address = address;
+ tsk->thread.sig_desc = SUBSIG_NOMAPPING;
send_sig(SIGSEGV, tsk, 1);
return 1;
}
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 04aa8284e..1a20b399b 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.36 1999/07/04 04:35:56 davem Exp $
+/* $Id: fault.c,v 1.39 1999/08/30 10:07:09 davem Exp $
* arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -84,10 +84,11 @@ void unhandled_fault(unsigned long address, struct task_struct *tsk,
printk(KERN_ALERT "Unable to handle kernel paging request "
"at virtual address %016lx\n", (unsigned long)address);
}
- printk(KERN_ALERT "tsk->mm->context = %016lx\n",
- (unsigned long) tsk->mm->context);
- printk(KERN_ALERT "tsk->mm->pgd = %016lx\n",
- (unsigned long) tsk->mm->pgd);
+ printk(KERN_ALERT "tsk->{mm,active_mm}->context = %016lx\n",
+ (tsk->mm ? tsk->mm->context : tsk->active_mm->context));
+ printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n",
+ (tsk->mm ? (unsigned long) tsk->mm->pgd :
+ (unsigned long) tsk->active_mm->pgd));
die_if_kernel("Oops", regs);
}
@@ -154,16 +155,45 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs, unsigned long address, in
* If we're in an interrupt or have no user
* context, we must not take the fault..
*/
- if (in_interrupt() || mm == &init_mm)
+ if (in_interrupt() || !mm)
goto do_kernel_fault;
down(&mm->mmap_sem);
#ifdef DEBUG_LOCKUPS
- if (regs->tpc == lastpc && address == lastaddr && write == lastwrite) {
+ if (regs->tpc == lastpc &&
+ address == lastaddr &&
+ write == lastwrite) {
lockcnt++;
if (lockcnt == 100000) {
- printk("do_sparc64_fault: possible fault loop for %016lx %s\n", address, write ? "write" : "read");
+ unsigned char tmp;
+ register unsigned long tmp1 asm("o5");
+ register unsigned long tmp2 asm("o4");
+
+ printk("do_sparc64_fault[%s:%d]: possible fault loop for %016lx %s\n",
+ current->comm, current->pid,
+ address, write ? "write" : "read");
+ printk("do_sparc64_fault: CHECK[papgd[%016lx],pcac[%016lx]]\n",
+ __pa(mm->pgd), pgd_val(mm->pgd[0])<<11UL);
+ __asm__ __volatile__(
+ "wrpr %%g0, 0x494, %%pstate\n\t"
+ "mov %3, %%g4\n\t"
+ "mov %%g7, %0\n\t"
+ "ldxa [%%g4] %2, %1\n\t"
+ "wrpr %%g0, 0x096, %%pstate"
+ : "=r" (tmp1), "=r" (tmp2)
+ : "i" (ASI_DMMU), "i" (TSB_REG));
+ printk("do_sparc64_fault: IS[papgd[%016lx],pcac[%016lx]]\n",
+ tmp1, tmp2);
+ printk("do_sparc64_fault: CHECK[ctx(%016lx)] IS[ctx(%016lx)]\n",
+ mm->context, spitfire_get_secondary_context());
+ __asm__ __volatile__("rd %%asi, %0"
+ : "=r" (tmp));
+ printk("do_sparc64_fault: CHECK[seg(%02x)] IS[seg(%02x)]\n",
+ current->thread.current_ds.seg, tmp);
show_regs(regs);
+ __sti();
+ while(1)
+ barrier();
}
} else {
lastpc = regs->tpc;
@@ -282,8 +312,18 @@ do_kernel_fault:
return;
}
} else {
- current->tss.sig_address = address;
- current->tss.sig_desc = SUBSIG_NOMAPPING;
+#if 0
+ extern void __show_regs(struct pt_regs *);
+ printk("SHIT(%s:%d:cpu(%d)): PC[%016lx] ADDR[%016lx]\n",
+ current->comm, current->pid, smp_processor_id(),
+ regs->tpc, address);
+ __show_regs(regs);
+ __sti();
+ while(1)
+ barrier();
+#endif
+ current->thread.sig_address = address;
+ current->thread.sig_desc = SUBSIG_NOMAPPING;
force_sig(SIGSEGV, current);
return;
}
@@ -293,8 +333,8 @@ do_kernel_fault:
do_sigbus:
up(&mm->mmap_sem);
- current->tss.sig_address = address;
- current->tss.sig_desc = SUBSIG_MISCERROR;
+ current->thread.sig_address = address;
+ current->thread.sig_desc = SUBSIG_MISCERROR;
force_sig(SIGBUS, current);
if (regs->tstate & TSTATE_PRIV)
goto do_kernel_fault;
diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c
index ccb0951cc..cf94f4250 100644
--- a/arch/sparc64/mm/generic.c
+++ b/arch/sparc64/mm/generic.c
@@ -1,4 +1,4 @@
-/* $Id: generic.c,v 1.8 1999/03/12 06:51:50 davem Exp $
+/* $Id: generic.c,v 1.9 1999/07/23 22:32:01 davem Exp $
* generic.c: Generic Sparc mm routines that are not dependent upon
* MMU type but are Sparc specific.
*
@@ -95,7 +95,8 @@ static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsign
space);
curend = address + 0x10000;
offset += 0x10000;
- }
+ } else
+ offset += PAGE_SIZE;
} else
offset += PAGE_SIZE;
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 8f176e885..c1d8d24ae 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.128 1999/05/25 16:53:24 jj Exp $
+/* $Id: init.c,v 1.135 1999/09/06 22:55:10 ecd Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -42,7 +42,10 @@ unsigned long *sparc64_valid_addr_bitmap;
unsigned long phys_base;
/* get_new_mmu_context() uses "cache + 1". */
+spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED;
unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
+#define CTX_BMAP_SLOTS (1UL << (CTX_VERSION_SHIFT - 6))
+unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
/* References to section boundaries */
extern char __init_begin, __init_end, etext, __bss_start;
@@ -163,7 +166,7 @@ static int dvma_pages_current_index;
static unsigned long dvmaiobase = 0;
static unsigned long dvmaiosz __initdata = 0;
-__initfunc(void dvmaio_init(void))
+void __init dvmaio_init(void)
{
long i;
@@ -184,7 +187,7 @@ __initfunc(void dvmaio_init(void))
}
}
-__initfunc(void iommu_init(int iommu_node, struct linux_sbus *sbus))
+void __init iommu_init(int iommu_node, struct linux_sbus *sbus)
{
extern int this_is_starfire;
extern void *starfire_hookup(int);
@@ -386,7 +389,7 @@ void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr,
dvma_pages_current_offset;
/* Map the CPU's view. */
- pgdp = pgd_offset(init_task.mm, addr);
+ pgdp = pgd_offset(&init_mm, addr);
pmdp = pmd_alloc_kernel(pgdp, addr);
ptep = pte_alloc_kernel(pmdp, addr);
pte = mk_pte(the_page, PAGE_KERNEL);
@@ -583,7 +586,8 @@ void mmu_set_sbus64(struct linux_sbus_device *sdev, int bursts)
struct linux_sbus *sbus = sdev->my_bus;
struct sysio_regs *sregs = sbus->iommu->sysio_regs;
int slot = sdev->slot;
- u64 *cfg, tmp;
+ volatile u64 *cfg;
+ u64 tmp;
switch(slot) {
case 0:
@@ -677,7 +681,7 @@ static inline void inherit_prom_mappings(void)
for (vaddr = trans[i].virt;
vaddr < trans[i].virt + trans[i].size;
vaddr += PAGE_SIZE) {
- pgdp = pgd_offset(init_task.mm, vaddr);
+ pgdp = pgd_offset(&init_mm, vaddr);
if (pgd_none(*pgdp)) {
pmdp = sparc_init_alloc(&mempool,
PMD_TABLE_SIZE);
@@ -739,7 +743,7 @@ void prom_world(int enter)
int i;
if (!enter)
- set_fs(current->tss.current_ds);
+ set_fs(current->thread.current_ds);
if (!prom_ditlb_set)
return;
@@ -957,9 +961,6 @@ void __flush_tlb_all(void)
: : "r" (pstate));
}
-#define CTX_BMAP_SLOTS (1UL << (CTX_VERSION_SHIFT - 6))
-unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
-
/* Caller does TLB context flushing on local CPU if necessary.
*
* We must be careful about boundary cases so that we never
@@ -969,14 +970,16 @@ unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
*/
void get_new_mmu_context(struct mm_struct *mm)
{
- unsigned long ctx = (tlb_context_cache + 1) & ~(CTX_VERSION_MASK);
- unsigned long new_ctx;
+ unsigned long ctx, new_ctx;
+ spin_lock(&ctx_alloc_lock);
+ ctx = CTX_HWBITS(tlb_context_cache + 1);
if (ctx == 0)
ctx = 1;
- if ((mm->context != NO_CONTEXT) &&
- !((mm->context ^ tlb_context_cache) & CTX_VERSION_MASK))
- clear_bit(mm->context & ~(CTX_VERSION_MASK), mmu_context_bmap);
+ if (CTX_VALID(mm->context)) {
+ unsigned long nr = CTX_HWBITS(mm->context);
+ mmu_context_bmap[nr>>6] &= ~(1UL << (nr & 63));
+ }
new_ctx = find_next_zero_bit(mmu_context_bmap, 1UL << CTX_VERSION_SHIFT, ctx);
if (new_ctx >= (1UL << CTX_VERSION_SHIFT)) {
new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1);
@@ -1003,12 +1006,13 @@ void get_new_mmu_context(struct mm_struct *mm)
goto out;
}
}
- set_bit(new_ctx, mmu_context_bmap);
+ mmu_context_bmap[new_ctx>>6] |= (1UL << (new_ctx & 63));
new_ctx |= (tlb_context_cache & CTX_VERSION_MASK);
out:
tlb_context_cache = new_ctx;
+ spin_unlock(&ctx_alloc_lock);
+
mm->context = new_ctx;
- mm->cpu_vm_mask = 0;
}
#ifndef __SMP__
@@ -1041,15 +1045,15 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
return NULL;
}
-__initfunc(static void
-allocate_ptable_skeleton(unsigned long start, unsigned long end))
+static void __init
+allocate_ptable_skeleton(unsigned long start, unsigned long end)
{
pgd_t *pgdp;
pmd_t *pmdp;
pte_t *ptep;
while (start < end) {
- pgdp = pgd_offset(init_task.mm, start);
+ pgdp = pgd_offset(&init_mm, start);
if (pgd_none(*pgdp)) {
pmdp = sparc_init_alloc(&mempool, PAGE_SIZE);
memset(pmdp, 0, PAGE_SIZE);
@@ -1073,7 +1077,7 @@ allocate_ptable_skeleton(unsigned long start, unsigned long end))
void sparc_ultra_mapioaddr(unsigned long physaddr, unsigned long virt_addr,
int bus, int rdonly)
{
- pgd_t *pgdp = pgd_offset(init_task.mm, virt_addr);
+ pgd_t *pgdp = pgd_offset(&init_mm, virt_addr);
pmd_t *pmdp = pmd_offset(pgdp, virt_addr);
pte_t *ptep = pte_offset(pmdp, virt_addr);
pte_t pte;
@@ -1095,7 +1099,7 @@ void sparc_ultra_unmapioaddr(unsigned long virt_addr)
pmd_t *pmdp;
pte_t *ptep;
- pgdp = pgd_offset(init_task.mm, virt_addr);
+ pgdp = pgd_offset(&init_mm, virt_addr);
pmdp = pmd_offset(pgdp, virt_addr);
ptep = pte_offset(pmdp, virt_addr);
@@ -1139,8 +1143,8 @@ void sparc_ultra_dump_dtlb(void)
extern unsigned long free_area_init(unsigned long, unsigned long);
extern unsigned long sun_serial_setup(unsigned long);
-__initfunc(unsigned long
-paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init
+paging_init(unsigned long start_mem, unsigned long end_mem)
{
extern pmd_t swapper_pmd_dir[1024];
extern unsigned int sparc64_vpte_patchme1[1];
@@ -1259,7 +1263,7 @@ paging_init(unsigned long start_mem, unsigned long end_mem))
return device_scan (PAGE_ALIGN (start_mem));
}
-__initfunc(static void taint_real_pages(unsigned long start_mem, unsigned long end_mem))
+static void __init taint_real_pages(unsigned long start_mem, unsigned long end_mem)
{
unsigned long tmp = 0, paddr, endaddr;
unsigned long end = __pa(end_mem);
@@ -1305,7 +1309,7 @@ __initfunc(static void taint_real_pages(unsigned long start_mem, unsigned long e
}
}
-__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
+void __init mem_init(unsigned long start_mem, unsigned long end_mem)
{
int codepages = 0;
int datapages = 0;
@@ -1319,6 +1323,7 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
max_mapnr = MAP_NR(end_mem);
high_memory = (void *) end_mem;
+ start_mem = ((start_mem + 7UL) & ~7UL);
sparc64_valid_addr_bitmap = (unsigned long *)start_mem;
i = max_mapnr >> ((22 - PAGE_SHIFT) + 6);
i += 1;
@@ -1472,4 +1477,6 @@ void si_meminfo(struct sysinfo *val)
}
val->totalram <<= PAGE_SHIFT;
val->sharedram <<= PAGE_SHIFT;
+ val->totalbig = 0;
+ val->freebig = 0;
}
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
index 3d3d1a289..71e05dc7e 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -1,9 +1,11 @@
-/* $Id: ultra.S,v 1.32 1999/03/28 08:39:34 davem Exp $
+/* $Id: ultra.S,v 1.34 1999/09/10 10:40:51 davem Exp $
* ultra.S: Don't expand these all over the place...
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/config.h>
+
#include <asm/asi.h>
#include <asm/pgtable.h>
#include <asm/spitfire.h>
@@ -136,36 +138,37 @@ __flush_tlb_range_pbp_slow:
flush_icache_page: /* %o0 = phys_page */
sethi %hi(1 << 13), %o2 ! IC_set bit
mov 1, %g1
- srlx %o0, 5, %o0 ! phys-addr comparitor
+ srlx %o0, 5, %o0
clr %o1 ! IC_addr
sllx %g1, 36, %g1
sub %g1, 1, %g2
- andn %g2, 0xff, %g2 ! IC_tag mask
- nop
+ or %o0, %g1, %o0 ! VALID+phys-addr comparitor
+ sllx %g2, 1, %g2
+ andn %g2, 0xfe, %g2 ! IC_tag mask
1: ldda [%o1] ASI_IC_TAG, %o4
and %o5, %g2, %o5
cmp %o5, %o0
be,pn %xcc, iflush1
- nop
+ add %o1, 0x20, %g3
2: ldda [%o1 + %o2] ASI_IC_TAG, %o4
and %o5, %g2, %o5
- cmp %o5, %o0
+ cmp %o5, %o0
be,pn %xcc, iflush2
nop
-3: add %o1, 0x20, %o1
- cmp %o1, %o2
+3: cmp %g3, %o2
bne,pt %xcc, 1b
- nop
+ mov %g3, %o1
retl
nop
+
iflush1:stxa %g0, [%o1] ASI_IC_TAG
- ba,pt %xcc, 2b
- flush %g6
+ flush %g6
+ ba,a,pt %xcc, 2b
iflush2:stxa %g0, [%o1 + %o2] ASI_IC_TAG
- ba,pt %xcc, 3b
- flush %g6
+ flush %g6
+ ba,a,pt %xcc, 3b
#ifdef __SMP__
/* These are all called by the slaves of a cross call, at
diff --git a/arch/sparc64/prom/bootstr.c b/arch/sparc64/prom/bootstr.c
index 6d53b8be2..064ba2472 100644
--- a/arch/sparc64/prom/bootstr.c
+++ b/arch/sparc64/prom/bootstr.c
@@ -1,4 +1,4 @@
-/* $Id: bootstr.c,v 1.5 1998/01/23 08:51:39 jj Exp $
+/* $Id: bootstr.c,v 1.6 1999/08/31 06:55:01 davem Exp $
* bootstr.c: Boot string/argument acquisition from the PROM.
*
* Copyright(C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -14,8 +14,8 @@ int bootstr_len = BARG_LEN;
static int bootstr_valid = 0;
static char bootstr_buf[BARG_LEN] = { 0 };
-__initfunc(char *
-prom_getbootargs(void))
+char * __init
+prom_getbootargs(void)
{
/* This check saves us from a panic when bootfd patches args. */
if (bootstr_valid) return bootstr_buf;
diff --git a/arch/sparc64/prom/init.c b/arch/sparc64/prom/init.c
index 4c1bd1e00..17166a72c 100644
--- a/arch/sparc64/prom/init.c
+++ b/arch/sparc64/prom/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.8 1998/03/15 10:14:44 ecd Exp $
+/* $Id: init.c,v 1.9 1999/08/31 06:55:03 davem Exp $
* init.c: Initialize internal variables used by the PROM
* library functions.
*
@@ -31,7 +31,7 @@ extern void prom_meminit(void);
extern void prom_ranges_init(void);
extern void prom_cif_init(void *, void *);
-__initfunc(void prom_init(void *cif_handler, void *cif_stack))
+void __init prom_init(void *cif_handler, void *cif_stack)
{
char buffer[80], *p;
int ints[3];
diff --git a/arch/sparc64/prom/memory.c b/arch/sparc64/prom/memory.c
index 3523c3b1d..92f4ff4fc 100644
--- a/arch/sparc64/prom/memory.c
+++ b/arch/sparc64/prom/memory.c
@@ -1,4 +1,4 @@
-/* $Id: memory.c,v 1.4 1998/11/25 10:04:06 jj Exp $
+/* $Id: memory.c,v 1.5 1999/08/31 06:55:04 davem Exp $
* memory.c: Prom routine for acquiring various bits of information
* about RAM on the machine, both virtual and physical.
*
@@ -37,8 +37,8 @@ struct linux_mem_p1275 prom_memlist;
/* Internal Prom library routine to sort a linux_mlist_p1275 memory
* list. Used below in initialization.
*/
-__initfunc(static void
-prom_sortmemlist(struct linux_mlist_p1275 *thislist))
+static void __init
+prom_sortmemlist(struct linux_mlist_p1275 *thislist)
{
int swapi = 0;
int i, mitr;
@@ -65,7 +65,7 @@ prom_sortmemlist(struct linux_mlist_p1275 *thislist))
}
/* Initialize the memory lists based upon the prom version. */
-__initfunc(void prom_meminit(void))
+void __init prom_meminit(void)
{
int node = 0;
unsigned int iter, num_regs;
diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c
index 83af773df..2a45a4bb5 100644
--- a/arch/sparc64/prom/misc.c
+++ b/arch/sparc64/prom/misc.c
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.14 1998/12/18 10:01:59 davem Exp $
+/* $Id: misc.c,v 1.15 1999/08/31 19:25:41 davem Exp $
* misc.c: Miscellaneous prom functions that don't belong
* anywhere else.
*
@@ -125,15 +125,37 @@ void prom_set_trap_table(unsigned long tba)
/* This is only used internally below. */
static int prom_get_mmu_ihandle(void)
{
- int node;
- int ret;
+ static int mmu_ihandle_cache = 0;
+ int node, ret;
+
+ if (mmu_ihandle_cache != 0)
+ return mmu_ihandle_cache;
node = prom_finddevice("/chosen");
ret = prom_getint(node, "mmu");
- if(ret == -1 || ret == 0) {
- prom_printf("PROMLIB: Fatal error, cannot get mmu ihandle.\n");
- prom_halt();
- }
+ if(ret == -1 || ret == 0)
+ mmu_ihandle_cache = -1;
+ else
+ mmu_ihandle_cache = ret;
+
+ return ret;
+}
+
+static int prom_get_memory_ihandle(void)
+{
+ static int memory_ihandle_cache = 0;
+ int node, ret;
+
+ if (memory_ihandle_cache != 0)
+ return memory_ihandle_cache;
+
+ node = prom_finddevice("/chosen");
+ ret = prom_getint(node, "memory");
+ if (ret == -1 || ret == 0)
+ memory_ihandle_cache = -1;
+ else
+ memory_ihandle_cache = ret;
+
return ret;
}
@@ -197,12 +219,18 @@ unsigned long prom_retain(char *name,
* etched into the motherboard next to the SIMM slot
* in question.
*/
-int prom_getunumber(unsigned long phys_lo, unsigned long phys_hi,
+int prom_getunumber(int syndrome_code,
+ unsigned long phys_addr,
char *buf, int buflen)
{
- return p1275_cmd("SUNW,get-unumber",
- (P1275_ARG(2, P1275_ARG_OUT_BUF) | P1275_INOUT(4, 1)),
- phys_lo, phys_hi, buf, buflen);
+ return p1275_cmd("call-method",
+ (P1275_ARG(0, P1275_ARG_IN_STRING) |
+ P1275_ARG(3, P1275_ARG_OUT_BUF) |
+ P1275_ARG(5, P1275_ARG_IN_64B) |
+ P1275_INOUT(8, 2)),
+ "SUNW,get-unumber", prom_get_memory_ihandle(),
+ buflen, buf, P1275_SIZE(buflen),
+ 0, phys_addr, syndrome_code);
}
/* Power management extensions. */
diff --git a/arch/sparc64/prom/p1275.c b/arch/sparc64/prom/p1275.c
index 9b1fafa37..f30bdd3a8 100644
--- a/arch/sparc64/prom/p1275.c
+++ b/arch/sparc64/prom/p1275.c
@@ -1,4 +1,4 @@
-/* $Id: p1275.c,v 1.15 1998/10/13 14:03:47 davem Exp $
+/* $Id: p1275.c,v 1.18 1999/09/10 10:40:53 davem Exp $
* p1275.c: Sun IEEE 1275 PROM low level interface routines
*
* Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -9,13 +9,13 @@
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/string.h>
+#include <linux/spinlock.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/system.h>
#include <asm/spitfire.h>
#include <asm/pstate.h>
-#include <asm/spinlock.h>
struct {
long prom_callback; /* 0x00 */
@@ -252,8 +252,8 @@ void prom_cif_callback(void)
* the counter is needed. -DaveM
*/
static int prom_entry_depth = 0;
-#ifdef __SMP__
static spinlock_t prom_entry_lock = SPIN_LOCK_UNLOCKED;
+#ifdef __SMP__
extern void smp_capture(void);
extern void smp_release(void);
#endif
@@ -321,6 +321,10 @@ long p1275_cmd (char *service, long fmt, ...)
p1275buf.prom_args[i + 3] =
(unsigned)va_arg(list, long);
break;
+ case P1275_ARG_IN_64B:
+ p1275buf.prom_args[i + 3] =
+ va_arg(list, unsigned long);
+ break;
case P1275_ARG_IN_STRING:
strcpy (p, va_arg(list, char *));
p1275buf.prom_args[i + 3] = (unsigned long)p;
diff --git a/arch/sparc64/prom/ranges.c b/arch/sparc64/prom/ranges.c
index 7b889bac1..048e3412a 100644
--- a/arch/sparc64/prom/ranges.c
+++ b/arch/sparc64/prom/ranges.c
@@ -1,4 +1,4 @@
-/* $Id: ranges.c,v 1.10 1998/03/24 05:54:29 ecd Exp $
+/* $Id: ranges.c,v 1.12 1999/08/31 06:55:05 davem Exp $
* ranges.c: Handle ranges in newer proms for obio/sbus.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -87,11 +87,11 @@ void prom_apply_central_ranges(struct linux_central *central,
central->num_central_ranges);
}
-__initfunc(void prom_ranges_init(void))
+void __init prom_ranges_init(void)
{
}
-__initfunc(void prom_sbus_ranges_init(int iommund, struct linux_sbus *sbus))
+void __init prom_sbus_ranges_init(int iommund, struct linux_sbus *sbus)
{
int success;
@@ -103,7 +103,7 @@ __initfunc(void prom_sbus_ranges_init(int iommund, struct linux_sbus *sbus))
sbus->num_sbus_ranges = (success/sizeof(struct linux_prom_ranges));
}
-__initfunc(void prom_central_ranges_init(int cnode, struct linux_central *central))
+void __init prom_central_ranges_init(int cnode, struct linux_central *central)
{
int success;
@@ -115,7 +115,7 @@ __initfunc(void prom_central_ranges_init(int cnode, struct linux_central *centra
central->num_central_ranges = (success/sizeof(struct linux_prom_ranges));
}
-__initfunc(void prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc))
+void __init prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc)
{
int success;
@@ -128,7 +128,7 @@ __initfunc(void prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc))
}
#ifdef CONFIG_PCI
-__initfunc(void prom_ebus_ranges_init(struct linux_ebus *ebus))
+void __init prom_ebus_ranges_init(struct linux_ebus *ebus)
{
int success;
@@ -140,7 +140,7 @@ __initfunc(void prom_ebus_ranges_init(struct linux_ebus *ebus))
ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges));
}
-__initfunc(void prom_ebus_intmap_init(struct linux_ebus *ebus))
+void __init prom_ebus_intmap_init(struct linux_ebus *ebus)
{
int success;
@@ -161,40 +161,6 @@ __initfunc(void prom_ebus_intmap_init(struct linux_ebus *ebus))
prom_halt();
}
}
-
-__initfunc(void prom_pbm_ranges_init(int pnode, struct linux_pbm_info *pbm))
-{
- int success;
-
- pbm->num_pbm_ranges = 0;
- success = prom_getproperty(pnode, "ranges",
- (char *)&pbm->pbm_ranges,
- sizeof(pbm->pbm_ranges));
- if(success != -1)
- pbm->num_pbm_ranges = (success/sizeof(struct linux_prom_pci_ranges));
-}
-
-__initfunc(void prom_pbm_intmap_init(int pnode, struct linux_pbm_info *pbm))
-{
- int success;
-
- pbm->num_pbm_intmap = 0;
- success = prom_getproperty(pnode, "interrupt-map",
- (char *)pbm->pbm_intmap,
- sizeof(pbm->pbm_intmap));
- if (success == -1)
- return;
-
- pbm->num_pbm_intmap = (success/sizeof(struct linux_prom_pci_intmap));
-
- success = prom_getproperty(pnode, "interrupt-map-mask",
- (char *)&pbm->pbm_intmask,
- sizeof(pbm->pbm_intmask));
- if (success == -1) {
- prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__);
- prom_halt();
- }
-}
#endif
void
diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
index 82a583c29..ac3071b50 100644
--- a/arch/sparc64/solaris/ioctl.c
+++ b/arch/sparc64/solaris/ioctl.c
@@ -1,4 +1,4 @@
-/* $Id: ioctl.c,v 1.11 1999/05/27 00:36:25 davem Exp $
+/* $Id: ioctl.c,v 1.13 1999/08/20 00:27:15 davem Exp $
* ioctl.c: Solaris ioctl emulation.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -367,7 +367,6 @@ static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg,
int len, int *len_p)
{
- struct inode *ino;
int ret;
switch (cmd & 0xff) {
@@ -459,7 +458,6 @@ static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd
mm_segment_t old_fs;
struct strioctl si;
struct inode *ino;
- struct file *filp;
struct sol_socket_struct *sock;
struct module_info *mi;
@@ -665,7 +663,7 @@ static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg)
#endif
case 87: /* SIOCGIFNUM */
{
- struct device *d;
+ struct net_device *d;
int i = 0;
read_lock_bh(&dev_base_lock);
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 4b3a1ce5d..c3176ac2c 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.13 1998/10/28 08:11:58 jj Exp $
+/* $Id: misc.c,v 1.14 1999/06/25 11:00:53 davem Exp $
* misc.c: Miscelaneous syscall emulation for Solaris
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
index f6d31920e..5eef5c208 100644
--- a/arch/sparc64/solaris/socksys.c
+++ b/arch/sparc64/solaris/socksys.c
@@ -1,4 +1,4 @@
-/* $Id: socksys.c,v 1.8 1998/08/26 10:28:28 davem Exp $
+/* $Id: socksys.c,v 1.10 1999/08/31 06:55:08 davem Exp $
* socksys.c: /dev/inet/ stuff for Solaris emulation.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -174,8 +174,8 @@ static struct file_operations socksys_fops = {
socksys_release,/* release */
};
-__initfunc(int
-init_socksys(void))
+int __init
+init_socksys(void)
{
int ret;
struct file * file;
diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
index cba34c36d..5ee6df467 100644
--- a/arch/sparc64/solaris/timod.c
+++ b/arch/sparc64/solaris/timod.c
@@ -1,4 +1,4 @@
-/* $Id: timod.c,v 1.2 1999/05/12 11:11:55 davem Exp $
+/* $Id: timod.c,v 1.4 1999/09/01 08:07:47 davem Exp $
* timod.c: timod emulation.
*
* Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
@@ -33,9 +33,7 @@ extern asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd,
u32 arg);
asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
-#ifdef __SMP__
spinlock_t timod_pagelock = SPIN_LOCK_UNLOCKED;
-#endif
static char * page = NULL ;
#ifndef DEBUG_SOLARIS_KMALLOC
@@ -679,7 +677,7 @@ int timod_getmsg(unsigned int fd, char *ctl_buf, int ctl_maxlen, s32 *ctl_len,
wait = &wait_table;
for(;;) {
SOLD("loop");
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
/* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
/* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
/* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
diff --git a/arch/sparc64/vmlinux.lds b/arch/sparc64/vmlinux.lds
index ec1ca0461..e6f6cf82a 100644
--- a/arch/sparc64/vmlinux.lds
+++ b/arch/sparc64/vmlinux.lds
@@ -39,8 +39,17 @@ SECTIONS
__init_begin = .;
.text.init : { *(.text.init) }
.data.init : { *(.data.init) }
+ . = ALIGN(16);
+ __setup_start = .;
+ .setup_init : { *(.setup.init) }
+ __setup_end = .;
+ __initcall_start = .;
+ .initcall.init : { *(.initcall.init) }
+ __initcall_end = .;
. = ALIGN(8192);
__init_end = .;
+ . = ALIGN(64);
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
__bss_start = .;
.sbss : { *(.sbss) *(.scommon) }
.bss :